Skip to content

Commit bc060b5

Browse files
committed
fix: further improve coloring for different themes
Uses the correct `textual` color for the ansi colors. Adjusts the terminal CSS to better handle light themes. Adds an option to manually specify that the `terminal_derived_theme` is a `light` theme.
1 parent 79400d5 commit bc060b5

17 files changed

+300
-259
lines changed

docs/customization.md

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Customization
22

3-
As eluded to in the [Getting Started section](./index.md),
3+
As alluded to in the [Getting Started section](./index.md),
44
`isd` is _very_ configurable.
55
Almost _all_ keybindings and commands are configurable!
66
During start-up `isd` will derive the settings from a global, a local configuration file and environment variables.
@@ -68,6 +68,7 @@ Just jump to the sections that sound interesting:
6868
- [Journal Pager](#journal-pager)
6969
- [Journal Pager Arguments](#journal-pager-arguments)
7070
- [Theme](#theme)
71+
- [terminal-derived-theme dark/light toggle](#darklight-terminal-derived-theme-mode)
7172
- [Layout](#layout)
7273
- [Keybindings](#keybindings)
7374
- [Generic Keybindings](#generic-keybindings)
@@ -186,20 +187,28 @@ These values can be adjusted according to personal preference.
186187
You can _temporarily_ view the themes via the `Change theme` command.
187188
But to persist the changes you _must_ update the configuration file.
188189

189-
<!-- If you are familiar with theming your terminal via -->
190-
<!-- [ansi escape codes](https://github.com/tinted-theming/home) -->
191-
<!-- you -->
190+
### Dark/Light `terminal-derived-theme` Mode
191+
192+
{{ config_block(11) }}
193+
194+
Assumes that the `terminal_derived_theme` is a `dark` theme by default.
195+
Only set this value to `False` if your terminal derived theme
196+
is `light`. There could be a different `light_terminal_derived_theme`
197+
option but since most users use a dark theme, I opted for an additional configuration option.
198+
I am hoping that this is less confusing than the alternative `light/dark_terminal_derived_theme`.
199+
Especially, since the color adjustments are minor.
200+
If you set this option, please let me know!
192201

193202
### Layout
194203

195204
`isd` allows you to customize the layout.
196205
Currently, the relative heights between the search results and preview widgets
197206
can be adjusted:
198207

199-
{{ config_block(11) }}
200-
201208
{{ config_block(12) }}
202209

210+
{{ config_block(13) }}
211+
203212
By default the preview widget is about twice as tall as the search results widget.
204213

205214
### Keybindings
@@ -231,25 +240,25 @@ for keybindings:
231240

232241
#### Generic Keybindings
233242

234-
{{ config_block(13) }}
243+
{{ config_block(14) }}
235244

236245
See [Keybindings](#keybindings) for more general information.
237246

238247
#### Main Keybindings
239248

240-
{{ config_block(14) }}
249+
{{ config_block(15) }}
241250

242251
See [Keybindings](#keybindings) for more general information.
243252

244253
#### Navigation Keybindings
245254

246-
{{ config_block(15) }}
255+
{{ config_block(16) }}
247256

248257
See [Keybindings](#keybindings) for more general information.
249258

250259
#### `systemctl` Keybindings
251260

252-
{{ config_block(16) }}
261+
{{ config_block(17) }}
253262

254263
This allows you to configure the `systemctl` commands and keybindings.
255264
It is important to note that the `command` key may contain spaces (like `edit --runtime`)
@@ -273,21 +282,21 @@ the [shell injection section](security.md/#shell-injection).
273282

274283
### Pager Arguments
275284

276-
{{ config_block(17) }}
285+
{{ config_block(18) }}
277286

278287
If you have to customize the pager arguments for a common pager,
279288
please open an issue!
280289

281290
### Journal Pager Arguments
282291

283-
{{ config_block(18) }}
292+
{{ config_block(19) }}
284293

285294
If you have to customize the pager arguments for a common pager,
286295
please open an issue!
287296

288297
### Maximum Preview Lines
289298

290-
{{ config_block(19) }}
299+
{{ config_block(20) }}
291300

292301
This value can mainly be configured if opening the journal preview
293302
window takes too long. Though, it should usually not be required

src/isd_tui/derive_terminal_theme.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ def query_foreground_color() -> Optional[str]:
8383
return parse_rgb(response)
8484

8585

86-
def derive_textual_theme() -> Optional[Theme]:
86+
def derive_textual_theme(is_dark: bool = True) -> Optional[Theme]:
8787
"""
8888
Derive a textual theme by quering the current terminal
8989
via OSC escape codes.
90+
By default, assume that the resulting `Theme` is a dark theme (`is_dark`).
91+
If it is a `dark` or `light` theme cannot be derived from the terminal itself.
9092
9193
Here, we assume that an iTerm2 color scheme (https://github.com/mbadolato/iTerm2-Color-Schemes) is used.
9294
This function may return `None` if the theme could not be derived.
@@ -124,4 +126,5 @@ def derive_textual_theme() -> Optional[Theme]:
124126
surface=bg,
125127
panel=iterm_colors[8],
126128
boost=iterm_colors[0],
129+
dark=True,
127130
)

src/isd_tui/dom.tcss

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,42 +69,45 @@ Preview:focus {
6969
background: $boost 20%;
7070
}
7171

72-
73-
#unit-selection>.selection-list--button {
74-
background: $boost 50% !important;
72+
CustomSelectionList>.option-list--separator {
73+
background: $primary;
7574
}
7675

77-
#unit-selection>.option-list--separator {
78-
background: $primary;
76+
CustomSelectionList:dark>.option-list--option-highlighted {
77+
background: $surface-lighten-1;
78+
}
79+
CustomSelectionList:light>.option-list--option-highlighted {
80+
background: $surface-darken-1;
7981
}
8082

81-
#unit-selection>.option-list--option-hover {
82-
background: $boost 50%;
83+
CustomSelectionList:dark>.option-list--option-hover {
84+
background: $surface-lighten-1 50%;
85+
}
86+
CustomSelectionList:light>.option-list--option-hover {
87+
background: $surface-darken-1 75%;
8388
}
8489

85-
/* Even if it isn't in focus, keep the highlight up */
86-
OptionList>.option-list--option-highlighted {
87-
background: $primary 25%;
90+
/* Button options */
91+
CustomSelectionList:focus>.selection-list--button-highlighted,
92+
CustomSelectionList>.selection-list--button-highlighted,
93+
CustomSelectionList>.selection-list--button-selected-highlighted {
94+
color: $accent;
95+
background: $accent;
8896
}
8997

98+
CustomSelectionList>.selection-list--button {
99+
background: $boost 50% !important;
100+
}
90101

91-
#unit-selection>.selection-list--button {
102+
CustomSelectionList>.selection-list--button {
92103
color: $primary;
93104
background: $primary;
94105
}
95106

96-
#unit-selection:focus>.selection-list--button,
97-
#unit-selection>.selection-list--button-selected,
98-
#unit-selection:focus>.selection-list--button-selected,
99-
{
100-
color: $primary;
101-
background: $accent;
102-
}
103-
104-
#unit-selection:focus>.selection-list--button-highlighted,
105-
#unit-selection>.selection-list--button-highlighted,
106-
#unit-selection>.selection-list--button-selected-highlighted {
107-
color: $accent;
107+
CustomSelectionList:focus>.selection-list--button,
108+
CustomSelectionList>.selection-list--button-selected,
109+
CustomSelectionList:focus>.selection-list--button-selected {
110+
color: $primary;
108111
background: $accent;
109112
}
110113

@@ -129,4 +132,4 @@ MainScreen OptionList {
129132

130133
* {
131134
scrollbar-size: 0 1;
132-
}
135+
}

src/isd_tui/isd.py

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,16 @@ class Settings(BaseSettings):
836836
default=Theme("textual-dark"), description="The theme of the application."
837837
)
838838

839+
terminal_derived_theme_is_dark: bool = Field(
840+
default=True,
841+
description=dedent("""\
842+
This option is used to set whether the
843+
`terminal_derived_theme` is a `dark` (default) or `light` theme.
844+
This theme information is used to tune some colors
845+
to ensure good legibility of text in different widgets.
846+
"""),
847+
)
848+
839849
search_results_height_fraction: PositiveInt = Field(
840850
default=1, description="Relative height compared to preview height."
841851
)
@@ -1278,10 +1288,18 @@ def render_state(
12781288

12791289
text = Text(unit)
12801290
if highlight_indices is not None and len(highlight_indices) > 0:
1281-
text.stylize("dim")
12821291
for idx in highlight_indices:
1283-
text.stylize(Style(dim=False, bold=True), start=idx, end=idx + 1)
1292+
text.stylize(
1293+
Style(bold=True),
1294+
start=idx,
1295+
end=idx + 1,
1296+
)
12841297

1298+
# One limitation is that `style` passes colors like:
1299+
# `auto 75%` for the _muted_ text.
1300+
# If the style is simply "injected" as a string, nothing
1301+
# "bad" happens, as it will be evaluated later.
1302+
# But it means that I cannot call `Style.parse` here.
12851303
return Text.assemble(prefix, " ", text, style=style)
12861304

12871305

@@ -2493,11 +2511,15 @@ async def refresh_selection(self) -> None:
24932511
match_dicts = self.search_results
24942512
# get the relevant color values from the theme.
24952513
vars = self.app.get_css_variables()
2514+
# Should NOT be `success-text` as this color is used
2515+
# to render text that sits ON TOP of a widget with
2516+
# a `success` color! But I am rendering it on a plain
2517+
# background, so I _should_ select the `success` color.
24962518
render_state_colors = {
2497-
"color_success": vars["text-success"],
2498-
"color_warn": vars["text-warning"],
2499-
"color_error": vars["text-error"],
2500-
"color_different": vars["text-warning"],
2519+
"color_success": vars["success"],
2520+
"color_warn": vars["warning"],
2521+
"color_error": vars["error"],
2522+
"color_different": vars["warning"],
25012523
"color_inactive": vars["text-muted"],
25022524
}
25032525
matches = [
@@ -2518,6 +2540,7 @@ async def refresh_selection(self) -> None:
25182540
Selection(
25192541
prompt=self.unit_to_state_dict[unit].render_state(
25202542
unit,
2543+
highlight_indices=None,
25212544
**render_state_colors,
25222545
),
25232546
value=unit,
@@ -2829,6 +2852,17 @@ def get_default_system_commands_subset(
28292852
self.action_show_help_panel,
28302853
)
28312854

2855+
async def on_theme_changed(self, event):
2856+
"""
2857+
Manually subscribed to a theme change via the
2858+
signal handler in `on_mount`.
2859+
Ensures that the `selection` and `preview` is updated with the
2860+
new theme as well.
2861+
"""
2862+
if isinstance(self.screen, MainScreen):
2863+
await self.screen.refresh_selection()
2864+
self.screen.refresh_preview()
2865+
28322866
def action_stop(self) -> None:
28332867
"""
28342868
Calls the `stop` function of the `MainScreen` and exists.
@@ -2845,7 +2879,9 @@ def on_mount(self) -> None:
28452879
t = self.settings.theme
28462880
if t == "terminal-derived-theme":
28472881
with self.app.suspend():
2848-
derived_theme = derive_textual_theme()
2882+
derived_theme = derive_textual_theme(
2883+
is_dark=self.settings.terminal_derived_theme_is_dark
2884+
)
28492885
if derived_theme is not None:
28502886
self.register_theme(derived_theme)
28512887
self.theme = t
@@ -2875,6 +2911,8 @@ def on_mount(self) -> None:
28752911
timeout=90,
28762912
)
28772913
error_log_file.write_text(error_text)
2914+
2915+
self.theme_changed_signal.subscribe(self, self.on_theme_changed)
28782916
self.push_screen("main")
28792917

28802918
if self.startup_count % 100 == 0:

tests/__snapshots__/test_visual/test_invalid_settings.svg

Lines changed: 14 additions & 16 deletions
Loading

tests/__snapshots__/test_visual/test_snap_donation_screen.svg

Lines changed: 20 additions & 21 deletions
Loading

tests/__snapshots__/test_visual/test_snap_height.svg

Lines changed: 13 additions & 13 deletions
Loading

tests/__snapshots__/test_visual/test_snap_preview[#--content-tab-cat].svg

Lines changed: 24 additions & 25 deletions
Loading

tests/__snapshots__/test_visual/test_snap_preview[#--content-tab-dependencies].svg

Lines changed: 21 additions & 22 deletions
Loading

0 commit comments

Comments
 (0)