# :coding: utf-8
# :copyright: Copyright (c) 2017 Martin Pengelly-Phillips
# :license: Apache License, Version 2.0. See LICENSE.txt.
from __future__ import unicode_literals
import copy
import prompt_toolkit.layout.controls
import prompt_toolkit.token
import plectrum.selection
[docs]class AbstractSelectControl(prompt_toolkit.layout.controls.TokenListControl):
'''Manage selection of items.'''
[docs] def __init__(self, items):
'''Initialise control with *items* to select from.'''
if not items:
raise ValueError('At least one item must be specified.')
self.selection = plectrum.selection.Selection()
self._items = items
self._count = len(self._items)
self._maximum_item_width = max(map(len, self._items))
self._current_index = 0
self._indicator = ' > '
self._spacer = ' ' * len(self._indicator)
super(AbstractSelectControl, self).__init__(self._get_tokens)
@property
def items(self):
'''Return items.
.. note::
Return copy to avoid indirect mutation.
'''
return copy.copy(self._items)
[docs] def next_item(self):
'''Move indicator to next item.'''
self._current_index = (self._current_index + 1) % self._count
[docs] def previous_item(self):
'''Move indicator to previous item.'''
self._current_index = (self._current_index - 1) % self._count
def _get_tokens(self, interface):
'''Return tokens to display for *interface*.
*interface* should be an instance of
:class:`prompt_toolkit.interface.CommandLineInterface`.
'''
tokens = []
Token = prompt_toolkit.token.Token
for index, item in enumerate(self._items):
tokens.append(
(
Token,
self._indicator if index == self._current_index
else self._spacer
)
)
tokens.append(
(
Token.Selected if index in self.selection else Token,
'{0:<{1}}'.format(item, self._maximum_item_width)
)
)
tokens.append((Token, '\n'))
return tokens
[docs]class SingleSelectControl(AbstractSelectControl):
'''Manage selection of single item.'''
[docs] def __init__(self, items):
'''Initialise control with *items* to select from.'''
super(SingleSelectControl, self).__init__(items)
self.select_current_item()
[docs] def select_current_item(self):
'''Select current item, replacing any existing selection.'''
self.selection.clear()
self.selection.add(self._current_index)
[docs] def next_item(self):
'''Move indicator to next item and select it.'''
super(SingleSelectControl, self).next_item()
self.select_current_item()
[docs] def previous_item(self):
'''Move indicator to previous item and select it.'''
super(SingleSelectControl, self).previous_item()
self.select_current_item()
[docs]class MultiSelectControl(AbstractSelectControl):
'''Manage selection of multiple items.'''
[docs] def toggle_current_item(self):
'''Toggle selection of current item.'''
self.selection.toggle(self._current_index)