Source code for bag.console

"""Functions for user interaction at the terminal/console."""

from typing import Any, Callable, Optional, Sequence


[docs]def ask(prompt: str = "", default: str = "") -> str: """Print the ``prompt``, get user's answer, return it -- or a default.""" if prompt: if default: prompt = prompt + " [" + default + "]" prompt = prompt + " " answer = None while not answer: answer = input(prompt) if default and not answer: return default return answer
[docs]def bool_input(prompt: str, default: Optional[bool] = None) -> bool: """Print ``prompt``; return True or False based on the user's choice.""" if default is None: choices = " (y/n) " elif default: choices = " (Y/n) " else: choices = " (y/N) " opt = input(prompt + choices).lower() if opt == "y": return True elif opt == "n": return False elif not opt and default is not None: return default else: # Invalid answer, let's ask again return bool_input(prompt)
[docs]def int_input(prompt: str) -> Optional[int]: """Print ``prompt``; ensure the user enters an integer and return it.""" text = input(prompt + " ") if not text: return None try: number = int(text) except ValueError: print("No, you must type an integer.") return int_input(prompt) return number
[docs]def pick_one_of( options: Sequence[Any], prompt: str = "Pick one: ", to_str: Callable = None, ) -> Any: """Let the user choose an item (from a sequence of options) by number. ``to_str()`` is a callback that must take an item as argument and must return a corresponding string to be displayed. """ alist = options if isinstance(options, list) else list(options) c = 0 for o in alist: c += 1 print(str(c).rjust(2) + ". " + to_str(o) if to_str else str(o)) while True: try: opt = int(input(prompt)) except ValueError: continue return alist[opt - 1]
[docs]def screen_header(text: str, decor: str = "=", max: int = 79) -> str: """Return a header to be displayed on screen, by decorating ``text``.""" text = str(text) available = max - len(text) if available > 3: text = " " + text + " " available -= 4 else: return text req_space = len(decor) * 2 while available >= req_space: text = decor + text + decor available -= req_space if len(text) == available - len(decor): # Add just one more = text += decor # in order to fill the whole screen available -= len(decor) return text
[docs]def announce(*a) -> None: """Make this message stand out from all the noise in the console.""" print("******** ", *a)