aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/atuin-client/src/settings.rs4
-rw-r--r--crates/atuin/src/command/client/search/history_list.rs31
-rw-r--r--crates/atuin/src/command/client/search/interactive.rs18
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(),);