2017-04-19 21 views
1

是否有一个用于内部使用gnu readline的节点的shell?基于gnu readline的节点shell

正如你所知,节点外壳吸引2种方式(其中包括): 它没有搜索历史记录。这可以通过使用像https://github.com/danielgtaylor/nesh 这样很难解决。使用gnu readline的shell(如psql,ipython,python,bash等)具有许多开箱即用的功能,并且全都共享您在〜/ .inputrc中设置的配置。例如我在上面列出的所有shell中都有很好的vim模式,因为它们都在内部使用gnu readline。如果有一个js的shell在内部也使用gnu readline,那么它将与我的其他shell一致。

+1

您是否尝试过'rlwrap'?它可以让你在任何程序中使用readline输入 –

+0

谢谢,它为我打开了一扇全新的大门。但不幸的是,即使我在'.inputrc'rlwrap'中设置了编辑模式vi'和'set keymap vi'并不尊重它,并且没有'vi-mode'。我尝试了socat,但它也有一些问题。 – Sassan

+0

VI-模式'rlwrap NC本地主机8000'的作品,但它不'node','nesh'也不'bc'工作 – Sassan

回答

5

that other guy是正确的:rlwrap会工作。不幸的是,它扔掉了 node自己完成。如何避免这是一个FAQ,所以这里遵循一种方法来恢复完成:不是通过喂食TAB到包装的命令,然后 以某种方式解析结果混乱,但使用过滤器。

Filters是充当 rlwrap插件的小脚本。可以重写用户输入,命令输出,提示,历史和完成单词列表。 他们可以写在perlpython并在管道中组合。

过滤器可以做一招:与用户的背后包装的命令交互(该cloak_and_dagger()法)

因此,如果我们教node,打印的prefix完井我们可以使用 列表的新命令rlwrap_complete(prefix)cloak_and_dagger("rlwrap_complete($prefix)")以获取所有possibe完成,并将其用于rlwrap自己的完成者。

这里是过滤器,perlnode写的,但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()。作为nodedoesn't use an init file like .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 

...并享受与REPL搜索历史 TAB完成!任何时候你按下TAB rlwrap将有一个(不可见的)与node聊天,拿出正确的完成。

其他rlwrap好东西(彩色提示,vi模式,附加过滤器)可以添加,如果你想要它们。

当然,任何REPL需要能够做一些元编程来访问自己的命名空间数据之前,我们可以使用相同的解决方案为node

+1

感谢您的详细解答。我想我们应该在rlwrap命令中加上'-c',以便完成'fs。 '也可以,否则在'fs的情况下前缀将是空字符串。 '。 – Sassan

+0

@Sassan:从分词字符列表中删除点'.'只是'-c'又名'--complete-filenames'选项的一个_side effect_(一般方法是使用'--break- chars'),但是你是对的:对于Javascript,你想完成像fs这样的前缀。你的评论让我意识到完成处理器需要将原来的@ completions加到'@ new_completions' - 如果不是'rlwrap - c'不能完成文件名。我相应地编辑了我的答案。 –

+1

感谢您的详细信息,我还使用'-e'''来完成后避免额外的空间。 – Sassan

1

rlwrap将允许您使用readline进行任意程序。

如果程序没有(或者不能确信不要)使用自己的行编辑,它的效果最好。特别是对于node,你可以使用:

NODE_NO_READLINE=1 rlwrap node 
+0

'NODE_NO_READLINE = 1'使它好多了。我知道'rlwrap'通过'-f'接受自动完成,但是有可能使用底层动态repl的自动完成?例如,当我输入'fs.'并按Tab键时,它会带来自动完成节点的建议? – Sassan

+1

@Sassan:不,唉。请参阅[是否有一种方法来禁用Tab完成运行rlwrap?](http://stackoverflow.com/questions/9210931/is-there-a-way-of-running-rlwrap-with-tab-completion -disabled) –

+0

@HansLub是的,我在那里阅读你的答案。感谢你在这里提到它。对此评论:http://stackoverflow.com/questions/9210931/is-there-a-way-of-running-rlwrap-with-tab-completion-disabled#comment11958744_9219349我在想,如果有可能写入特定代码处理特定的REPL。我正在讨论至少针对流行的REPL处理标签填写情况。问题在于节点周围的社区没有多少希望使用readline或任何标准的东西。 – Sassan