Hurray, challenge on Monday! And I'm mad alright thank-you, so I qualify. Haven't seen OP's code nor spoilers, so maybe I didn't quite get it. Basic logic would be:
use strict; use warnings; ############################# OP data # dummy items to play with my @animals = (qw( cow camel dog cat )); my @foods = (qw( fish pasture meat )); my @places = (qw( wood sea desert )); # commands my $commands = { select => { completion_list => \@animals, commands => { give => { completion_list => \@foods, }, take_to => { completion_list => \@places, }, }, }, kill => { completion_list => \@animals, } }; ############################# my $branch = { commands => $commands }; my @path; BRANCH: { if ( exists $branch-> { completion_list }) { my $choice = choose( @{ $branch-> { completion_list }}); push @path, $choice } if ( exists $branch-> { commands }) { my $choice = choose( sort keys %{ $branch-> { commands }}); push @path, $choice; $branch = $branch-> { commands }{ $choice }; redo BRANCH } } sub choose { $_[ 0 ]} print "Excellent choice! ===> [ @path ]\n";
Which prints:
Excellent choice! ===> [ kill cow ]
Oh, great... in the Monastery... Blame Discipulus. But subroutine must better be tweaked ASAP:
sub choose { my @list = @_; use Term::Completion; STDOUT-> autoflush( 1 ); my $tc = Term::Completion-> new( prompt => "Choose (@list): ", choices => \@list, columns => 80, validation => 'nonempty fromchoices', ); return $tc-> complete }
In fact, it won't work as expected at all. Term::Completion should be (a) fixed and (b) tweaked.
Auto-flushing must be turned on (here in Strawberry at least), easily fixed from outside as above. Terminal width must be supplied to constructor (again, Strawberry); I think I know where to fix the source so that Term::ReadKey::GetTerminalSize is actually used under Win32, but again easier to fix from outside as above.
Next bug is serious, POD talks about validate and validation options, which are different, but code seems to mess them up. Quite a surprise how it made to 1.00. Fixed in patch below.
Tweaks are for Discipulus's preferred autocompletion behaviour:
Actually, distribution author suggests sub-classing, but since (a) bug is fixed anyway, (b) subclass's long complete method would be almost exact copy of original -- here's simply a patch:
--- Completion.pm.orig Sat Feb 23 18:39:15 2013 +++ Completion.pm Mon Feb 13 15:06:00 2023 @@ -179,19 +179,24 @@ # (TAB) attempt completion $_ =~ $this->{tab} && do { + last GETC if grep /^$return$/, $this->get_choices($return +); if($tab_pressed++) { - $this->show_choices($return); - redo LOOP; +# $this->show_choices($return); +# redo LOOP; } my @match = $this->get_choices($return); if (@match == 0) { + $this->show_choices($return); + redo LOOP; # sound bell if there is no match - $this->bell(); +# $this->bell(); } else { my $l = length(my $test = shift(@match)); if(@match) { + $this->show_choices($return); + redo LOOP; # sound bell if multiple choices - $this->bell(); +# $this->bell(); } elsif($this->{delim}) { $test .= $this->{delim}; @@ -361,7 +366,7 @@ { my __PACKAGE__ $this = shift; my $return = shift; - unless($this->{validate}) { + unless($this->{validation}) { return $return; } elsif(ref $this->{validate}) { @@ -376,7 +381,7 @@ } # we may have several validation options - my @vals = split(/[\s,]+/, $this->{validate}); + my @vals = split(/[\s,]+/, $this->{validation}); VALIDATE_OPTIONS: foreach my $val (@vals) {
Here to mimic sample session from OP:
Choose (kill select): # TAB (for choices) kill select Choose (kill select): select # sTAB (to complete) + TAB or ENTER Choose (cow camel dog cat): c # cTAB (for choices) cow camel cat Choose (cow camel dog cat): ca # aTAB (for choices) camel cat Choose (cow camel dog cat): camel # mTAB (to complete) + TAB or ENTER Choose (give take_to): take_to # tTAB (to complete) + TAB or ENTER Choose (wood sea desert): desert # dTAB (to complete) + TAB or ENTER Excellent choice! ===> [ select camel take_to desert ]
Runnable code (check), reputation (duh! 100), no fines for peeping (check), no Term::ReadLine (check; Term::Completion uses Term::ReadKey, of course; would be self-inflicted masochism not to use Term::ReadKey for task like this), "correct use of BACKSPACE to have editable lines" (check, + a few other keys to use), severe case of OP's Enter-o-phobia not aggravated (check). Now, where is my prize?
In reply to Re: [challenge] Nested autocompletion
by Anonymous Monk
in thread [challenge] Nested autocompletion
by Discipulus
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |