that other guy is right: rlwrap
will work. Unfortunately, it throws away
node
s own completion. How to avoid this is a FAQ, so here follows a way to restore completion: not by feeding a TAB to the wrapped command and then
somehow parsing the resulting mess, but using a filter.
Filters是一些小脚本,充当rlwrap
插件。可以重写用户输入、命令输出、提示、历史记录和完成单词列表。
它们可以写成perl
or python
并组合在管道中。
过滤器还可以做一个技巧:在用户背后与包装的命令进行交互(cloak_and_dagger()
method)
所以如果我们教node
一个新命令rlwrap_complete(prefix)
打印完成列表prefix
我们可以用cloak_and_dagger("rlwrap_complete($prefix)")
掌握所有可能的完成情况,并将其用于rlwrap
自己的完成者。
这是过滤器,为node
, in perl
, but a python
不同命令的版本看起来非常相似:
#!/usr/bin/env perl
use lib ($ENV{RLWRAP_FILTERDIR} or ".");
use RlwrapFilter;
use strict;
my $filter = new RlwrapFilter;
$filter -> completion_handler( sub {
my($line, $prefix, @completions) = @_;
my $command = "rlwrap_complete('$prefix')";
my $completion_list = $filter -> cloak_and_dagger($command, "> ", 0.1); # read until we see a new prompt "> "
my @new_completions = grep /^$prefix/, split /\r\n/, $completion_list; # split on CRNL and weed out rubbish
return (@completions, @new_completions);
});
$filter -> run;
现在我们要教node
命令rlwrap_complete()
. As node
不使用像这样的初始化文件.noderc我们必须
创建一个 REPL 实例并扩展它:
#!/usr/bin/env node
// terminal:false disables readline (just like env NODE_NO_READLINE=1):
var myrepl = require("repl").start({terminal:false});
// add REPL command rlwrap_complete(prefix) that prints a simple list of completions of prefix
myrepl.context['rlwrap_complete'] = function(prefix) {
myrepl.complete(prefix, function(err,data) { for (x of data[0]) {console.log(x)}});
}
将过滤器代码移至$RLWRAP_FILTERDIR/node_complete
,将上面的代码另存为myrepl.js
并使其可执行。然后调用:
$ rlwrap -z node_complete ./myrepl.js
... and enjoy a REPL with searchable history and TAB completion! Any time you press TAB rlwrap
will have an (invisible) chat with node
to come up with the right completions.
Other rlwrap
好东西(彩色提示,vi
如果需要,可以添加其他过滤器)。
当然,任何 REPL 都需要能够进行一些元编程来访问其自己的命名空间作为数据,然后我们才能使用与node