Allow per-item styling for text and options
When adding text or an option a style can now be passed along. An option allows an additional highlighted_style to be passed.
This commit is contained in:
parent
030492b353
commit
19ad4f3e8b
|
@ -14,18 +14,21 @@ from prompt_toolkit.widgets import SearchToolbar
|
|||
|
||||
class _CliMenuHeader:
|
||||
"""Hold a menu header"""
|
||||
def __init__(self, text, indent=False):
|
||||
def __init__(self, text, indent=False, style=None):
|
||||
self.text = text
|
||||
self.indent = indent
|
||||
self.style = style
|
||||
self.focusable = False
|
||||
|
||||
|
||||
class _CliMenuOption:
|
||||
"""Hold a menu option"""
|
||||
def __init__(self, text, num, item=None):
|
||||
def __init__(self, text, num, item=None, style=None, highlighted_style=None):
|
||||
self.text = text
|
||||
self.num = num
|
||||
self.item = item
|
||||
self.style = style
|
||||
self.highlighted_style = highlighted_style
|
||||
self.focusable = True
|
||||
|
||||
|
||||
|
@ -122,14 +125,15 @@ class CliMenu:
|
|||
def add_header(self, *args, **kwargs):
|
||||
return self.add_text(*args, **kwargs)
|
||||
|
||||
def add_text(self, title, indent=True):
|
||||
def add_text(self, title, indent=True, style=None):
|
||||
for text in title.split('\n'):
|
||||
self._items.append(_CliMenuHeader(text, indent=indent))
|
||||
self._items.append(_CliMenuHeader(text, indent=indent, style=style))
|
||||
|
||||
def add_option(self, text, item=_EmptyParameter):
|
||||
def add_option(self, text, item=_EmptyParameter, style=None, highlighted_style=None):
|
||||
if item == _EmptyParameter:
|
||||
item = text
|
||||
self._items.append(_CliMenuOption(text, self._item_num, item=item))
|
||||
self._items.append(_CliMenuOption(text, self._item_num, item=item,
|
||||
style=style, highlighted_style=highlighted_style))
|
||||
self._item_num += 1
|
||||
|
||||
@property
|
||||
|
@ -162,12 +166,22 @@ class CliMenu:
|
|||
def _transform_prefix(self, item, lineno, prefix):
|
||||
return prefix
|
||||
|
||||
def _get_style(self, item, lineno, highlighted):
|
||||
s = self._style
|
||||
if item.focusable:
|
||||
if highlighted:
|
||||
return item.highlighted_style if item.highlighted_style is not None else s.highlighted
|
||||
else:
|
||||
return item.style if item.style is not None else s.option
|
||||
else:
|
||||
return item.style if item.style is not None else s.text
|
||||
|
||||
def _transform_line(self, ti):
|
||||
if len(list(ti.fragments)) == 0:
|
||||
return Transformation(ti.fragments)
|
||||
style, text = list(ti.fragments)[0]
|
||||
item = self._items[ti.lineno]
|
||||
s = self._style
|
||||
style = self._get_style(item, ti.lineno, ti.lineno == self._pos)
|
||||
|
||||
# cursor
|
||||
indent = ''
|
||||
|
@ -179,14 +193,11 @@ class CliMenu:
|
|||
|
||||
if ti.lineno == self._pos:
|
||||
prefix += '{}{}'.format(self._cursor, self._option_prefix)
|
||||
style = s.highlighted
|
||||
else:
|
||||
prefix += ' ' * len(self._cursor) + self._option_prefix + ' ' * self._dedent_selection
|
||||
style = s.option
|
||||
else:
|
||||
if item.indent:
|
||||
indent += ' ' * (self._header_indent + len(self._cursor) + 1)
|
||||
style = s.text
|
||||
|
||||
items = [(s if s else style, t) for s, t in ti.fragments]
|
||||
prefix = self._transform_prefix(item, ti.lineno, prefix)
|
||||
|
|
|
@ -75,3 +75,14 @@ q = ["Foo", "Bar", "Baz"]
|
|||
m = CliMenu(q, "Time to choose:\n", option_prefix=' <<<', option_suffix='>>>')
|
||||
print("You selected", m.get_selection())
|
||||
print()
|
||||
|
||||
# --- colorize everything ---
|
||||
m = CliMenu()
|
||||
m.add_text("Time to choose:\n", style="green")
|
||||
m.add_option("Yellow foo", style="yellow", highlighted_style="black bg:yellow")
|
||||
m.add_option("Green bar", style="green", highlighted_style="black bg:green")
|
||||
m.add_option("Blue baz", style="blue", highlighted_style="black bg:blue")
|
||||
m.add_text("\n...go for it!")
|
||||
|
||||
print("You selected", m.get_selection())
|
||||
print()
|
||||
|
|
Loading…
Reference in New Issue