Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Term::ReadLine should use have a generic event loop hook #11875

Closed
p5pRT opened this issue Jan 17, 2012 · 100 comments
Closed

Term::ReadLine should use have a generic event loop hook #11875

p5pRT opened this issue Jan 17, 2012 · 100 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 17, 2012

Migrated from rt.perl.org#108470 (status was 'resolved')

Searchable as RT108470$

@p5pRT
Copy link
Author

p5pRT commented Jan 17, 2012

From darin.mcbride@shaw.ca

Created by darin.mcbride@shaw.ca

Term​::ReadLine only allows the Tk event loop to be called during
a readline call. This should be updated to use AnyEvent which will
still work with Tk, as well as any other event loop the user may need.

The only downside of this patch is that users currently using TRL with Tk
will need to install AE, too.

Inline Patch
diff -u -r Term-ReadLine-1.07.orig/blib/lib/Term/ReadLine.pm Term-ReadLine-1.07/blib/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/blib/lib/Term/ReadLine.pm	2011-07-07 09:10:31.000000000 -0600
+++ Term-ReadLine-1.07/blib/lib/Term/ReadLine.pm	2012-01-17 13:06:11.000000000 -0700
@@ -109,10 +109,10 @@
 
 =over 12
 
-=item C<tkRunning>
+=item C<AERunning>
 
-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes AnyEvent event loop run when waiting for user input (i.e., during
+C<readline> method). C<tkRunning> is an alias for this.
 
 =item C<ornaments>
 
@@ -161,7 +161,7 @@
 use strict;
 
 package Term::ReadLine::Stub;
-our @ISA = qw'Term::ReadLine::Tk Term::ReadLine::TermCap';
+our @ISA = qw'Term::ReadLine::AE Term::ReadLine::TermCap';
 
 $DB::emacs = $DB::emacs;	# To peacify -w
 our @rl_term_set;
@@ -175,9 +175,8 @@
   my ($in,$out,$str) = @$self;
   my $prompt = shift;
   print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2]; 
-  $self->register_Tk 
-     if not $Term::ReadLine::registered and $Term::ReadLine::toloop
-	and defined &Tk::DoOneEvent;
+  $self->register_AE
+     if $Term::ReadLine::toloop;
   #$str = scalar <$in>;
   $str = $self->get_line;
   utf8::upgrade($str)
@@ -296,7 +295,7 @@
     eval "use Term::ReadLine::Gnu;";
   } elsif ($which =~ /\bperl\b/i) {
     eval "use Term::ReadLine::Perl;";
-  } elsif ($which =~ /^(Stub|TermCap|Tk)$/) {
+  } elsif ($which =~ /^(Stub|TermCap|AE)$/) {
     # it is already in memory to avoid false exception as seen in:
     # PERL_RL=Stub perl -e'$SIG{__DIE__} = sub { print @_ }; require Term::ReadLine'
   } else {
@@ -357,41 +356,50 @@
 }
 
 
-package Term::ReadLine::Tk;
+package Term::ReadLine::AE;
 
-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
+our $cv;
+our $fe;
 
-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
-  # Tk->tkwait('variable',\$giveup);	# needs Widget
-  $count_DoOne++, Tk::DoOneEvent(0) until $giveup;
-  $count_loop++;
-  $giveup = 0;
+# for the other modules to use
+if (not defined &Tk::DoOneEvent)
+{
+    *Tk::DoOneEvent = sub {
+        die "what?"; # this shouldn't be called.
+    }
 }
 
-sub register_Tk {
-  my $self = shift;
-  $Term::ReadLine::registered++ 
-    or Tk->fileevent($self->IN,'readable',\&handle);
+sub AE_loop {
+    my $self = shift;
+    $cv = AE::cv();
+    $cv->recv();
+}
+# backwards compatibility
+*Tk_loop = \&AE_loop;
+
+sub register_AE {
+    my $self = shift;
+    $fe ||= AE::io($self->IN, 0, sub { $cv->send() });
 }
+# backwards compatibility
+*register_Tk = \&register_AE;
 
-sub tkRunning {
+sub AErunning {
   $Term::ReadLine::toloop = $_[1] if @_ > 1;
   $Term::ReadLine::toloop;
 }
+# backwards compatibility
+*tkRunning = \&AErunning;
 
 sub get_c {
   my $self = shift;
-  $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
+  $self->AE_loop if $Term::ReadLine::toloop;
   return getc $self->IN;
 }
 
 sub get_line {
   my $self = shift;
-  $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
+  $self->AE_loop if $Term::ReadLine::toloop;
   my $in = $self->IN;
   local ($/) = "\n";
   return scalar <$in>;
Only in Term-ReadLine-1.07/blib/man3: Term::ReadLine.3pm
Inline Patch
diff -u -r Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm Term-ReadLine-1.07/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm	2011-07-07 09:10:31.000000000 -0600
+++ Term-ReadLine-1.07/lib/Term/ReadLine.pm	2012-01-17 13:08:39.000000000 -0700
@@ -109,10 +109,10 @@
 
 =over 12
 
-=item C<tkRunning>
+=item C<AERunning>
 
-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes AnyEvent event loop run when waiting for user input (i.e., during
+C<readline> method). C<tkRunning> is an alias for this.
 
 =item C<ornaments>
 
@@ -161,7 +161,7 @@
 use strict;
 
 package Term::ReadLine::Stub;
-our @ISA = qw'Term::ReadLine::Tk Term::ReadLine::TermCap';
+our @ISA = qw'Term::ReadLine::AE Term::ReadLine::TermCap';
 
 $DB::emacs = $DB::emacs;	# To peacify -w
 our @rl_term_set;
@@ -175,9 +175,8 @@
   my ($in,$out,$str) = @$self;
   my $prompt = shift;
   print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2]; 
-  $self->register_Tk 
-     if not $Term::ReadLine::registered and $Term::ReadLine::toloop
-	and defined &Tk::DoOneEvent;
+  $self->register_AE
+     if $Term::ReadLine::toloop;
   #$str = scalar <$in>;
   $str = $self->get_line;
   utf8::upgrade($str)
@@ -296,7 +295,7 @@
     eval "use Term::ReadLine::Gnu;";
   } elsif ($which =~ /\bperl\b/i) {
     eval "use Term::ReadLine::Perl;";
-  } elsif ($which =~ /^(Stub|TermCap|Tk)$/) {
+  } elsif ($which =~ /^(Stub|TermCap|AE)$/) {
     # it is already in memory to avoid false exception as seen in:
     # PERL_RL=Stub perl -e'$SIG{__DIE__} = sub { print @_ }; require Term::ReadLine'
   } else {
@@ -357,41 +356,51 @@
 }
 
 
-package Term::ReadLine::Tk;
+package Term::ReadLine::AE;
 
-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
+our $cv;
+our $fe;
 
-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
-  # Tk->tkwait('variable',\$giveup);	# needs Widget
-  $count_DoOne++, Tk::DoOneEvent(0) until $giveup;
-  $count_loop++;
-  $giveup = 0;
+# for the other modules to use to check if it exists,
+# should be eventually removed.
+if (not defined &Tk::DoOneEvent)
+{
+    *Tk::DoOneEvent = sub {
+        die "what?"; # this shouldn't be called.
+    }
 }
 
-sub register_Tk {
-  my $self = shift;
-  $Term::ReadLine::registered++ 
-    or Tk->fileevent($self->IN,'readable',\&handle);
+sub AE_loop {
+    my $self = shift;
+    $cv = AE::cv();
+    $cv->recv();
+}
+# backwards compatibility
+*Tk_loop = \&AE_loop;
+
+sub register_AE {
+    my $self = shift;
+    $fe ||= AE::io($self->IN, 0, sub { $cv->send() });
 }
+# backwards compatibility
+*register_Tk = \&register_AE;
 
-sub tkRunning {
+sub AErunning {
   $Term::ReadLine::toloop = $_[1] if @_ > 1;
   $Term::ReadLine::toloop;
 }
+# backwards compatibility
+*tkRunning = \&AErunning;
 
 sub get_c {
   my $self = shift;
-  $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
+  $self->AE_loop if $Term::ReadLine::toloop;
   return getc $self->IN;
 }
 
 sub get_line {
   my $self = shift;
-  $self->Tk_loop if $Term::ReadLine::toloop && defined &Tk::DoOneEvent;
+  $self->AE_loop if $Term::ReadLine::toloop;
   my $in = $self->IN;
   local ($/) = "\n";
   return scalar <$in>;
Perl Info

Flags:
    category=library
    severity=wishlist
    module=Term::ReadLine

Site configuration information for perl 5.12.4:

Configured by Gentoo at Wed Sep 28 07:02:37 MDT 2011.

Summary of my perl5 (revision 5 version 12 subversion 4) configuration:
   
  Platform:
    osname=linux, osvers=2.6.39-gentoo-r3, archname=x86_64-linux-thread-multi
    uname='linux naboo 2.6.39-gentoo-r3 #1 smp sun jul 17 07:13:38 mdt 2011 x86_64 intel(r) core(tm) i7 cpu 930 @ 2.80ghz genuineintel gnulinux '
    config_args='-des -Duseshrplib -Darchname=x86_64-linux-thread -Dcc=x86_64-pc-linux-gnu-gcc -Doptimize=-O3 -pipe -march=core2 -Dldflags=-Wl,-O1 -Wl,--as-needed -Dprefix=/usr -Dsiteprefix=/usr -Dvendorprefix=/usr -Dscriptdir=/usr/bin -Dprivlib=/usr/lib64/perl5/5.12.4 -Darchlib=/usr/lib64/perl5/5.12.4/x86_64-linux-thread-multi -Dsitelib=/usr/lib64/perl5/site_perl/5.12.4 -Dsitearch=/usr/lib64/perl5/site_perl/5.12.4/x86_64-linux-thread-multi -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.12.4 -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.12.4/x86_64-linux-thread-multi -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/share/man/man1 -Dsiteman3dir=/usr/share/man/man3 -Dvendorman1dir=/usr/share/man/man1 -Dvendorman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3pm -Dlibperl=libperl.so.5.12.4 -Dlocincpth=  -Duselargefiles -Dd_semctl_semun -Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@localhost -Dinstallusrbinperl=n -Ud_csh -Uusenm -Di_ndbm -Di_gdbm 
 -Di_db -Dusethreads -DDEBUGGING=none -Dinc_version_list=5.12.3/x86_64-linux-thread-multi 5.12.3 5.12.2/x86_64-linux-thread-multi 5.12.2 5.12.1/x86_64-linux-thread-multi 5.12.1 5.12.0/x86_64-linux-thread-multi 5.12.0  -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='x86_64-pc-linux-gnu-gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O3 -pipe -march=core2',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe'
    ccversion='', gccversion='4.5.3', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='x86_64-pc-linux-gnu-gcc', ldflags ='-Wl,-O1 -Wl,--as-needed'
    libpth=/usr/local/lib64 /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.12.2.so, so=so, useshrplib=true, libperl=libperl.so.5.12.4
    gnulibc_version='2.12.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O3 -pipe -march=core2 -Wl,-O1 -Wl,--as-needed'

Locally applied patches:
    0001-gentoo_MakeMaker-RUNPATH.diff
    0002-gentoo_config_over.diff
    0003-gentoo_cpan_definstalldirs.diff
    0004-gentoo_cpanplus_definstalldirs.diff
    0005-gentoo_create-libperl-soname.diff
    0006-gentoo_MakeMaker-delete_packlist.diff
    0007-fixes_8d66b3f9_h2hp_fix.diff
    0008-fixes_f178b03b_h2ph_using_deprecated_goto.diff
    0009-gentoo_mod-paths.diff
    0010-gentoo_enc2xs.diff
    0011-gentoo_IO-Compress_AutoLoader_dropped_from_Compress-Zlib.diff
    0012-gentoo_drop-fstack-protector.diff


@INC for perl 5.12.4:
    /etc/perl
    /usr/lib64/perl5/site_perl/5.12.4/x86_64-linux-thread-multi
    /usr/lib64/perl5/site_perl/5.12.4
    /usr/lib64/perl5/vendor_perl/5.12.4/x86_64-linux-thread-multi
    /usr/lib64/perl5/vendor_perl/5.12.4
    /usr/lib64/perl5/site_perl/5.12.3/x86_64-linux-thread-multi
    /usr/lib64/perl5/site_perl/5.12.3
    /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux-thread-multi
    /usr/lib64/perl5/site_perl/5.12.2
    /usr/lib64/perl5/site_perl
    /usr/lib64/perl5/vendor_perl/5.12.3/x86_64-linux-thread-multi
    /usr/lib64/perl5/vendor_perl/5.12.3
    /usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux-thread-multi
    /usr/lib64/perl5/vendor_perl/5.12.2
    /usr/lib64/perl5/vendor_perl
    /usr/lib64/perl5/5.12.4/x86_64-linux-thread-multi
    /usr/lib64/perl5/5.12.4
    /usr/local/lib/site_perl
    .


Environment for perl 5.12.4:
    HOME=/home/dmcbride
    LANG=en_US.utf8
    LANGUAGE=
    LC_ALL=en_US.utf8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/home/dmcbride/bin:/usr/lib/distcc/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/i686-pc-linux-gnu/gcc-bin/4.5.3:/usr/x86_64-pc-linux-gnu/gcc-bin/4.5.3:/share/cvs/bin:/usr/games/bin:/share/bin:/share/darin/bin:/share/cvs/work/shared
    PERL5LIB (unset)
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jan 17, 2012

From @cpansprout

On Tue Jan 17 12​:27​:38 2012, dmcbride wrote​:

The only downside of this patch is that users currently using TRL with
Tk
will need to install AE, too.

Couldn’t you detect whether Tk is installed without AnyEvent, and fall
back to the old code in that case?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 17, 2012

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @dmcbride

On Tuesday January 17 2012 1​:09​:03 PM you wrote​:

Couldn’t you detect whether Tk is installed without AnyEvent, and
fall
back to the old code in that case?

Yes. I guess the first question is whether anyone with the
power/authority to
commit a change would be interested in it. I was providing the patch
as much
as a possible tactic as to simply check if anyone was interested. Even
this
patch likely requires some documentation changes (beyond that which
is given
here)​:

diff -u -r Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm Term-
ReadLine-1.07/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm 2011-07-07
09​:10​:31.000000000 -0600
+++ Term-ReadLine-1.07/lib/Term/ReadLine.pm 2012-01-17
16​:20​:40.000000000
-0700
@​@​ -111,8 +111,9 @​@​

=item C<tkRunning>

-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes an event loop run when waiting for user input (i.e., during
+C<readline> method). If AnyEvent is loaded, it is used, otherwise
Tk
+is used.

=item C<ornaments>

@​@​ -176,8 +177,7 @​@​
  my $prompt = shift;
  print $out $rl_term_set[0], $prompt, $rl_term_set[1],
$rl_term_set[2];
  $self->register_Tk
- if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop
- and defined &Tk​::DoOneEvent;
+ if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop;
  #$str = scalar <$in>;
  $str = $self->get_line;
  utf8​::upgrade($str)
@​@​ -359,23 +359,50 @​@​

package Term​::ReadLine​::Tk;

-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
-
-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
- # Tk->tkwait('variable',\$giveup); # needs Widget
- $count_DoOne++, Tk​::DoOneEvent(0) until $giveup;
- $count_loop++;
- $giveup = 0;
+# if AnyEvent is loaded, use it.
+if (defined &AE​::cv)
+{
+ my ($cv, $fe);
+
+ # maintain old name for backward-compatibility
+ *AE_loop = *Tk_loop = sub {
+ my $self = shift;
+ $cv = AE​::cv();
+ $cv->recv();
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $fe ||= AE​::io($self->IN, 0, sub { $cv->send() });
+ };
+
+ # just because AE is loaded doesn't mean Tk isn't.
+ if (not defined &Tk​::DoOneEvent)
+ {
+ # create the stub as some T​::RL implementations still check
+ # this directly. This should eventually be removed.
+ *Tk​::DoOneEvent = sub {
+ die "should not happen";
+ };
+ }
}
+else
+{
+ my ($giveup);
+
+ # technically, not AE, but maybe in the future the Tk-specific
+ # aspects will be removed.
+ *AE_loop = *Tk_loop = sub {
+ Tk​::DoOneEvent(0) until $giveup;
+ $giveup = 0;
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $Term​::ReadLine​::registered++
+ or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+ };

-sub register_Tk {
- my $self = shift;
- $Term​::ReadLine​::registered++
- or Tk->fileevent($self->IN,'readable',\&handle);
}

sub tkRunning {
@​@​ -385,13 +412,13 @​@​

sub get_c {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined
&Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  return getc $self->IN;
}

sub get_line {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined
&Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  my $in = $self->IN;
  local ($/) = "\n";
  return scalar <$in>;

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From [Unknown Contact. See original ticket]

On Tuesday January 17 2012 1​:09​:03 PM you wrote​:

Couldn’t you detect whether Tk is installed without AnyEvent, and
fall
back to the old code in that case?

Yes. I guess the first question is whether anyone with the
power/authority to
commit a change would be interested in it. I was providing the patch
as much
as a possible tactic as to simply check if anyone was interested. Even
this
patch likely requires some documentation changes (beyond that which
is given
here)​:

diff -u -r Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm Term-
ReadLine-1.07/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm 2011-07-07
09​:10​:31.000000000 -0600
+++ Term-ReadLine-1.07/lib/Term/ReadLine.pm 2012-01-17
16​:20​:40.000000000
-0700
@​@​ -111,8 +111,9 @​@​

=item C<tkRunning>

-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes an event loop run when waiting for user input (i.e., during
+C<readline> method). If AnyEvent is loaded, it is used, otherwise
Tk
+is used.

=item C<ornaments>

@​@​ -176,8 +177,7 @​@​
  my $prompt = shift;
  print $out $rl_term_set[0], $prompt, $rl_term_set[1],
$rl_term_set[2];
  $self->register_Tk
- if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop
- and defined &Tk​::DoOneEvent;
+ if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop;
  #$str = scalar <$in>;
  $str = $self->get_line;
  utf8​::upgrade($str)
@​@​ -359,23 +359,50 @​@​

package Term​::ReadLine​::Tk;

-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
-
-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
- # Tk->tkwait('variable',\$giveup); # needs Widget
- $count_DoOne++, Tk​::DoOneEvent(0) until $giveup;
- $count_loop++;
- $giveup = 0;
+# if AnyEvent is loaded, use it.
+if (defined &AE​::cv)
+{
+ my ($cv, $fe);
+
+ # maintain old name for backward-compatibility
+ *AE_loop = *Tk_loop = sub {
+ my $self = shift;
+ $cv = AE​::cv();
+ $cv->recv();
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $fe ||= AE​::io($self->IN, 0, sub { $cv->send() });
+ };
+
+ # just because AE is loaded doesn't mean Tk isn't.
+ if (not defined &Tk​::DoOneEvent)
+ {
+ # create the stub as some T​::RL implementations still check
+ # this directly. This should eventually be removed.
+ *Tk​::DoOneEvent = sub {
+ die "should not happen";
+ };
+ }
}
+else
+{
+ my ($giveup);
+
+ # technically, not AE, but maybe in the future the Tk-specific
+ # aspects will be removed.
+ *AE_loop = *Tk_loop = sub {
+ Tk​::DoOneEvent(0) until $giveup;
+ $giveup = 0;
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $Term​::ReadLine​::registered++
+ or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+ };

-sub register_Tk {
- my $self = shift;
- $Term​::ReadLine​::registered++
- or Tk->fileevent($self->IN,'readable',\&handle);
}

sub tkRunning {
@​@​ -385,13 +412,13 @​@​

sub get_c {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined
&Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  return getc $self->IN;
}

sub get_line {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined
&Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  my $in = $self->IN;
  local ($/) = "\n";
  return scalar <$in>;

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @cpansprout

On Tue Jan 17 20​:33​:48 2012, dmcbride@​cpan.org wrote​:

On Tuesday January 17 2012 1​:09​:03 PM you wrote​:

Couldn’t you detect whether Tk is installed without AnyEvent, and
fall
back to the old code in that case?

Yes. I guess the first question is whether anyone with the
power/authority to
commit a change would be interested in it. I was providing the patch
as much
as a possible tactic as to simply check if anyone was interested.

Not being a user of the module, it’s hard for me to say that I’m
interested. But if you find it helpful, and you think others will,
that’s good enough for me.

Is there any way you can write tests for this, either using a dummy
module or using AE but skipping the tests when it is not installed?
Otherwise I would feel very uncomfortable committing it, even if I can
prove to myself that the code works.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @dmcbride

On Tuesday January 17 2012 1​:09​:03 PM you wrote​:

Couldn’t you detect whether Tk is installed without AnyEvent, and fall
back to the old code in that case?

Yes. I guess the first question is whether anyone with the power/authority to
commit a change would be interested in it. I was providing the patch as much
as a possible tactic as to simply check if anyone was interested. Even this
patch likely requires some documentation changes (beyond that which is given
here)​:

diff -u -r Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm Term-
ReadLine-1.07/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm 2011-07-07
09​:10​:31.000000000 -0600
+++ Term-ReadLine-1.07/lib/Term/ReadLine.pm 2012-01-17 16​:20​:40.000000000
-0700
@​@​ -111,8 +111,9 @​@​

=item C<tkRunning>

-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes an event loop run when waiting for user input (i.e., during
+C<readline> method). If AnyEvent is loaded, it is used, otherwise Tk
+is used.

=item C<ornaments>

@​@​ -176,8 +177,7 @​@​
  my $prompt = shift;
  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
  $self->register_Tk
- if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop
- and defined &Tk​::DoOneEvent;
+ if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop;
  #$str = scalar <$in>;
  $str = $self->get_line;
  utf8​::upgrade($str)
@​@​ -359,23 +359,50 @​@​

package Term​::ReadLine​::Tk;

-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
-
-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
- # Tk->tkwait('variable',\$giveup); # needs Widget
- $count_DoOne++, Tk​::DoOneEvent(0) until $giveup;
- $count_loop++;
- $giveup = 0;
+# if AnyEvent is loaded, use it.
+if (defined &AE​::cv)
+{
+ my ($cv, $fe);
+
+ # maintain old name for backward-compatibility
+ *AE_loop = *Tk_loop = sub {
+ my $self = shift;
+ $cv = AE​::cv();
+ $cv->recv();
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $fe ||= AE​::io($self->IN, 0, sub { $cv->send() });
+ };
+
+ # just because AE is loaded doesn't mean Tk isn't.
+ if (not defined &Tk​::DoOneEvent)
+ {
+ # create the stub as some T​::RL implementations still check
+ # this directly. This should eventually be removed.
+ *Tk​::DoOneEvent = sub {
+ die "should not happen";
+ };
+ }
}
+else
+{
+ my ($giveup);
+
+ # technically, not AE, but maybe in the future the Tk-specific
+ # aspects will be removed.
+ *AE_loop = *Tk_loop = sub {
+ Tk​::DoOneEvent(0) until $giveup;
+ $giveup = 0;
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $Term​::ReadLine​::registered++
+ or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+ };

-sub register_Tk {
- my $self = shift;
- $Term​::ReadLine​::registered++
- or Tk->fileevent($self->IN,'readable',\&handle);
}

sub tkRunning {
@​@​ -385,13 +412,13 @​@​

sub get_c {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  return getc $self->IN;
}

sub get_line {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  my $in = $self->IN;
  local ($/) = "\n";
  return scalar <$in>;

1 similar comment
@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @dmcbride

On Tuesday January 17 2012 1​:09​:03 PM you wrote​:

Couldn’t you detect whether Tk is installed without AnyEvent, and fall
back to the old code in that case?

Yes. I guess the first question is whether anyone with the power/authority to
commit a change would be interested in it. I was providing the patch as much
as a possible tactic as to simply check if anyone was interested. Even this
patch likely requires some documentation changes (beyond that which is given
here)​:

diff -u -r Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm Term-
ReadLine-1.07/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm 2011-07-07
09​:10​:31.000000000 -0600
+++ Term-ReadLine-1.07/lib/Term/ReadLine.pm 2012-01-17 16​:20​:40.000000000
-0700
@​@​ -111,8 +111,9 @​@​

=item C<tkRunning>

-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes an event loop run when waiting for user input (i.e., during
+C<readline> method). If AnyEvent is loaded, it is used, otherwise Tk
+is used.

=item C<ornaments>

@​@​ -176,8 +177,7 @​@​
  my $prompt = shift;
  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
  $self->register_Tk
- if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop
- and defined &Tk​::DoOneEvent;
+ if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop;
  #$str = scalar <$in>;
  $str = $self->get_line;
  utf8​::upgrade($str)
@​@​ -359,23 +359,50 @​@​

package Term​::ReadLine​::Tk;

-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
-
-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
- # Tk->tkwait('variable',\$giveup); # needs Widget
- $count_DoOne++, Tk​::DoOneEvent(0) until $giveup;
- $count_loop++;
- $giveup = 0;
+# if AnyEvent is loaded, use it.
+if (defined &AE​::cv)
+{
+ my ($cv, $fe);
+
+ # maintain old name for backward-compatibility
+ *AE_loop = *Tk_loop = sub {
+ my $self = shift;
+ $cv = AE​::cv();
+ $cv->recv();
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $fe ||= AE​::io($self->IN, 0, sub { $cv->send() });
+ };
+
+ # just because AE is loaded doesn't mean Tk isn't.
+ if (not defined &Tk​::DoOneEvent)
+ {
+ # create the stub as some T​::RL implementations still check
+ # this directly. This should eventually be removed.
+ *Tk​::DoOneEvent = sub {
+ die "should not happen";
+ };
+ }
}
+else
+{
+ my ($giveup);
+
+ # technically, not AE, but maybe in the future the Tk-specific
+ # aspects will be removed.
+ *AE_loop = *Tk_loop = sub {
+ Tk​::DoOneEvent(0) until $giveup;
+ $giveup = 0;
+ };
+
+ *register_AE = *register_Tk = sub {
+ my $self = shift;
+ $Term​::ReadLine​::registered++
+ or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+ };

-sub register_Tk {
- my $self = shift;
- $Term​::ReadLine​::registered++
- or Tk->fileevent($self->IN,'readable',\&handle);
}

sub tkRunning {
@​@​ -385,13 +412,13 @​@​

sub get_c {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  return getc $self->IN;
}

sub get_line {
  my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->Tk_loop if $Term​::ReadLine​::toloop;
  my $in = $self->IN;
  local ($/) = "\n";
  return scalar <$in>;

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From joelz@pobox.com

On Tue, Jan 17, 2012 at 12​:27​:39PM -0800, Darin McBride wrote​:

# New Ticket Created by Darin McBride
# Please include the string​: [perl #108470]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=108470 >

This is a bug report for perl from darin.mcbride@​shaw.ca,
generated with the help of perlbug 1.39 running under perl 5.12.4.

-----------------------------------------------------------------
[Please describe your issue here]

Term​::ReadLine only allows the Tk event loop to be called during
a readline call. This should be updated to use AnyEvent which will
still work with Tk, as well as any other event loop the user may need.

The only downside of this patch is that users currently using TRL with Tk
will need to install AE, too.

Hi Darin,

I am author of a Audio​::Nama, a Tk application that uses
Term​::ReadLine​::Gnu with the tkRunning option to allow the
user to control the app by entering commands via T​::RL
as well as by manipulating Tk widgets.

While I don't really understand how event loops work,
it appears that the tkRunning setting actually
belongs to Term​::ReadLine​::Gnu. IOW, it is necessary to
install the latter for the tkRunning setting to work.

So I wonder, will it be sufficient to patch
Term​::ReadLine? Perhaps Gnu ReadLine will
need patched as well?

Second, I wonder, why change the existing API?
Couldn't another setting, AERunning, be simply
added rather than replacing tkRunning?
As you point out, not everyone may want to
add another dependency to their code.

Third, if such patches were proposed, I would want
them to be tested fully (and I will be happy to help.)

A final note, Audio​::Nama already uses AnyEvent,
allowing a choice of event loops. Event is selected
for terminal-only mode and Tk for terminal+Tk mode.

As far as I understand, the Tk event loop will
still be required for Tk applications to play friendly
with Term​::ReadLine, however the AnyEvent layer
might allow me to, for example, rewrite the GUI in Qt.

Bonus questions​: Does any know if tkRunning setting supports
other Tk implementations such as Tcl​::Tk or Tkx? Do they
provide events such as Tk​::after?

If so, it may be necessary that these sister implementations
of Tk be verified to function properly under patches
proposed to Term​::ReadLine, Term​::ReadLine​::Gnu, or
possibly Gnu ReadLine.

All this is written in theoretical ignorance, but with
a measure of actual experience with the packages in
question.

Regards,

Joel Roth

diff -u -r Term-ReadLine-1.07.orig/blib/lib/Term/ReadLine.pm Term-ReadLine-1.07/blib/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/blib/lib/Term/ReadLine.pm 2011-07-07 09​:10​:31.000000000 -0600
+++ Term-ReadLine-1.07/blib/lib/Term/ReadLine.pm 2012-01-17 13​:06​:11.000000000 -0700
@​@​ -109,10 +109,10 @​@​

=over 12

-=item C<tkRunning>
+=item C<AERunning>

-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes AnyEvent event loop run when waiting for user input (i.e., during
+C<readline> method). C<tkRunning> is an alias for this.

=item C<ornaments>

@​@​ -161,7 +161,7 @​@​
use strict;

package Term​::ReadLine​::Stub;
-our @​ISA = qw'Term​::ReadLine​::Tk Term​::ReadLine​::TermCap';
+our @​ISA = qw'Term​::ReadLine​::AE Term​::ReadLine​::TermCap';

$DB​::emacs = $DB​::emacs; # To peacify -w
our @​rl_term_set;
@​@​ -175,9 +175,8 @​@​
my ($in,$out,$str) = @​$self;
my $prompt = shift;
print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
- $self->register_Tk
- if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop
- and defined &Tk​::DoOneEvent;
+ $self->register_AE
+ if $Term​::ReadLine​::toloop;
#$str = scalar <$in>;
$str = $self->get_line;
utf8​::upgrade($str)
@​@​ -296,7 +295,7 @​@​
eval "use Term​::ReadLine​::Gnu;";
} elsif ($which =~ /\bperl\b/i) {
eval "use Term​::ReadLine​::Perl;";
- } elsif ($which =~ /^(Stub|TermCap|Tk)$/) {
+ } elsif ($which =~ /^(Stub|TermCap|AE)$/) {
# it is already in memory to avoid false exception as seen in​:
# PERL_RL=Stub perl -e'$SIG{__DIE__} = sub { print @​_ }; require Term​::ReadLine'
} else {
@​@​ -357,41 +356,50 @​@​
}

-package Term​::ReadLine​::Tk;
+package Term​::ReadLine​::AE;

-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
+our $cv;
+our $fe;

-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
- # Tk->tkwait('variable',\$giveup); # needs Widget
- $count_DoOne++, Tk​::DoOneEvent(0) until $giveup;
- $count_loop++;
- $giveup = 0;
+# for the other modules to use
+if (not defined &Tk​::DoOneEvent)
+{
+ *Tk​::DoOneEvent = sub {
+ die "what?"; # this shouldn't be called.
+ }
}

-sub register_Tk {
- my $self = shift;
- $Term​::ReadLine​::registered++
- or Tk->fileevent($self->IN,'readable',\&handle);
+sub AE_loop {
+ my $self = shift;
+ $cv = AE​::cv();
+ $cv->recv();
+}
+# backwards compatibility
+*Tk_loop = \&AE_loop;
+
+sub register_AE {
+ my $self = shift;
+ $fe ||= AE​::io($self->IN, 0, sub { $cv->send() });
}
+# backwards compatibility
+*register_Tk = \&register_AE;

-sub tkRunning {
+sub AErunning {
$Term​::ReadLine​::toloop = $_[1] if @​_ > 1;
$Term​::ReadLine​::toloop;
}
+# backwards compatibility
+*tkRunning = \&AErunning;

sub get_c {
my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->AE_loop if $Term​::ReadLine​::toloop;
return getc $self->IN;
}

sub get_line {
my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->AE_loop if $Term​::ReadLine​::toloop;
my $in = $self->IN;
local ($/) = "\n";
return scalar <$in>;
Only in Term-ReadLine-1.07/blib/man3​: Term​::ReadLine.3pm
diff -u -r Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm Term-ReadLine-1.07/lib/Term/ReadLine.pm
--- Term-ReadLine-1.07.orig/lib/Term/ReadLine.pm 2011-07-07 09​:10​:31.000000000 -0600
+++ Term-ReadLine-1.07/lib/Term/ReadLine.pm 2012-01-17 13​:08​:39.000000000 -0700
@​@​ -109,10 +109,10 @​@​

=over 12

-=item C<tkRunning>
+=item C<AERunning>

-makes Tk event loop run when waiting for user input (i.e., during
-C<readline> method).
+makes AnyEvent event loop run when waiting for user input (i.e., during
+C<readline> method). C<tkRunning> is an alias for this.

=item C<ornaments>

@​@​ -161,7 +161,7 @​@​
use strict;

package Term​::ReadLine​::Stub;
-our @​ISA = qw'Term​::ReadLine​::Tk Term​::ReadLine​::TermCap';
+our @​ISA = qw'Term​::ReadLine​::AE Term​::ReadLine​::TermCap';

$DB​::emacs = $DB​::emacs; # To peacify -w
our @​rl_term_set;
@​@​ -175,9 +175,8 @​@​
my ($in,$out,$str) = @​$self;
my $prompt = shift;
print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
- $self->register_Tk
- if not $Term​::ReadLine​::registered and $Term​::ReadLine​::toloop
- and defined &Tk​::DoOneEvent;
+ $self->register_AE
+ if $Term​::ReadLine​::toloop;
#$str = scalar <$in>;
$str = $self->get_line;
utf8​::upgrade($str)
@​@​ -296,7 +295,7 @​@​
eval "use Term​::ReadLine​::Gnu;";
} elsif ($which =~ /\bperl\b/i) {
eval "use Term​::ReadLine​::Perl;";
- } elsif ($which =~ /^(Stub|TermCap|Tk)$/) {
+ } elsif ($which =~ /^(Stub|TermCap|AE)$/) {
# it is already in memory to avoid false exception as seen in​:
# PERL_RL=Stub perl -e'$SIG{__DIE__} = sub { print @​_ }; require Term​::ReadLine'
} else {
@​@​ -357,41 +356,51 @​@​
}

-package Term​::ReadLine​::Tk;
+package Term​::ReadLine​::AE;

-our($count_handle, $count_DoOne, $count_loop);
-$count_handle = $count_DoOne = $count_loop = 0;
+our $cv;
+our $fe;

-our($giveup);
-sub handle {$giveup = 1; $count_handle++}
-
-sub Tk_loop {
- # Tk->tkwait('variable',\$giveup); # needs Widget
- $count_DoOne++, Tk​::DoOneEvent(0) until $giveup;
- $count_loop++;
- $giveup = 0;
+# for the other modules to use to check if it exists,
+# should be eventually removed.
+if (not defined &Tk​::DoOneEvent)
+{
+ *Tk​::DoOneEvent = sub {
+ die "what?"; # this shouldn't be called.
+ }
}

-sub register_Tk {
- my $self = shift;
- $Term​::ReadLine​::registered++
- or Tk->fileevent($self->IN,'readable',\&handle);
+sub AE_loop {
+ my $self = shift;
+ $cv = AE​::cv();
+ $cv->recv();
+}
+# backwards compatibility
+*Tk_loop = \&AE_loop;
+
+sub register_AE {
+ my $self = shift;
+ $fe ||= AE​::io($self->IN, 0, sub { $cv->send() });
}
+# backwards compatibility
+*register_Tk = \&register_AE;

-sub tkRunning {
+sub AErunning {
$Term​::ReadLine​::toloop = $_[1] if @​_ > 1;
$Term​::ReadLine​::toloop;
}
+# backwards compatibility
+*tkRunning = \&AErunning;

sub get_c {
my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->AE_loop if $Term​::ReadLine​::toloop;
return getc $self->IN;
}

sub get_line {
my $self = shift;
- $self->Tk_loop if $Term​::ReadLine​::toloop && defined &Tk​::DoOneEvent;
+ $self->AE_loop if $Term​::ReadLine​::toloop;
my $in = $self->IN;
local ($/) = "\n";
return scalar <$in>;

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags​:
category=library
severity=wishlist
module=Term​::ReadLine
---
Site configuration information for perl 5.12.4​:

Configured by Gentoo at Wed Sep 28 07​:02​:37 MDT 2011.

Summary of my perl5 (revision 5 version 12 subversion 4) configuration​:

Platform​:
osname=linux, osvers=2.6.39-gentoo-r3, archname=x86_64-linux-thread-multi
uname='linux naboo 2.6.39-gentoo-r3 #1 smp sun jul 17 07​:13​:38 mdt 2011 x86_64 intel(r) core(tm) i7 cpu 930 @​ 2.80ghz genuineintel gnulinux '
config_args='-des -Duseshrplib -Darchname=x86_64-linux-thread -Dcc=x86_64-pc-linux-gnu-gcc -Doptimize=-O3 -pipe -march=core2 -Dldflags=-Wl,-O1 -Wl,--as-needed -Dprefix=/usr -Dsiteprefix=/usr -Dvendorprefix=/usr -Dscriptdir=/usr/bin -Dprivlib=/usr/lib64/perl5/5.12.4 -Darchlib=/usr/lib64/perl5/5.12.4/x86_64-linux-thread-multi -Dsitelib=/usr/lib64/perl5/site_perl/5.12.4 -Dsitearch=/usr/lib64/perl5/site_perl/5.12.4/x86_64-linux-thread-multi -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.12.4 -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.12.4/x86_64-linux-thread-multi -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/share/man/man1 -Dsiteman3dir=/usr/share/man/man3 -Dvendorman1dir=/usr/share/man/man1 -Dvendorman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3pm -Dlibperl=libperl.so.5.12.4 -Dlocincpth= -Duselargefiles -Dd_semctl_semun -Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@​localhost -Dinstallusrbinperl=n -Ud_csh -Uusenm -Di_ndbm -Di_gdbm
-Di_db -Dusethreads -DDEBUGGING=none -Dinc_version_list=5.12.3/x86_64-linux-thread-multi 5.12.3 5.12.2/x86_64-linux-thread-multi 5.12.2 5.12.1/x86_64-linux-thread-multi 5.12.1 5.12.0/x86_64-linux-thread-multi 5.12.0 -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=define, use64bitall=define, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='x86_64-pc-linux-gnu-gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O3 -pipe -march=core2',
cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe'
ccversion='', gccversion='4.5.3', gccosandvers=''
intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries​:
ld='x86_64-pc-linux-gnu-gcc', ldflags ='-Wl,-O1 -Wl,--as-needed'
libpth=/usr/local/lib64 /lib64 /usr/lib64
libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc -lgdbm_compat
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
libc=/lib/libc-2.12.2.so, so=so, useshrplib=true, libperl=libperl.so.5.12.4
gnulibc_version='2.12.2'
Dynamic Linking​:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -O3 -pipe -march=core2 -Wl,-O1 -Wl,--as-needed'

Locally applied patches​:
0001-gentoo_MakeMaker-RUNPATH.diff
0002-gentoo_config_over.diff
0003-gentoo_cpan_definstalldirs.diff
0004-gentoo_cpanplus_definstalldirs.diff
0005-gentoo_create-libperl-soname.diff
0006-gentoo_MakeMaker-delete_packlist.diff
0007-fixes_8d66b3f9_h2hp_fix.diff
0008-fixes_f178b03b_h2ph_using_deprecated_goto.diff
0009-gentoo_mod-paths.diff
0010-gentoo_enc2xs.diff
0011-gentoo_IO-Compress_AutoLoader_dropped_from_Compress-Zlib.diff
0012-gentoo_drop-fstack-protector.diff

---
@​INC for perl 5.12.4​:
/etc/perl
/usr/lib64/perl5/site_perl/5.12.4/x86_64-linux-thread-multi
/usr/lib64/perl5/site_perl/5.12.4
/usr/lib64/perl5/vendor_perl/5.12.4/x86_64-linux-thread-multi
/usr/lib64/perl5/vendor_perl/5.12.4
/usr/lib64/perl5/site_perl/5.12.3/x86_64-linux-thread-multi
/usr/lib64/perl5/site_perl/5.12.3
/usr/lib64/perl5/site_perl/5.12.2/x86_64-linux-thread-multi
/usr/lib64/perl5/site_perl/5.12.2
/usr/lib64/perl5/site_perl
/usr/lib64/perl5/vendor_perl/5.12.3/x86_64-linux-thread-multi
/usr/lib64/perl5/vendor_perl/5.12.3
/usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux-thread-multi
/usr/lib64/perl5/vendor_perl/5.12.2
/usr/lib64/perl5/vendor_perl
/usr/lib64/perl5/5.12.4/x86_64-linux-thread-multi
/usr/lib64/perl5/5.12.4
/usr/local/lib/site_perl
.

---
Environment for perl 5.12.4​:
HOME=/home/dmcbride
LANG=en_US.utf8
LANGUAGE=
LC_ALL=en_US.utf8
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/local/bin​:/home/dmcbride/bin​:/usr/lib/distcc/bin​:/usr/bin​:/bin​:/opt/bin​:/usr/x86_64-pc-linux-gnu/i686-pc-linux-gnu/gcc-bin/4.5.3​:/usr/x86_64-pc-linux-gnu/gcc-bin/4.5.3​:/share/cvs/bin​:/usr/games/bin​:/share/bin​:/share/darin/bin​:/share/cvs/work/shared
PERL5LIB (unset)
PERL_BADLANG (unset)
SHELL=/bin/bash

--
Joel Roth

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From darin.mcbride@shaw.ca

My apologies for the duplicate posts... apparently the delay on email was
longer than I had expected. :-(

On Wednesday January 18 2012 1​:40​:21 AM you wrote​:

I am author of a Audio​::Nama, a Tk application that uses
Term​::ReadLine​::Gnu with the tkRunning option to allow the
user to control the app by entering commands via T​::RL
as well as by manipulating Tk widgets.

While I don't really understand how event loops work,
it appears that the tkRunning setting actually
belongs to Term​::ReadLine​::Gnu. IOW, it is necessary to
install the latter for the tkRunning setting to work.

Looking through the T​::RL​::G code, it calls $self->register_Tk, which is in
T​::RL​::Tk - where my patches are, and I *think* it registers the perl Tk_getc
function as the getc for readline (it's hard for me to follow), which, again,
is where my patches are.

So I wonder, will it be sufficient to patch
Term​::ReadLine? Perhaps Gnu ReadLine will
need patched as well?

Perhaps. However, at worst, the Tk mode won't be affected.

Second, I wonder, why change the existing API?
Couldn't another setting, AERunning, be simply
added rather than replacing tkRunning?
As you point out, not everyone may want to
add another dependency to their code.

The existing API isn't changed, but my answer to that is that AE is both more
modern (not sufficient by itself) and more generic. The point of AE seems to be
to support any event model you might need, including Tk.

Third, if such patches were proposed, I would want
them to be tested fully (and I will be happy to help.)

My issue here is merely that the existing tests seem less than adequate. I've
run some sample code manually - with AE, Tk, and AE & Tk, and it all seemed to
work. However, that's all manual, and with T​::RL​::Perl, not T​::RL​::Gnu (I
never have luck with T​::RL​::G, I don't know why). I'll have to look at the
tests for the T​::RL implementations to see if they have anything I can use for
a base for testing. Otherwise, I have some really nasty ideas - we'll have to
see. I'm having problems enough keeping up the test files for $work :-)

A final note, Audio​::Nama already uses AnyEvent,
allowing a choice of event loops. Event is selected
for terminal-only mode and Tk for terminal+Tk mode.

I'm curious as to how you would receive events registered wtih Event while
T​::RL is waiting for text, since T​::RL is currently going to be spinning the
Tk event loop, not the Event event loop, unless you have an idle callback
registered with Tk that simply spins the Event loop once.

In other words, as far as I can tell, today, T​::RL will only spin a Tk loop.
If Tk isn't loaded, it won't spin any loop, and all events will be on hold
(with a possible exception of signal handlers) until the user hits enter.

As far as I understand, the Tk event loop will
still be required for Tk applications to play friendly
with Term​::ReadLine, however the AnyEvent layer
might allow me to, for example, rewrite the GUI in Qt.

Right - by switching T​::RL to use AE (or at least default to it when it's
there), your GUI can use anything. I would also suggest reading some of the
Anyevent​::Impl​::* modules' perldocs - they're informative as to what bugs the
author had to overcome. In the Tk module, he talks about limitations
regarding the event loop, and how the event IDs can wrap around, clobbering
events. "So don't run Tk programs for more than an hour or so." Allowing the
user of the module the ability to work around these types of issues simply by
using another event model seems prudent.

Bonus questions​: Does any know if tkRunning setting supports
other Tk implementations such as Tcl​::Tk or Tkx? Do they
provide events such as Tk​::after?

One of my "test that I didn't break anything" scripts is using Tk​::after just
to prove that the events are being called. I don't know about Tcl​::Tk or Tkx
- I actually don't use Tk, which is one of the driving factors behind this
itch.

If so, it may be necessary that these sister implementations
of Tk be verified to function properly under patches
proposed to Term​::ReadLine, Term​::ReadLine​::Gnu, or
possibly Gnu ReadLine.

More testing == good. (But too much testing == unreasonable delay) Since my
new patch leaves everything alone when AE is not loaded, but works fine with Tk
when AE and Tk are loaded, these should continue to work. But testing our
questions is definitely good - I just don't know anything about these other
modules to know how to test them.

All this is written in theoretical ignorance, but with
a measure of actual experience with the packages in
question.

:-)

Thanks!

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @nwc10

On Wed, Jan 18, 2012 at 07​:27​:35AM -0700, Darin McBride wrote​:

The existing API isn't changed, but my answer to that is that AE is both more
modern (not sufficient by itself) and more generic. The point of AE seems to be
to support any event model you might need, including Tk.

And more portable?

Or less portable?

Given the author in question, and his preferences for how he spends his time
and where the cost/benefit of work arounds tips, I know which I'm going to
bet on.

ie I'd love to see AnyEvent as an option, even the default. But I don't feel
comfortable with making it a hard dependency, and removing the option to use
the existing Tk code.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @Tux

On Wed, 18 Jan 2012 15​:39​:58 +0000, Nicholas Clark <nick@​ccl4.org>
wrote​:

On Wed, Jan 18, 2012 at 07​:27​:35AM -0700, Darin McBride wrote​:

The existing API isn't changed, but my answer to that is that AE is both more
modern (not sufficient by itself) and more generic. The point of AE seems to be
to support any event model you might need, including Tk.

And more portable?

Or less portable?

Given the author in question, and his preferences for how he spends his time
and where the cost/benefit of work arounds tips, I know which I'm going to
bet on.

ie I'd love to see AnyEvent as an option, even the default. But I don't feel
comfortable with making it a hard dependency, and removing the option to use
the existing Tk code.

You are so capable of writing my opinion way better that I would have
been able myself :)

--
H.Merijn Brand http​://tux.nl Perl Monger http​://amsterdam.pm.org/
using 5.00307 through 5.14 and porting perl5.15.x on HP-UX 10.20, 11.00,
11.11, 11.23 and 11.31, OpenSuSE 10.1, 11.0 .. 11.4 and AIX 5.2 and 5.3.
http​://mirrors.develooper.com/hpux/ http​://www.test-smoke.org/
http​://qa.perl.org http​://www.goldmark.org/jeff/stupid-disclaimers/

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @nwc10

On Wed, Jan 18, 2012 at 04​:43​:11PM +0100, H.Merijn Brand wrote​:

You are so capable of writing my opinion way better that I would have
been able myself :)

I had 3 or 4 edits to get it right.

Portability is a trade off.

And if one is putting in portability for platforms one doesn't know, hasn't
used, doesn't use, and likely never will, it's (likely) an externality being
dumped on one.

So it's not wrong not to do it. [Abigail has made similar valid arguments
about File​::Copy versus system("cp", ...). I think that MJD has emphasised
in at least one talk that it's a trade off, not a mantra]

But there's more than one way to express this :-/

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From darin.mcbride@shaw.ca

On Wednesday January 18 2012 7​:40​:35 AM Nicholas Clark via RT wrote​:

ie I'd love to see AnyEvent as an option, even the default. But I don't feel
comfortable with making it a hard dependency, and removing the option to
use the existing Tk code.

Tk is not a hard dependency at the moment, unless you want an event loop. AE
will not be a hard dependency (with my proposed patch), either. I don't want
to see AE dragged in to the core. At least, not due to this wishlist item -
that's a completely separate discussion which I'm not interested in opening
here.

It's a soft dependency​: if you want to use AE, T​::RL should be able to support
it. If you want to use Tk, I'd suggest using AE anyway, but the revised patch
doesn't force it. If you don't want any event loop, that still works as
before, too. I don't want to force users of T​::RL into using an event loop as
I expect that wanting an event loop is likely to be a minority.

So, other than a lack of automated unit tests, I see the revised patch as one
that likely answers your concerns.

As for portability, I have no idea. According to cpantesters, AE seems to
pass on all platforms, so I'm not sure where the concern is there, and, even
then, if it doesn't work on your platform, don't use it, this patch still
falls back to Tk-only if Tk is loaded but AE isn't.

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @nwc10

On Wed, Jan 18, 2012 at 10​:32​:08AM -0700, Darin McBride wrote​:

It's a soft dependency​: if you want to use AE, T​::RL should be able to support
it. If you want to use Tk, I'd suggest using AE anyway, but the revised patch
doesn't force it. If you don't want any event loop, that still works as
before, too. I don't want to force users of T​::RL into using an event loop as
I expect that wanting an event loop is likely to be a minority.

So, other than a lack of automated unit tests, I see the revised patch as one
that likely answers your concerns.

It does. I'd missed that this was in the revised patch. Thanks.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From joelz@pobox.com

On Wed, Jan 18, 2012 at 07​:27​:35AM -0700, Darin McBride wrote​:

On Wednesday January 18 2012 1​:40​:21 AM Joel Roth wrote​:

A final note, Audio​::Nama already uses AnyEvent,
allowing a choice of event loops. Event is selected
for terminal-only mode and Tk for terminal+Tk mode.

I'm curious as to how you would receive events registered wtih Event while
T​::RL is waiting for text, since T​::RL is currently going to be spinning the
Tk event loop, not the Event event loop, unless you have an idle callback
registered with Tk that simply spins the Event loop once.

I use Event in a situation that the app runs without loaded
the Tk based GUI, to provide timers, etc. In that case,
tkRunning is not set.

In other words, as far as I can tell, today, T​::RL will only spin a Tk loop.
If Tk isn't loaded, it won't spin any loop, and all events will be on hold
(with a possible exception of signal handlers) until the user hits enter.

I'm glad no one told *me* that! :-)

A T​::RL based command prompt seems to run fine alongside
an Event event loop. I may be able to dig up some
test code to verify this FYI.

As far as I understand, the Tk event loop will
still be required for Tk applications to play friendly
with Term​::ReadLine, however the AnyEvent layer
might allow me to, for example, rewrite the GUI in Qt.

Right - by switching T​::RL to use AE (or at least default to it when it's
there), your GUI can use anything. I would also suggest reading some of the
Anyevent​::Impl​::* modules' perldocs - they're informative as to what bugs the
author had to overcome. In the Tk module, he talks about limitations
regarding the event loop, and how the event IDs can wrap around, clobbering
events. "So don't run Tk programs for more than an hour or so." Allowing the
user of the module the ability to work around these types of issues simply by
using another event model seems prudent.

Ouch! This is an audio app that might record or play for
long periods. Thanks, I will look into it.

Bonus questions​: Does any know if tkRunning setting supports
other Tk implementations such as Tcl​::Tk or Tkx? Do they
provide events such as Tk​::after?

One of my "test that I didn't break anything" scripts is using Tk​::after just
to prove that the events are being called. I don't know about Tcl​::Tk or Tkx
- I actually don't use Tk, which is one of the driving factors behind this
itch.

If so, it may be necessary that these sister implementations
of Tk be verified to function properly under patches
proposed to Term​::ReadLine, Term​::ReadLine​::Gnu, or
possibly Gnu ReadLine.

More testing == good. (But too much testing == unreasonable delay) Since my
new patch leaves everything alone when AE is not loaded, but works fine with Tk
when AE and Tk are loaded, these should continue to work. But testing our
questions is definitely good - I just don't know anything about these other
modules to know how to test them.

All this is written in theoretical ignorance, but with
a measure of actual experience with the packages in
question.

:-)

Thanks!

Seems to be going both ways. :-)

--
Joel Roth

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From darin.mcbride@shaw.ca

On Wednesday January 18 2012 10​:13​:48 AM you wrote​:

I'm curious as to how you would receive events registered wtih Event while
T​::RL is waiting for text, since T​::RL is currently going to be spinning
the Tk event loop, not the Event event loop, unless you have an idle
callback registered with Tk that simply spins the Event loop once.

I use Event in a situation that the app runs without loaded
the Tk based GUI, to provide timers, etc. In that case,
tkRunning is not set.

Yeah, I'm very curious. Are you running multi-threaded? That should do it,
but otherwise, I can't figure it out.

In other words, as far as I can tell, today, T​::RL will only spin a Tk
loop. If Tk isn't loaded, it won't spin any loop, and all events will be
on hold (with a possible exception of signal handlers) until the user
hits enter.
I'm glad no one told *me* that! :-)

A T​::RL based command prompt seems to run fine alongside
an Event event loop. I may be able to dig up some
test code to verify this FYI.

You've piqued my curiosity. :-) Here's the test I've been running, it's as
simple as I can make it. If you uncomment out the two tk lines and comment
out the Event line, it works. But if you try to remove Tk, the timer doesn't
print out the elapsed time (or something approximating such) at the top of the
console, assuming ANSI escape sequences are being interpreted (I was too lazy
to do any other method of controlling the cursor as this one dates back to my
DOS 5.0 days).

I assume that if I moved the Event loop to one thread and the Tk loop (or
basically, T​::RL without tk) to a separate thread from the Event loop, it'll
work. But that now comes with all the joys and tribulations of
multithreading. As opposed to the joys and tribulations of event programming.

#!/usr/bin/perl

use strict;
use warnings;

use Event;
#use Tk;
use AnyEvent;
use Term​::ReadLine;

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

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @rcaputo

On Jan 18, 2012, at 10​:39, Nicholas Clark wrote​:

On Wed, Jan 18, 2012 at 07​:27​:35AM -0700, Darin McBride wrote​:

The existing API isn't changed, but my answer to that is that AE is both more
modern (not sufficient by itself) and more generic. The point of AE seems to be
to support any event model you might need, including Tk.

And more portable?

Or less portable?

Given the author in question, and his preferences for how he spends his time
and where the cost/benefit of work arounds tips, I know which I'm going to
bet on.

Interoperability requires cooperation from the author, and he's been known to break it for modules he doesn't like. Ask Paul Evans and/or Matt Trout about this​:

https://metacpan.org/source/MLEHMANN/AnyEvent-6.13/lib/AnyEvent.pm#L1396

--
Rocco Caputo <rcaputo@​pobox.com>

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @cpansprout

On Wed Jan 18 12​:53​:06 2012, rcaputo wrote​:

On Jan 18, 2012, at 10​:39, Nicholas Clark wrote​:

On Wed, Jan 18, 2012 at 07​:27​:35AM -0700, Darin McBride wrote​:

The existing API isn't changed, but my answer to that is that AE is
both more
modern (not sufficient by itself) and more generic. The point of
AE seems to be
to support any event model you might need, including Tk.

And more portable?

Or less portable?

Given the author in question, and his preferences for how he spends
his time
and where the cost/benefit of work arounds tips, I know which I'm
going to
bet on.

Interoperability requires cooperation from the author, and he's been
known to break it for modules he doesn't like. Ask Paul Evans and/or
Matt Trout about this​:

https://metacpan.org/source/MLEHMANN/AnyEvent-
6.13/lib/AnyEvent.pm#L1396

Tying %INC could solve that. :-)

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From darin.mcbride@shaw.ca

On Wednesday January 18 2012 12​:53​:07 PM you wrote​:

Interoperability requires cooperation from the author, and he's been known
to break it for modules he doesn't like.

We have more than one developer in our community who has issues with their
attitude. Without speaking a personal opinion on whether AE's author is one
or not, or outing myself, I don't see this as a barrier​: today, T​::RL supports
one event loop. With this patch, it will support *most* event loops available
in Perl. And any that aren't supported could potentially be added to AE
without having to maintain T​::RL's event support, benefiting not just T​::RL,
but any other AE-based module.

So, I suppose before we stray entirely off-topic, is it the opinion of someone
willing to commit this or a similar patch to T​::RL that all that is missing is
some useful unit tests, or are there other, more basic issues that need to be
resolved?

Also, do the tests need to conform to core-modules-only (plus AE and Tk), or
can they be skippable tests that use other modules? (Coro may make testing
this much easier, for example, I'm not sure yet.)

@p5pRT
Copy link
Author

p5pRT commented Jan 18, 2012

From @cpansprout

On Wed Jan 18 15​:21​:51 2012, dmcbride wrote​:

So, I suppose before we stray entirely off-topic, is it the opinion of
someone
willing to commit this or a similar patch to T​::RL that all that is
missing is
some useful unit tests, or are there other, more basic issues that
need to be
resolved?

Unless you can get someone else familiar with this to sign off on the
patch, I would have to spend some time studying it myself before I feel
comfortable applying it.

Also, do the tests need to conform to core-modules-only (plus AE and
Tk), or
can they be skippable tests that use other modules? (Coro may make
testing
this much easier, for example, I'm not sure yet.)

It would make testing easier if you could avoid non-core modules (fewer
modules for people to install to make sure they don’t break things).

It would make testing even easier if you could use a mock object
(preferably in addition to the AE/Tk tests).

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From vadim.konovalov@alcatel-lucent.com

From​: Darin McBride

today, T​::RL supports
one event loop. With this patch, it will support *most*
event loops available
in Perl. And any that aren't supported could potentially be
added to AE
without having to maintain T​::RL's event support, benefiting
not just T​::RL,
but any other AE-based module.

what most event loops it do support?
Gtk? Tcl? Qt?

Actually, when looking into ./lib/Term/ReadLine.pm and seeking
for "tk" I found inside
  package Term​::ReadLine​::Tk;

IMO this should not be there - you support your favourite GUI but
not mine.

This Term​::ReadLine​::Tk should be on CPAN and not in the CORE.
This small group of users of Term​::ReadLine​::Tk will find it on CPAN.

Regards,
Vadim.

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @demerphq

On 18 January 2012 21​:52, Rocco Caputo <rcaputo@​pobox.com> wrote​:

On Jan 18, 2012, at 10​:39, Nicholas Clark wrote​:

On Wed, Jan 18, 2012 at 07​:27​:35AM -0700, Darin McBride wrote​:

The existing API isn't changed, but my answer to that is that AE is both more
modern (not sufficient by itself) and more generic.  The point of AE seems to be
to support any event model you might need, including Tk.

And more portable?

Or less portable?

Given the author in question, and his preferences for how he spends his time
and where the cost/benefit of work arounds tips, I know which I'm going to
bet on.

Interoperability requires cooperation from the author, and he's been known to break it for modules he doesn't like.  Ask Paul Evans and/or Matt Trout about this​:

https://metacpan.org/source/MLEHMANN/AnyEvent-6.13/lib/AnyEvent.pm#L1396

Wow.

IMO the author of IO​::Async​::Loop​::AnyEvent should just redefine
AnyEvent​::detect() to bypass this monstrosity.

But if they do are we going to see an arms race over what modules you
allowed to use with other modules?!

I consider the piece of code you pointed out to most unperlish, and an
affront to the community and the spirit of CPAN.

IMO AnyEvent should be removed from CPAN until this code is removed,
it seems inappropriate for CPAN to host code that forbids you from
using something else on CPAN.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @leonerd

On Thu, Jan 19, 2012 at 07​:06​:11AM +0100, Konovalov, Vadim (Vadim)** CTR ** wrote​:

From​: Darin McBride

today, T​::RL supports
one event loop. With this patch, it will support *most*
event loops available
in Perl. And any that aren't supported could potentially be
added to AE
without having to maintain T​::RL's event support, benefiting
not just T​::RL,
but any other AE-based module.

what most event loops it do support?
Gtk? Tcl? Qt?

Actually, when looking into ./lib/Term/ReadLine.pm and seeking
for "tk" I found inside
package Term​::ReadLine​::Tk;

IMO this should not be there - you support your favourite GUI but
not mine.

This Term​::ReadLine​::Tk should be on CPAN and not in the CORE.
This small group of users of Term​::ReadLine​::Tk will find it on CPAN.

+1

This has no business in core's Term​::ReadLine. Anyone who wants
integration with their favourite event loop of choice can go to CPAN and
install Term​::ReadLine​::AnyEvent, Term​::ReadLine​::IOAsync,
Term​::ReadLine​::POE, Term​::ReadLine​::Reflex, Term​::ReadLine​::Tk, ...

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http​://www.leonerd.org.uk/

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @leonerd

On Thu, Jan 19, 2012 at 01​:01​:39PM +0100, demerphq wrote​:

Interoperability requires cooperation from the author, and he's been known to break it for modules he doesn't like.  Ask Paul Evans and/or Matt Trout about this​:

https://metacpan.org/source/MLEHMANN/AnyEvent-6.13/lib/AnyEvent.pm#L1396

Wow.

IMO the author of IO​::Async​::Loop​::AnyEvent should just redefine
AnyEvent​::detect() to bypass this monstrosity.

But if they do are we going to see an arms race over what modules you
allowed to use with other modules?!

I'm not going to get into a silly childish arms-race over this issue.

MLEHMANN is upset because I found a way to layer IO​::Async atop AnyEvent
instead of vice versa, but doing so required a small peek inside the
internals to obtain one feature the AE API doesn't provide (namely, a
"run this piece of code after the next event timeslice"). Were that
added, there could be no possible objection to
IO​::Async​::Loop​::AnyEvent, as it becomes simply another AE-API using
module.

He choses not to do that, thus forcing me to peek inside, and so he gets
upset.

I consider the piece of code you pointed out to most unperlish, and an
affront to the community and the spirit of CPAN.

Which again is why I'm not going to get into an arms race as it will
only end badly.

IMO AnyEvent should be removed from CPAN until this code is removed,
it seems inappropriate for CPAN to host code that forbids you from
using something else on CPAN.

That seems a -little- OTT as a response, surely? Perhaps a far better
solution would simply be to bring this change to more people's
attention, and point out that other alternatives exist (namely
IO​::Async, POE and Reflex come to mind); and that people should be free
to decide which one(s) they want to use.

See also

  http​://leonerds-code.blogspot.com/2011/05/wearing-two-hats.html

TMTOWTDI, after all...

--
Paul "LeoNerd" Evans

leonerd@​leonerd.org.uk
ICQ# 4135350 | Registered Linux# 179460
http​://www.leonerd.org.uk/

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @demerphq

On 19 January 2012 17​:42, Paul LeoNerd Evans <leonerd@​leonerd.org.uk> wrote​:

On Thu, Jan 19, 2012 at 01​:01​:39PM +0100, demerphq wrote​:

Interoperability requires cooperation from the author, and he's been known to break it for modules he doesn't like.  Ask Paul Evans and/or Matt Trout about this​:

https://metacpan.org/source/MLEHMANN/AnyEvent-6.13/lib/AnyEvent.pm#L1396

Wow.

IMO the author of IO​::Async​::Loop​::AnyEvent should just redefine
AnyEvent​::detect() to bypass this monstrosity.

But if they do are we going to see an arms race over what modules you
allowed to use with other modules?!

I'm not going to get into a silly childish arms-race over this issue.

MLEHMANN is upset because I found a way to layer IO​::Async atop AnyEvent
instead of vice versa, but doing so required a small peek inside the
internals to obtain one feature the AE API doesn't provide (namely, a
"run this piece of code after the next event timeslice"). Were that
added, there could be no possible objection to
IO​::Async​::Loop​::AnyEvent, as it becomes simply another AE-API using
module.

He choses not to do that, thus forcing me to peek inside, and so he gets
upset.

I consider the piece of code you pointed out to most unperlish, and an
affront to the community and the spirit of CPAN.

Which again is why I'm not going to get into an arms race as it will
only end badly.

IMO AnyEvent should be removed from CPAN until this code is removed,
it seems inappropriate for CPAN to host code that forbids you from
using something else on CPAN.

That seems a -little- OTT as a response, surely? Perhaps a far better
solution would simply be to bring this change to more people's
attention, and point out that other alternatives exist (namely
IO​::Async, POE and Reflex come to mind); and that people should be free
to decide which one(s) they want to use.

Yeah, its probably OTT as a response. And I am glad you aren't going
to start an arms race over it.

I guess I shouldn't let it bother me, but it just seems wrong to do
something like that​: the antithesis of the intent of CPAN and sharing.
"You can only use my module if you obey my rules" does not seem to be
the right attitude for something on CPAN.

I actually checked to see if Larry Wall had said anything relevant
about stuff like this and I found two quotes I think fit​:

from perlstyle​: · Be nice.
from Larry Wall*​: Perl doesn't have an infatuation with enforced
privacy. It would prefer that you stayed out of its living room
because you weren't invited, not because it has a shotgun

Seems to me that the code we are discussing violates both.

cheers,
yves

* http​://www.goodreads.com/quotes/show/81807

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @Mons

Paul, I know, Marc is very hard man to talk, but why don’t you and Marc
come to mutual understanding?

Your :​:Loop​::AnyEvent goes into AE's internals. It's not a good point of
interaction with other modules

You abuse Marc's module, so he insert a protection from abusing.

If I know, that something on CPAN will not work, or will work badly with my
module I prefer to protect from such interaction.

Just try to talk with him and many users of AE and IO​::Async will win
instead of stupid war between AE and IO​::Async

On Thu, Jan 19, 2012 at 4​:42 AM, Paul LeoNerd Evans
<leonerd@​leonerd.org.uk>wrote​:

On Thu, Jan 19, 2012 at 01​:01​:39PM +0100, demerphq wrote​:

Interoperability requires cooperation from the author, and he's been
known to break it for modules he doesn't like. Ask Paul Evans and/or Matt
Trout about this​:

https://metacpan.org/source/MLEHMANN/AnyEvent-6.13/lib/AnyEvent.pm#L1396

IMO AnyEvent should be removed from CPAN until this code is removed,
it seems inappropriate for CPAN to host code that forbids you from
using something else on CPAN.

That seems a -little- OTT as a response, surely? Perhaps a far better
solution would simply be to bring this change to more people's
attention, and point out that other alternatives exist (namely
IO​::Async, POE and Reflex come to mind); and that people should be free
to decide which one(s) they want to use.

--
Best wishes,
Vladimir V. Perepelitsa aka Mons Anderson
<inthrax@​gmail.com>, <mons@​cpan.org>
http​://github.com/Mons

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @demerphq

On 19 January 2012 18​:08, Vladimir V. Perepelitsa <inthrax@​gmail.com> wrote​:

Paul, I know, Marc is very hard man to talk, but why don’t you and Marc come
to mutual understanding?

Your :​:Loop​::AnyEvent goes into AE's internals. It's not a good point of
interaction with other modules

You abuse Marc's module, so he insert a protection from abusing.

This is a gift culture. Its not up to the giver to determine how the
receiver uses the gift.

It is also not Perlish to prevent someone from doing something that
they want to do because you don't think its a good idea. That is up to
the consumer of the module to decide.

It seems to me that if the module warned, perhaps something like "You
have loaded ... prior to this module, which is known to cause
instability in other things using this module. Please do not report
bugs about problems you might encounter" then it would be pretty
reasonable.

But forbidding someone to use a module because you want to use another
module the author does not approve of seems pretty unreasonable to me.

If I know, that something on CPAN will not work, or will work badly with my
module I prefer to protect from such interaction.

If that is your attitude you should hide your code away and make sure
that anyone that uses it signs a contract about terms of use. But that
also means it doesn't belong on CPAN and isn't really what I would
call "free software". AnyEvent is released under the same terms as
Perl itself. Therefore it is "free software". Therefore anyone can
take the code and do pretty much whatever they want to it. But they
can't do the same with the version on CPAN, doesn't that strike you as
being the antithesis of "free software"?

It simply is not YOUR problem what happens when someone decides to do
something you think is stupid with your code. It is that persons
problem. Trying to forbid people from doing something you think is
stupid just means you are going to stop someone smarter than you doing
something smart that you never thought of. This actually seems like a
good example of that.

Just try to talk with him and many users of AE and IO​::Async will win
instead of stupid war between AE and IO​::Async

Of course it is always better to talk about things. Hopefully they can
figure something out.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @Mons

It is also not Perlish to prevent someone from doing something that
they want to do because you don't think its a good idea. That is up to
the consumer of the module to decide.

That's a bit another problem.
Let's look​: I'm a user of AE and IO​::Async. I don't know about possible
problems when I will use them together.
So, from point of user I rather say thanks to Marc for warning me (maybe in
a too strict way​: warn would be enough), than to Paul for anyevent brokage
(possible) without warning.

So I respect that point of author. And if I'm an author of "gun", then I
will try to protect user from "shells", which should be loaded via barrel,
instead of lock.

Of course, there are some smart users of our modules, that will do things
right and will not cry "A-a-a, that module is bad", just because something
was used wrong. But unfortunatelly there are much more such users (

It seems to me that if the module warned, perhaps something like "You
have loaded ... prior to this module, which is known to cause
instability in other things using this module. Please do not report
bugs about problems you might encounter" then it would be pretty
reasonable.

But forbidding someone to use a module because you want to use another
module the author does not approve of seems pretty unreasonable to me.

Completely agree

If I know, that something on CPAN will not work, or will work badly with
my
module I prefer to protect from such interaction.

If that is your attitude you should hide your code away and make sure
that anyone that uses it signs a contract about terms of use. But that
also means it doesn't belong on CPAN and isn't really what I would
call "free software". AnyEvent is released under the same terms as
Perl itself. Therefore it is "free software". Therefore anyone can
take the code and do pretty much whatever they want to it. But they
can't do the same with the version on CPAN, doesn't that strike you as
being the antithesis of "free software"?

It simply is not YOUR problem what happens when someone decides to do
something you think is stupid with your code. It is that persons
problem. Trying to forbid people from doing something you think is
stupid just means you are going to stop someone smarter than you doing
something smart that you never thought of. This actually seems like a
good example of that.

Just try to talk with him and many users of AE and IO​::Async will win
instead of stupid war between AE and IO​::Async

Of course it is always better to talk about things. Hopefully they can
figure something out.

cheers,
Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

--
Best wishes,
Vladimir V. Perepelitsa aka Mons Anderson
<inthrax@​gmail.com>, <mons@​cpan.org>
http​://github.com/Mons

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2012

From @Leont

On Thu, Jan 19, 2012 at 6​:08 PM, Vladimir V. Perepelitsa
<inthrax@​gmail.com> wrote​:

You abuse Marc's module, so he insert a protection from abusing.

Define 'abusing'​: AFAIK Paul didn't actually break anyone else's code,
which would be the only argument that would impress me. If you define
abuse as «doing something with a piece of code that the author hadn't
envisioned», then I'll gladly be an abuser of code ;-)

Leon

@p5pRT
Copy link
Author

p5pRT commented Feb 2, 2012

From schmorp@schmorp.de

On Thu, Feb 02, 2012 at 04​:28​:16PM +0000, Paul LeoNerd Evans <leonerd@​leonerd.org.uk> wrote​:

On Thu, Feb 02, 2012 at 02​:21​:22AM +0100, Marc Lehmann wrote​:

- IO​::Async can use e.g. AnyEvent​::Loop to be compatible, which _has_
the required functionality.

As said in my other mail, no. It doesn't. But I have suggested what
would be required to support it, so hopefully we can resolve this there.

I have explained to you that it can't be done, becaue AnyEvent can only offer
what is implementable with event loops, and I have also explained that it's
not even fixing any real problem.

- I warned IO​::Async's author long before on why his module will break
and why it is inevitable, and especially why it is a disservice to his
users, and how to fix it. I didn't receive a reaction.

You did not warn me "long before".

Well, did not "warn" you at all - I pointed out that your module creates
problems, multiple times, and explained to you _why_ it does so and what
needs to be changed.

You ignored that, so I added a diagnostic to warn users that they should
not use your module because it doesn't work.

12 Aug 2011​:
At this point I decided I wouldn't reply, as you were quite firm in

04 Oct 2011​: AnyEvent 6.1 is released on CPAN. Part of its changes
adds the 'die' line conditional on the presence of
IO​::Async​::Loop​::AnyEvent; the line of source code at the centre of
this discussion.

So you disagree that three weeks is not "long before", ok, granted, I
feel different. However, since you freely admit that you didn'T bother
reeplying and resolving the problem, no amount of time would have made any
difference, so the point is moot, right?

Now, all this shitting on my head when I actually _did_ secretly
support IO​::Async​::Loop​::AnyEvent for as long as I could is... rather
dishonest​: Suddenly, module authors have to support every third-party
module that abuses its internals? Seriously?

You did not.

Of course I did, until people started to suffer, and I got the burden of
maintainance.

immediate reply was to tell me to stop and that you would actively look
for ways to prevent me continuing along that path. Thereafter, and

Bullshit, this is what I wrote​:

  It's morally wrong, and I will certainly not help you making the
  world worse for perl coders :) In fact, since I think it's so evil, I will
  actively fight it :)

That doesn't mean I was looking for ways to prevent you continuing along
that path, and in fact, it's also not what I did then.

Now, that mail was 3kb in size, in which I explained why your approach is
wrong, and whats needed to fix it. Claiming I didn't explain it to you is
simply wrong (the e-mail is available on request, if you agree).

However, since the very approach is wrong, it can't be fixed by any simple
means, so much is true.

without further notification to me, you released a version of AnyEvent

Well, you admitted you ignored me, so what's your point?

I asked your opinion on how to fix a problem. You had a choice there;
you could have worked with me to find a solution, you could have ignored

I did. You didnt like the solution and the explanation, so it is your
problem until people come to me and complain, then it is my problem, and
then I will act.

Sorry, but saying you didn't bother with a reply is not my idea of trying
to resolve a problem.

my email, you could have said "no, that's silly please go away". Any of
these would have been acceptable solutions.

I explained in many ways why the approach is wrong.

Instead, you _actively_ went out of your way to break cross
compatibility between these two modules.

Bullshit, the module was broken from the very beginning, and causing
problems.

That is quite a step beyond. As Matt Trout points out, it's one thing to
scream loudly and tell someone they've pointed a gun at their own feet,
it is quite another entirely to pull the trigger for them themself.

Not everything that limps along is an analogy.

What I did was simply add a diagnostic because your module breaks othe
rmodules using AnyEvent (or other event loops).

Ah, but it's buggy and causes mysterious failures that are hard to
diagnose for users after the required functionality had been removed. This
has been reported, and the author of IO​::Async​::Loop​::AnyEvent has had
ample time to fix it.

As you did to Rocco, I claim "citation needed".

Condvars stop working, as well as programs using other event loops than
IO​::Async.

Specifcally, I would like to know where it was you tried to explain to
me how to fix this module, other than by saying "don't do it".

Well, your module *is not fixable*, it's broken by design.

I have explained to you what needs to be done to actually make IO​::Async use
AnyEvent, but you didn't like that solution.

That's not my problem, sorry.

I believe my "later" functionallity (see other mail) is sufficient to
stop this API abuse. Please either implement it, or explain why it is
insufficient and how else you propose to solve it.

See my other mail, it can't be solved by the design you choose, and the
later function cannot be implemented.

That's OK. I am the author, and I will claim that responsibility

Good, then how about doing so?

* The implementation of the loop_once method requires the use of an
undocumented AnyEvent method (one_event before version 6, _poll
thereafter). This happens to work at the time of writing, but as it
is undocumented it may be subject to change.

It does not work "at the time of the writing" vecause one_event wasn't
even implemented by all backends.

Is there anything about this description you find inaccurate? Or do you
agree with this statement of affairs?

I think you fundamentally misunderstand AnyEvent - you think AnyEvent is just
another event module, it is not. The closest thing AnyEvent has that is that
is AnyEvent​::Loop.

AnyEvent is just an adaptor to existing event loops. It does not block, like
IO​::Async does.

Once again - neither myself, nor Matt, nor anybody else has ever asked
that you do support it.

When people run into problems and I have to waste my time debugging your code
then it's already too late. Not supporting it will not help.

And if you don't want me to support it, what exatcly is your problem? I do
not support it, I do not condone it, and it doesn't work (and di not work,
ever) - I am entirely fine with that state of affirs, although I would
have hoped you'd be interested in a real solution. You are not.

of your way to kill it. A 'die' statement at require time conditional
merely on an %INC hash key, feels to me at least, to be doing just that.

I can change it into a warning if that makes you happy, but that will not fix
your module in any way.

In any case, if that is all you wanted, you could have mentioned that - I
was alway wwilling to tlak about things, keep in mind that you are the one
who refused to communicate.

It does not and has not implemented any prejuduice against any other event
loops - it simply embraces them, if possible.

Other than

https://metacpan.org/source/MLEHMANN/AnyEvent-6.13/lib/AnyEvent.pm#L1396

At least in firefox that just gives me the AnyEvent manpage - presumably
there is a supposed anchor L1396, but firefox doesn't find it.

You probably need to be more specific - if you refer to​:

  # IO​::Async​::Loop​::AnyEvent is extremely evil, refuse to work with it

then please read what I wrote​: "It does not and has not implemented any
prejuduice against any other event loops" - your module is not an event loop
in any sense of the word.

Your event loop is called IO​::Async (actually an event framework), and it
does come with a numbe rof event loops.

AnyEvent is supposed to work just fine with IO​::Async as event loop -
anything else is a bug. Please don't imply anything to the contrary.

--
  The choice of a Deliantra, the free code+content MORPG
  -----==- _GNU_ http​://www.deliantra.net
  ----==-- _ generation
  ---==---(_)__ __ ____ __ Marc Lehmann
  --==---/ / _ \/ // /\ \/ / schmorp@​schmorp.de
  -=====/_/_//_/\_,_/ /_/\_\

@p5pRT
Copy link
Author

p5pRT commented Feb 2, 2012

From @ap

* Marc Lehmann <schmorp@​schmorp.de> [2012-02-02 20​:55]​:

On Thu, Feb 02, 2012 at 04​:28​:16PM +0000, Paul LeoNerd Evans <leonerd@​leonerd.org.uk> wrote​:

* The implementation of the loop_once method requires the use of an
undocumented AnyEvent method (one_event before version 6, _poll
thereafter). This happens to work at the time of writing, but as
it is undocumented it may be subject to change.

It does not work "at the time of the writing" vecause one_event wasn't
even implemented by all backends.

I think you fundamentally misunderstand AnyEvent - you think AnyEvent
is just another event module, it is not. The closest thing AnyEvent
has that is that is AnyEvent​::Loop.

AnyEvent is just an adaptor to existing event loops. It does not
block, like IO​::Async does.

Marc, an option to resolve is to add an interface similar to what Plack
has for its handlers, where each handler has a way to communicate its
capabilities, e.g. whether it supports streaming. Then middlewares or
apps which require streaming can throw an error when run under servers
that do not support it. That allows Plack to support more than just the
absolute least common denominator of server semantics in its handlers​:
it’s up to the user to pick a server that supports enough.

By analogy IOALoopAE could mention in POD that it requires `one_event`
support and AE could let it know whether it is running under an event
loop that provides that, which IOALoopAE could then check and bail out
(possibly lazily iff client code actually tries to use the `later`
feature).

That way AE could support *common* event loop semantics instead of just
the *universal* semantics.

Effectively AE already does that – I do not recall what it was but there
was a use case that the docs describe as working under Coro or the like,
but not under non-concurrent event loops. There just is no formalised
system for event loop feature support declaration.

Regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2012

From schmorp@schmorp.de

On Thu, Feb 02, 2012 at 04​:26​:40PM +0100, Leon Timmermans <fawaka@​gmail.com> wrote​:

What ever was discussed previously, it doesn't appear to have been
discussed in the open (in particular, the bugtracker of
IO​::Async​::Loop​::AnyEvent remains empty). You assert it's evil, but
don't explain why it is. Why can't it work? You list facts, but the
ones that actually matters are still in the fog (how/when does it
break? How can that by fixed? Or why shouldn't it be?).

That's true (but in the meantime, has been explained).

The way you're handling this is raising more questions than it answers

Well, keep in mind​:

1. perl5-porters is not the place to discuss this thing, it's simply off-topic
2. this has been discussed in private with the IO​::Async author before, who
  opted to ignore my suggestions completely, and didn't even bother to
  reply.
3. I didn't drag this into the public here, Rocco did with his fabricated
  statement.

and it gives the general impression you don't *want* this to work. That
is what gets people pissed off.

And keep in mind that this impression comes from what other people said,
not by what I said - I wasn't even consulted nor notified, and if I hadn't
see a notification about this on twitter, rocco's fabrication would have
gone unnoticed by me. Nobody sought for my input - I gave my input freely
to the IO​::Async author, and anybody who cared to ask. Why is it suddenly
my fault for notifying people and being ignored?

What pisses me off is that Rocco can spread fud on p5p and people like
demerphq go as far as asking for the removal of my module from CPAN.

Really, don't you think people here were awfully quick to make up their mind
without even asking me for my side of the story, and in most cases, not even
looking at the actual code, but instead blindly believing what others have
said (others with an agenda of pushing their own modules?). Or people openly
asking for the removal of AnyEvent from CPAN? Without actually having read or
understand the issues at all; without even *trying* to?

I am trying to clarify things, but why do you want to drag out this fud
campaign on p5p? Why do you want to give this thing a forum on p5p? Can I
also use p5p for slinging mud at people now? Do you really think this is
acceptable? Do you actuallly *want* that?

I don't.

I am not the author of IO​::Async​::Loop​::AnyEvent, and am not responsible
for it when it breaks. Making me responsible is highly disingenious.

It's not just broken, you've actively forbidden other people from
trying to make it work.

I have never done that, nor do I have the power to enforce that, so please
stay to facts, ok? This fud campagin doesn't help anybody.

If all that was wrong was IO​::Async​::Loop​::AnyEvent being buggy, no one
would have been mad at you.

All that is wrong is IO​::Async​::Loop​::AnyEvent being buggy by design and
causing problems for users who use AnyEvent. I don't see how that changes
anything of relevance that would enable anybody to be mad at me.

Unlike others, I am acting in good faith here, trying to discuss things
*first*. Nothing like that has been attempted by you or anybody else on
p5p. Look into the mirror please when you get angry at people who don't
openly discuss things.

So, one last time, keep in mind that I didn't drag this onto p5p, that p5p is
the wrong place for this discussion and I didn't start to sling mud around,
Rocco did.

However, reactions like yours do piss me off. You find it ok to change p5p
into a forum for slamming other people, and then think those other people
need to explain themselves?

Sorry, not so - I have the (moral) right to correct when people spread
fud (in roccos case actual lies) about me and my code, but I am not
required to take part in a p5p slamming campaign against me, and I am,
understandably, not very motivated to give in to this kind of blackmail.

That might be your style, but not mine.

And as such, I reserve the right to print warnings or fatal out in any way I
want in my module. If you don't like it, you can bring it up and we can talk,
or you can ignore my module, or you can tell others not to use it because of
that, but joining a fud campaign on the wrong mailinglist is simply not ok.

--
  The choice of a Deliantra, the free code+content MORPG
  -----==- _GNU_ http​://www.deliantra.net
  ----==-- _ generation
  ---==---(_)__ __ ____ __ Marc Lehmann
  --==---/ / _ \/ // /\ \/ / schmorp@​schmorp.de
  -=====/_/_//_/\_,_/ /_/\_\

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2012

From @tsee

On 02/03/2012 02​:32 AM, Marc Lehmann wrote​:
[...]

And as such, I reserve the right to print warnings or fatal out in any way I
want in my module. If you don't like it, you can bring it up and we can talk,
or you can ignore my module, or you can tell others not to use it because of
that, but joining a fud campaign on the wrong mailinglist is simply not ok.

There are many things I disagree about with you, Marc, including the
notion of this being a campaign of some sort[1], but not the rest of the
above paragraph. I agree that it's your right to do whatever you want[2]
with your CPAN contributions. More importantly, demerphq, who originally
reacted so strongly, has publicly expressed that he has come around to
this line of thinking as well.

In the context, I would like to kindly suggest that this thread pass
away in relative peace to whatever place that flame wars go to when they
die. (This directed at everyone.)

Thank you.
Steffen

[1] But that's a detail I do not care to discuss at length.

[2] Within limits. I draw the line at, for example, racism, or malware.
And I am quite certain that the other PAUSE admins, most notably
Andreas, have a similar view on this.

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2012

From schmorp@schmorp.de

On Fri, Feb 03, 2012 at 08​:07​:56AM +0100, Steffen Mueller <smueller@​cpan.org> wrote​:

On 02/03/2012 02​:32 AM, Marc Lehmann wrote​:
[...]

And as such, I reserve the right to print warnings or fatal out in any way I
want in my module. If you don't like it, you can bring it up and we can talk,
or you can ignore my module, or you can tell others not to use it because of
that, but joining a fud campaign on the wrong mailinglist is simply not ok.

There are many things I disagree about with you, Marc, including the
notion of this being a campaign of some sort[1]

Why else would somebody (Rocco) post fabricated statements ot this list to
badmouth my person? I challenged Rocco to provide evidence, but he failed
to do so and failed to take back his lie.

At the very least that's his campaign, or give me another reason why Rocco
would spread such a lie publicly? It serves no other purpose than to
slander me, because he must be well aware that he's not telling the truth.

And it even worked with a few people (fortunately not too many) here.

want[2] with your CPAN contributions. More importantly, demerphq,
who originally reacted so strongly, has publicly expressed that he
has come around to this line of thinking as well.

While I don't read his mail the same waa as you apparently (he didn't only
really reverted a tiny part of what he said), I appreciate that he did, it
really wasn't appropriate.

In the context, I would like to kindly suggest that this thread pass
away in relative peace to whatever place that flame wars go to when
they die. (This directed at everyone.)

This is not a just flamewar - Rocco abused this list to slander my person
specifically with fabricated statements, and this needs to be spelled out.

I fully agree that discussing the actual issues on this list is wrong,
too, but make sure you don't get confused and remember who started it, and
how.

[2] Within limits. I draw the line at, for example, racism, or
malware. And I am quite certain that the other PAUSE admins, most
notably Andreas, have a similar view on this.

I have a very similar view on that too. Seems that the closest thing to
the powers-to-be on CPAN agree with me, as well, and it's good to hear
that demerphq got to his senses as well.

Perl developers asking for modules to be removed because of their personal
taste is really a very bad sign to module authors, so it really should not
happen.

--
  The choice of a Deliantra, the free code+content MORPG
  -----==- _GNU_ http​://www.deliantra.net
  ----==-- _ generation
  ---==---(_)__ __ ____ __ Marc Lehmann
  --==---/ / _ \/ // /\ \/ / schmorp@​schmorp.de
  -=====/_/_//_/\_,_/ /_/\_\

@p5pRT
Copy link
Author

p5pRT commented Feb 3, 2012

From @rjbs

I don't care who started it. This thread is over.

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Feb 6, 2012

From @nwc10

On Wed Feb 01 10​:58​:27 2012, mst@​shadowcat.co.uk wrote​:

On Wed, Feb 01, 2012 at 09​:33​:02AM +0000, Paul LeoNerd Evans wrote​:

On Tue, Jan 31, 2012 at 09​:34​:00AM -0800, Father Chrysostomos via RT
wrote​:

OK, then let me repeat my two questions​: Does anyone want to
write a
patch for that? Should I revert Darin McBride’s patch
(b60dd40)?

Unless there's any reason to do it a different way, I'd vote for​:

"Tell us where to look to get a pre-dmcbride-patch version, let
somebody
provide a new patch against that, and once that's considered good
revert
his patch and introduce the new one."

Agree, because what we have now is tested, and better than what we had
before.

Although I'd be somewhat averse to allowing his patch to escape blead
if
we can possibly avoid it.

Yes, it would be nice to avoid a visible intermediate step.
Much simpler for the end user that way.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Feb 12, 2012

@cpansprout - Status changed from 'resolved' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

From @rcaputo

On Mon Feb 06 05​:15​:27 2012, nicholas wrote​:

On Wed Feb 01 10​:58​:27 2012, mst@​shadowcat.co.uk wrote​:

On Wed, Feb 01, 2012 at 09​:33​:02AM +0000, Paul LeoNerd Evans wrote​:

On Tue, Jan 31, 2012 at 09​:34​:00AM -0800, Father Chrysostomos via RT
wrote​:

OK, then let me repeat my two questions​: Does anyone want to
write a
patch for that? Should I revert Darin McBride’s patch
(b60dd40)?

Unless there's any reason to do it a different way, I'd vote for​:

"Tell us where to look to get a pre-dmcbride-patch version, let
somebody
provide a new patch against that, and once that's considered good
revert
his patch and introduce the new one."

Agree, because what we have now is tested, and better than what we had
before.

Challenge accepted. See attachment. Patched directly against blead.

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

From @rcaputo

any-loop.patch
commit 0f3f478ba6fa705f85c7d09f25c68de98fff73c6
Author: Rocco Caputo <rcaputo@cpan.org>
Date:   Sun Feb 19 00:16:50 2012 -0500

    [perl #108470] Make Term::ReadLine compatible with any event loop.
    
    Refactored readline() so its implementation may be used by any event
    loop without necessarily revising applications to use a different
    event loop than they already may have implemented.

diff --git a/dist/Term-ReadLine/lib/Term/ReadLine.pm b/dist/Term-ReadLine/lib/Term/ReadLine.pm
index aead1cc..32e0824 100644
--- a/dist/Term-ReadLine/lib/Term/ReadLine.pm
+++ b/dist/Term-ReadLine/lib/Term/ReadLine.pm
@@ -111,9 +111,12 @@ additional methods:
 
 =item C<tkRunning>
 
-makes an event loop run when waiting for user input (i.e., during
-C<readline> method).  If AnyEvent is loaded, it is used, otherwise Tk
-is used.
+makes Tk's event loop run when waiting for user input (i.e., during
+the C<readline> method).
+
+Term::ReadLine supports any event loop, including unpubished ones and
+simple IO::Select loops without the need to rewrite existing code for
+any particular framework.  See IN(), print_prompt(), and get_line().
 
 =item C<ornaments>
 
@@ -128,11 +131,59 @@ standout, last two to make the input line standout.
 takes two arguments which are input filehandle and output filehandle.
 Switches to use these filehandles.
 
+=item C<print_prompt>
+
+prints a prompt and returns immediately.  readline() uses it to print
+its prompt before calling get_line().  See L</"Using Event Loops"> for
+an example of its use.
+
+=item C<get_line>
+
+gets a line of input from the terminal.  If Tk is used and tkRunning()
+has been set, then get_line() will dispatch Tk events while waiting
+for a line of input.  The full readline() API is a print_prompt() call
+followed immediately by get_input().  See L</"Using Event Loops">.
+
 =back
 
 One can check whether the currently loaded ReadLine package supports
 these methods by checking for corresponding C<Features>.
 
+=head1 Using Event Loops
+
+Term::ReadLine provides IN(), print_prompt(), and get_line() so that
+it may be used by any event loop that can watch for input on a file
+handle.  This includes most event loops including ones that haven't
+been published.
+
+Term::ReadLine's readline() method prints a prompt and returns a line
+of input got from its input filehandle:
+
+  sub readline {
+    my ($self,$prompt) = @_;
+    $self->print_prompt($prompt);
+    $self->get_line();
+  }
+
+A Tk readline function may be implemented by having Tk dispatch its
+own events between the time the prompt is printed and the line is got.
+This example function dispatches Tk events while Term::ReadLine waits
+for console input.  It can completely replace Term::ReadLine's
+existing Tk support.
+
+  sub tk_read_line {
+    my ($term, $prompt) = @_;
+    $term->print_prompt($prompt);
+
+    my $got_input;
+    Tk->fileevent($term->IN, 'readable', sub { $got_input = 1 });
+    Tk::DoOneEvent(0) until $got_input;
+
+    return $term->get_line();
+  }
+
+Other event loops are equally possible.
+
 =head1 EXPORTS
 
 None
@@ -168,25 +219,17 @@ $DB::emacs = $DB::emacs;	# To peacify -w
 our @rl_term_set;
 *rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
 
-sub PERL_UNICODE_STDIN () { 0x0001 }
+sub print_prompt {
+  my ($self, $prompt) = @_;
+  my $out = $self->[1];
+  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2]; 
+}
 
 sub ReadLine {'Term::ReadLine::Stub'}
 sub readline {
-  my $self = shift;
-  my ($in,$out,$str) = @$self;
-  my $prompt = shift;
-  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2]; 
-  $self->register_Tk 
-     if not $Term::ReadLine::registered and $Term::ReadLine::toloop;
-  #$str = scalar <$in>;
-  $str = $self->get_line;
-  utf8::upgrade($str)
-      if (${^UNICODE} & PERL_UNICODE_STDIN || defined ${^ENCODING}) &&
-         utf8::valid($str);
-  print $out $rl_term_set[3]; 
-  # bug in 5.000: chomping empty string creats length -1:
-  chomp $str if defined $str;
-  $str;
+  my ($self,$prompt) = @_;
+  $self->print_prompt($prompt);
+  $self->get_line();
 }
 sub addhistory {}
 
@@ -359,70 +402,56 @@ sub ornaments {
 
 package Term::ReadLine::Tk;
 
-# if AnyEvent is loaded, use it.
-#use Enbugger; Enbugger->stop;
-if (defined &AE::cv)
-{
-    my ($cv, $fe);
-
-    # maintain old name for backward-compatibility
-    *AE_loop = *Tk_loop = sub {
-        my $self = shift;
-        $cv = AE::cv();
-        $cv->recv();
-    };
-    
-    *register_AE = *register_Tk = sub {
-        my $self = shift;
-        $fe ||= AE::io($self->IN, 0, sub { $cv->send() });
-    };
-
-    # just because AE is loaded doesn't mean Tk isn't.
-    if (not defined &Tk::DoOneEvent)
-    {
-        # create the stub as some T::RL implementations still check
-        # this directly.  This should eventually be removed.
-        *Tk::DoOneEvent = sub {
-            die "should not happen";
-        };
-    }
-}
-else
-{
-    my ($giveup);
-
-    # technically, not AE, but maybe in the future the Tk-specific
-    # aspects will be removed.
-    *AE_loop = *Tk_loop = sub {
-        Tk::DoOneEvent(0) until $giveup;
-        $giveup = 0;
-    };
-    
-    *register_AE = *register_Tk = sub {
-        my $self = shift;
-        $Term::ReadLine::registered++
-            or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
-    };
-
-}
+# This package inserts a Tk->fileevent() before the diamond operator.
+# The Tk watcher dispatches Tk events until the filehandle returned by
+# the$term->IN() accessor becomes ready for reading.  It's assumed
+# that the diamond operator will return a line of input immediately at
+# that point.
+#
+# Any event loop can use $term-IN() and $term->readline() directly
+# without adding code for any event loop specifically to this.
+
+my ($giveup);
+
+# maybe in the future the Tk-specific aspects will be removed.
+sub Tk_loop{
+    Tk::DoOneEvent(0) until $giveup;
+    $giveup = 0;
+};
+
+sub register_Tk {
+    my $self = shift;
+    $Term::ReadLine::registered++
+        or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+};
 
 sub tkRunning {
   $Term::ReadLine::toloop = $_[1] if @_ > 1;
   $Term::ReadLine::toloop;
 }
 
-sub get_c {
-  my $self = shift;
-  $self->Tk_loop if $Term::ReadLine::toloop;
-  return getc $self->IN;
-}
+sub PERL_UNICODE_STDIN () { 0x0001 }
 
 sub get_line {
   my $self = shift;
-  $self->Tk_loop if $Term::ReadLine::toloop;
-  my $in = $self->IN;
+  my ($in,$out,$str) = @$self;
+
+  if ($Term::ReadLine::toloop) {
+    $self->register_Tk if not $Term::ReadLine::registered;
+    $self->Tk_loop;
+  }
+
   local ($/) = "\n";
-  return scalar <$in>;
+  $str = <$in>;
+
+  utf8::upgrade($str)
+      if (${^UNICODE} & PERL_UNICODE_STDIN || defined ${^ENCODING}) &&
+         utf8::valid($str);
+  print $out $rl_term_set[3]; 
+  # bug in 5.000: chomping empty string creats length -1:
+  chomp $str if defined $str;
+
+  $str;
 }
 
 1;
diff --git a/dist/Term-ReadLine/t/AE.t b/dist/Term-ReadLine/t/AE.t
deleted file mode 100644
index d0515dc..0000000
--- a/dist/Term-ReadLine/t/AE.t
+++ /dev/null
@@ -1,33 +0,0 @@
-#!perl
-
-use Test::More;
-
-eval "use AnyEvent; 1" or
-    plan skip_all => "AnyEvent is not installed.";
-
-# seeing as the entire point of this test is to test the event handler,
-# we need to mock as little as possible.  To keep things tightly controlled,
-# we'll use the Stub directly.
-BEGIN {
-    $ENV{PERL_RL} = 'Stub o=0';
-}
-plan tests => 3;
-
-# need to delay this so that AE is loaded first.
-require Term::ReadLine;
-use File::Spec;
-
-my $t = Term::ReadLine->new('AE');
-ok($t, "Created object");
-is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
-$t->tkRunning(1);
-
-my $text = 'some text';
-my $T = $text . "\n";
-my $w = AE::timer(0,1,sub { 
-pass("Event loop called");
-exit 0;
-});
-
-my $result = $t->readline('Do not press enter>');
-fail("Should not get here.");
diff --git a/dist/Term-ReadLine/t/AETk.t b/dist/Term-ReadLine/t/AETk.t
deleted file mode 100644
index 9546a8c..0000000
--- a/dist/Term-ReadLine/t/AETk.t
+++ /dev/null
@@ -1,42 +0,0 @@
-#!perl
-
-use Test::More;
-
-eval "use Tk; use AnyEvent; 1" or
-    plan skip_all => "AnyEvent and/or Tk is not installed.";
-
-# seeing as the entire point of this test is to test the event handler,
-# we need to mock as little as possible.  To keep things tightly controlled,
-# we'll use the Stub directly.
-BEGIN {
-    $ENV{PERL_RL} = 'Stub o=0';
-    # ensure AE uses Tk.
-    $ENV{PERL_ANYEVENT_MODEL} = 'Tk';
-}
-
-eval {
-    use File::Spec;
-    my $mw = MainWindow->new(); $mw->withdraw();
-    1;
-} or plan skip_all => "Tk can't start. DISPLAY not set?";
-
-plan tests => 3;
-
-# need to delay this so that AE is loaded first.
-require Term::ReadLine;
-use File::Spec;
-
-my $t = Term::ReadLine->new('AE/Tk');
-ok($t, "Created object");
-is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
-$t->tkRunning(1);
-
-my $text = 'some text';
-my $T = $text . "\n";
-my $w = AE::timer(0,1,sub { 
-pass("Event loop called");
-exit 0;
-});
-
-my $result = $t->readline('Do not �press enter>');
-fail("Should not get here.");
diff --git a/dist/Term-ReadLine/t/TkExternal.t b/dist/Term-ReadLine/t/TkExternal.t
new file mode 100644
index 0000000..7c4cf69
--- /dev/null
+++ b/dist/Term-ReadLine/t/TkExternal.t
@@ -0,0 +1,59 @@
+#!perl
+
+use Test::More;
+
+eval "use Tk; 1" or
+    plan skip_all => "Tk is not installed.";
+
+# seeing as the entire point of this test is to test the event handler,
+# we need to mock as little as possible.  To keep things tightly controlled,
+# we'll use the Stub directly.
+BEGIN {
+    $ENV{PERL_RL} = 'Stub o=0';
+}
+
+my $mw;
+eval {
+    use File::Spec;
+    $mw = MainWindow->new(); $mw->withdraw();
+    1;
+} or plan skip_all => "Tk can't start. DISPLAY not set?";
+
+# need to delay this so that Tk is loaded first.
+require Term::ReadLine;
+
+plan tests => 3;
+
+my $t = Term::ReadLine->new('Tk');
+ok($t, "Created object");
+is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
+
+# This test will dispatch Tk events externally.
+$t->tkRunning(0);
+
+my $text = 'some text';
+my $T = $text . "\n";
+
+my $w = Tk::after($mw,0,
+                  sub {
+                      pass("Event loop called");
+                      exit 0;
+                  });
+
+my $result = tk_readline($t, 'Do not press enter>');
+fail("Should not get here.");
+
+# A Tk-dispatching readline that doesn't require Tk (or any other
+# event loop) support to be hard-coded into Term::ReadLine.
+
+sub tk_readline {
+  my ($term, $prompt) = @_;
+
+  $term->print_prompt($prompt);
+
+  my $got_input;
+  Tk->fileevent($term->IN, 'readable', sub { $got_input = 1 });
+  Tk::DoOneEvent(0) until $got_input;
+
+  return $term->get_line();
+}

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

From @cpansprout

On Sat Feb 18 21​:33​:01 2012, rcaputo wrote​:

On Mon Feb 06 05​:15​:27 2012, nicholas wrote​:

On Wed Feb 01 10​:58​:27 2012, mst@​shadowcat.co.uk wrote​:

On Wed, Feb 01, 2012 at 09​:33​:02AM +0000, Paul LeoNerd Evans wrote​:

On Tue, Jan 31, 2012 at 09​:34​:00AM -0800, Father Chrysostomos via RT
wrote​:

OK, then let me repeat my two questions​: Does anyone want to
write a
patch for that? Should I revert Darin McBride’s patch
(b60dd40)?

Unless there's any reason to do it a different way, I'd vote for​:

"Tell us where to look to get a pre-dmcbride-patch version, let
somebody
provide a new patch against that, and once that's considered good
revert
his patch and introduce the new one."

Agree, because what we have now is tested, and better than what we had
before.

Challenge accepted. See attachment. Patched directly against blead.

I would very much like to see this in 5.15.8, but unfortunately I am
extremely busy and doubt I will have the time. Would any other
committer be able to take care of this?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

From @rjbs

Thanks, applied as fc013e9 with some subsequent manifest fixups.

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

From [Unknown Contact. See original ticket]

Thanks, applied as fc013e9 with some subsequent manifest fixups.

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

@rjbs - Status changed from 'open' to 'resolved'

@p5pRT
Copy link
Author

p5pRT commented Feb 19, 2012

From @Corion

Am 19.02.2012 07​:47, schrieb Father Chrysostomos via RT​:

On Sat Feb 18 21​:33​:01 2012, rcaputo wrote​:

On Mon Feb 06 05​:15​:27 2012, nicholas wrote​:

On Wed Feb 01 10​:58​:27 2012, mst@​shadowcat.co.uk wrote​:

On Wed, Feb 01, 2012 at 09​:33​:02AM +0000, Paul LeoNerd Evans wrote​:

On Tue, Jan 31, 2012 at 09​:34​:00AM -0800, Father Chrysostomos via RT
wrote​:

OK, then let me repeat my two questions​: Does anyone want to
write a
patch for that? Should I revert Darin McBride’s patch
(b60dd40)?

Unless there's any reason to do it a different way, I'd vote for​:

"Tell us where to look to get a pre-dmcbride-patch version, let
somebody
provide a new patch against that, and once that's considered good
revert
his patch and introduce the new one."

Agree, because what we have now is tested, and better than what we had
before.

Challenge accepted. See attachment. Patched directly against blead.

I would very much like to see this in 5.15.8, but unfortunately I am
extremely busy and doubt I will have the time. Would any other
committer be able to take care of this?

Thanks, applied (with small whitespace editing) as

fc013e9

Unfortunately, I didn't apply the patch through `git am` but through
`git apply`, so the original attribution to Rocco got lost.

-max

@p5pRT
Copy link
Author

p5pRT commented Mar 5, 2012

From darin.mcbride@shaw.ca

On Sunday February 19 2012 7​:10​:08 AM you wrote​:

Thanks, applied (with small whitespace editing) as

fc013e9

Unfortunately, I didn't apply the patch through `git am` but through
`git apply`, so the original attribution to Rocco got lost.

-max

I'm wondering if anyone actually tested this with the example programs I
showed. Because 5.15.8 doesn't work at all with this. Note that I have
Term​::ReadLine​::Perl installed with 5.15.8.

#!/usr/bin/perl

use strict;
use warnings;

use EV;
use AnyEvent;
use Term​::ReadLine;

my $esc;
BEGIN { $esc = "\x1b[";
  print "${esc}2J${esc}3H";
}

my $t = 0;
my $w = AE​::timer (0,1,sub {print STDERR "${esc}s${esc}1H$t s ${esc}u";++$t});
my $term = Term​::ReadLine->new('...');

sub tk_read_line {
  my ($term, $prompt) = @​_;
  $term->print_prompt($prompt);
 
  my $got_input;
  my $cv = AE​::cv;
  my $w = AE​::io($term->IN(), 0, $cv);
  $cv->recv();
 
  return $term->get_line();
}

my $x = tk_read_line($term,'> ');
print "Got​: [$x] in $t s\n";
__END__

This doesn't show the prompt. The text I type is in normal font (T​::RL​::P
will display it in bold normally). Then everything shows up as expected after
I hit enter. Completion won't work, either.

That's because you're bypassing the mechanisms that the underlying
implementations use to base everything off. Term​::ReadLine​::Perl implements
its own readline function that did not get changed here, so if I try to do my
own print_prompt and get_line, none of the prep-work is done. You'd have to
go and make similar invasive changes to all the implementations (​::Perl and
:​:Gnu at least).

Instead, providing a way to override the get_line and get_c functions (it must
be both!) is about the only way this will work. And that's what my patches
did, albeit for only AnyEvent.

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2012

@rjbs - Status changed from 'resolved' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2012

From darin.mcbride@shaw.ca

One more attempt. This is tested against :​:Perl and :​:Gnu and :​:Stub, more
extensively than I know how to automate in .t files. I've even tested it under
Coro, which was my original goal.

This is against blead. Thanks, Corion, for the help in IRC getting it as a
patch in git (I'm a git newb).

The usage is entirely different than Rocco's patch because it didn't work with
:​:Perl or :​:Gnu, both of which override the readline method. Both of them,
however, call Tk_loop (one as a method, one not). And this is where we can
insert something that is useful everywhere.

After this actually gets accepted and the dust settles, I will likely open
bugs for both :​:Perl and :​:Gnu to stop checking for defined &Tk​::DoOneEvent -
it's not needed.

@p5pRT
Copy link
Author

p5pRT commented Mar 8, 2012

From darin.mcbride@shaw.ca

ae.patch
diff --git a/dist/Term-ReadLine/lib/Term/ReadLine.pm b/dist/Term-ReadLine/lib/Term/ReadLine.pm
index 7262596..3cf4bd4 100644
--- a/dist/Term-ReadLine/lib/Term/ReadLine.pm
+++ b/dist/Term-ReadLine/lib/Term/ReadLine.pm
@@ -111,12 +111,38 @@ additional methods:
 
 =item C<tkRunning>
 
-makes Tk's event loop run when waiting for user input (i.e., during
-the C<readline> method).
+makes Tk event loop run when waiting for user input (i.e., during
+C<readline> method).
 
-Term::ReadLine supports any event loop, including unpubished ones and
-simple IO::Select loops without the need to rewrite existing code for
-any particular framework.  See IN(), print_prompt(), and get_line().
+=item C<event_loop>
+
+Registers call-backs to wait for user input (i.e., during C<readline>
+method).  This supercedes tkRunning.
+
+The first call-back registered is the call back for waiting.  It is
+expected that the callback will call the current event loop until
+there is something waiting to get on the input filehandle.
+
+The second call-back registered is the call back for registration.  The
+input filehandle (often STDIN, but not necessarily) will be passed in.
+
+For example, with AnyEvent:
+
+    my ($cv, $fe);
+    $term->event_loop(sub {
+        $cv = AE::cv();
+        $cv->recv();
+    }, sub {
+        my $fh = shift;
+        $fe ||= AE::io($fh, 0, sub { $cv->send() });
+    });
+
+Note that $fe must not go out of scope while $term is still in scope,
+or the io watcher will terminate.  Similar concerns may exist for other
+event loops.
+
+The second call-back is optional if you register your callback prior to
+the call to $term-E<gt>readline.
 
 =item C<ornaments>
 
@@ -131,59 +157,11 @@ standout, last two to make the input line standout.
 takes two arguments which are input filehandle and output filehandle.
 Switches to use these filehandles.
 
-=item C<print_prompt>
-
-prints a prompt and returns immediately.  readline() uses it to print
-its prompt before calling get_line().  See L</"Using Event Loops"> for
-an example of its use.
-
-=item C<get_line>
-
-gets a line of input from the terminal.  If Tk is used and tkRunning()
-has been set, then get_line() will dispatch Tk events while waiting
-for a line of input.  The full readline() API is a print_prompt() call
-followed immediately by get_input().  See L</"Using Event Loops">.
-
 =back
 
 One can check whether the currently loaded ReadLine package supports
 these methods by checking for corresponding C<Features>.
 
-=head1 Using Event Loops
-
-Term::ReadLine provides IN(), print_prompt(), and get_line() so that
-it may be used by any event loop that can watch for input on a file
-handle.  This includes most event loops including ones that haven't
-been published.
-
-Term::ReadLine's readline() method prints a prompt and returns a line
-of input got from its input filehandle:
-
-  sub readline {
-    my ($self,$prompt) = @_;
-    $self->print_prompt($prompt);
-    $self->get_line();
-  }
-
-A Tk readline function may be implemented by having Tk dispatch its
-own events between the time the prompt is printed and the line is got.
-This example function dispatches Tk events while Term::ReadLine waits
-for console input.  It can completely replace Term::ReadLine's
-existing Tk support.
-
-  sub tk_read_line {
-    my ($term, $prompt) = @_;
-    $term->print_prompt($prompt);
-
-    my $got_input;
-    Tk->fileevent($term->IN, 'readable', sub { $got_input = 1 });
-    Tk::DoOneEvent(0) until $got_input;
-
-    return $term->get_line();
-  }
-
-Other event loops are equally possible.
-
 =head1 EXPORTS
 
 None
@@ -219,17 +197,25 @@ $DB::emacs = $DB::emacs;	# To peacify -w
 our @rl_term_set;
 *rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
 
-sub print_prompt {
-  my ($self, $prompt) = @_;
-  my $out = $self->[1];
-  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
-}
+sub PERL_UNICODE_STDIN () { 0x0001 }
 
 sub ReadLine {'Term::ReadLine::Stub'}
 sub readline {
-  my ($self,$prompt) = @_;
-  $self->print_prompt($prompt);
-  $self->get_line();
+  my $self = shift;
+  my ($in,$out,$str) = @$self;
+  my $prompt = shift;
+  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2]; 
+  $self->register_Tk 
+     if not $Term::ReadLine::registered and $Term::ReadLine::toloop;
+  #$str = scalar <$in>;
+  $str = $self->get_line;
+  utf8::upgrade($str)
+      if (${^UNICODE} & PERL_UNICODE_STDIN || defined ${^ENCODING}) &&
+         utf8::valid($str);
+  print $out $rl_term_set[3]; 
+  # bug in 5.000: chomping empty string creats length -1:
+  chomp $str if defined $str;
+  $str;
 }
 sub addhistory {}
 
@@ -407,22 +393,35 @@ package Term::ReadLine::Tk;
 # the$term->IN() accessor becomes ready for reading.  It's assumed
 # that the diamond operator will return a line of input immediately at
 # that point.
-#
-# Any event loop can use $term-IN() and $term->readline() directly
-# without adding code for any event loop specifically to this.
 
 my ($giveup);
 
 # maybe in the future the Tk-specific aspects will be removed.
 sub Tk_loop{
-    Tk::DoOneEvent(0) until $giveup;
-    $giveup = 0;
+    if (ref $Term::ReadLine::toloop)
+    {
+        $Term::ReadLine::toloop->[0]->();
+    }
+    else
+    {
+        Tk::DoOneEvent(0) until $giveup;
+        $giveup = 0;
+    }
 };
 
 sub register_Tk {
     my $self = shift;
-    $Term::ReadLine::registered++
-        or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+    unless ($Term::ReadLine::registered++)
+    {
+        if (ref $Term::ReadLine::toloop)
+        {
+            $Term::ReadLine::toloop->[1]->($self->IN) if $Term::ReadLine::toloop->[1];
+        }
+        else
+        {
+            Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+        }
+    }
 };
 
 sub tkRunning {
@@ -430,6 +429,25 @@ sub tkRunning {
   $Term::ReadLine::toloop;
 }
 
+sub event_loop {
+    shift;
+
+    # T::RL::Gnu and T::RL::Perl check that this exists, if not,
+    # it doesn't call the loop.  Those modules will need to be
+    # fixed before this can be removed.
+    if (not defined &Tk::DoOneEvent)
+    {
+        *Tk::DoOneEvent = sub {
+            die "what?"; # this shouldn't be called.
+        }
+    }
+
+    # store the callback in toloop, again so that other modules will
+    # recognise it and call us for the loop.
+    $Term::ReadLine::toloop = [ @_ ] if @_ > 1;
+    $Term::ReadLine::toloop;
+}
+
 sub PERL_UNICODE_STDIN () { 0x0001 }
 
 sub get_line {
diff --git a/dist/Term-ReadLine/t/AE.t b/dist/Term-ReadLine/t/AE.t
new file mode 100644
index 0000000..8fccecb
--- /dev/null
+++ b/dist/Term-ReadLine/t/AE.t
@@ -0,0 +1,43 @@
+#!perl
+
+use Test::More;
+
+eval "use AnyEvent; 1" or
+    plan skip_all => "AnyEvent is not installed.";
+
+# seeing as the entire point of this test is to test the event handler,
+# we need to mock as little as possible.  To keep things tightly controlled,
+# we'll use the Stub directly.
+BEGIN {
+    $ENV{PERL_RL} = 'Stub o=0';
+}
+plan tests => 3;
+
+# need to delay this so that AE is loaded first.
+require Term::ReadLine;
+use File::Spec;
+
+my $t = Term::ReadLine->new('AE');
+ok($t, "Created object");
+is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
+
+my ($cv, $fe);
+$t->event_loop(
+               sub {
+                   $cv = AE::cv();
+                   $cv->recv();
+               }, sub {
+                   my $fh = shift;
+                   $fe ||= AE::io($fh, 0, sub { $cv->send() });
+               }
+              );
+
+my $text = 'some text';
+my $T = $text . "\n";
+my $w = AE::timer(0,1,sub { 
+pass("Event loop called");
+exit 0;
+});
+
+my $result = $t->readline('Do not press enter>');
+fail("Should not get here.");
diff --git a/dist/Term-ReadLine/t/AETk.t b/dist/Term-ReadLine/t/AETk.t
new file mode 100644
index 0000000..80bab63
--- /dev/null
+++ b/dist/Term-ReadLine/t/AETk.t
@@ -0,0 +1,52 @@
+#!perl
+
+use Test::More;
+
+eval "use Tk; use AnyEvent; 1" or
+    plan skip_all => "AnyEvent and/or Tk is not installed.";
+
+# seeing as the entire point of this test is to test the event handler,
+# we need to mock as little as possible.  To keep things tightly controlled,
+# we'll use the Stub directly.
+BEGIN {
+    $ENV{PERL_RL} = 'Stub o=0';
+    # ensure AE uses Tk.
+    $ENV{PERL_ANYEVENT_MODEL} = 'Tk';
+}
+
+eval {
+    use File::Spec;
+    my $mw = MainWindow->new(); $mw->withdraw();
+    1;
+} or plan skip_all => "Tk can't start. DISPLAY not set?";
+
+plan tests => 3;
+
+# need to delay this so that AE is loaded first.
+require Term::ReadLine;
+use File::Spec;
+
+my $t = Term::ReadLine->new('AE/Tk');
+ok($t, "Created object");
+is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
+my ($cv, $fe);
+$t->event_loop(
+               sub {
+                   $cv = AE::cv();
+                   $cv->recv();
+               }, sub {
+                   my $fh = shift;
+                   $fe ||= AE::io($fh, 0, sub { $cv->send() });
+               }
+              );
+
+
+my $text = 'some text';
+my $T = $text . "\n";
+my $w = AE::timer(0,1,sub { 
+pass("Event loop called");
+exit 0;
+});
+
+my $result = $t->readline('Do not �press enter>');
+fail("Should not get here.");
diff --git a/dist/Term-ReadLine/t/TkExternal.t b/dist/Term-ReadLine/t/TkExternal.t
deleted file mode 100644
index 7c4cf69..0000000
--- a/dist/Term-ReadLine/t/TkExternal.t
+++ /dev/null
@@ -1,59 +0,0 @@
-#!perl
-
-use Test::More;
-
-eval "use Tk; 1" or
-    plan skip_all => "Tk is not installed.";
-
-# seeing as the entire point of this test is to test the event handler,
-# we need to mock as little as possible.  To keep things tightly controlled,
-# we'll use the Stub directly.
-BEGIN {
-    $ENV{PERL_RL} = 'Stub o=0';
-}
-
-my $mw;
-eval {
-    use File::Spec;
-    $mw = MainWindow->new(); $mw->withdraw();
-    1;
-} or plan skip_all => "Tk can't start. DISPLAY not set?";
-
-# need to delay this so that Tk is loaded first.
-require Term::ReadLine;
-
-plan tests => 3;
-
-my $t = Term::ReadLine->new('Tk');
-ok($t, "Created object");
-is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
-
-# This test will dispatch Tk events externally.
-$t->tkRunning(0);
-
-my $text = 'some text';
-my $T = $text . "\n";
-
-my $w = Tk::after($mw,0,
-                  sub {
-                      pass("Event loop called");
-                      exit 0;
-                  });
-
-my $result = tk_readline($t, 'Do not press enter>');
-fail("Should not get here.");
-
-# A Tk-dispatching readline that doesn't require Tk (or any other
-# event loop) support to be hard-coded into Term::ReadLine.
-
-sub tk_readline {
-  my ($term, $prompt) = @_;
-
-  $term->print_prompt($prompt);
-
-  my $got_input;
-  Tk->fileevent($term->IN, 'readable', sub { $got_input = 1 });
-  Tk::DoOneEvent(0) until $got_input;
-
-  return $term->get_line();
-}

@p5pRT
Copy link
Author

p5pRT commented Mar 10, 2012

From @dmcbride

I hope this is the last one. This is still a patch against blead. It
incorporates dngor's proposed patch in #p5p. It also includes extra
documentation for that proposal that wasn't given in dngor's patch, as
well as modification for the snippet in the perldoc for how to use this with
AnyEvent. It also includes documentation on deregistration, should that
be needed by anyone using this with another event loop.

I plan on publishing a separate CPAN distribution with no (or little) real
code, but with examples of how to use this with various loops. I don't
think these really belong in core, but would still be handy for anyone
looking to integrate T​::RL into their event-based application. First, of
course, the patch needs to be applied :-)

@p5pRT
Copy link
Author

p5pRT commented Mar 10, 2012

From @dmcbride

full.patch
diff --git a/dist/Term-ReadLine/lib/Term/ReadLine.pm b/dist/Term-ReadLine/lib/Term/ReadLine.pm
index 7262596..cb463a7 100644
--- a/dist/Term-ReadLine/lib/Term/ReadLine.pm
+++ b/dist/Term-ReadLine/lib/Term/ReadLine.pm
@@ -111,12 +111,48 @@ additional methods:
 
 =item C<tkRunning>
 
-makes Tk's event loop run when waiting for user input (i.e., during
-the C<readline> method).
+makes Tk event loop run when waiting for user input (i.e., during
+C<readline> method).
 
-Term::ReadLine supports any event loop, including unpubished ones and
-simple IO::Select loops without the need to rewrite existing code for
-any particular framework.  See IN(), print_prompt(), and get_line().
+=item C<event_loop>
+
+Registers call-backs to wait for user input (i.e., during C<readline>
+method).  This supercedes tkRunning.
+
+The first call-back registered is the call back for waiting.  It is
+expected that the callback will call the current event loop until
+there is something waiting to get on the input filehandle.  The parameter
+passed in is the return value of the second call back.
+
+The second call-back registered is the call back for registration.  The
+input filehandle (often STDIN, but not necessarily) will be passed in.
+
+For example, with AnyEvent:
+
+    $term->event_loop(sub {
+        my $data = shift;
+        $data->[1] = AE::cv();
+        $data->[1]->recv();
+    }, sub {
+        my $fh = shift;
+        my $data = [];
+        $data->[0] = AE::io($fh, 0, sub { $data->[1]->send() });
+        $data;
+    });
+
+The second call-back is optional if the call back is registered prior to
+the call to $term-E<gt>readline.
+
+Deregistration is done in this case by calling event_loop with C<undef>
+as its parameter:
+
+    $term->event_loop(undef);
+
+This will cause the data array ref to be removed, allowing normal garbage
+collection to clean it up.  With AnyEvent, that will cause $data->[0] to
+be cleaned up, and AnyEvent will automatically cancel the watcher at that
+time.  If another loop requires more than that to clean up a file watcher,
+that will be up to the caller to handle.
 
 =item C<ornaments>
 
@@ -131,59 +167,11 @@ standout, last two to make the input line standout.
 takes two arguments which are input filehandle and output filehandle.
 Switches to use these filehandles.
 
-=item C<print_prompt>
-
-prints a prompt and returns immediately.  readline() uses it to print
-its prompt before calling get_line().  See L</"Using Event Loops"> for
-an example of its use.
-
-=item C<get_line>
-
-gets a line of input from the terminal.  If Tk is used and tkRunning()
-has been set, then get_line() will dispatch Tk events while waiting
-for a line of input.  The full readline() API is a print_prompt() call
-followed immediately by get_input().  See L</"Using Event Loops">.
-
 =back
 
 One can check whether the currently loaded ReadLine package supports
 these methods by checking for corresponding C<Features>.
 
-=head1 Using Event Loops
-
-Term::ReadLine provides IN(), print_prompt(), and get_line() so that
-it may be used by any event loop that can watch for input on a file
-handle.  This includes most event loops including ones that haven't
-been published.
-
-Term::ReadLine's readline() method prints a prompt and returns a line
-of input got from its input filehandle:
-
-  sub readline {
-    my ($self,$prompt) = @_;
-    $self->print_prompt($prompt);
-    $self->get_line();
-  }
-
-A Tk readline function may be implemented by having Tk dispatch its
-own events between the time the prompt is printed and the line is got.
-This example function dispatches Tk events while Term::ReadLine waits
-for console input.  It can completely replace Term::ReadLine's
-existing Tk support.
-
-  sub tk_read_line {
-    my ($term, $prompt) = @_;
-    $term->print_prompt($prompt);
-
-    my $got_input;
-    Tk->fileevent($term->IN, 'readable', sub { $got_input = 1 });
-    Tk::DoOneEvent(0) until $got_input;
-
-    return $term->get_line();
-  }
-
-Other event loops are equally possible.
-
 =head1 EXPORTS
 
 None
@@ -219,17 +207,25 @@ $DB::emacs = $DB::emacs;	# To peacify -w
 our @rl_term_set;
 *rl_term_set = \@Term::ReadLine::TermCap::rl_term_set;
 
-sub print_prompt {
-  my ($self, $prompt) = @_;
-  my $out = $self->[1];
-  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2];
-}
+sub PERL_UNICODE_STDIN () { 0x0001 }
 
 sub ReadLine {'Term::ReadLine::Stub'}
 sub readline {
-  my ($self,$prompt) = @_;
-  $self->print_prompt($prompt);
-  $self->get_line();
+  my $self = shift;
+  my ($in,$out,$str) = @$self;
+  my $prompt = shift;
+  print $out $rl_term_set[0], $prompt, $rl_term_set[1], $rl_term_set[2]; 
+  $self->register_Tk 
+     if not $Term::ReadLine::registered and $Term::ReadLine::toloop;
+  #$str = scalar <$in>;
+  $str = $self->get_line;
+  utf8::upgrade($str)
+      if (${^UNICODE} & PERL_UNICODE_STDIN || defined ${^ENCODING}) &&
+         utf8::valid($str);
+  print $out $rl_term_set[3]; 
+  # bug in 5.000: chomping empty string creats length -1:
+  chomp $str if defined $str;
+  $str;
 }
 sub addhistory {}
 
@@ -407,22 +403,35 @@ package Term::ReadLine::Tk;
 # the$term->IN() accessor becomes ready for reading.  It's assumed
 # that the diamond operator will return a line of input immediately at
 # that point.
-#
-# Any event loop can use $term-IN() and $term->readline() directly
-# without adding code for any event loop specifically to this.
 
 my ($giveup);
 
 # maybe in the future the Tk-specific aspects will be removed.
 sub Tk_loop{
-    Tk::DoOneEvent(0) until $giveup;
-    $giveup = 0;
+    if (ref $Term::ReadLine::toloop)
+    {
+        $Term::ReadLine::toloop->[0]->($Term::ReadLine::toloop->[2]);
+    }
+    else
+    {
+        Tk::DoOneEvent(0) until $giveup;
+        $giveup = 0;
+    }
 };
 
 sub register_Tk {
     my $self = shift;
-    $Term::ReadLine::registered++
-        or Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+    unless ($Term::ReadLine::registered++)
+    {
+        if (ref $Term::ReadLine::toloop)
+        {
+            $Term::ReadLine::toloop->[2] = $Term::ReadLine::toloop->[1]->($self->IN) if $Term::ReadLine::toloop->[1];
+        }
+        else
+        {
+            Tk->fileevent($self->IN,'readable',sub { $giveup = 1});
+        }
+    }
 };
 
 sub tkRunning {
@@ -430,6 +439,25 @@ sub tkRunning {
   $Term::ReadLine::toloop;
 }
 
+sub event_loop {
+    shift;
+
+    # T::RL::Gnu and T::RL::Perl check that this exists, if not,
+    # it doesn't call the loop.  Those modules will need to be
+    # fixed before this can be removed.
+    if (not defined &Tk::DoOneEvent)
+    {
+        *Tk::DoOneEvent = sub {
+            die "what?"; # this shouldn't be called.
+        }
+    }
+
+    # store the callback in toloop, again so that other modules will
+    # recognise it and call us for the loop.
+    $Term::ReadLine::toloop = [ @_ ] if @_ > 1;
+    $Term::ReadLine::toloop;
+}
+
 sub PERL_UNICODE_STDIN () { 0x0001 }
 
 sub get_line {
diff --git a/dist/Term-ReadLine/t/AE.t b/dist/Term-ReadLine/t/AE.t
new file mode 100644
index 0000000..8fccecb
--- /dev/null
+++ b/dist/Term-ReadLine/t/AE.t
@@ -0,0 +1,43 @@
+#!perl
+
+use Test::More;
+
+eval "use AnyEvent; 1" or
+    plan skip_all => "AnyEvent is not installed.";
+
+# seeing as the entire point of this test is to test the event handler,
+# we need to mock as little as possible.  To keep things tightly controlled,
+# we'll use the Stub directly.
+BEGIN {
+    $ENV{PERL_RL} = 'Stub o=0';
+}
+plan tests => 3;
+
+# need to delay this so that AE is loaded first.
+require Term::ReadLine;
+use File::Spec;
+
+my $t = Term::ReadLine->new('AE');
+ok($t, "Created object");
+is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
+
+my ($cv, $fe);
+$t->event_loop(
+               sub {
+                   $cv = AE::cv();
+                   $cv->recv();
+               }, sub {
+                   my $fh = shift;
+                   $fe ||= AE::io($fh, 0, sub { $cv->send() });
+               }
+              );
+
+my $text = 'some text';
+my $T = $text . "\n";
+my $w = AE::timer(0,1,sub { 
+pass("Event loop called");
+exit 0;
+});
+
+my $result = $t->readline('Do not press enter>');
+fail("Should not get here.");
diff --git a/dist/Term-ReadLine/t/AETk.t b/dist/Term-ReadLine/t/AETk.t
new file mode 100644
index 0000000..80bab63
--- /dev/null
+++ b/dist/Term-ReadLine/t/AETk.t
@@ -0,0 +1,52 @@
+#!perl
+
+use Test::More;
+
+eval "use Tk; use AnyEvent; 1" or
+    plan skip_all => "AnyEvent and/or Tk is not installed.";
+
+# seeing as the entire point of this test is to test the event handler,
+# we need to mock as little as possible.  To keep things tightly controlled,
+# we'll use the Stub directly.
+BEGIN {
+    $ENV{PERL_RL} = 'Stub o=0';
+    # ensure AE uses Tk.
+    $ENV{PERL_ANYEVENT_MODEL} = 'Tk';
+}
+
+eval {
+    use File::Spec;
+    my $mw = MainWindow->new(); $mw->withdraw();
+    1;
+} or plan skip_all => "Tk can't start. DISPLAY not set?";
+
+plan tests => 3;
+
+# need to delay this so that AE is loaded first.
+require Term::ReadLine;
+use File::Spec;
+
+my $t = Term::ReadLine->new('AE/Tk');
+ok($t, "Created object");
+is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
+my ($cv, $fe);
+$t->event_loop(
+               sub {
+                   $cv = AE::cv();
+                   $cv->recv();
+               }, sub {
+                   my $fh = shift;
+                   $fe ||= AE::io($fh, 0, sub { $cv->send() });
+               }
+              );
+
+
+my $text = 'some text';
+my $T = $text . "\n";
+my $w = AE::timer(0,1,sub { 
+pass("Event loop called");
+exit 0;
+});
+
+my $result = $t->readline('Do not �press enter>');
+fail("Should not get here.");
diff --git a/dist/Term-ReadLine/t/TkExternal.t b/dist/Term-ReadLine/t/TkExternal.t
deleted file mode 100644
index 7c4cf69..0000000
--- a/dist/Term-ReadLine/t/TkExternal.t
+++ /dev/null
@@ -1,59 +0,0 @@
-#!perl
-
-use Test::More;
-
-eval "use Tk; 1" or
-    plan skip_all => "Tk is not installed.";
-
-# seeing as the entire point of this test is to test the event handler,
-# we need to mock as little as possible.  To keep things tightly controlled,
-# we'll use the Stub directly.
-BEGIN {
-    $ENV{PERL_RL} = 'Stub o=0';
-}
-
-my $mw;
-eval {
-    use File::Spec;
-    $mw = MainWindow->new(); $mw->withdraw();
-    1;
-} or plan skip_all => "Tk can't start. DISPLAY not set?";
-
-# need to delay this so that Tk is loaded first.
-require Term::ReadLine;
-
-plan tests => 3;
-
-my $t = Term::ReadLine->new('Tk');
-ok($t, "Created object");
-is($t->ReadLine, 'Term::ReadLine::Stub', 'Correct type');
-
-# This test will dispatch Tk events externally.
-$t->tkRunning(0);
-
-my $text = 'some text';
-my $T = $text . "\n";
-
-my $w = Tk::after($mw,0,
-                  sub {
-                      pass("Event loop called");
-                      exit 0;
-                  });
-
-my $result = tk_readline($t, 'Do not press enter>');
-fail("Should not get here.");
-
-# A Tk-dispatching readline that doesn't require Tk (or any other
-# event loop) support to be hard-coded into Term::ReadLine.
-
-sub tk_readline {
-  my ($term, $prompt) = @_;
-
-  $term->print_prompt($prompt);
-
-  my $got_input;
-  Tk->fileevent($term->IN, 'readable', sub { $got_input = 1 });
-  Tk::DoOneEvent(0) until $got_input;
-
-  return $term->get_line();
-}

@p5pRT
Copy link
Author

p5pRT commented Mar 10, 2012

From @rjbs

This is now in smoke-me/rjbs/readline-loop before merging.

@p5pRT
Copy link
Author

p5pRT commented Mar 16, 2012

From @rjbs

This has been smoked, bugfixed, and merged, and everyone involved seems happy. Darin is
working on a collection of examples for using this feature with other loops, and it seems to be
going well. Unblocked!

@p5pRT
Copy link
Author

p5pRT commented Mar 16, 2012

From [Unknown Contact. See original ticket]

This has been smoked, bugfixed, and merged, and everyone involved seems happy. Darin is
working on a collection of examples for using this feature with other loops, and it seems to be
going well. Unblocked!

@p5pRT
Copy link
Author

p5pRT commented Mar 16, 2012

@rjbs - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant