在Node.js readline shell中清除终端窗口

21

我有一个用Coffeescript编写的简单的readline shell:

rl = require 'readline'
cli = rl.createInterface process.stdin, process.stdout, null
cli.setPrompt "hello> "

cli.on 'line', (line) ->
  console.log line
  cli.prompt()

cli.prompt()

运行这个命令会显示一个提示符:

$ coffee cli.coffee 
hello> 

我希望能够按下Ctrl-L来清除屏幕。这种操作是否可行?

我还注意到,无论是在node还是coffee的REPL中,我都无法按下Ctrl-L

我的系统是Ubuntu 11.04。

8个回答

31
你可以自己监听按键事件并清除屏幕。
process.stdin.on 'keypress', (s, key) ->
  if key.ctrl && key.name == 'l'
    process.stdout.write '\u001B[2J\u001B[0;0f'

清除操作可以使用类似于这里写的ASCII控制序列进行,具体内容请参考http://ascii-table.com/ansi-escape-sequences-vt-100.php

第一个代码\u001B[2J指示终端进行清屏操作,第二个代码\u001B[0;0f将光标强制返回到0,0的位置。

注意

keypress事件已经不再是Node >= 0.10.x中标准API的一部分,但您可以使用keypress模块代替。


这里需要在擦除后加上 '\u001B[0;0f',但现在已经完美运行。谢谢。 - mkopala
不知道这个存在!我几乎要因为它看起来太美而哭了 x') - stringparser
我在0.8.x之后被移除了。我猜是因为太啰嗦了。 - stringparser
1
@stringparser 请查看我的注释。 - loganfsmyth
@loganfsmyth 谢谢!我也发现这个在 core 库的 readline 中可用。留下了答案! :) - stringparser

7

这是唯一一个可以清除屏幕并且滚动历史记录的答案。

function clear() {
  // 1. Print empty lines until the screen is blank.
  process.stdout.write('\033[2J');

  // 2. Clear the scrollback.
  process.stdout.write('\u001b[H\u001b[2J\u001b[3J');
}

// Try this example to see it in action!
(function loop() {
  let i = -40; // Print 40 lines extra.
  (function printLine() {
    console.log('line ' + (i + 41));
    if (++i < process.stdout.columns) {
      setTimeout(printLine, 40);
    }
    else {
      clear();
      setTimeout(loop, 3000);
    }
  })()
})()
  • 第一行代码确保可见行始终被清除。

  • 第二行代码确保滚动历史记录被清除。


这完全符合我的需求。谢谢!我建议将上面的033八进制数更新为0o33,以便在JS严格模式下也能正常工作。 - Gustav Streicher

6
在MAC终端中,要清除NodeJS控制台,只需要像在Google开发者工具控制台中一样按下COMMAND+K,所以我猜在Windows上应该是CTRL+K

我认为他的意思是通过编程方式清除控制台,而不是通过用户输入。 - Chev
有没有一种方法可以从Node程序中以编程方式触发COMMAND+K - roundrobin

4

同时也可以尝试:

var rl = require('readline');
rl.cursorTo(process.stdout, 0, 0);
rl.clearScreenDown(process.stdout);

3

回应@loganfsmyth在他的答案中的评论(感谢编辑!)。

我一直在这里和那里寻找,除了神奇的keypress模块之外,还有一个核心模块可以创建带有所有标准终端行为的cli(我们今天认为理所当然的所有事情,例如历史记录、提供自动完成功能的选项以及输入事件,例如keypress都在那里)。

该模块是readlinedocumentation)。好消息是所有标准行为已经为我们完成,因此无需附加事件处理程序(例如历史记录,在Ctrl+L上清除屏幕,如果您提供自动完成功能,则会在Tab按下时出现)。

只是作为一个例子

var readline = require('readline')
  , cli = readline.createInterface({
      input : process.stdin,
      output : process.stdout
  });

var myPrompt = ' > myPropmt '
cli.setPrompt(myPrompt, myPrompt.length); 
// prompt length so you can use "color" in your prompt
cli.prompt(); 
// Display ' > myPrompt ' with all standard features (history also!)

cli.on('line', function(cmd){ // fired each time the input has a new line       
   cli.prompt();
})

cli.input.on('keypress', function(key){  // self explanatory
  // arguments is a "key" object
  // with really nice properties such as ctrl : false
  process.stdout.write(JSON.stringify(arguments))
});

真正的好发现。

我使用的节点版本是v0.10.29。我一直在看变更日志,自2010年(提交10d8ad)以来就一直在那里。


2

Vorpal.js可以轻松实现这类事情。

要在您的应用程序上下文中实现具有clear命令以及REPL的交互式CLI,请执行以下操作:

var vorpal = require('vorpal')();
var repl = require('vorpal-repl');

vorpal
  .delimiter('hello>')
  .use(repl)
  .show();

vorpal
  .command('clear', 'Clears the screen.')
  .action(function (args, cb) {
    var blank = '';
    for (var i = 0; i < process.stdout.rows; ++i) {
      blank += '\n';
    }
    vorpal.ui.rewrite(blank);
    vorpal.ui.rewrite('');
    cb();
  });

2

您可以使用 console.log() 和转义序列来清除屏幕。

cli.on 'line', (line) ->
  if line == 'cls'
    console.log("\033[2J\033[0f")
  else
    console.log line
cli.prompt()

0
如果你正在使用readline.createInterface,你可以做如下操作:
function clearPrompt() {
  rl.setPrompt("");
  rl.prompt();
}

请注意,这不会清除整个终端,只会清除readline提示符。如果您希望用户在终端中保留其位置,则仍然很有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接