As of Click 7, click.Choice appears only to support choice prompting by string, i.e. the user must specify the exact string (modulo case sensitivity) from the choices. It would be nice if Click could support two additional modes of selection:
Numeric:
Choose from:
[1] Choice A...
[2] Choice B...
[3] Choice C...
Enter the index for one of the above choices: 2
"Choice B..." was selected
or partial matches as long as what the user enters is unique:
Choose from:
This thing
That thing
Those things
Enter choice: thi
"This thing" was selected
("thi" is unique amongst the three strings so is chosen)
I thought it would be easy to implement this by subclassing click.Choice but unfortunately not: click.Choice does not provide the initial prompt message (only the prompt after an invalid choice) - this is provided by click.prompt from the specified choices list. The prompt message in at least the first example above would require to be changed to add numeric indexes. It seems to me therefore that this functionality requires more structural changes to click and so I thought I'd submit this issue.
I implemented numeric choices as a subclass of click.Choice:
class NumericChoice(click.Choice):
def __init__(self, choices, **kwargs):
choicepairs = []
choicestrs = []
for i, choice in enumerate(choices, start=1):
choicepairs.append((str(i), choice))
choicestrs.append("[{}] {}".format(i, choice))
self.choicemap = dict(choicepairs)
super().__init__(choicestrs, **kwargs)
def convert(self, value, param, ctx):
try:
return self.choicemap[value]
except KeyError as e:
self.fail('invalid choice: %s. (choose from %s)' %
(value, ', '.join(self.choices)), param, ctx)
It works for me, but I'm targeting Python 3.6+ only. If this might be useful I can clean it up and make a pull request at some point. It might be best to add this as an option to the existing click.Choice, though.
For partial string matching, perhaps difflib would be useful. I haven't thought how to do that yet.
@SeanDS in addition to (or possibly instead of) partial string matching, supporting completion on the click.Choice types is arguably even better; though I'm not quite sure how that would be implemented either
Selecting the choice would be much nicer. Like this: https://github.com/Mckinsey666/bullet#bullet-lists-and-checkboxes
Selecting the choice would be much nicer. Like this: https://github.com/Mckinsey666/bullet#bullet-lists-and-checkboxes
I disagree. For mutually exclusive choices, selection by index or prefix is quicker in general, despite being "less pretty".
Selecting the choice would be much nicer. Like this: https://github.com/Mckinsey666/bullet#bullet-lists-and-checkboxes
I disagree. For mutually exclusive choices, selection by index or prefix is quicker in general, despite being "less pretty".
I think selection by index or prefix is not great for those reasons :
I think the style of https://github.com/bchao1/bullet#bullet-lists-and-checkboxes makes more sense.
For typical lists for which I'd use these methods of selection (n <= 15), selection by index requires less key strokes. Of course, shorter the list, smaller the advantage.
It's more error prone.
Because it's quicker and the index is easily memorizable (which is an advantage). It's a tradeoff. Note that there's no problem if either:
For long lists, it might not be possible to display all options on the screen.
For long lists, both methods (in their "plain" version) are terrible. It's actually the worst-case scenario for selection by arrows. You want filtering/completion for long lists.
For multiple choices, it gets quite weird to specify multiple index
Absolutely agree. Indeed I specified "mutually exclusive choices" in my previous comment.
I'm +1 on making it possible for a type to customize what is shown in the prompt, although I don't plan to modify how Click's built-in Choice type works any further. That way, users can make a choice type with whatever matching behavior they want.
I'm +1 on making it possible for a type to customize what is shown in the prompt, although I don't plan to modify how Click's built-in
Choicetype works any further. That way, users can make a choice type with whatever matching behavior they want.
That's fair enough, the lack of ability to customise the message was what I missed most in the original issue.
Most helpful comment
Selecting the choice would be much nicer. Like this: https://github.com/Mckinsey666/bullet#bullet-lists-and-checkboxes