aboutsummaryrefslogblamecommitdiffstats
path: root/testing/lib/Test/Irssi/Driver.pm
blob: 0ff90e9770dbfb67a858efd4899ab7f8a2478abb (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                            


                                         

                                                         

                        


            

                                






                                                          

                                       













                                                  
                                                         



                                                                

                                      












                                                                                 

                                                           

                                                              
 
                                          
 
 


                                        


                                        




                                                                      
                    
                                                       
 

                                        



                                      
     
 

                                  






                                                  
                                         
                  






                                                       
 


                                                                   
           







                                                           




















                                                 












                                                                        






                                             





























                                                                        
use strictures 1;

package Test::Irssi::Driver;

use Moose;
use lib $ENV{HOME} . "/projects/poe/lib";

#use MooseX::POE;
use POE qw( Wheel::ReadWrite Wheel::Run Filter::Stream );
use POSIX;
use feature qw/say/;
use Data::Dump qw/dump/;

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


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

    $self->log("Start handler called");

    $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(),
      );
    $self->log("stdio options: " . dump(@stdio_options));

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

    $self->log("Created stdio wheel");

    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(),
      );

    $self->log("wheel options: " . dump(@program_options));

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

    $self->log("Created child run wheel");

}

sub STOP {
    my ($self, $heap) = @_[OBJECT,HEAP];
    $self->log("STOP called");
    $self->restore_term_settings($heap);
    $self->parent->_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 terminal_stdin {
    my ($self, $heap, $input) = @_[OBJECT, HEAP, ARG0];

    if ($input =~ m/\003/g) {
        $input = "/echo I like cakes\n";
    } elsif ($input =~ m/\005/g) {
        $self->log( $self->vt_dump());
    } elsif ($input =~ m/\x17/g) {
        $input = "/quit\n";
    }

    $heap->{program}->put($input);
}

# delegate to Callbacks.
sub vt_dump {
    my ($self) = @_;
    my $cb = $self->parent->_callbacks->vt_dump();
}

### Handle STDOUT from the child program.
sub 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 setup {
    my $self = shift;

    my @states =
      (
       object_states =>
       [ $self =>
         {
          _start => 'START',
          _stop  => 'STOP',
          got_terminal_stdin => 'terminal_stdin',
          got_child_stdout   => 'child_stdout',
          got_sigchld        => 'CHILD',
         }
       ]
      );
    $self->log("creating root session");

    POE::Session->create(@states);
    $self->log("session created");

}

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 restore_term_settings {
    my ($self, $heap) = @_;

    $heap->{stdin_tio}->setattr (0, TCSANOW);
    $heap->{stdout_tio}->setattr(1, TCSANOW);
    $heap->{stderr_tio}->setattr(2, TCSANOW);
}

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;