def err(i): print(f"Not a choice: {i}") def choiced_input(prompt, choices): if len(choices) < 2: exit("Achievement unlocked: How did we get here?") prompt_add = f"{', '.join(choices[:-1])} or {choices[-1]}" while (i := input(prompt + f" ({prompt_add}) ")) not in choices: err(i) return i def choiced_input_ci(prompt, choices): if len(choices) < 2: exit("Achievement unlocked: How did we get here?") prompt_add = f"{', '.join(choices[:-1])} or {choices[-1]}" while (i := input(prompt + f" ({prompt_add}) ")).casefold() not in choices: err(i) return i def yes_or_no(prompt, default_pos=False): positive = list("+y") + ["yes"] negative = list("-n") + ["no"] choices = positive + negative + [""] while (i := input(prompt)).strip().casefold() not in choices: err(i) if i == "": return default_pos return i in positive def ranged_input_int(prompt, _range): try: while int((i := input(prompt)).strip().casefold()) not in _range: err(i) except ValueError: return ranged_input_int(prompt, _range) return i def iwrapper(func, *args): try: return func(*args) except (EOFError, KeyboardInterrupt): return None def ichoiced_input(prompt, choices): return iwrapper(choiced_input, prompt, choices) def ichoiced_input_ci(prompt, choices): return iwrapper(choiced_input_ci, prompt, choices) def iyes_or_no(prompt, default_pos=False): return iwrapper(yes_or_no, prompt, default_pos) def iranged_input_int(prompt, _ranged): return iwrapper(ranged_input_int, prompt, _ranged) if __name__ == "__main__": print("TESTS AHEAD!!! :3") print(iranged_input_int("HIIII (-10-10) ", range(-10, 11))) exit() print(ichoiced_input("x or y (no z)?", ["x", "y"])) print(ichoiced_input_ci("X or Y or other case?", ["x", "y"]))