jline / jline3

JLine is a Java library for handling console input.
Other
1.46k stars 214 forks source link

Make it possible to cancel console-ui prompts #1035

Closed quintesse closed 3 days ago

quintesse commented 2 months ago

Right now you can only EXIT by making a selection or hitting enter, etc. It would be nice to be able to cancel out of a prompt, for example by using the escape key.

Doing that by default might not be backward-compatible, but perhaps we could add a .cancelable(true) option to the prompt builders which would then add an extra CANCEL action to the prompt's key bindings. If the user then hits the escape key we could have the prompt return null to indicate that the prompt was cancelled..

If there's interest for this feature I could try to create a PR for it.

gnodet commented 1 month ago

@mattirn ?

mattirn commented 1 month ago

@quintesse, I think that the possibility canceling prompts would be nice to have... I wrote an other similar ticket #1042 if you are interested to create PR also for it.

quintesse commented 1 month ago

hi @mattirn , that's indeed an issue that's very related to this one! In fact ESC could simply be used to cancel the current question, which would then mean returning to the previous one. And only when you hit ESC on the first question would we exit. That seems like a good way to fix both issues.

quintesse commented 1 month ago

I opened a PR for this feature, not sure if this is how you'd want to tackle this, but I wanted to maintain backwards compatibility, meaning that old code doesn't suddenly reacts differently by allowing prompts to be cancelled when before that wasn't possible.

How it works is that at any time the user can hit the ESC key and that will cancel the current prompt item. If there were previously answered prompts the code will back up a single question and re-execute that prompt. If we were at the first or only prompt the result of the entire prompt will be null;

How it was implemented:

  1. added a CANCEL operation to all prompt items
  2. added a cancellable property to all prompt items that has to be passed to their constructor (but devs should be using the builders so there shouldn't be a problem with this change)
  3. in the bindKeys() of each prompt item we check if cancellable is true and only then we add a binding between CANCEL and the ESC key.
  4. added a cancellable(boolean) method to ConsolePrompt, its value will be passed to the constructors of all prompt items

This gives devs a very simple way to enable this feature, they can simply change a line like:

ConsolePrompt prompt = new ConsolePrompt(....);

to:

ConsolePrompt prompt = new ConsolePrompt(....).cancellable(true);

and they'll have opted in to the new feature.

I thought about making it possible to set this property on a per-item basis but it would mean a lot more changes while not making the feature much more useful. (Is it really useful to be able to cancel some questions but not others?)

I also thought about adding the cancellable(boolean) method to the PromptBuilder instead, but the way the API is designed makes that somewhat ambiguous, so I decided against that option.