1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//! The built-in palette selector. Config supplies the startup choice;
//! `--theme` overrides it and `:theme` switches only this session.
//! Existing terminals receive an asynchronous palette-default update.
use super::Editor;
use strop_core::theme::{self, ThemeId};
use strop_picker::{Item, Payload, Picker};
impl Editor {
/// `:theme` opens the selector; `:theme NAME` applies a registered
/// palette. Unknown names leave the current choice untouched.
pub(crate) fn theme_command(&mut self, arg: &str) {
let arg = arg.trim();
if arg.is_empty() {
self.open_theme_picker();
return;
}
match ThemeId::from_name(arg) {
Some(id) => self.apply_theme(id),
None => {
self.message = format!(
"theme takes {} — not {arg:?}",
ThemeId::ALL
.iter()
.map(|id| id.name())
.collect::<Vec<_>>()
.join(" or ")
);
}
}
}
fn open_theme_picker(&mut self) {
let current = theme::current_id();
let items: Vec<Item> = ThemeId::ALL
.into_iter()
.map(|id| Item {
badge: None,
text: format!(
"{} — {}{}",
id.name(),
id.description(),
if id == current { " — current" } else { "" }
),
payload: Payload::ThemeChoice(id),
})
.collect();
let picker = Picker::new(strop_picker::Kind::Theme, items, false);
self.set_picker(super::picker::PickerGlue::diagnostics(picker));
}
/// The one mutation path: selector rows and the direct argument
/// land here alike.
pub(crate) fn apply_theme(&mut self, id: ThemeId) {
theme::set_current(id);
self.message = match self.refresh_terminal_themes() {
Ok(()) => format!("theme: {} palette", id.name()),
Err(error) => format!("theme: {}; terminal refresh failed: {error}", id.name()),
};
}
}