Added MenuEntry class

This commit is contained in:
2Shirt 2019-05-30 21:41:17 -06:00
parent 49983fa4e1
commit 0623b070c3
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C

View file

@ -15,11 +15,43 @@ COLORS = {
'PURPLE': '\033[35m', 'PURPLE': '\033[35m',
'CYAN': '\033[36m', 'CYAN': '\033[36m',
} }
VALID_ENTRY_TYPES = (
'Action',
'Option',
'Set',
'Toggle',
)
# Classes # Classes
class MenuEntry():
"""Class for advanced menu entries"""
# pylint: disable=too-few-public-methods
def __init__(self, **kwargs):
kwargs = {str(k).lower(): v for k, v in kwargs.items()}
self.name = kwargs.pop('name', None)
self.type = kwargs.pop('type', None)
self.disabled = kwargs.pop('disabled', False)
self.hidden = kwargs.pop('hidden', False)
self.selected = kwargs.pop('selected', False)
self.separator = kwargs.pop('separator', False)
# Other attributes
for _key, _value in kwargs.items():
setattr(self, _key, kwargs.get(_key))
del kwargs
# Check attributes
self.check()
def check(self):
"""Check for invalid or missing attributes."""
assert self.name, 'Invalid menu entry name.'
assert self.type in VALID_ENTRY_TYPES, 'Invalid menu entry type.'
class MenuState(): class MenuState():
"""Class to track various parts of a menu.""" """Class to track various parts of the advanced menu."""
def __init__(self, title): def __init__(self, title):
self.checkmark = '' if 'DISPLAY' in os.environ else '*' self.checkmark = '' if 'DISPLAY' in os.environ else '*'
self.entries = OrderedDict({}) self.entries = OrderedDict({})
@ -28,21 +60,16 @@ class MenuState():
self.sep_len = 0 self.sep_len = 0
self.title = title self.title = title
def add_entry(self, name, kind, **kwargs): def add_entry(self, **kwargs):
"""Add entry and update state.""" """Add entry and update state."""
if name in self.entries: _e = MenuEntry(**kwargs)
raise Exception('Entry {} already exists.'.format(name)) assert _e.name not in self.entries, 'Duplicate menu entry.'
# Add to entries # Add to entries
self.entries[name] = { self.entries[_e.name] = _e
'Kind': kind,
'Selected': False,
'Disabled': kwargs.get('Disabled', False),
}
self.entries[name].update(**kwargs)
# Update sep length # Update sep length
self.sep_len = max(len(name), self.sep_len) self.sep_len = max(len(_e.name), self.sep_len)
def make_single_selection(self): def make_single_selection(self):
"""Select single entry.""" """Select single entry."""
@ -51,31 +78,31 @@ class MenuState():
valid_answers = {} valid_answers = {}
# Safety Check # Safety Check
assert self.entries, "No menu entries defined." assert self.entries, 'No menu entries defined.'
# Build Menu # Build Menu
i = 1 i = 1
for name, details in self.entries.items(): for name, entry in self.entries.items():
# Skip sets # Skip sets
if details['Kind'] in ('Set', 'Toggle'): if entry.type in ('Set', 'Toggle'):
continue continue
# Separators # Separators
if details.get('Separator', False): if entry.separator:
display_list.append(self.sep * _sep_len) display_list.append(self.sep * _sep_len)
# Entries # Entries
_prefix = None _prefix = None
if details['Kind'] == 'Option': if entry.type == 'Option':
_prefix = str(i) _prefix = str(i)
i += 1 i += 1
elif details['Kind'] == 'Action': elif entry.type == 'Action':
_prefix = name[0:1].upper() _prefix = name[0:1].upper()
display_list.append('{}: {}'.format(_prefix, name)) display_list.append('{}: {}'.format(_prefix, name))
valid_answers[_prefix] = name valid_answers[_prefix] = name
# Disable entry if necessary # Disable entry if necessary
if details['Disabled']: if entry.disabled:
display_list[-1] = '{ORANGE}{text}{CLEAR}'.format( display_list[-1] = '{ORANGE}{text}{CLEAR}'.format(
text=display_list[-1], text=display_list[-1],
**COLORS, **COLORS,
@ -83,7 +110,7 @@ class MenuState():
valid_answers.pop(_prefix) valid_answers.pop(_prefix)
# Hide action entry if necessary # Hide action entry if necessary
if details['Kind'] == 'Action' and details.get('Hidden', False): if entry.type == 'Action' and entry.hidden:
display_list.pop() display_list.pop()
# Show Menu and make selection # Show Menu and make selection
@ -110,4 +137,4 @@ def clear():
os.system('clear') os.system('clear')
if __name__ == '__main__': if __name__ == '__main__':
print("This file is not meant to be called directly.") print('This file is not meant to be called directly.')