我想编写一些小脚本,它们在命令行上进行增量搜索(find-as-type-type)。
使用案例:我通过USB连接手机,使用gammu --sendsms TEXT我可以写短信。我将电话簿作为CSV,并希望在其上搜索我的类型。
最简单/最好的方法是什么?它可能是在bash / zsh / Perl / Python或任何其他脚本语言中。
编辑: 解决方案:修改Term::Complete做了我想要的。请参阅下面的答案。
答案 0 :(得分:4)
我得到的印象 GNU Readline 支持这种事情。虽然,我自己没有用过它。 Here is a C++ example自定义自动完成,也可以在C中轻松完成。 readline还有一个Python API。
This StackOverflow question在Python中提供了示例,其中一个是......
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)
关于Bash自动完成的this article可能有所帮助。本文还提供了编程bash自动完成功能的示例。
答案 1 :(得分:4)
继艾登贝尔的暗示之后,我在Perl尝试了Readline。 解决方案1使用Term :: Complete(我认为CPAN也使用):
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");
}
按\完成,按Ctrl-D查看所有可能性。
解决方案2:Ctrl-D是一次击键,因此使用标准的Term :: Readline可以完成并仅使用\来显示可能的完成。
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");
}
此解决方案仍需要完成。
编辑:最终解决方案 修改术语::完成(http://search.cpan.org/~jesse/perl-5.12.0/lib/Term/Complete.pm)确实让我即时完成。
源代码:http://search.cpan.org/CPAN/authors/id/J/JE/JESSE/perl-5.12.0.tar.gz 解决方案编号1适用于此修改。如果有人可以使用,我会将整个样本放在其他地方
Completion.pm的修改(只是重复使用Control-D的代码和每个字符的\):
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; }
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; }