Skip to content

Commit e0cfa7b

Browse files
authored
Apply fallback style for quirky terminals (#173)
* Apply fallback style for quirky terminals * Use different color theme for Apple Terminal * Fix defmt being incorrectly highlighted
1 parent 2cf01f2 commit e0cfa7b

File tree

2 files changed

+101
-36
lines changed

2 files changed

+101
-36
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020

2121
### Changed
2222

23+
- The visual style in certain terminals no longer uses emojis (#173)
24+
2325
### Fixed
2426

2527
- The generated project no longer contains `template.yaml`. (#142)

src/tui.rs

Lines changed: 99 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,6 @@ use esp_generate::{
1313
use esp_metadata::Chip;
1414
use ratatui::{prelude::*, style::palette::tailwind, widgets::*};
1515

16-
const TODO_HEADER_BG: Color = tailwind::BLUE.c950;
17-
const NORMAL_ROW_COLOR: Color = tailwind::SLATE.c950;
18-
const HELP_ROW_COLOR: Color = tailwind::SLATE.c800;
19-
const DISABLED_STYLE_FG: Color = tailwind::GRAY.c600;
20-
const TEXT_COLOR: Color = tailwind::SLATE.c200;
21-
22-
const SELECTED_ACTIVE_BACKGROUND: Color = tailwind::BLUE.c950;
23-
const SELECTED_INACTIVE_TEXT: Color = tailwind::SLATE.c400;
24-
const SELECTED_INACTIVE_BACKGROUND: Color = tailwind::GRAY.c800;
25-
26-
const SELECTED_ACTIVE_STYLE: Style = Style::new()
27-
.add_modifier(Modifier::BOLD)
28-
.fg(TEXT_COLOR)
29-
.bg(SELECTED_ACTIVE_BACKGROUND);
30-
31-
const SELECTED_INACTIVE_STYLE: Style = Style::new()
32-
.add_modifier(Modifier::BOLD)
33-
.fg(SELECTED_INACTIVE_TEXT)
34-
.bg(SELECTED_INACTIVE_BACKGROUND);
35-
3616
type AppResult<T> = Result<T, Box<dyn Error>>;
3717

3818
pub struct Repository<'app> {
@@ -115,7 +95,7 @@ impl<'app> Repository<'app> {
11595
self.path.pop();
11696
}
11797

118-
fn current_level_desc(&self, width: u16) -> Vec<(bool, String)> {
98+
fn current_level_desc(&self, width: u16, style: &UiElements) -> Vec<(bool, String)> {
11999
let level = self.current_level();
120100
let level_active = self.current_level_is_active();
121101

@@ -129,11 +109,11 @@ impl<'app> Repository<'app> {
129109
};
130110
let indicator =
131111
if self.config.selected.iter().any(|o| o == v.name()) && level_active {
132-
"✅"
112+
style.selected
133113
} else if v.is_category() {
134-
"▶️"
114+
style.category
135115
} else {
136-
" "
116+
style.unselected
137117
};
138118
let padding = width as usize - v.title().len() - 4; // 2 spaces + the indicator
139119
(
@@ -165,21 +145,99 @@ pub fn restore_terminal() -> AppResult<()> {
165145
Ok(())
166146
}
167147

148+
struct UiElements {
149+
selected: &'static str,
150+
unselected: &'static str,
151+
category: &'static str,
152+
}
153+
154+
struct Colors {
155+
app_background: Color,
156+
header_bg: Color,
157+
normal_row_color: Color,
158+
help_row_color: Color,
159+
disabled_style_fg: Color,
160+
text_color: Color,
161+
162+
selected_active_style: Style,
163+
selected_inactive_style: Style,
164+
}
165+
166+
impl Colors {
167+
const RGB: Self = Self {
168+
app_background: tailwind::SLATE.c950,
169+
header_bg: tailwind::BLUE.c950,
170+
normal_row_color: tailwind::SLATE.c950,
171+
help_row_color: tailwind::SLATE.c800,
172+
disabled_style_fg: tailwind::GRAY.c600,
173+
text_color: tailwind::SLATE.c200,
174+
175+
selected_active_style: Style::new()
176+
.add_modifier(Modifier::BOLD)
177+
.fg(tailwind::SLATE.c200)
178+
.bg(tailwind::BLUE.c950),
179+
selected_inactive_style: Style::new()
180+
.add_modifier(Modifier::BOLD)
181+
.fg(tailwind::SLATE.c400)
182+
.bg(tailwind::GRAY.c800),
183+
};
184+
const ANSI: Self = Self {
185+
app_background: Color::Black,
186+
header_bg: Color::DarkGray,
187+
normal_row_color: Color::Black,
188+
help_row_color: Color::DarkGray,
189+
disabled_style_fg: Color::DarkGray,
190+
text_color: Color::Gray,
191+
192+
selected_active_style: Style::new()
193+
.add_modifier(Modifier::BOLD)
194+
.fg(Color::White)
195+
.bg(Color::Blue),
196+
selected_inactive_style: Style::new()
197+
.add_modifier(Modifier::BOLD)
198+
.fg(Color::DarkGray)
199+
.bg(Color::LightBlue),
200+
};
201+
}
202+
203+
impl UiElements {
204+
const FANCY: Self = Self {
205+
selected: "✅",
206+
unselected: " ",
207+
category: "▶️",
208+
};
209+
const FALLBACK: Self = Self {
210+
selected: "*",
211+
unselected: " ",
212+
category: ">",
213+
};
214+
}
215+
168216
pub struct App<'app> {
169217
state: Vec<ListState>,
170218
repository: Repository<'app>,
171219
confirm_quit: bool,
220+
ui_elements: UiElements,
221+
colors: Colors,
172222
}
173223

174224
impl<'app> App<'app> {
175225
pub fn new(repository: Repository<'app>) -> Self {
176226
let mut initial_state = ListState::default();
177227
initial_state.select(Some(0));
178228

229+
let (ui_elements, colors) = match std::env::var("TERM_PROGRAM").as_deref() {
230+
Ok("vscode") => (UiElements::FALLBACK, Colors::RGB),
231+
Ok("Apple_Terminal") => (UiElements::FALLBACK, Colors::ANSI),
232+
_ => (UiElements::FANCY, Colors::RGB),
233+
};
234+
179235
Self {
180236
repository,
181237
state: vec![initial_state],
182238
confirm_quit: false,
239+
ui_elements,
240+
colors,
183241
}
184242
}
185243
pub fn selected(&self) -> usize {
@@ -299,6 +357,7 @@ impl App<'_> {
299357
Paragraph::new("esp-generate")
300358
.bold()
301359
.centered()
360+
.bg(self.colors.app_background)
302361
.render(area, buf);
303362
}
304363

@@ -307,13 +366,13 @@ impl App<'_> {
307366
// list (inner).
308367
let outer_block = Block::default()
309368
.borders(Borders::NONE)
310-
.fg(TEXT_COLOR)
311-
.bg(TODO_HEADER_BG)
369+
.fg(self.colors.text_color)
370+
.bg(self.colors.header_bg)
312371
.title_alignment(Alignment::Center);
313372
let inner_block = Block::default()
314373
.borders(Borders::NONE)
315-
.fg(TEXT_COLOR)
316-
.bg(NORMAL_ROW_COLOR);
374+
.fg(self.colors.text_color)
375+
.bg(self.colors.normal_row_color);
317376

318377
// We get the inner area from outer_block. We'll use this area later to render
319378
// the table.
@@ -326,13 +385,13 @@ impl App<'_> {
326385
// Iterate through all elements in the `items` and stylize them.
327386
let items: Vec<ListItem> = self
328387
.repository
329-
.current_level_desc(area.width)
388+
.current_level_desc(area.width, &self.ui_elements)
330389
.into_iter()
331390
.map(|(enabled, value)| {
332391
ListItem::new(value).style(if enabled {
333392
Style::default()
334393
} else {
335-
Style::default().fg(DISABLED_STYLE_FG)
394+
Style::default().fg(self.colors.disabled_style_fg)
336395
})
337396
})
338397
.collect();
@@ -349,17 +408,18 @@ impl App<'_> {
349408
.current_level()
350409
.get(idx.min(items.len() - 1))
351410
}) {
352-
self.repository.config.is_active(current)
411+
self.repository.current_level_is_active()
412+
&& self.repository.config.is_active(current)
353413
} else {
354414
false
355415
};
356416

357417
let items = List::new(items)
358418
.block(inner_block)
359419
.highlight_style(if current_item_active {
360-
SELECTED_ACTIVE_STYLE
420+
self.colors.selected_active_style
361421
} else {
362-
SELECTED_INACTIVE_STYLE
422+
self.colors.selected_inactive_style
363423
})
364424
.highlight_spacing(HighlightSpacing::Always);
365425
StatefulWidget::render(items, inner_area, buf, current_state);
@@ -392,8 +452,8 @@ impl App<'_> {
392452

393453
let help_block = Block::default()
394454
.borders(Borders::NONE)
395-
.fg(TEXT_COLOR)
396-
.bg(HELP_ROW_COLOR);
455+
.fg(self.colors.text_color)
456+
.bg(self.colors.help_row_color);
397457

398458
Some(
399459
Paragraph::new(help_text)
@@ -424,7 +484,10 @@ impl App<'_> {
424484
"Use ↓↑ to move, ESC/← to go up, → to go deeper or change the value, s/S to save and generate, ESC/q to cancel"
425485
};
426486

427-
Paragraph::new(text).centered().wrap(Wrap { trim: false })
487+
Paragraph::new(text)
488+
.centered()
489+
.bg(self.colors.app_background)
490+
.wrap(Wrap { trim: false })
428491
}
429492

430493
fn footer_lines(&self, area: Rect) -> u16 {

0 commit comments

Comments
 (0)