Tanktalus has asked for the wisdom of the Perl Monks concerning the following question:
I'm trying to see if I can get Term::ReadLine to work in an event loop other than Tk, but the authors have made it somewhat difficult. And I've been having a bit of trouble trying to override things appropriately.
The first step was simply to test that something was happening in the background while waiting, just with the Tk loop. I found it easiest just to put a timer in with some ANSI control codes to move the cursor around - not the best way of doing this, but it works.
This works. I get a prompt, I can type in it, and the timer triggers counting the seconds at the top of the console. Unfortunately, it's using Tk. I'm using AnyEvent for the timer at least, because I really don't want to be looking at all the event loops to figure out how to get that to work.#!/usr/bin/perl use 5.12.1; my $esc; BEGIN { $esc = "\x1b["; print "${esc}2J${esc}3H"; } use Tk; use AnyEvent; use Term::ReadLine; my $t = 0; my $w = AE::timer (0,1,sub {print "${esc}s${esc}1H$t s ${esc}u";+ ++$t}); my $term = Term::ReadLine->new('...'); $term->tkRunning(1); my $x = $term->readline('> ');
My next attempt was to try to get the loop itself done in AnyEvent. Here things start to go downhill. Note that I'm still using Tk, just in case.
The basic code is the same, I've merely inserted a new package to override the Tk_loop and register_Tk functions - register seems to register the filehandle for monitoring while the loop, well, loops until characters are ready on the input. However, it "doesn't work." Specifically, the timer still fires, but the input isn't recognised. The io watcher never fires. (The override on Tk::DoOneEvent also isn't used - that was there for what I was hoping to be the next step - switching Tk to EV.)#!/usr/bin/perl use Tk; use AnyEvent; use Term::ReadLine; use IO::File; use 5.12.1; sub LOG { state $fh; open $fh, '>', '/tmp/sopw.out' unless $fh; die $! unless $fh; autoflush $fh 1; say $fh @_; } package Term::ReadLine::AE; # mangle their tree, inserting ourselves in the front. unshift @Term::ReadLine::Stub::ISA, __PACKAGE__; #use Data::Dump qw(ddx); #ddx(\%INC); if (not defined &Tk::DoOneEvent) { ::LOG("overriding"); *Tk::DoOneEvent = sub { AnyEvent->_poll(); }; ::LOG("Not created?") unless defined &Tk::DoOneEvent; } our $cv; sub Tk_loop { my $self = shift; ::LOG("Entering Tk_loop");# unless $cv; $cv = AE::cv; $cv->recv(); } sub register_Tk { my $self = shift; ::LOG("Registering"); $Term::ReadLine::registered++ or AE::io($self->IN, 0, sub { $cv->send() }); } package main; use 5.12.1; my $esc; BEGIN { $esc = "\x1b["; print "${esc}2J${esc}3H"; } my $t = 0; my $w = AE::timer (0,1,sub {print "${esc}s${esc}1H$t s ${esc}u";+ ++$t}); my $term = Term::ReadLine->new('...'); $term->tkRunning(1); my $x = $term->readline('> ');
It looks like AnyEvent's Tk implementation duplicates filehandles all over the place for monitoring, the author claims it's to workaround some Tk bugs. I don't know, but even if I switch out EV for Tk, I get the same behaviour: my typing isn't recognised but the timer fires fine. I'm kind of at a loss to explain what's going on here and hoping someone else has the required tuits.
Thanks!
Update: Nevermind. Found the solution. I forgot that AE events have watcher objects. I need to keep the return from AE::io, otherwise the object goes out of scope and is deleted. I'll have to store the watcher:
And suddenly they all work. Now to figure out how to make this suggestion to the owners of TRL :-)our $fe; sub register_Tk { my $self = shift; ::LOG("Registering"); $fe ||= AE::io($self->IN, 0, sub { $cv->send() }); }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Using Term::ReadLine in an event loop other than Tk
by zentara (Cardinal) on Jan 17, 2012 at 12:13 UTC | |
by Tanktalus (Canon) on Jan 17, 2012 at 14:49 UTC | |
|
Re: Using Term::ReadLine in an event loop other than Tk
by Anonymous Monk on Jan 17, 2012 at 07:46 UTC | |
by Tanktalus (Canon) on Jan 17, 2012 at 14:41 UTC | |
|
Re: Using Term::ReadLine in an event loop other than Tk
by Khen1950fx (Canon) on Jan 17, 2012 at 11:41 UTC | |
by Tanktalus (Canon) on Jan 17, 2012 at 14:45 UTC | |
|
Using AnyEvent with Term::ReadLine::Gnu
by gnosti (Chaplain) on Jan 22, 2012 at 03:18 UTC |