Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

about Term::ReadLine and it's imported function

by Discipulus (Canon)
on Nov 24, 2014 at 13:10 UTC ( [id://1108255]=perlquestion: print w/replies, xml ) Need Help??

Discipulus has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,
i used readline::rl_basic_commands as only way to have autocompletion working in win32. if i remember correctly i found the mention here.

I had used this sub in some programs based on various Strawberry distros without any problem.

Now i have a new program i would like to run on Win32 as in Linux and it uses only core modules.
I developped on my strawberry Perl but when tried on the Linux box it complains about that missing sub:
Undefined subroutine &readline::rl_basic_commands called at...
So i changed the call in something like:
if (exists &readline::rl_basic_commands){&readline::rl_basic_commands( +keys %cmds);}

Now on Linux works (without autocompletion), but using that syntax on win32 made the first time intialization of available commands not working. The following working example shows my problem:
#!perl use strict; use warnings; use Term::ReadLine; $ENV{TERM}=undef; my $term = Term::ReadLine->new('xxx'); my %cmds = (a=>1,b=>2); # THIS WORKS &readline::rl_basic_commands(keys %cmds); # THE FOLLOWING CHECK DOES NOT WORK if (exists &readline::rl_basic_commands){print "BEFORE WHILE EXISTS +\n"; &readline::rl_basic_commands(keys %cmds);} while ( defined ( $_ = $term->readline( '>') ) ) { print "$_\n"; } continue{ # THIS CHECK WORKS INDEED! if (exists &readline::rl_basic_commands){print "IN CONTINUE EXISTS\ +n"; &readline::rl_basic_commands(keys %cmds);} }

Where and when the sub is defined?
There is safe way to deal with it?
There is a way have it working on both Linux and Win32, even in the sad case without autocompletion?

Thanks for the attention.
L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: about Term::ReadLine and it's imported function
by LanX (Saint) on Nov 24, 2014 at 13:31 UTC
    rl_basic_commands seems to be a Term::ReadLine::Perl or Term::ReadLine::Perl5 only thing.

    You'll need to install one of them and according to Term::ReadLine doku's last paragraph set $ENV{PERL_RL}="Perl" prior² to use Term::ReadLine¹

    As a side note: I had no problems yet just using Term::ReadLine::Gnu with tab completion.

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

    ¹) Term::ReadLine is kind of a wrapper module proxying to other Term::ReadLine:* modules

    edit
    s/Term::ReadLine::Perl/Term::ReadLine::Perl5/ ³

    update

    ²) since use happens very early in compilation you'll most likely need to set the ENV within a BEGIN block.

    (That's for sure a silly interface, Term::ReadLine should have a config option for the importer.)

    update
    ³) both should work, but looking thru this Perl4 code with ' as package separator is aching my eyes...

    update

    looking into the source revealed the following line as fall back if PERL_RL is not found in %ENV

      eval "use Term::ReadLine::Gnu; 1" or eval "use Term::ReadLine::Perl; 1";

    This means Term::ReadLine::Perl is only used by default if Term::ReadLine::Gnu wasn't found! Since you are using a T::RL::Perl* only feature you MUST set the env.

    Maybe check with print $term->ReadLine; which module was loaded

      Thanks LanX
      i'm still in the fog..
      CPAN Terminal> l Term::ReadLine .. Version Installed 1.14 Version on CPAN 1.14 CPAN Terminal> l Term::ReadLine::Perl .. Version Installed 1.0303 Version on CPAN 1.0303 #anyway using Term::ReadLine::Perl directly cause some error: io@COMP:C>perl -MTerm::ReadLine::Perl -e 0 Can't locate object method "Features" via package "Term::ReadLine::Stu +b" at C:/ulisse/strawberry/perl/lib/Term/ReadLine Perl.pm line 101. Compilation failed in require. BEGIN failed--compilation aborted.
      Eventually, modifying the code to use the ENV var seems to produce the same results:
      #!perl use strict; use warnings; use Term::ReadLine; BEGIN{$ENV{PERL_RL}="Perl"} print "\$ENV{PERL_RL} $ENV{PERL_RL}\n"; $ENV{TERM}=undef; my $term = Term::ReadLine->new('xxx'); print $term->ReadLine; my %cmds = (a=>1,b=>2); # THIS WORKS &readline::rl_basic_commands(keys %cmds); # THE FOLLOWING CHECK DOES NOT WORK if (exists &readline::rl_basic_commands){print "BEFORE WHILE EXISTS +\n"; &readline::rl_basic_commands(keys %cmds);} while ( defined ( $_ = $term->readline( '>') ) ) { print "$_\n"; } continue{ # THIS CHECK WORKS INDEED! if (exists &readline::rl_basic_commands){print "IN CONTINUE EXISTS\ +n"; &readline::rl_basic_commands(keys %cmds);} } ###OUTPUT $ENV{PERL_RL} Perl > ###if you press TAB the current dir content is dumped: this is the def +ault behaviour if ###you does not provide autocompletion list ###but after, if you press ENTER: > Term::ReadLine::Perl IN CONTINUE EXISTS > a b >
      That said, it seems to be an headache builder. Thanks for the suggestions.

      L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
        I've posted working code (plz read again), build on this and you'll find your error. ( we are at a point were you should show more efforts ;-)

        Beside of this, you are using an internal feature of Term::ReadLine::Perl while Term::ReadLine offers an official interface for all sub-modules.

        I've tested it with the debugger setting env and either *::Gnu *::Perl and *::Zoid did tab-completion w/o problems.

        Have a look at Attribs

        Cheers Rolf

        (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: about Term::ReadLine and it's imported function
by LanX (Saint) on Nov 24, 2014 at 16:47 UTC
    Jeez ... I h-h-h-hate that antique Perl4 stuff!!!

    this works for me after installing Term::ReadLine::Perl

    perl -e' BEGIN { $ENV{PERL_RL}="Perl" } $\="\n"; use Term::ReadLine; $term=Term::ReadLine->new("test"); print $term->ReadLine; ' Term::ReadLine::Perl

    But an exists on rl_basic_commands is very unreliable...

    ... which is not surprising after I noticed that Term::ReadLine::Perl has some AUTOLOAD and tie magic.

    I didn't try to dig deeper into it, you might wanna try out Term::ReadLine::Perl5 or Term::ReadLine::Zoid (no guaranty)

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

      No luck with T::RL::Perl5 too..
      cpan> force install Term::ReadLine::Perl5 ... INST_VERSION 1.41 cpanp -i Win32::Console::ANSI #needed by T::RL::Perl5 INST_VERSION 1.08 ## i have no completion working with the changed lines about T::RL::Pe +rl5 use Term::ReadLine::Perl5; BEGIN{$ENV{PERL_RL}="Perl5"} print "\$ENV{PERL_RL} $ENV{PERL_RL}\n"; $ENV{TERM}=undef; my $term = Term::ReadLine::Perl5->new('xxx');
      I think i need to stick with the less bogus behaviour.

      Thanks L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
        Thanks LanX for not presenting the solution but sparse hints, seriously.

        The best of such hints was: Have a look at Attribs.

        My problem was that i was relaying on the function readline::rl_basic that, as explained by LanX, is used internally by Term::ReadLine::Perl and a strange behaviour (still obscure to me) happened: the code presented above seems to reveal that this function is not defined the first time we check for it but is defined in the continue block.
        To overcomplicate things, win32 is strange and dumb as console (we need some hacks at it..).

        The solution is to access $term->Attribs->{completion_function} and configure manually that feature. Here i present a working example to play with and that demonstrate what stated above.

        #!perl use strict; use warnings; BEGIN { # you can force Term::ReadLine to load the ::Perl # by setting the ENV PERL_RL variable # but you have to do it in a begin block # before the use statement # try to comment next line: probably ::Perl will be loaded # anyway if it is installed # try to set to a non available sub module # see details: https://metacpan.org/pod/Term::ReadLine#ENVIRON +MENT $ENV{PERL_RL}="Perl"; # on win32 systems it ENV TERM is 'dumb' # autocompletion is not possible. # try to comment next line on win32 and watch how does not wor +k # see also http://bvr.github.io/2010/11/term-readline/ $ENV{TERM} = 'not dumb' if $^O eq 'MSWin32'; } use Term::ReadLine; my $term=Term::ReadLine->new("test"); # Term::ReadLine is a wrapper module: it initilizes an Attribs hasref # internally used to fill in the right configuration. # You can use this hashref to set autompletion manually. As i did here +. # # YOU MUST NOT USE readline::rl_basic_commands DIRECTLY! # # you cannot print anything from hashref returned by $term->Attribs #foreach my $k (keys $term->Attribs){print "$k ${$term->Attribs}{$k}\n +"} my %cmd = (run1=>1, Rename1=>1, quit1=>1, QUONDAM1=>1); my %alt = (run_2=>1,Rename_2=>1,quit_2=>1,QUONDAM_2=>1); my $hr = \%cmd; # default hashref is a ref to %cmd # first time initialization of autocompletion &define_completion_func($hr); print "The Term::ReadLine effective module loaded is: ",$term->ReadLin +e,"\n"; print <<"END"; There are 2 sets of commands available: \%cmd QUONDAM1 Rename1 quit1 run1 \%alt QUONDAM_2 Rename_2 quit_2 run_2 You can switch to alternates one entering 'alt' and switch back with 'cmd' TAB completion works and is set case insesitive END while ( defined ( $_ = $term->readline( 'prompt>') ) ) { /^$/ ? next : chomp; s/\s+//g; if ($_ eq 'cmd'){ print "switching hashref to \%cmd\n"; $hr = +\%cmd } elsif ($_ eq 'alt'){ print "switching hashref to \%alt\n"; $hr = +\%alt } elsif (exists $$hr{$_} ) {print "OK $_ is defined in the current +hashref of commands\n"} else {next} } continue{ &define_completion_func($hr);} sub define_completion_func { my $cur_hr = shift; # is time to access the $term->Attribs and set # the sub that will be used to do autocompletion # This version is case insensitive because of the i modifier $term->Attribs->{completion_function} = sub { my ($text, $line, $start) = @_; # uncomment next line to see debug stuff while you stress +autocomplete #print 'DEBUG: $text, $line, $start = >'.(join '< >',$text +, $line, $start)."<\n"; return grep { /^$text/i } sort keys %$cur_hr ; }; }

        HtH
        L*
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: about Term::ReadLine and it's imported function
by gnosti (Chaplain) on Nov 25, 2014 at 20:40 UTC
    Hi,

    The docs for Term::ReadLine note that for attribute keys and imported methods, the rl_ prefix is stripped. Maybe you could try "basic_commands" instead of "rl_basic_commands"??

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1108255]
Approved by Corion
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2024-03-19 09:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found