diff --git a/crates/atuin-client/src/theme.rs b/crates/atuin-client/src/theme.rs index 9ebe6f9cfe1..0933a27f8ee 100644 --- a/crates/atuin-client/src/theme.rs +++ b/crates/atuin-client/src/theme.rs @@ -51,7 +51,7 @@ pub struct ThemeDefinitionConfigBlock { pub parent: Option, } -use crossterm::style::{Color, ContentStyle}; +use crossterm::style::{Color, ContentStyle, Attributes, Attribute}; // For now, a theme is loaded as a mapping of meanings to colors, but it may be desirable to // expand that in the future to general styles, so we populate a Meaning->ContentStyle hashmap. @@ -233,6 +233,14 @@ impl StyleFactory { ..ContentStyle::default() } } + + fn from_fg_color_and_attributes(color: Color, attributes: Attributes) -> ContentStyle { + ContentStyle { + foreground_color: Some(color), + attributes: attributes, + ..ContentStyle::default() + } + } } // Built-in themes. Rather than having extra files added before any theming @@ -280,7 +288,7 @@ lazy_static! { ), ( Meaning::Important, - StyleFactory::from_fg_color(Color::White), + StyleFactory::from_fg_color_and_attributes(Color::White, Attributes::from(Attribute::Bold)), ), (Meaning::Muted, StyleFactory::from_fg_color(Color::Grey)), (Meaning::Base, ContentStyle::default()), @@ -290,6 +298,18 @@ lazy_static! { static ref BUILTIN_THEMES: HashMap<&'static str, Theme> = { HashMap::from([ ("default", HashMap::new()), + ("(none)", + HashMap::from([ + (Meaning::AlertError, ContentStyle::default()), + (Meaning::AlertWarn, ContentStyle::default()), + (Meaning::AlertInfo, ContentStyle::default()), + (Meaning::Annotation, ContentStyle::default()), + (Meaning::Guidance, ContentStyle::default()), + (Meaning::Important, ContentStyle::default()), + (Meaning::Muted, ContentStyle::default()), + (Meaning::Base, ContentStyle::default()), + ]) + ), ( "autumn", HashMap::from([ @@ -461,7 +481,7 @@ impl ThemeManager { Ok(theme) => theme, Err(err) => { log::warn!("Could not load theme {}: {}", name, err); - built_ins.get("default").unwrap() + built_ins.get("(none)").unwrap() } }, } diff --git a/crates/atuin/src/command/client/search/inspector.rs b/crates/atuin/src/command/client/search/inspector.rs index 1bfd6550c08..ae6d0ec0d10 100644 --- a/crates/atuin/src/command/client/search/inspector.rs +++ b/crates/atuin/src/command/client/search/inspector.rs @@ -9,7 +9,7 @@ use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyModifiers}, layout::Rect, prelude::{Constraint, Direction, Layout}, - style::{Color, Modifier, Style}, + style::Style, text::{Span, Text}, widgets::{Bar, BarChart, BarGroup, Block, Borders, Padding, Paragraph, Row, Table}, Frame, @@ -60,9 +60,7 @@ pub fn draw_commands( let command = Paragraph::new(Text::from(Span::styled( history.command.clone(), - Style::default() - .add_modifier(Modifier::BOLD) - .fg(Color::White), + theme.as_style(Meaning::Important) ))) .block(if compact { Block::new() @@ -364,11 +362,7 @@ mod tests { use time::OffsetDateTime; use super::draw_ultracompact; - #[test] - fn correct_height_for_ultracompact() { - let backend = TestBackend::new(22, 5); - let mut terminal = Terminal::new(backend).expect("Could not create terminal"); - let chunk = Rect::new(0, 0, 22, 5); + fn mock_history_stats() -> (History, HistoryStats) { let history = History { id: HistoryId::from("test1".to_string()), timestamp: OffsetDateTime::now_utc(), @@ -411,8 +405,20 @@ mod tests { day_of_week: Vec::new(), duration_over_time: Vec::new(), }; + (history, stats) + } + + #[test] + fn test_output_looks_correct_for_ultracompact() { + let backend = TestBackend::new(22, 5); + let mut terminal = Terminal::new(backend).expect("Could not create terminal"); + let chunk = Rect::new(0, 0, 22, 5); + let (history, stats) = mock_history_stats(); + let prev = stats.previous.clone().unwrap(); + let next = stats.next.clone().unwrap(); + let mut manager = ThemeManager::new(Some(true), Some("".to_string())); - let theme = manager.load_theme("default", None); + let theme = manager.load_theme("(none)", None); let _ = terminal.draw(|f| draw_ultracompact( f, chunk, @@ -420,21 +426,12 @@ mod tests { &stats, &theme, )); - let mut lines = [" "; 5].map(|l| Line::from(l)); - let mut l = lines[0].to_string(); - l.replace_range(0..prev.command.len(), &prev.command); - lines[0] = Line::styled(l, Color::DarkGray); - - // Line one highlights just the history command. - let l = lines[1].to_string(); - lines[1] = Line::from(vec![ - Span::styled(&history.command, Style::new().fg(Color::White).add_modifier(Modifier::BOLD)), - Span::styled(&l[history.command.len()..], Color::Reset), - ]); - - let mut l = lines[2].to_string(); - l.replace_range(0..next.command.len(), &next.command); - lines[2] = Line::styled(l, Color::DarkGray); + let mut lines = [" "; 5].map(|l| Line::from(l)); + for (n, entry) in [prev, history, next].iter().enumerate() { + let mut l = lines[n].to_string(); + l.replace_range(0..entry.command.len(), &entry.command); + lines[n] = Line::from(l); + } terminal.backend().assert_buffer_lines(lines); } diff --git a/crates/atuin/src/command/client/search/interactive.rs b/crates/atuin/src/command/client/search/interactive.rs index 633df0f865d..73316c8cc20 100644 --- a/crates/atuin/src/command/client/search/interactive.rs +++ b/crates/atuin/src/command/client/search/interactive.rs @@ -291,6 +291,7 @@ impl State { KeyCode::Right if cursor_at_end_of_line => { Some(InputAction::Accept(self.results_state.selected())) } + KeyCode::Left if cursor_at_start_of_line => Some(Self::handle_key_exit(settings)), KeyCode::Char('o') if ctrl => { self.tab_index = (self.tab_index + 1) % TAB_TITLES.len(); Some(InputAction::Continue) @@ -860,11 +861,11 @@ impl State { Compactness::Full => 1, _ => 0, }; - f.set_cursor_position( + f.set_cursor_position(( // Put cursor past the end of the input text input_chunk.x + extra_width as u16 + PREFIX_LENGTH + 1 + cursor_offset, input_chunk.y + cursor_offset, - ); + )); } fn build_title(&self, theme: &Theme) -> Paragraph {