You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 03:15:03