diff options
| -rw-r--r-- | crates/atuin-client/src/settings.rs | 4 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/search/history_list.rs | 31 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/search/interactive.rs | 18 |
3 files changed, 31 insertions, 22 deletions
diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs index f7750914..466bc8f1 100644 --- a/crates/atuin-client/src/settings.rs +++ b/crates/atuin-client/src/settings.rs @@ -481,8 +481,8 @@ impl UiColumnType { /// The Command column returns 0 as it expands to fill remaining space. pub fn default_width(&self) -> u16 { match self { - UiColumnType::Duration => 5, - UiColumnType::Time => 9, // "459ms ago" with padding + UiColumnType::Duration => 5, // "814ms" + UiColumnType::Time => 9, // "459ms ago" UiColumnType::Datetime => 16, // "2025-01-22 14:35" UiColumnType::Directory => 20, UiColumnType::Host => 15, diff --git a/crates/atuin/src/command/client/search/history_list.rs b/crates/atuin/src/command/client/search/history_list.rs index 864a161c..23c23548 100644 --- a/crates/atuin/src/command/client/search/history_list.rs +++ b/crates/atuin/src/command/client/search/history_list.rs @@ -203,8 +203,12 @@ impl DrawState<'_> { .width .saturating_sub(indicator_width + fixed_width); + let style = self.theme.as_style(Meaning::Base); // Render each configured column - for column in self.columns { + for (idx, column) in self.columns.iter().enumerate() { + if idx != 0 { + self.draw(" ", Style::from_crossterm(style)); + } let width = if column.expand { expand_width } else { @@ -256,7 +260,7 @@ impl DrawState<'_> { let formatted = format_duration(duration); let w = width as usize; // Right-align duration within its column width, plus trailing space - let display = format!("{formatted:>w$} "); + let display = format!("{formatted:>w$}"); self.draw(&display, Style::from_crossterm(style)); } @@ -271,10 +275,11 @@ impl DrawState<'_> { let since = (self.now)() - h.timestamp; let time = format_duration(since.try_into().unwrap_or_default()); - // Format as "Xs ago" right-aligned within column width, plus trailing space + // Format as "Xs ago" right-aligned within column width let w = width as usize; let time_str = format!("{time} ago"); - let display = format!("{time_str:>w$} "); + + let display = format!("{time_str:>w$}"); self.draw(&display, Style::from_crossterm(style)); } @@ -337,7 +342,7 @@ impl DrawState<'_> { ) .unwrap_or_else(|_| "????-??-?? ??:??".to_string()); let w = width as usize; - let display = format!("{formatted:w$} "); + let display = format!("{formatted:w$}"); self.draw(&display, Style::from_crossterm(style)); } @@ -351,9 +356,9 @@ impl DrawState<'_> { // Use character count for comparison and skip for UTF-8 safety let display = if char_count > w && w >= 4 { let truncated: String = cwd.chars().skip(char_count - (w - 3)).collect(); - format!("...{truncated} ") + format!("...{truncated}") } else { - format!("{cwd:w$} ") + format!("{cwd:w$}") }; self.draw(&display, Style::from_crossterm(style)); } @@ -361,16 +366,16 @@ impl DrawState<'_> { /// Render the host column (just the hostname) fn host(&mut self, h: &History, width: u16) { let style = self.theme.as_style(Meaning::Annotation); - let w = width as usize - 1; + let w = width as usize; // Database stores hostname as "hostname:username" let host = h.hostname.split(':').next().unwrap_or(&h.hostname); let char_count = host.chars().count(); // Use character count for comparison and take for UTF-8 safety let display = if char_count > w && w >= 4 { let truncated: String = host.chars().take(w.saturating_sub(4)).collect(); - format!("{truncated}... ") + format!("{truncated}...") } else { - format!("{host:w$} ") + format!("{host:w$}") }; self.draw(&display, Style::from_crossterm(style)); } @@ -385,9 +390,9 @@ impl DrawState<'_> { // Use character count for comparison and take for UTF-8 safety let display = if char_count > w && w >= 4 { let truncated: String = user.chars().take(w.saturating_sub(4)).collect(); - format!("{truncated}... ") + format!("{truncated}...") } else { - format!("{user:w$} ") + format!("{user:w$}") }; self.draw(&display, Style::from_crossterm(style)); } @@ -400,7 +405,7 @@ impl DrawState<'_> { self.theme.as_style(Meaning::AlertError) }; let w = width as usize; - let display = format!("{:>w$} ", h.exit); + let display = format!("{:>w$}", h.exit); self.draw(&display, Style::from_crossterm(style)); } diff --git a/crates/atuin/src/command/client/search/interactive.rs b/crates/atuin/src/command/client/search/interactive.rs index 116421a2..e42400d0 100644 --- a/crates/atuin/src/command/client/search/interactive.rs +++ b/crates/atuin/src/command/client/search/interactive.rs @@ -1009,9 +1009,12 @@ impl State { .ui .columns .iter() - .filter_map(|col| if col.expand { None } else { Some(col.width) }) + .take_while(|col| !col.expand) + .map(|col| col.width + 1) .sum::<u16>() - + " > ".len() as u16; + + " > ".len() as u16; + #[allow(clippy::cast_possible_truncation)] + let min_prefix_width = "[ SRCH: FULLTXT ] ".len() as u16; self.draw_preview( f, style, @@ -1019,7 +1022,7 @@ impl State { compactness, preview_chunk, preview, - prefix_width, + std::cmp::max(prefix_width, min_prefix_width), ); } } @@ -1035,7 +1038,7 @@ impl State { preview: Paragraph, prefix_width: u16, ) { - let input = self.build_input(style, prefix_width - 2); + let input = self.build_input(style, prefix_width); f.render_widget(input, input_chunk); f.render_widget(preview, preview_chunk); @@ -1048,7 +1051,7 @@ impl State { }; f.set_cursor_position(( // Put cursor past the end of the input text - input_chunk.x + extra_width as u16 + prefix_width + 1 + cursor_offset, + input_chunk.x + extra_width as u16 + prefix_width + cursor_offset, input_chunk.y + cursor_offset, )); } @@ -1163,13 +1166,14 @@ impl State { } } - fn build_input(&self, style: StyleState, max_width: u16) -> Paragraph<'_> { + fn build_input(&self, style: StyleState, prefix_width: u16) -> Paragraph<'_> { let (pref, mode) = if self.switched_search_mode { (" SRCH:", self.search_mode.as_str()) } else { ("", self.search.filter_mode.as_str()) }; - let mode_width = usize::from(max_width) - pref.len(); + // 3: surrounding "[" "] " + let mode_width = usize::from(prefix_width) - pref.len() - 3; // sanity check to ensure we don't exceed the layout limits debug_assert!(mode_width >= mode.len(), "mode name '{mode}' is too long!"); let input = format!("[{pref}{mode:^mode_width$}] {}", self.search.input.as_str(),); |
