如何通过Deno的prompt函数区分Ctrl-c与EOF输入?
在Deno中区分Ctrl+C与Ctrl+D并复刻Bash行为
默认的prompt()函数无法区分Ctrl+C和Ctrl+D(两者都会返回null),且信号处理器的异步特性进一步增加了区分难度。要实现你想要的行为,需要直接操作标准输入流(stdin)并配合信号监听来精确控制流程。
实现思路
- 监听SIGINT信号(Ctrl+C):设置一个同步标志位,标记当前是否触发了中断,后续在循环中检测该标志位并执行
continue逻辑。 - 直接读取stdin流:通过
Deno.stdin.readable获取输入读取器,读取到done: true时即为EOF(对应Ctrl+D),此时退出进程。 - 处理读取中断:捕获Ctrl+C导致的读取中断错误,同步更新标志位,确保流程正确跳转。
完整代码实现
let isInterrupted = false; // 监听Ctrl+C(SIGINT)信号,设置中断标志 Deno.addSignalListener("SIGINT", () => { isInterrupted = true; console.log(); // 换行消除^C的显示干扰 }); async function main() { const reader = Deno.stdin.readable.getReader(); const decoder = new TextDecoder(); console.log("Enter something:"); // 初始提示符 while (true) { // 检测到中断时重置标志,重新显示提示符并进入下一轮循环 if (isInterrupted) { isInterrupted = false; console.log("Enter something:"); continue; } try { const { done, value } = await reader.read(); if (done) { // 读取到EOF,对应Ctrl+D,退出进程 Deno.exit(0); } // 解码输入并去除换行符 const command = decoder.decode(value).trim(); // 这里可添加自定义命令处理逻辑 console.log(`你输入了: ${command}`); console.log("Enter something:"); } catch (err) { // 捕获Ctrl+C导致的读取中断错误 if (err.name === "Interrupted") { isInterrupted = true; } else { throw err; } } } } main();
关键细节说明
- 信号监听同步化:通过标志位
isInterrupted将异步的信号事件转换为同步可检测的状态,避免异步逻辑和循环流程冲突。 - 精确区分EOF与中断:stdin读取器返回
done: true时明确是Ctrl+D触发的EOF,而读取中断错误则对应Ctrl+C。 - 提示符手动控制:由于不再使用
prompt(),需要自行处理提示符的显示,确保每次循环或中断后都能正确提示输入。
内容的提问来源于stack exchange,提问作者Finley Baker
相关产品推荐
相关产品推荐

