pmb.helpers.cli: add tab completion option for ask() helper (!1875)
Add a helper class that provides readline-based tab completion and an extra optional argument "completion_choices" with possible completion targets. While at this, also improve paramters documentation for ask() func.
This commit is contained in:
parent
804743e65a
commit
7e61e62044
|
@ -3,14 +3,46 @@
|
|||
import datetime
|
||||
import logging
|
||||
import re
|
||||
import readline
|
||||
|
||||
|
||||
class ReadlineTabCompleter:
|
||||
""" Stores intermediate state for completer function """
|
||||
def __init__(self, options):
|
||||
"""
|
||||
:param options: list of possible completions
|
||||
"""
|
||||
self.options = sorted(options)
|
||||
self.matches = []
|
||||
|
||||
def completer_func(self, input_text, iteration):
|
||||
"""
|
||||
:param input_text: text that shall be autocompleted
|
||||
:param iteration: how many times "tab" was hit
|
||||
"""
|
||||
# First time: build match list
|
||||
if iteration == 0:
|
||||
if input_text:
|
||||
self.matches = [s for s in self.options if s and s.startswith(input_text)]
|
||||
else:
|
||||
self.matches = self.options[:]
|
||||
|
||||
# Return the N'th item from the match list, if we have that many.
|
||||
if iteration < len(self.matches):
|
||||
return self.matches[iteration]
|
||||
return None
|
||||
|
||||
|
||||
def ask(args, question="Continue?", choices=["y", "n"], default="n",
|
||||
lowercase_answer=True, validation_regex=None):
|
||||
lowercase_answer=True, validation_regex=None, complete=None):
|
||||
"""
|
||||
Ask a question on the terminal. When validation_regex is set, the user gets
|
||||
asked until the answer matches the regex.
|
||||
:returns: the user's answer
|
||||
Ask a question on the terminal.
|
||||
:param question: display prompt
|
||||
:param choices: short list of possible answers, displayed after prompt if set
|
||||
:param default: default value to return if user doesn't input anything
|
||||
:param lowercase_answer: if True, convert return value to lower case
|
||||
:param validation_regex: if set, keep asking until regex matches
|
||||
:param complete: set to a list to enable tab completion
|
||||
"""
|
||||
while True:
|
||||
date = datetime.datetime.now().strftime("%H:%M:%S")
|
||||
|
@ -20,7 +52,16 @@ def ask(args, question="Continue?", choices=["y", "n"], default="n",
|
|||
if default:
|
||||
question_full += " [" + str(default) + "]"
|
||||
|
||||
if complete:
|
||||
readline.parse_and_bind('tab: complete')
|
||||
readline.set_completer(ReadlineTabCompleter(complete).completer_func)
|
||||
|
||||
ret = input(question_full + ": ")
|
||||
|
||||
# Stop completing (question is answered)
|
||||
if complete:
|
||||
readline.set_completer(None)
|
||||
|
||||
if lowercase_answer:
|
||||
ret = ret.lower()
|
||||
if ret == "":
|
||||
|
|
|
@ -34,7 +34,7 @@ def fake_answers(monkeypatch, answers):
|
|||
the second question with "n" and so on.
|
||||
"""
|
||||
def fake_ask(args, question="Continue?", choices=["y", "n"], default="n",
|
||||
lowercase_answer=True, validation_regex=None):
|
||||
lowercase_answer=True, validation_regex=None, complete=None):
|
||||
answer = answers.pop(0)
|
||||
logging.info("pmb.helpers.cli.ask() fake answer: " + answer)
|
||||
return answer
|
||||
|
|
Loading…
Reference in New Issue