cjm
cjm

Reputation: 62109

How can I get case-insensitive completion with Term::ReadLine::Gnu?

I can't seem to get case-insensitive completion when using Term::ReadLine::Gnu. Take this example script:

use strict;
use warnings;
use 5.010;
use Term::ReadLine;

my $term = Term::ReadLine->new('test');
say "Using " . $term->ReadLine;

if (my $attr = $term->Attribs) {
  $term->ornaments(0);
  $attr->{basic_word_break_characters}     = ". \t\n";
  $attr->{completer_word_break_characters} = " \t\n";
  $attr->{completion_function} = \&complete_word;
} # end if attributes

my @words = qw(apple approve Adam America UPPER UPPERCASE UNUSED);

sub complete_word
{
  my ($text, $line, $start) = @_;
  return grep(/^$text/i, @words);
} # end complete_word

while (1) {
  $_ = $term->readline(']');
  last unless /\S/;             # quit on empty input
} # end while 1

Note that complete_word does case-insensitive matching. If I run this with Term::ReadLine::Perl (by doing PERL_RL=Perl perl script.pl) it works as I expect. Typing a<TAB><TAB> lists all 4 words. Typing u<TAB><TAB> converts u to U and lists 3 words.

When I use Term::ReadLine::Gnu instead (PERL_RL=Gnu perl script.pl or just perl script.pl), it only does case-sensitive completion. Typing a<TAB> gives app. Typing u<TAB><TAB> doesn't list any completions.

I even have set completion-ignore-case on in my /etc/inputrc, but it still doesn't work here. (It works fine in bash, though.)

Is there any way to get Term::ReadLine::Gnu to do case-insensitive completion?

Upvotes: 4

Views: 921

Answers (1)

MisterEd
MisterEd

Reputation: 1735

It would appear the problem is in the Term::ReadLine::Gnu::XS::_trp_completion_function() (a wrapper for the user-defined completion function).

Your matches are retrieved correctly from your complete_word() function, but then the following snippet from the wrapper does its own case-sensitive match:

for (; $_i <= $#_matches; $_i++) {
    return $_matches[$_i] if ($_matches[$_i] =~ /^\Q$text/);
}

where @_matches is the result of your complete_word() and $text is the completed text so far.

So it looks like the answer is no, there is no supported way to get Term::ReadLine::Gnu to do case-insensitive completion. You would have to to override the private Term::ReadLine::Gnu::XS::_trp_completion_function (an ugly hack to be sure) -- or modify XS.pm directly (arguably an even uglier hack).

EDIT: Term::ReadLine::Gnu version used: 1.20

Upvotes: 3

Related Questions