"""Tab completion against a list of strings (readline)"""
import readline
from typing import Any, List, Union
class ReadlineCompleter:
"""A readline completer."""
def __init__(self, options: List[str]):
"""Store the options = ['word1', 'word2']."""
readline.set_completer_delims('')
self.options = options
self.matches: List[str] = []
def complete(self, _, state):
"""Complete a readline sentence."""
if state == 0:
origline = readline.get_line_buffer()
begin = readline.get_begidx()
end = readline.get_endidx()
being_completed = origline[begin:end]
words = origline.split()
if not words:
self.matches = self.options[:]
else:
try:
if begin == 0:
matches = self.options[:]
else:
first = words[0]
matches = self.options[first]
if being_completed:
self.matches = [w for w in matches
if w.startswith(being_completed)]
else:
self.matches = matches
except (KeyError, IndexError):
self.matches = []
try:
return self.matches[state]
except IndexError:
return None
def input_completion(prompt: Any,
list_options: Union[None, List[str]] = None):
"""Read a string from standard input and complete against 'list_options'.
The trailing newline is stripped. The prompt string is printed to
standard output without a trailing newline before reading input.
If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise
EOFError. On *nix systems, readline is used if available.
"""
readline.parse_and_bind('tab: complete')
if list_options is None:
list_options = []
save_completer = readline.get_completer()
try:
readline.set_completer(
ReadlineCompleter(list_options).complete
)
return input(prompt)
finally:
readline.set_completer(save_completer)
def main():
"""Try input_completion()."""
list_options = ["yes", "no", "cancel"]
value = input_completion("Proceed (press the Tab key)? ",
list_options=list_options)
print("Value:", value)
if __name__ == "__main__":
main()
Code language: Python (python)