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
74a411a52e
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
 
@@ -118,12 +121,13 @@ class CliMenu:
118 121
     def add_header(self, *args, **kwargs):
119 122
         return self.add_text(*args, **kwargs)
120 123
 
121
-    def add_text(self, title, indent=True):
124
+    def add_text(self, title, indent=True, style=None):
122 125
         for text in title.split('\n'):
123
-            self._items.append(_CliMenuHeader(text, indent=indent))
126
+            self._items.append(_CliMenuHeader(text, indent=indent, style=style))
124 127
 
125
-    def add_option(self, text, item=None):
126
-        self._items.append(_CliMenuOption(text, self._item_num, item=item))
128
+    def add_option(self, text, item=None, style=None, highlighted_style=None):
129
+        self._items.append(_CliMenuOption(text, self._item_num, item=item,
130
+                                          style=style, highlighted_style=highlighted_style))
127 131
         self._item_num += 1
128 132
 
129 133
     @property
@@ -156,12 +160,22 @@ class CliMenu:
156 160
     def _transform_prefix(self, item, lineno, prefix):
157 161
         return prefix
158 162
 
163
+    def _get_style(self, item, lineno, highlighted):
164
+        s = self._style
165
+        if item.focusable:
166
+            if highlighted:
167
+                return item.highlighted_style if item.highlighted_style is not None else s.highlighted
168
+            else:
169
+                return item.style if item.style is not None else s.option
170
+        else:
171
+            return item.style if item.style is not None else s.text
172
+
159 173
     def _transform_line(self, ti):
160 174
         if len(list(ti.fragments)) == 0:
161 175
             return Transformation(ti.fragments)
162 176
         style, text = list(ti.fragments)[0]
163 177
         item = self._items[ti.lineno]
164
-        s = self._style
178
+        style = self._get_style(item, ti.lineno, ti.lineno == self._pos)
165 179
 
166 180
         # cursor
167 181
         indent = ''
@@ -173,14 +187,11 @@ class CliMenu:
173 187
 
174 188
             if ti.lineno == self._pos:
175 189
                 prefix += '{}{}'.format(self._cursor, self._option_prefix)
176
-                style = s.highlighted
177 190
             else:
178 191
                 prefix += ' ' * len(self._cursor) + self._option_prefix + ' ' * self._dedent_selection
179
-                style = s.option
180 192
         else:
181 193
             if item.indent:
182 194
                 indent += ' ' * (self._header_indent + len(self._cursor) + 1)
183
-            style = s.text
184 195
 
185 196
         items = [(s if s else style, t) for s, t in ti.fragments]
186 197
         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