sql_cli/
history_manager.rs1use crate::history::{CommandHistory, HistoryMatch};
2
3pub struct HistoryManager {
5 pub search_query: String,
6 pub matches: Vec<HistoryMatch>,
7 pub selected_index: usize,
8}
9
10impl HistoryManager {
11 #[must_use]
12 pub fn new() -> Self {
13 Self {
14 search_query: String::new(),
15 matches: Vec::new(),
16 selected_index: 0,
17 }
18 }
19
20 pub fn update_matches(&mut self, history: &CommandHistory) {
22 if self.search_query.is_empty() {
23 self.matches = history
25 .get_session_entries()
26 .iter()
27 .map(|entry| HistoryMatch {
28 entry: entry.clone(),
29 score: 100,
30 indices: Vec::new(),
31 })
32 .collect();
33 } else {
34 self.matches = history.search(&self.search_query);
36 }
37
38 if self.selected_index >= self.matches.len() && !self.matches.is_empty() {
40 self.selected_index = self.matches.len() - 1;
41 }
42 }
43
44 pub fn next_match(&mut self) {
46 if !self.matches.is_empty() {
47 self.selected_index = (self.selected_index + 1) % self.matches.len();
48 }
49 }
50
51 pub fn previous_match(&mut self) {
53 if !self.matches.is_empty() {
54 if self.selected_index == 0 {
55 self.selected_index = self.matches.len() - 1;
56 } else {
57 self.selected_index -= 1;
58 }
59 }
60 }
61
62 #[must_use]
64 pub fn get_selected(&self) -> Option<&HistoryMatch> {
65 if self.selected_index < self.matches.len() {
66 self.matches.get(self.selected_index)
67 } else {
68 None
69 }
70 }
71
72 pub fn clear(&mut self) {
74 self.search_query.clear();
75 self.matches.clear();
76 self.selected_index = 0;
77 }
78
79 pub fn set_search(&mut self, query: String, history: &CommandHistory) {
81 self.search_query = query;
82 self.update_matches(history);
83 }
84
85 #[must_use]
87 pub fn get_visible_range(&self, height: usize) -> (usize, usize) {
88 if self.matches.is_empty() {
89 return (0, 0);
90 }
91
92 let total = self.matches.len();
93 let half_height = height / 2;
94
95 let start = if self.selected_index <= half_height {
97 0
98 } else if self.selected_index + half_height >= total {
99 total.saturating_sub(height)
100 } else {
101 self.selected_index - half_height
102 };
103
104 let end = (start + height).min(total);
105 (start, end)
106 }
107}
108
109impl Default for HistoryManager {
110 fn default() -> Self {
111 Self::new()
112 }
113}