fix(tui): don't panic when search result is empty and up is pressed (#2395)

In the event there are no results and up is pressed, saturating_sub()
should be used to avoid underflowing the usize. This was already present
on scroll_down().

fixes #2393
This commit is contained in:
Jeremy Cline 2024-10-02 20:43:19 -04:00 committed by GitHub
parent c7447e84da
commit a1a157cc97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -534,7 +534,8 @@ impl State {
fn scroll_up(&mut self, scroll_len: usize) { fn scroll_up(&mut self, scroll_len: usize) {
let i = self.results_state.selected() + scroll_len; let i = self.results_state.selected() + scroll_len;
self.results_state.select(i.min(self.results_len - 1)); self.results_state
.select(i.min(self.results_len.saturating_sub(1)));
} }
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
@ -1211,8 +1212,15 @@ fn set_clipboard(_s: String) {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use atuin_client::database::Context;
use atuin_client::history::History; use atuin_client::history::History;
use atuin_client::settings::{Preview, PreviewStrategy, Settings}; use atuin_client::settings::{
FilterMode, KeymapMode, Preview, PreviewStrategy, SearchMode, Settings,
};
use time::OffsetDateTime;
use crate::command::client::search::engines::{self, SearchState};
use crate::command::client::search::history_list::ListState;
use super::State; use super::State;
@ -1368,4 +1376,38 @@ mod tests {
assert_eq!(preview_static_limit_at_4, 4 + border_space); assert_eq!(preview_static_limit_at_4, 4 + border_space);
assert_eq!(settings_preview_fixed, 15 + border_space); assert_eq!(settings_preview_fixed, 15 + border_space);
} }
// Test when there's no results, scrolling up or down doesn't underflow
#[test]
fn state_scroll_up_underflow() {
let mut state = State {
history_count: 0,
update_needed: None,
results_state: ListState::default(),
switched_search_mode: false,
search_mode: SearchMode::Fuzzy,
results_len: 0,
accept: false,
keymap_mode: KeymapMode::Auto,
prefix: false,
current_cursor: None,
tab_index: 0,
search: SearchState {
input: String::new().into(),
filter_mode: FilterMode::Directory,
context: Context {
session: String::new(),
cwd: String::new(),
hostname: String::new(),
host_id: String::new(),
git_root: None,
},
},
engine: engines::engine(SearchMode::Fuzzy),
now: Box::new(OffsetDateTime::now_utc),
};
state.scroll_up(1);
state.scroll_down(1);
}
} }