如何在NodeJS REPL中使用“反向交互式搜索”?

时间:2017-10-12 16:12:38

标签: node.js

我希望reverse interactive search使用NodeJS Ctrl + r bashirbCtrl + r

v8.5.0未触发互动搜索。有没有办法在Nodejs REPL中使用该函数?

我正在使用MacOS Sierra,而NodeJS的版本为bacteria_id generation DNA_vector 213 230 23 254 230 18 256 229 39 289 229 16 310 228 24 324 228 45

2 个答案:

答案 0 :(得分:1)

最近I pity the foo()博客文章中回答了这个问题......

  

可以在Node的REPL中使用命令历史中的反向搜索吗?

     

目前似乎不可能。 Node REPL允许将历史记录保存到文件中,然后加载它,但不允许反向搜索它。

因此看起来REPL本身不支持反向历史搜索。

但是,您可以安装rlwrap实用程序并在Node REPL之上运行它以提供类似的功能。 REPL documentation网站提供了一些基本说明,可帮助您启动和运行。我有点好奇幕后发生的事情,所以谷歌更多地从Learning Node: Moving to the Server Side出现了这一部分,其中详细介绍了与使用rlwrap相关的权衡。例如......

  

与rlwrap一样有用的是,每当我们输入一个不返回值的表达式时,我们仍然会得到undefined。但是,我们可以通过创建我们自己的自定义REPL来调整此功能和其他功能,下面将对此进行讨论。

答案 1 :(得分:1)

我看到赏金即将结束......我可以拥有吗?如果我告诉你怎么办?

如果您熟悉历史搜索并希望将其用作替代方法,请跳至代码部分。

您熟悉zsh的历史搜索吗?它几乎就像反向搜索,除了你可以在命令行输入内容并按下up箭头键后开始搜索。我发现它比反向搜索更快,并且更频繁地使用它。缺点(我认为这是次要的)是您无法在搜索后更新原始搜索查询,除非您通过"返回"返回它。例如:

历史(自上而下)

foo
bar
foo-ish
fubar
...

在你的提示上:

> fo

up

> foo

up

> foo-ish

down

> foo

down

> fo

注意:只要您更改搜索结果并再次点击up,更改后的文字就会成为您的新查询。

守则

const PROMPT = '> ';

// history search
let input = '';
let searchInput = input;
let searchResults = [];
let searchResultIndex = 0;
process.stdin.on('keypress', (_, key) => {
  // update 'input' on changes, excluding history
  if (input !== server.line && !['up', 'down'].includes(key.name)) {
    input = server.line;
  }
  // search is initiated if a user presses the 'up' key after having inputted
  if (input !== '' && (
    key.name === 'up' ||
    (key.name === 'down' && searchResultIndex > 0)
  )) {
    // reset on fresh search or if user changed input during search
    if (searchInput !== input) {
      searchResultIndex = 0;
      // first search result is always user's input
      searchResults = [input, ...server.history.filter(item => item.includes(input))];
      searchInput = input;
    }
    const increment = key.name === 'up' ? 1 : -1;
    searchResultIndex = Math.min(searchResultIndex + increment, searchResults.length - 1);
    server.historyIndex = -1;
    server.line = '';
    process.stdout.clearLine();
    process.stdout.cursorTo(0);
    const result = searchResults[searchResultIndex];
    process.stdout.write(PROMPT + result);
    server.cursor = result.length;
    server.line = result;
  }
});

奖金 - 实施持久性历史记录:

const HISTSIZE = 100;

const server = repl.start({
  prompt: PROMPT,
  historySize: HISTSIZE,
  removeHistoryDuplicates: true,
});

// load history or create file
historyFile = path.join(path.dirname(require.main.filename), 
'.repl_history');
try {
  fs.statSync(historyFile);
  fs.readFileSync(historyFile, 'utf8')
    .split('\n')
    .filter(line => line.trim())
    .map(line => server.history.push(line));
}
catch (e) {
  console.log(e);
  fs.closeSync(fs.openSync(historyFile, 'w'));
}

server.on('exit', () => {
  // save history
  fs.writeFileSync(historyFile, server.history.slice(0, HISTSIZE).join('\n'));
  console.log('Thank you. Come again.');
  process.exit();
});