Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re^3: about Term::ReadLine and it's imported function The Solution

by Discipulus (Canon)
on Nov 25, 2014 at 09:54 UTC ( [id://1108329]=note: print w/replies, xml ) Need Help??

in reply to Re^2: about Term::ReadLine and it's imported function
in thread about Term::ReadLine and it's imported function

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: +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 $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 ; }; }

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^4: about Term::ReadLine and it's imported function The Solution
by LanX (Saint) on Nov 25, 2014 at 14:52 UTC
    Discipulus I'm very glad you managed it on your own, seriously! :)

    Term::ReadLine is indeed very confusing and it took me many attempts to understand the debugger and long studies of the documentation of gnu-readline (i.e. the original c-library) including sample scripts in Term::ReadLine::Gnu to get used to it.

    IMHO gnu-readline predates T'RL and it was originally only thought as a wrapper with a thin Stub as fall back. People were meant to know gnu-readline and to understand the limitations.

    > and a strange behaviour (still obscure to me)

    as I told you it's using Autoloading, i.e. the function is installed after first use, such that exists fails before that.

    >  continue{ &define_completion_func($hr);}

    this really confused me, till I understood that you want to set up a new set of commands in the $hr hashref.

    But since its a closed over variable in the completion-function you might also simply reset it with something like %$hr=%CMD .

    PLEASE NOTE that your code should now work with most Term::ReadLine::* sub-packages (except ::Stub of course)

    The following code is a proof of concept I wrote yesterday, you can pass the name of the implementation module to test it or hardcode the module to test by default.

    #!/usr/bin/perl use strict; use warnings; my $module; BEGIN { my $opt = $ARGV[0]; $ENV{PERL_RL} = $opt || qw(Gnu Perl Zoid)[0]; # choose module $module = $ENV{PERL_RL}; } use Term::ReadLine; my $term = Term::ReadLine->new('sample'); my $attribs = $term->Attribs; completion_words('print', 'list', 'quit', 'run', 'status'); $term->readline("$module> "); sub completion_words { my @basic_commands = @_; my $c_completion = sub { my ($text, $line, $start) = @_; #return () if $start != 0; # only at start grep(/^$text/, @basic_commands); }; $attribs->{completion_function} = $c_completion; }

    Cheers Rolf

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

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1108329]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (2)
As of 2024-06-19 06:16 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.