diff --git a/voussoirkit/getpermission.py b/voussoirkit/getpermission.py index 5c63461..2ede0d4 100644 --- a/voussoirkit/getpermission.py +++ b/voussoirkit/getpermission.py @@ -1,36 +1,5 @@ -YES_STRINGS = ['yes', 'y'] -NO_STRINGS = ['no', 'n'] +import warnings +warnings.warn('Please switch to voussoirkit.interactive.getpermission') -def getpermission( - prompt=None, - *, - yes_strings=YES_STRINGS, - no_strings=NO_STRINGS, - must_pick=False, - ): - ''' - Prompt the user with a yes or no question. - - Return True for yes, False for no, and None if undecided. - - You can customize the strings that mean yes or no. For example, you could - create a "type the name of the thing you're about to delete" prompt. - - If `must_pick`, then undecided is not allowed and the input will repeat - until they choose an acceptable answer. Either way, the intended usage of - `if getpermission():` will always only accept in case of explicit yes. - ''' - if prompt is not None: - print(prompt) - while True: - answer = input(f'{yes_strings[0]}/{no_strings[0]}> ').strip() - yes = answer.lower() in (option.lower() for option in yes_strings) - no = answer.lower() in (option.lower() for option in no_strings) - if yes or no or not must_pick: - break - - if yes: - return True - if no: - return False - return None +from voussoirkit import interactive +getpermission = interactive.getpermission diff --git a/voussoirkit/interactive.py b/voussoirkit/interactive.py new file mode 100644 index 0000000..d973105 --- /dev/null +++ b/voussoirkit/interactive.py @@ -0,0 +1,120 @@ +#################################################################################################### +## ABC_CHOOSER ##################################################################################### +#################################################################################################### + +def _abc_make_option_letters(options): + import math + import string + from voussoirkit import basenumber + option_letters = {} + letter_length = math.ceil(len(options) / 26) + for (index, option) in enumerate(options): + letter = basenumber.to_base(index, 26, alphabet=string.ascii_lowercase).rjust(letter_length, 'a') + option_letters[letter] = option + + return option_letters + +def abc_chooser(options, prompt='', must_pick=False): + ''' + Given a list of options, the user will pick one by the corresponding letter. + The return value is the item from the options list, or None if must_pick is + False and the user entered nothing. + ''' + option_letters = _abc_make_option_letters(options) + + while True: + message = [] + for (letter, option) in option_letters.items(): + message.append(f'{letter}. {option}') + print('\n'.join(message)) + choice = input(prompt).strip().lower() + + if not choice: + if must_pick: + print() + continue + else: + return + + if choice not in option_letters: + print() + continue + + return option_letters[choice] + +def abc_chooser_many(options, prompt='', label='X'): + ''' + Given a list of options, the user may pick zero or many options by their + corresponding letter. They can toggle the options on and off as long as + they like, and submit their selection by entering one more blank line. + The return value is a list of items from the options list. + ''' + selected = set() + option_letters = _abc_make_option_letters(options) + + while True: + message = [] + for (letter, option) in option_letters.items(): + this_label = label if letter in selected else '' + this_label = this_label.center(len(label)) + message.append(f'{letter}. [{this_label}] {option}') + print('\n'.join(message)) + + choice = input(prompt).strip().lower() + + if not choice: + break + + if choice not in option_letters: + print() + continue + + if choice in selected: + selected.remove(choice) + else: + selected.add(choice) + print() + + choices = [option_letters[letter] for letter in option_letters if letter in selected] + return choices + +#################################################################################################### +## GETPERMISSION ################################################################################### +#################################################################################################### + +YES_STRINGS = ['yes', 'y'] +NO_STRINGS = ['no', 'n'] + +def getpermission( + prompt=None, + *, + yes_strings=YES_STRINGS, + no_strings=NO_STRINGS, + must_pick=False, + ): + ''' + Prompt the user with a yes or no question. + + Return True for yes, False for no, and None if undecided. + + You can customize the strings that mean yes or no. For example, you could + create a "type the name of the thing you're about to delete" prompt. + + If `must_pick`, then undecided is not allowed and the input will repeat + until they choose an acceptable answer. Either way, the intended usage of + `if getpermission():` will always only accept in case of explicit yes. + ''' + if prompt is not None: + print(prompt) + while True: + answer = input(f'{yes_strings[0]}/{no_strings[0]}> ').strip() + yes = answer.lower() in (option.lower() for option in yes_strings) + no = answer.lower() in (option.lower() for option in no_strings) + if yes or no or not must_pick: + break + + if yes: + return True + if no: + return False + return None