How can I implement incremental (find-as-you-type) search on command line?

后端 未结 2 407
暗喜
暗喜 2021-02-04 21:05

I\'d like to write small scripts which feature incremental search (find-as-you-type) on the command line.

Use case: I have my mobile phone connected via USB, Using gamm

相关标签:
2条回答
  • 2021-02-04 21:37

    Following Aiden Bell's hint, I tried Readline in Perl. Solution 1 using Term::Complete (also used by CPAN, I think):

    use Term::Complete;   
    my $F; 
    open($F,"<","bin/phonebook.csv"); 
    my @terms = <$F>; chomp(@terms); 
    close($F);
    
    
    my $input;
    while (!defined $input) {
       $input = Complete("Enter a name or number: ",@terms);
       my ($name,$number) = split(/\t/,$input);
       print("Sending SMS to $name ($number).\n");
       system("sudo gammu --sendsms TEXT $number");
    }
    

    Press \ to complete, press Ctrl-D to see all possibilities.

    Solution 2: Ctrl-D is one keystroke to much, so using standard Term::Readline allows completion and the display off possible completions using only \.

    use Term::ReadLine;
    
    my $F;
    open($F,"<","bin/phonebook.csv");
    my @terms = <$F>; chomp(@terms);
    close($F);
    
    my $term = new Term::ReadLine;
    $term->Attribs->{completion_function} = sub { return @terms; };
    
    my $prompt = "Enter name or number >> ";
    
    my $OUT = $term->OUT || \*STDOUT;
    while ( defined (my $input = $term->readline($prompt)) ) {
       my ($name,$number) = split(/\t/,$input);
       print("Sending SMS to $name ($number).\n");
       system("sudo gammu --sendsms TEXT $number");
    }
    

    This solution still needs a for completion.

    Edit: Final Solution Modifying Term::Complete (http://search.cpan.org/~jesse/perl-5.12.0/lib/Term/Complete.pm) does give me on the fly completion.

    Source code: http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/perl-5.12.0.tar.gz Solution number 1 works with this modification. I will put the whole sample online somewhere else if this can be used by somebody

    Modifications of Completion.pm (just reusing it's code for Control-D and \ for each character):

    170c172,189

            my $redo=0;
    
                    @match = grep(/^\Q$return/, @cmp_lst);
                    unless ($#match < 0) {
                        $l = length($test = shift(@match));
                        foreach $cmp (@match) {
                            until (substr($cmp, 0, $l) eq substr($test, 0, $l)) {
                                $l--;
                            }
                        }
                        print("\a");
                        print($test = substr($test, $r, $l - $r));
                              $redo = $l - $r == 0;
                              if ($redo) { print(join("\r\n", '', grep(/^\Q$return/, @cmp_lst)), "\r\n"); }
                        $r = length($return .= $test);
                    }
                        if ($redo) { redo LOOP; } else { last CASE; }
    

    0 讨论(0)
  • 2021-02-04 21:52

    I get the impression GNU Readline supports this kind of thing. Though, I have not used it myself. Here is a C++ example of custom auto complete, which could easily be done in C too. There is also a Python API for readline.

    This StackOverflow question gives examples in Python, one of which is ...

    import readline
    def completer(text, state):
        options = [x in addrs where x.startswith(text)]
        if state < options.length:
            return options[state]
        else
            return None
    readline.set_completer(completer)
    

    this article on Bash autocompletion may help. This article also gives examples of programming bash's auto complete feature.

    0 讨论(0)
提交回复
热议问题