aboutsummaryrefslogblamecommitdiffstats
path: root/testing/lib/Test/Irssi/Driver.pm
blob: 8aa547a1a2aaddded73beaa410299c849aa4f578 (plain) (tree)
























































































































































                                                                                 
use strictures 1;

package Test::Irssi::Driver;

use Moose;
use MooseX::POE;
use POE qw( Wheel::ReadWrite Wheel::Run Filter::Stream );
use POSIX;

has 'parent'
  => (
      is => 'ro',
      isa => 'Test::Irssi',
      required => 1,
     );


sub  START {
    my ($self, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP];

    $self->save_term_settings($heap);

    # Set a signal handler.
    $kernel->sig(CHLD => "got_sigchld");

    $self->make_raw_terminal;

    my @stdio_options =
      (
       InputHandle  => \*STDIN,
       OutputHandle => \*STDOUT,
       InputEvent   => "got_terminal_stdin",
       Filter       => POE::Filter::Stream->new(),
      );

    # Start the terminal reader/writer.
    $heap->{stdio} = POE::Wheel::ReadWrite->new(@stdio_options);

    my $rows = $self->parent->terminal_height;
    my $cols = $self->parent->terminal_width;

    my @program_options =
      (
       Program     => $self->parent->irssi_binary,
       ProgramArgs => ['--noconnect', '--home=' . $self->parent->irssi_homedir ],
       Conduit     => "pty",
       Winsize     => [$rows, $cols, 0, 0],
       StdoutEvent => "got_child_stdout",
       StdioFilter => POE::Filter::Stream->new(),
      );

    # Start the asynchronous child process.
    $heap->{program} = POE::Wheel::Run->new(@program_options);
}



sub STOP {
    my ($self, $heap) = @_[OBJECT,HEAP];
    $heap->{stdin_tio}->setattr (0, TCSANOW);
    $heap->{stdout_tio}->setattr(1, TCSANOW);
    $heap->{stderr_tio}->setattr(2, TCSANOW);
    $self->_logfile_fh->close();
}

### Handle terminal STDIN.  Send it to the background program's STDIN.
### If the user presses ^C, then echo a little string

sub handle_terminal_stdin {
    my ($self, $heap, $input) = @_[OBJECT, HEAP, ARG0];
    if ($input =~ m/\003/g) {
        $input = "/echo I like cakes\n";
    } elsif ($input =~ m/\004/g) {
        $self->log( vt_dump());
    }
    $heap->{program}->put($input);
}
##
### Handle STDOUT from the child program.
sub handle_child_stdout {
    my ($self, $heap, $input) = @_[OBJECT, HEAP, ARG0];
    # process via vt
    $self->parent->vt->process($input);
    # send to terminal
    $heap->{stdio}->put($input);
}

### Handle SIGCHLD.  Shut down if the exiting child process was the
### one we've been managing.

sub  CHILD {
    my ($self, $heap, $child_pid) = @_[OBJECT, HEAP, ARG1];
    if ($child_pid == $heap->{program}->PID) {
        delete $heap->{program};
        delete $heap->{stdio};
    }
    return 0;
}

sub bacon { 
    POE::Session->create
        (
         inline_states => {
                           _start             => \&handle_start,
                           _stop              => \&handle_stop,
                           got_terminal_stdin => \&handle_terminal_stdin,
                           got_child_stdout   => \&handle_child_stdout,
                           got_sigchld        => \&handle_sigchld,
                          },
        );
}

sub save_term_settings {
    my ($self, $heap) = @_;
    # Save the original terminal settings so they can be restored later.
    $heap->{stdin_tio} = POSIX::Termios->new();
    $heap->{stdin_tio}->getattr(0);
    $heap->{stdout_tio} = POSIX::Termios->new();
    $heap->{stdout_tio}->getattr(1);
    $heap->{stderr_tio} = POSIX::Termios->new();
    $heap->{stderr_tio}->getattr(2);
}


sub make_raw_terminal {
    my ($self) = @_;
    # Put the terminal into raw input mode.  Otherwise discrete
    # keystrokes will not be read immediately.
    my $tio = POSIX::Termios->new();
    $tio->getattr(0);
    my $lflag = $tio->getlflag;
    $lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG);
    $tio->setlflag($lflag);
    my $iflag = $tio->getiflag;
    $iflag &= ~(BRKINT | INPCK | ISTRIP | IXON);
    $tio->setiflag($iflag);
    my $cflag = $tio->getcflag;
    $cflag &= ~(CSIZE | PARENB);
    $tio->setcflag($cflag);
    $tio->setattr(0, TCSANOW);
}

sub log {
    my ($self, $msg) = @_;
    my $fh = $self->parent->_logfile_fh;
    $fh->say($msg);
}


__PACKAGE__->meta->make_immutable;

no Moose;