| # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """User input handlers.""" |
| |
| |
| class InputError(Exception): |
| """An error with a user provided input.""" |
| |
| |
| class _InputHandler(object): |
| """An input handler base class.""" |
| |
| def get_choices_supplements(self): |
| """Returns a pair of supplement strings representing input choices. |
| |
| @return: A pair consisting of a detailed representation of available |
| choices, and a corresponding concise descriptor of available |
| input choices with optional default. |
| """ |
| input_choices, default = self._get_input_choices_and_default() |
| if input_choices: |
| input_choices = '[%s]' % input_choices |
| if default is not None: |
| input_choices += ' (default: %s)' % default |
| |
| return self._get_choices_details(), input_choices |
| |
| |
| def _get_input_choices_and_default(self): |
| """Returns an input choices descriptor and a default (if any).""" |
| raise NotImplementedError |
| |
| |
| def _get_choices_details(self): |
| """Returns a detailed description (string) of input choices.""" |
| raise NotImplementedError |
| |
| |
| def process(self, input_str): |
| """Returns the result of processing the user input. |
| |
| @param input_str: The user input. |
| |
| @return: The result of processing the input. |
| |
| @raise InputError: Provided input is invalid. |
| """ |
| raise NotImplementedError |
| |
| |
| class PauseInputHandler(_InputHandler): |
| """A quiet input handler that just returns on any input.""" |
| |
| # Interface overrides. |
| # |
| def _get_input_choices_and_default(self): |
| return None, None |
| |
| |
| def _get_choices_details(self): |
| return None |
| |
| |
| def process(self, input_str): |
| pass |
| |
| |
| class YesNoInputHandler(_InputHandler): |
| "A yes/no input handler with optional default.""" |
| |
| def __init__(self, default=None): |
| """Initializes the input handler. |
| |
| @param default: The Boolean value to return by default. |
| """ |
| self._default = default |
| self._input_choices = '%s/%s' % ('Y' if default is True else 'y', |
| 'N' if default is False else 'n') |
| |
| |
| # Interface overrides. |
| # |
| def _get_input_choices_and_default(self): |
| # We highlight the default by uppercasing the corresponding choice |
| # directly, so no need to return a default separately. |
| return self._input_choices, None |
| |
| |
| def _get_choices_details(self): |
| return None |
| |
| |
| def process(self, input_str): |
| input_str = input_str.lower().strip() |
| if input_str == 'y': |
| return True |
| if input_str == 'n': |
| return False |
| if not input_str and self._default is not None: |
| return self._default |
| raise InputError |
| |
| |
| class MultipleChoiceInputHandler(_InputHandler): |
| """A multiple choice input handler with optional default.""" |
| |
| def __init__(self, choices, default=None): |
| """Initializes the input handler. |
| |
| @param choices: An iterable of input choices. |
| @param default: Index of default choice (integer). |
| """ |
| max_idx = len(choices) |
| if not (default is None or default in range(1, max_idx + 1)): |
| raise ValueError('Default choice is not a valid index') |
| self._choices = choices |
| self._idx_range = '1-%d' % max_idx if max_idx > 1 else str(max_idx) |
| self._default = None if default is None else str(default) |
| |
| |
| # Interface overrides. |
| # |
| def _get_input_choices_and_default(self): |
| return self._idx_range, self._default |
| |
| |
| def _get_choices_details(self): |
| return '\n'.join(['%d) %s' % (idx, choice) |
| for idx, choice in enumerate(self._choices, 1)]) |
| |
| |
| def process(self, input_str): |
| """Returns the index (zero-based) and value of the chosen option.""" |
| input_str = input_str or self._default |
| if input_str: |
| try: |
| input_idx = int(input_str) - 1 |
| if input_idx in range(len(self._choices)): |
| return input_idx, self._choices[input_idx] |
| except ValueError: |
| pass |
| |
| raise InputError |