Node.js中如何禁用终端键盘输入回显仍捕获按键事件?
解决方案
要实现临时禁用终端键盘回显但保留按键捕获功能,可以利用Node.js的终端输入流(process.stdin本身是tty.ReadStream实例)控制终端原始模式,同时实现disableKeyboard和enableKeyboard函数来切换状态。
以下是修改后的完整代码:
let originalStdinMode; // 禁用键盘回显,开启原始模式以捕获按键 function disableKeyboard() { if (process.stdin.isTTY) { // 保存终端原始模式,开启raw模式(关闭输入回显,直接捕获每个按键) originalStdinMode = process.stdin.setRawMode(true); process.stdin.resume(); process.stdin.setEncoding('utf8'); } } // 恢复键盘正常输入和回显 function enableKeyboard() { if (process.stdin.isTTY && originalStdinMode !== undefined) { // 恢复终端原始模式 process.stdin.setRawMode(originalStdinMode); process.stdin.pause(); // 输出换行避免后续输入与现有文本重叠 process.stdout.write('\n'); } } const KHGO = {}; process.stdin.on('keypress', (str, key) => { // 处理Ctrl+C正常退出程序 if (key.ctrl && key.name === 'c') { enableKeyboard(); process.exit(0); } KHGO[key.name] = true; setTimeout(() => { KHGO[key.name] = false; }, 100); }); async function spell(string, ms) { let skipped = false; const characterArray = string.split(""); console.log(""); // 进入spell逻辑时禁用键盘回显 disableKeyboard(); // 逐字符输出,按空格跳过剩余内容 for (let i = 0; i < characterArray.length; i++) { process.stdout.write(characterArray[i]); if (!skipped) await sleep(ms); if (KHGO.space) { skipped = true; // 直接输出剩余所有字符 process.stdout.write(characterArray.slice(i + 1).join('')); break; } KHGO.space = false; } // 等待空格按下以继续 while(true) { if (KHGO.space) { KHGO.space = false; break; } await sleep(1); } // spell逻辑结束后恢复键盘正常状态 enableKeyboard(); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } (async function(){ await spell("Example text", 40); await spell("Example text2", 40); })();
关键说明:
- 终端模式控制:
setRawMode(true)会让终端进入原始模式,此时输入的字符不会被回显,每个按键(包括特殊键)都会直接触发keypress事件。disableKeyboard保存原始模式,enableKeyboard负责恢复,实现临时控制。 - 按键捕获:原始模式下
process.stdin的keypress事件可正常捕获所有按键,你的KHGO对象逻辑可保留,用于记录按键状态。 - 退出处理:添加Ctrl+C的处理逻辑,确保在原始模式下能正常退出程序,避免终端状态异常。
- 跳过逻辑优化:按下空格时直接输出剩余所有字符,减少不必要的循环等待。
内容的提问来源于stack exchange,提问作者Andoni
相关产品推荐
相关产品推荐

