Browse Source

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.
Sebastian Lohff 1 year ago
parent
commit
19ad4f3e8b
2 changed files with 32 additions and 10 deletions
  1. 21
    10
      clintermission/climenu.py
  2. 11
    0
      examples/basic_usage.py

+ 21
- 10
clintermission/climenu.py View File

@@ -14,18 +14,21 @@ from prompt_toolkit.widgets import SearchToolbar
14 14
 
15 15
 class _CliMenuHeader:
16 16
     """Hold a menu header"""
17
-    def __init__(self, text, indent=False):
17
+    def __init__(self, text, indent=False, style=None):
18 18
         self.text = text
19 19
         self.indent = indent
20
+        self.style = style
20 21
         self.focusable = False
21 22
 
22 23
 
23 24
 class _CliMenuOption:
24 25
     """Hold a menu option"""
25
-    def __init__(self, text, num, item=None):
26
+    def __init__(self, text, num, item=None, style=None, highlighted_style=None):
26 27
         self.text = text
27 28
         self.num = num
28 29
         self.item = item
30
+        self.style = style
31
+        self.highlighted_style = highlighted_style
29 32
         self.focusable = True
30 33
 
31 34
 
@@ -122,14 +125,15 @@ class CliMenu:
122 125
     def add_header(self, *args, **kwargs):
123 126
         return self.add_text(*args, **kwargs)
124 127
 
125
-    def add_text(self, title, indent=True):
128
+    def add_text(self, title, indent=True, style=None):
126 129
         for text in title.split('\n'):
127
-            self._items.append(_CliMenuHeader(text, indent=indent))
130
+            self._items.append(_CliMenuHeader(text, indent=indent, style=style))
128 131
 
129
-    def add_option(self, text, item=_EmptyParameter):
132
+    def add_option(self, text, item=_EmptyParameter, style=None, highlighted_style=None):
130 133
         if item == _EmptyParameter:
131 134
             item = text
132
-        self._items.append(_CliMenuOption(text, self._item_num, item=item))
135
+        self._items.append(_CliMenuOption(text, self._item_num, item=item,
136
+                                          style=style, highlighted_style=highlighted_style))
133 137
         self._item_num += 1
134 138
 
135 139
     @property
@@ -162,12 +166,22 @@ class CliMenu:
162 166
     def _transform_prefix(self, item, lineno, prefix):
163 167
         return prefix
164 168
 
169
+    def _get_style(self, item, lineno, highlighted):
170
+        s = self._style
171
+        if item.focusable:
172
+            if highlighted:
173
+                return item.highlighted_style if item.highlighted_style is not None else s.highlighted
174
+            else:
175
+                return item.style if item.style is not None else s.option
176
+        else:
177
+            return item.style if item.style is not None else s.text
178
+
165 179
     def _transform_line(self, ti):
166 180
         if len(list(ti.fragments)) == 0:
167 181
             return Transformation(ti.fragments)
168 182
         style, text = list(ti.fragments)[0]
169 183
         item = self._items[ti.lineno]
170
-        s = self._style
184
+        style = self._get_style(item, ti.lineno, ti.lineno == self._pos)
171 185
 
172 186
         # cursor
173 187
         indent = ''
@@ -179,14 +193,11 @@ class CliMenu:
179 193
 
180 194
             if ti.lineno == self._pos:
181 195
                 prefix += '{}{}'.format(self._cursor, self._option_prefix)
182
-                style = s.highlighted
183 196
             else:
184 197
                 prefix += ' ' * len(self._cursor) + self._option_prefix + ' ' * self._dedent_selection
185
-                style = s.option
186 198
         else:
187 199
             if item.indent:
188 200
                 indent += ' ' * (self._header_indent + len(self._cursor) + 1)
189
-            style = s.text
190 201
 
191 202
         items = [(s if s else style, t) for s, t in ti.fragments]
192 203
         prefix = self._transform_prefix(item, ti.lineno, prefix)

+ 11
- 0
examples/basic_usage.py View File

@@ -75,3 +75,14 @@ q = ["Foo", "Bar", "Baz"]
75 75
 m = CliMenu(q, "Time to choose:\n", option_prefix=' <<<', option_suffix='>>>')
76 76
 print("You selected", m.get_selection())
77 77
 print()
78
+
79
+# --- colorize everything ---
80
+m = CliMenu()
81
+m.add_text("Time to choose:\n", style="green")
82
+m.add_option("Yellow foo", style="yellow", highlighted_style="black bg:yellow")
83
+m.add_option("Green bar", style="green", highlighted_style="black bg:green")
84
+m.add_option("Blue baz", style="blue", highlighted_style="black bg:blue")
85
+m.add_text("\n...go for it!")
86
+
87
+print("You selected", m.get_selection())
88
+print()

Loading…
Cancel
Save