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
dc3b03c653
commit
74a411a52e
|
@ -14,18 +14,21 @@ from prompt_toolkit.widgets import SearchToolbar
|
||||||
|
|
||||||
class _CliMenuHeader:
|
class _CliMenuHeader:
|
||||||
"""Hold a menu header"""
|
"""Hold a menu header"""
|
||||||
def __init__(self, text, indent=False):
|
def __init__(self, text, indent=False, style=None):
|
||||||
self.text = text
|
self.text = text
|
||||||
self.indent = indent
|
self.indent = indent
|
||||||
|
self.style = style
|
||||||
self.focusable = False
|
self.focusable = False
|
||||||
|
|
||||||
|
|
||||||
class _CliMenuOption:
|
class _CliMenuOption:
|
||||||
"""Hold a menu option"""
|
"""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.text = text
|
||||||
self.num = num
|
self.num = num
|
||||||
self.item = item
|
self.item = item
|
||||||
|
self.style = style
|
||||||
|
self.highlighted_style = highlighted_style
|
||||||
self.focusable = True
|
self.focusable = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,12 +121,13 @@ class CliMenu:
|
||||||
def add_header(self, *args, **kwargs):
|
def add_header(self, *args, **kwargs):
|
||||||
return self.add_text(*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'):
|
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=None):
|
def add_option(self, text, item=None, style=None, highlighted_style=None):
|
||||||
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
|
self._item_num += 1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -156,12 +160,22 @@ class CliMenu:
|
||||||
def _transform_prefix(self, item, lineno, prefix):
|
def _transform_prefix(self, item, lineno, prefix):
|
||||||
return 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):
|
def _transform_line(self, ti):
|
||||||
if len(list(ti.fragments)) == 0:
|
if len(list(ti.fragments)) == 0:
|
||||||
return Transformation(ti.fragments)
|
return Transformation(ti.fragments)
|
||||||
style, text = list(ti.fragments)[0]
|
style, text = list(ti.fragments)[0]
|
||||||
item = self._items[ti.lineno]
|
item = self._items[ti.lineno]
|
||||||
s = self._style
|
style = self._get_style(item, ti.lineno, ti.lineno == self._pos)
|
||||||
|
|
||||||
# cursor
|
# cursor
|
||||||
indent = ''
|
indent = ''
|
||||||
|
@ -173,14 +187,11 @@ class CliMenu:
|
||||||
|
|
||||||
if ti.lineno == self._pos:
|
if ti.lineno == self._pos:
|
||||||
prefix += '{}{}'.format(self._cursor, self._option_prefix)
|
prefix += '{}{}'.format(self._cursor, self._option_prefix)
|
||||||
style = s.highlighted
|
|
||||||
else:
|
else:
|
||||||
prefix += ' ' * len(self._cursor) + self._option_prefix + ' ' * self._dedent_selection
|
prefix += ' ' * len(self._cursor) + self._option_prefix + ' ' * self._dedent_selection
|
||||||
style = s.option
|
|
||||||
else:
|
else:
|
||||||
if item.indent:
|
if item.indent:
|
||||||
indent += ' ' * (self._header_indent + len(self._cursor) + 1)
|
indent += ' ' * (self._header_indent + len(self._cursor) + 1)
|
||||||
style = s.text
|
|
||||||
|
|
||||||
items = [(s if s else style, t) for s, t in ti.fragments]
|
items = [(s if s else style, t) for s, t in ti.fragments]
|
||||||
prefix = self._transform_prefix(item, ti.lineno, prefix)
|
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='>>>')
|
m = CliMenu(q, "Time to choose:\n", option_prefix=' <<<', option_suffix='>>>')
|
||||||
print("You selected", m.get_selection())
|
print("You selected", m.get_selection())
|
||||||
print()
|
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