From 1c1f1c93f947e442a1f6d8122c31d747544a5775 Mon Sep 17 00:00:00 2001 From: dstrohl Date: Fri, 2 Jan 2015 21:32:42 -0800 Subject: [PATCH] Added option prompt --- clint/textui/prompt.py | 94 +++++++++++++++++++++++++++++++++++++- clint/textui/validators.py | 18 ++++++++ examples/prompt.py | 9 +++- 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/clint/textui/prompt.py b/clint/textui/prompt.py index 7a76dac..7995e97 100644 --- a/clint/textui/prompt.py +++ b/clint/textui/prompt.py @@ -14,7 +14,7 @@ from .core import puts from .colored import yellow -from .validators import RegexValidator +from .validators import RegexValidator, OptionValidator try: raw_input @@ -88,3 +88,95 @@ def query(prompt, default='', validators=None, batch=False): return user_input except Exception as e: puts(yellow(e.message)) + + + +def options(prompt, options, default=None, batch=False): + ''' + + :param prompt: + :param options: + this can be either a list of strings, in which case it will be presented like: + prompt: + (1) this is the first string + (2) this is the second string + (3) this is the third string + + please select 1-3: + + or a list of dictionaries in the format of: + { { 'selector' : 'this is what the user will enter to select the option' + 'prompt': 'this is the string that will be displayed, this can be omitted if the selector is also a prompt', + 'return': 'this is what is returned to the calling procedure, if omitted, the option selector will be used' } + + so, to replicate the above, the dict could look like: + + [ {'selector':1,'prompt':'this is the first string','return':1}, + {'selector':2,'prompt':'this is the second string','return':2}, + {'selector':3,'prompt':'this is the third string'} + + :param default: should be set to the default selector (if desired) + :param batch: True/False, will auto-return the default + :return: + ''' + # Build fix options and build validator + + validator_list = [] + return_dict = {} + + if isinstance(options[0],dict): + for item in options: + item['selector'] = str(item['selector']) + item['prompt'] = str(item['prompt']) + if 'return' not in item: + item['return'] = item['selector'] + validator_list.append(item['selector']) + return_dict[item['selector']] = item['return'] + else: + options_strings = options + options = [] + for key, opt in enumerate(options_strings): + item = {} + item['selector'] = str(key+1) + item['prompt'] = str(opt) + item['return'] = key+1 + + return_dict[item['selector']] = item['return'] + validator_list.append(item['selector']) + options.append(item) + + validators = [OptionValidator(validator_list)] + + # Let's build the prompt + + prompt += '\n' + + # building the options list + for o in options: + prompt += '[{selector}] {prompt}\n'.format(**o) + + prompt += '\n' + + if default: + prompt += '[' + default + '] ' + + # If input is not valid keep asking + while True: + # If batch option is True then auto reply + # with default input + if not batch: + user_input = raw_input(prompt).strip() or default + else: + print(prompt) + user_input = '' + + + # Validate the user input + try: + for validator in validators: + user_input = validator(user_input) + # convert user input to defined return value + user_input = return_dict[user_input] + return user_input + except Exception as e: + puts(yellow(e.message)) diff --git a/clint/textui/validators.py b/clint/textui/validators.py index 7a12094..78100b3 100644 --- a/clint/textui/validators.py +++ b/clint/textui/validators.py @@ -102,3 +102,21 @@ def __call__(self, value): return int(value) except (TypeError, ValueError): raise ValidationError(self.message) + +class OptionValidator(object): + message = 'Select from the list of valid options.' + + def __init__(self, options, message=None): + self.options = options + if message is not None: + self.message = message + + def __call__(self, value): + """ + Validates that the input is in the options list. + """ + if value in self.options: + return value + else: + raise ValidationError(self.message) + diff --git a/examples/prompt.py b/examples/prompt.py index f14b108..dad0b52 100644 --- a/examples/prompt.py +++ b/examples/prompt.py @@ -15,7 +15,14 @@ # Set validators to an empty list for an optional input language = prompt.query("Your favorite tool (optional)?", validators=[]) + # Shows a list of options to select from + inst_options = [{'selector':'1','prompt':'Full','return':'full'}, + {'selector':'2','prompt':'Partial','return':'partial'}, + {'selector':'3','prompt':'None','return':'no install'}] + inst = prompt.options("Full or Partial Install", inst_options) + # Use a default value and a validator path = prompt.query('Installation Path', default='/usr/local/bin/', validators=[validators.PathValidator()]) - puts(colored.blue('Hi {0}. Install {1} to {2}'.format(name, language or 'nothing', path))) + puts(colored.blue('Hi {0}. Install {1} {2} to {3}'.format(name, inst, language or 'nothing', path))) +