Hello Listeners and Listers,

I've just finished the first working version of $Subjec - a rewrite
of POE::Wheel::ReadLine which uses the GNU readline library:

http://perlmonks.org/?node_id=667205

I'll check for compatibility with POE::Wheel::ReadLine, and run its tests
against the new module.

cheers,
0--gg-

-- 
_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s,/,($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e,e && print}
package POE::Wheel::ReadLine::Gnu;
use Carp   qw( croak carp );
use Symbol qw( gensym );
use POE    qw( Wheel );

use Term::ReadLine;
our @ISA = qw(Term::ReadLine);

# Private STDIN and STDOUT.
my $stdin  = gensym();
open($stdin, "<&STDIN") or die "Can't open private STDIN: $!";

my $stdout = gensym;
open($stdout, ">&STDOUT") or die "Can't open private STDOUT: $!";

# Offsets into $self->{POE}.
# OBJECT ($self) is 0
sub SELF_INPUT          () { 1 }
sub SELF_EVENT_INPUT    () { 2 }
sub SELF_READING_LINE   () { 3 }
sub SELF_STATE_READ     () { 4 }
sub SELF_STATE_IDLE     () { 5 }
sub SELF_UNIQUE_ID      () { 6 }
sub SELF_APP            () { 7 }

#------------------------------------------------------------------------------

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my %params = @_;
    croak "$class requires a working Kernel" unless defined $poe_kernel;

    my $input_event = delete $params{InputEvent};
    croak "$class requires an InputEvent parameter" unless defined $input_event;

    my $put_mode = delete $params{PutMode};
    $put_mode = 'idle' unless defined $put_mode;
    croak "$class PutMode must be either 'immediate', 'idle', or 'after'"
        unless $put_mode =~ /^(immediate|idle|after)$/;

    my $idle_time = delete $params{IdleTime};
    $idle_time = 2 unless defined $idle_time;

    my $app = delete $params{appname};
    $app ||= 'poe-readline';

    if (scalar keys %params) {
        carp(
            "unknown parameters in $class constructor call: ",
            join(', ', keys %params)
        );
    }
    my $self = $proto->SUPER::new();# $stdin, $stdout);

    $self->{POE} = [
        undef,                                  # OBJECT
        undef,                                  # SELF_INPUT
        $input_event,                           # SELF_EVENT_INPUT
        0,                                      # SELF_READING_LINE
        undef,                                  # SELF_STATE_READ
        undef,                                  # SELF_STATE_IDLE
        &POE::Wheel::allocate_wheel_id(),       # SELF_UNIQUE_ID
        $app,                                   # SELF_APP

    ];
    bless $self, $class; 
    # set unbuffered IO
    select((select($stdout), $| = 1)[0]);
    # Set up the event handlers.  Idle goes first.
    $self->{POE}->[SELF_STATE_IDLE] = (
        ref($self) . "(" . $self->{POE}->[SELF_UNIQUE_ID] . ") -> input timeout"
    );
    $poe_kernel->state($self->{POE}->[SELF_STATE_IDLE], $self, '_idle_state');
    $self->{POE}->[SELF_STATE_READ] = (
        ref($self) . "(" . $self->{POE}->[SELF_UNIQUE_ID] . ") -> select read"
    );
    $poe_kernel->state($self->{POE}->[SELF_STATE_READ], $self, '_read_state');
    rl_callback_handler_install($self,$prompt,sub { $self->got_line(@_) } );

    return $self;
}

sub get {
    my ($self,$prompt,$preput) = @_;
    return if $self->{POE}->[SELF_READING_LINE];
    $self->{POE}->[SELF_READING_LINE] = 1;
    my $Attribs = $self->Attribs;
    # ornament support (now prompt only)
    $prompt = ${$Attribs{term_set}}[0] . $prompt . ${$Attribs{term_set}}[1];
    $Attribs{completion_entry_function} = $Attribs{_trp_completion_function}
        if (!defined $Attribs{completion_entry_function}
            && defined $Attribs{completion_function});
    $self->rl_set_prompt($prompt);
    $self->rl_insert_text($preput) if defined $preput;
    $self->rl_redisplay();
    $poe_kernel->select_read($stdin, $self->{POE}->[SELF_STATE_READ]);
}

sub got_line {
    my $self = $_[OBJECT];
    $self->{POE}->[SELF_READING_LINE] = 0;
    $poe_kernel->select_read($stdin);
    $self->rl_set_prompt('');
    $poe_kernel->yield( $self->{POE}->[SELF_EVENT_INPUT],$_[SELF_INPUT]);
}
sub _idle_state { }
sub _read_state { $_[OBJECT]->rl_callback_read_char }

sub DESTROY {
    my $self = shift;
    $self->rl_deprep_terminal();
}
1;

Reply via email to