AnyEvent::Impl::Irssi - AnyEvent adaptor for Irssi


AnyEvent documentation Contained in the AnyEvent distribution.

Index


Code Index:

NAME

Top

AnyEvent::Impl::Irssi - AnyEvent adaptor for Irssi

SYNOPSIS

Top

   use AnyEvent;

   # this module gets loaded automatically when running under irssi

DESCRIPTION

Top

This module provides transparent support for AnyEvent. You don't have to do anything to make Irssi scripts work with AnyEvent.

Limitations of this backend and implementation details:

* This backend does not support blocking waits.

That means you must set a callback on any condvars, or otherwise make sure to never call recv on a condvar that hasn't been signalled yet.

* Child exits will be handled by AnyEvent.

AnyEvent will take over child handling, as Irssi only polls for children once/second and cannot handle unspecific child watchers.

This should have no negative effect, as AnyEvent will emit a pidwait signal just like irssi itself would.

* Artificial timer delays.

Irssi artificially enforces timers to have at least a 10ms delay (by croaking, even).

This means that some applications will be limited to a rate of 100Hz (for example, Coro::AnyEvent thread scheduling).

* Irssi leaks memory like hell.

Yeah.

Apart from that, documentation is notoriously wrong (e.g. file handles are not supported by input_add, contrary to documentation), hooking into irssi has to be done in... weird... ways, but otherwise, Irssi is surprisingly full-featured (for basically being a hack).

SEE ALSO

Top

AnyEvent, Irssi.

AUTHOR

Top

 Marc Lehmann <schmorp@schmorp.de>
 http://home.schmorp.de/


AnyEvent documentation Contained in the AnyEvent distribution.
package AnyEvent::Impl::Irssi;

use AnyEvent (); BEGIN { AnyEvent::common_sense }
use Carp ();
use Irssi ();

our @ISA;

# irssi works only from certain namespaces, so we
# create one and use it.
sub init {
   my $pkg = caller;

   push @ISA, $pkg;

   local $/;
   eval "package $pkg; " . <DATA>;
   print "AnyEvent::Impl::Irssi fatal compilation error: $@" if $@;

   close DATA;
}

Irssi::command "/script exec -permanent AnyEvent::Impl::Irssi::init 'AnyEvent adaptor'";

1;

__DATA__

BEGIN { AnyEvent::common_sense }
use base "AnyEvent::Base";

sub io {
   my ($class, %arg) = @_;
   
   my $cb = $arg{cb};
   my $fd = fileno $arg{fh};
   defined $fd or $fd = $arg{fh};

   my $source = Irssi::input_add
      $fd,
      $arg{poll} eq "r" ? Irssi::INPUT_READ : Irssi::INPUT_WRITE,
      $cb,
      undef;

   bless \\$source, "AnyEvent::Impl::Irssi::io"
}

sub AnyEvent::Impl::Irssi::io::DESTROY {
   Irssi::input_remove $${$_[0]};
}

sub timer {
   my ($class, %arg) = @_;
   
   my $cb    = $arg{cb};
   my $ival  = $arg{interval} * 1000;
   my $after = $arg{after} * 1000;

   my $source; $source = Irssi::timeout_add_once $after > 10 ? $after : 10,
      ($ival ? sub {
                 $source = Irssi::timeout_add $ival > 10 ? $ival : 10, $cb, undef;
                 &$cb;
                 0
               }
             : $cb),
      undef;

   bless \\$source, "AnyEvent::Impl::Irssi::timer"
}

sub AnyEvent::Impl::Irssi::timer::DESTROY {
   Irssi::timeout_remove $${$_[0]};
}

my $_pidwait = sub {
   my ($rpid, $rstatus) = @_;

   AnyEvent::Base->_emit_childstatus ($rpid, $rstatus);
};

Irssi::signal_add pidwait => $_pidwait;

sub _emit_childstatus {
   my ($self, $rpid, $rstatus) = @_;
   $self->SUPER::_emit_childstatus ($rpid, $rstatus);

   Irssi::signal_remove pidwait => $_pidwait;
   Irssi::signal_emit   pidwait => $rpid+0, $rstatus+0;
   Irssi::signal_add    pidwait => $_pidwait;
}

sub one_event {
   Carp::croak "Irssi does not support blocking waits";
}