javascriptsignalsdenosigint

How do I distinguish a user hitting Ctrl-c vs EOF using Deno's prompt function?


Let's say I have a simple program like this:

while (true) {
  const command = prompt('Enter something');
  if (!command) {
    Deno.exit(0);
  }
}

What I want to do is replicate bash's behavior where:

  1. Hitting Ctrl-d exits the process
  2. Hitting Ctrl-c is effectively just a continue so it goes to the next iteration of the loop

But it looks like by default the prompt function returns null in either case. Since the signal handler is async, I can't see how I'd use one to distinguish whether the input was Ctrl-c vs Ctrl-d. Is there another way to do this?


Solution

  • There is actually a workaround for this behavior though it's a bit obtuse. I think the issue is that the signal comes in while the prompt is waiting for user input. We can overcome this obstacle by using a promise and setTimeout:

    let sigint = false;
    Deno.addSignalListener("SIGINT", () => {
      sigint = true;
    });
    
    // Add a timeout to prevent process exiting immediately.
    while (true) {
      const val = prompt("Prompt: ");
      const printHandlerPromise = new Promise((resolve, reject) => {
        console.log(val);
        setTimeout(() => {
          if (sigint) {
            console.log('sigint!');
            sigint = false;
          }
          resolve(null);
        }, 0);
      });
      await printHandlerPromise;
    }