NodeJS readline 自动完成几个单词

问题描述 投票:0回答:2

我正在使用 Readline 模块使用 NodeJS 制作一个简单的 CLI 应用程序。我想自动完成用户的输入。为此,我使用模块的自动完成功能

function completer(line) {
   const completions = '.help .error .exit .quit .q'.split(' ');
   const hits = completions.filter((c) => c.startsWith(line));
   // show all completions if none found
   return [hits.length ? hits : completions, line];
}

使用此功能,我可以完成一个命令,但不能在同一行中完成多个命令:

例如:

(CLI App) > .e<tab>
            .error .exit

(CLI App) > .err<tab>
(CLI App) > .error

(CLI App) > .error .ex<tab>
            .help .error .exit .quit .q

我修改了完成函数以仅获取用户正在编写的当前命令的自动完成建议:

function completer(line) {
   const completions = '.help .error .exit .quit .q'.split(' ');
   const hits = completions.filter((c) => c.startsWith(line.split(' ').slice(-1)));

   return [hits.length ? hits : completions, line];
}

我得到了正确的建议,但用户输入没有改变:

(CLI App) > .e<tab>
            .error .exit

(CLI App) > .err<tab>
(CLI App) > .error

(CLI App) > .error .ex<tab>
            .exit
(CLI App) > .error .ex

有什么办法可以解决这个问题吗?如果您能提供任何帮助,我们将不胜感激。

谢谢。

node.js autocomplete console-application command-line-interface
2个回答
2
投票

使用克里斯的提示,我得到了一个解决方案:将

line
的最后一部分替换为命中(当我只有一个时)。

我计算

line
(我想要自动完成的实际命令)最后一部分的长度,以将光标移动到该命令的开头。然后,我得到所有减去当前命令的行并连接命中。最后,我将光标设置在行尾。

我尝试使用docs中的方法,但没有运气:

readline.cursorTo(stream, x, y)
readline.moveCursor(stream, dx, dy)
对我不起作用。

readline.clearLine(stream, dir)
方法清除所有行,并且没有“从光标右侧”(我想要的行为),尽管它存在于doc中。

function completer(line) {
    const completions = '.help .error .exit .quit .q'.split(' ');
    let cmds = line.split(' ');
    const hits = completions.filter((c) => c.startsWith(cmds.slice(-1)));

    if ((cmds.length > 1) && (hits.length === 1)) {
        let lastCmd = cmds.slice(-1)[0];
        let pos = lastCmd.length;
        rl.line = line.slice(0, -pos).concat(hits[0]);
        rl.cursor = rl.line.length + 1;
    }

    return [hits.length ? hits.sort() : completions.sort(), line];
}    

0
投票

我想扩展正确的答案,因为我想知道如何做同样的事情。我发现如果更改结果数组中的最后一个参数,则不需要重置行或光标。您可以传递当前正在完成的单词或命令,而不是传递行,而 readline 完成器将为您处理其他所有事情:

function completer(line) {
  const parts = line.trim().split(/\s+/);
  const completions = '.help .error .exit .quit .q'.split(' ');
  const command = parts.slice(-1)[0];

  const hits = completions.filter((c) => c.startsWith(command));
  return [hits.length ? hits : completions, command];
}
© www.soinside.com 2019 - 2024. All rights reserved.