Open matteosacchetto opened 6 days ago
Interesting... I think a more universal solution would be to modify useKeypress
inside the core itself to ignore CTRL+C
and CTRL+D
(and macOS/linux equivalent.) Otherwise that'll be a weird edge cases for any prompts forgetting to check for that code.
I wonder if you'd encounter the same issue with a prompt with an async validator? (where there's a timeout to animate the loading animation.)
While that can help, I do not think it fully addresses the problem
The reason being that, if the timeout is started and then CTRL+C
or D
is clicked, it still waits for the whole timeout before closing the prompt and throwing the error even if the useKeypress
is not triggered by that key combination.
I think that a solution could be, on top of ignoring those key combinations, to also provide some kind of hook/callback which gets called when the prompt exit condition is triggered. This would allow for resource cleanup, like deleting the timeout.
Ah you're right!
I think as of now cleanups from useEffect will trigger on force exit š¤ - e.g useEffect(() => () => cleanup(), []);
. I'm not 100% sure, so we'd need to validate this (and if not, I'm pretty sure it should!)
I think we can keep this as-is in the core, and only use this inside select
. WDYT?
I tried with the useEffect
method, and I can confirm that it gets called on exit. Though it seems that the exit handler only gets called after the timeout is expired
https://github.com/SBoudrias/Inquirer.js/blob/85a3d400014280c5cdae03f6de63d2256ea6b2df/packages/core/src/lib/create-prompt.mts#L38-L43
I am still investigating the behavior to understand why it's behaving in this way
When terminating the
@inquirer/select
prompt withCTRL+C
orCTRL+D
it properly throws the ErrorUser force closed the prompt with 0 null
Though, it does so after the timeoutsearchTimeoutRef
is expired.Example reproduction In this reproduction, try running
node index.mjs
and stop it withCTRL+C
orCTRL+D
. To compare the behavior, I also added theindex2.mjs
which uses@inquirer/input
By debugging the behavior, I noticed that on
CTRL+C
orCTRL+D
, theuseKeypress
callback is called, the timeout is cleared and then, since the key combination does not match any of theif
/else if
statements, it enters theelse
condition. Here the timeout is created again, and after that timeout expires the Error is thrown.https://github.com/SBoudrias/Inquirer.js/blob/ac687691f6847816e89a80a589e82738bc4c13b0/packages/select/src/index.mts#L124-L142
To address it, the simplest solution would be to change the
else
statement to anelse if
checking that it does not matchCTRL+C
orCTRL+D
. Though, other strategies may be used.Once we agree on a strategy, I am willing to open a PR to address this.
Tested version:
@inquirer/select: 2.3.8