diff --git a/src/app.rs b/src/app.rs index b226b3f5..5df1aa9d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -172,7 +172,7 @@ impl App { .widget_states .values_mut() .for_each(|state| { - state.search_state.search_state.reset(); + state.proc_search.search_state.reset(); }); // Clear current delete list @@ -223,7 +223,7 @@ impl App { { if current_proc_state.is_search_enabled() || current_proc_state.is_sort_open { - current_proc_state.search_state.search_state.is_enabled = false; + current_proc_state.proc_search.search_state.is_enabled = false; current_proc_state.is_sort_open = false; self.is_force_redraw = true; return; @@ -236,7 +236,7 @@ impl App { .get_mut_widget_state(self.current_widget.widget_id - 1) { if current_proc_state.is_search_enabled() { - current_proc_state.search_state.search_state.is_enabled = false; + current_proc_state.proc_search.search_state.is_enabled = false; self.move_widget_selection(&WidgetDirection::Up); self.is_force_redraw = true; return; @@ -325,7 +325,7 @@ impl App { _ => 0, }, ) { - proc_widget_state.search_state.search_state.is_enabled = true; + proc_widget_state.proc_search.search_state.is_enabled = true; self.move_widget_selection(&WidgetDirection::Down); self.is_force_redraw = true; } @@ -412,12 +412,12 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget && proc_widget_state.is_search_enabled() { - proc_widget_state.search_state.search_toggle_ignore_case(); + proc_widget_state.proc_search.search_toggle_ignore_case(); proc_widget_state.update_query(); proc_widget_state.force_update = true; // Remember, it's the opposite (ignoring case is case "in"sensitive) - is_case_sensitive = Some(!proc_widget_state.search_state.is_ignoring_case); + is_case_sensitive = Some(!proc_widget_state.proc_search.is_ignoring_case); } } @@ -463,12 +463,12 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget && proc_widget_state.is_search_enabled() { - proc_widget_state.search_state.search_toggle_whole_word(); + proc_widget_state.proc_search.search_toggle_whole_word(); proc_widget_state.update_query(); proc_widget_state.force_update = true; is_searching_whole_word = - Some(proc_widget_state.search_state.is_searching_whole_word); + Some(proc_widget_state.proc_search.is_searching_whole_word); } } @@ -518,12 +518,12 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget && proc_widget_state.is_search_enabled() { - proc_widget_state.search_state.search_toggle_regex(); + proc_widget_state.proc_search.search_toggle_regex(); proc_widget_state.update_query(); proc_widget_state.force_update = true; is_searching_with_regex = - Some(proc_widget_state.search_state.is_searching_with_regex); + Some(proc_widget_state.proc_search.is_searching_with_regex); } } @@ -631,10 +631,10 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget { - if proc_widget_state.search_state.search_state.is_enabled + if proc_widget_state.proc_search.search_state.is_enabled && proc_widget_state.get_search_cursor_position() < proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len() @@ -644,17 +644,17 @@ impl App { .search_walk_forward(proc_widget_state.get_search_cursor_position()); let _removed_chars: String = proc_widget_state - .search_state + .proc_search .search_state .current_search_query .drain(current_cursor..proc_widget_state.get_search_cursor_position()) .collect(); - proc_widget_state.search_state.search_state.grapheme_cursor = + proc_widget_state.proc_search.search_state.grapheme_cursor = GraphemeCursor::new( current_cursor, proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), @@ -680,7 +680,7 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget - && proc_widget_state.search_state.search_state.is_enabled + && proc_widget_state.proc_search.search_state.is_enabled && proc_widget_state.get_search_cursor_position() > 0 { let current_cursor = proc_widget_state.get_search_cursor_position(); @@ -688,17 +688,17 @@ impl App { .search_walk_back(proc_widget_state.get_search_cursor_position()); let removed_chars: String = proc_widget_state - .search_state + .proc_search .search_state .current_search_query .drain(proc_widget_state.get_search_cursor_position()..current_cursor) .collect(); - proc_widget_state.search_state.search_state.grapheme_cursor = + proc_widget_state.proc_search.search_state.grapheme_cursor = GraphemeCursor::new( proc_widget_state.get_search_cursor_position(), proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), @@ -706,11 +706,11 @@ impl App { ); proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position -= UnicodeWidthStr::width(removed_chars.as_str()); - proc_widget_state.search_state.search_state.cursor_direction = + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Left; proc_widget_state.update_query(); @@ -722,7 +722,7 @@ impl App { pub fn get_process_filter(&self, widget_id: u64) -> &Option<query::Query> { if let Some(process_widget_state) = self.proc_state.widget_states.get(&widget_id) { - &process_widget_state.search_state.search_state.query + &process_widget_state.proc_search.search_state.query } else { &None } @@ -819,15 +819,15 @@ impl App { .search_walk_back(proc_widget_state.get_search_cursor_position()); if proc_widget_state.get_search_cursor_position() < prev_cursor { let str_slice = &proc_widget_state - .search_state + .proc_search .search_state .current_search_query [proc_widget_state.get_search_cursor_position()..prev_cursor]; proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position -= UnicodeWidthStr::width(str_slice); - proc_widget_state.search_state.search_state.cursor_direction = + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Left; } } @@ -889,15 +889,15 @@ impl App { ); if proc_widget_state.get_search_cursor_position() > prev_cursor { let str_slice = &proc_widget_state - .search_state + .proc_search .search_state .current_search_query [prev_cursor..proc_widget_state.get_search_cursor_position()]; proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position += UnicodeWidthStr::width(str_slice); - proc_widget_state.search_state.search_state.cursor_direction = + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Right; } } @@ -1005,21 +1005,21 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget { - proc_widget_state.search_state.search_state.grapheme_cursor = + proc_widget_state.proc_search.search_state.grapheme_cursor = GraphemeCursor::new( 0, proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), true, ); proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position = 0; - proc_widget_state.search_state.search_state.cursor_direction = + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Left; } } @@ -1037,31 +1037,31 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget { - proc_widget_state.search_state.search_state.grapheme_cursor = + proc_widget_state.proc_search.search_state.grapheme_cursor = GraphemeCursor::new( proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), true, ); proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position = UnicodeWidthStr::width( proc_widget_state - .search_state + .proc_search .search_state .current_search_query .as_str(), ); - proc_widget_state.search_state.search_state.cursor_direction = + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Right; } } @@ -1117,16 +1117,16 @@ impl App { } let removed_chars: String = proc_widget_state - .search_state + .proc_search .search_state .current_search_query .drain(start_index..end_index) .collect(); - proc_widget_state.search_state.search_state.grapheme_cursor = GraphemeCursor::new( + proc_widget_state.proc_search.search_state.grapheme_cursor = GraphemeCursor::new( start_index, proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), @@ -1134,12 +1134,11 @@ impl App { ); proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position -= UnicodeWidthStr::width(removed_chars.as_str()); - proc_widget_state.search_state.search_state.cursor_direction = - CursorDirection::Left; + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Left; proc_widget_state.update_query(); proc_widget_state.force_update = true; @@ -1214,23 +1213,23 @@ impl App { && proc_widget_state.is_search_enabled() && UnicodeWidthStr::width( proc_widget_state - .search_state + .proc_search .search_state .current_search_query .as_str(), ) <= MAX_SEARCH_LENGTH { proc_widget_state - .search_state + .proc_search .search_state .current_search_query .insert(proc_widget_state.get_search_cursor_position(), caught_char); - proc_widget_state.search_state.search_state.grapheme_cursor = + proc_widget_state.proc_search.search_state.grapheme_cursor = GraphemeCursor::new( proc_widget_state.get_search_cursor_position(), proc_widget_state - .search_state + .proc_search .search_state .current_search_query .len(), @@ -1240,14 +1239,14 @@ impl App { .search_walk_forward(proc_widget_state.get_search_cursor_position()); proc_widget_state - .search_state + .proc_search .search_state .char_cursor_position += UnicodeWidthChar::width(caught_char).unwrap_or(0); proc_widget_state.update_query(); proc_widget_state.force_update = true; - proc_widget_state.search_state.search_state.cursor_direction = + proc_widget_state.proc_search.search_state.cursor_direction = CursorDirection::Right; return; diff --git a/src/app/widgets/process_widget.rs b/src/app/widgets/process_widget.rs index bf449e85..dcd1503c 100644 --- a/src/app/widgets/process_widget.rs +++ b/src/app/widgets/process_widget.rs @@ -306,7 +306,7 @@ impl TableComponentHeader for ProcWidgetColumn { pub struct ProcWidget { pub mode: ProcWidgetMode, - pub search_state: ProcessSearchState, + pub proc_search: ProcessSearchState, pub table_state: TableComponentState<ProcWidgetColumn>, pub sort_table_state: TableComponentState, @@ -391,7 +391,7 @@ impl ProcWidget { }; ProcWidget { - search_state: process_search_state, + proc_search: process_search_state, table_state, sort_table_state, is_sort_open: false, @@ -419,10 +419,10 @@ impl ProcWidget { /// call it before this function. pub fn update_displayed_process_data(&mut self, data_collection: &DataCollection) { // Now update everything else. - let search_query = if self.search_state.search_state.is_invalid_or_blank_search() { + let search_query = if self.proc_search.search_state.is_invalid_or_blank_search() { &None } else { - &self.search_state.search_state.query + &self.proc_search.search_state.query }; let table_data = match &self.mode { ProcWidgetMode::Tree { collapsed_pids } => { @@ -863,7 +863,7 @@ impl ProcWidget { } /// Marks the selected column as hidden, and automatically resets the selected column if currently selected. - pub fn hide_column(&mut self, index: usize) { + fn hide_column(&mut self, index: usize) { if let Some(col) = self.table_state.columns.get_mut(index) { col.is_hidden = true; @@ -877,7 +877,7 @@ impl ProcWidget { } /// Marks the selected column as shown. - pub fn show_column(&mut self, index: usize) { + fn show_column(&mut self, index: usize) { if let Some(col) = self.table_state.columns.get_mut(index) { col.is_hidden = false; } @@ -964,48 +964,48 @@ impl ProcWidget { } pub fn get_search_cursor_position(&self) -> usize { - self.search_state.search_state.grapheme_cursor.cur_cursor() + self.proc_search.search_state.grapheme_cursor.cur_cursor() } pub fn get_char_cursor_position(&self) -> usize { - self.search_state.search_state.char_cursor_position + self.proc_search.search_state.char_cursor_position } pub fn is_search_enabled(&self) -> bool { - self.search_state.search_state.is_enabled + self.proc_search.search_state.is_enabled } pub fn get_current_search_query(&self) -> &String { - &self.search_state.search_state.current_search_query + &self.proc_search.search_state.current_search_query } pub fn update_query(&mut self) { if self - .search_state + .proc_search .search_state .current_search_query .is_empty() { - self.search_state.search_state.is_blank_search = true; - self.search_state.search_state.is_invalid_search = false; - self.search_state.search_state.error_message = None; + self.proc_search.search_state.is_blank_search = true; + self.proc_search.search_state.is_invalid_search = false; + self.proc_search.search_state.error_message = None; } else { match parse_query( - &self.search_state.search_state.current_search_query, - self.search_state.is_searching_whole_word, - self.search_state.is_ignoring_case, - self.search_state.is_searching_with_regex, + &self.proc_search.search_state.current_search_query, + self.proc_search.is_searching_whole_word, + self.proc_search.is_ignoring_case, + self.proc_search.is_searching_with_regex, ) { Ok(parsed_query) => { - self.search_state.search_state.query = Some(parsed_query); - self.search_state.search_state.is_blank_search = false; - self.search_state.search_state.is_invalid_search = false; - self.search_state.search_state.error_message = None; + self.proc_search.search_state.query = Some(parsed_query); + self.proc_search.search_state.is_blank_search = false; + self.proc_search.search_state.is_invalid_search = false; + self.proc_search.search_state.error_message = None; } Err(err) => { - self.search_state.search_state.is_blank_search = false; - self.search_state.search_state.is_invalid_search = true; - self.search_state.search_state.error_message = Some(err.to_string()); + self.proc_search.search_state.is_blank_search = false; + self.proc_search.search_state.is_invalid_search = true; + self.proc_search.search_state.error_message = Some(err.to_string()); } } } @@ -1014,31 +1014,32 @@ impl ProcWidget { } pub fn clear_search(&mut self) { - self.search_state.search_state.reset(); + self.proc_search.search_state.reset(); } pub fn search_walk_forward(&mut self, start_position: usize) { - self.search_state + self.proc_search .search_state .grapheme_cursor .next_boundary( - &self.search_state.search_state.current_search_query[start_position..], + &self.proc_search.search_state.current_search_query[start_position..], start_position, ) .unwrap(); } pub fn search_walk_back(&mut self, start_position: usize) { - self.search_state + self.proc_search .search_state .grapheme_cursor .prev_boundary( - &self.search_state.search_state.current_search_query[..start_position], + &self.proc_search.search_state.current_search_query[..start_position], 0, ) .unwrap(); } + /// Returns the number of columns *visible*. pub fn num_shown_columns(&self) -> usize { self.table_state .columns @@ -1047,6 +1048,8 @@ impl ProcWidget { .count() } + /// Returns the number of columns *enabled*. Note this differs from *visible* - a column may be enabled but not + /// visible (e.g. off screen). pub fn num_enabled_columns(&self) -> usize { self.table_state .columns @@ -1055,6 +1058,7 @@ impl ProcWidget { .count() } + /// Sets the [`ProcWidget`]'s current sort index to whatever was in the sort table. pub(crate) fn use_sort_table_value(&mut self) { if let SortState::Sortable(st) = &mut self.table_state.sort_state { st.update_sort_index(self.sort_table_state.current_scroll_position); diff --git a/src/canvas/components/text_table.rs b/src/canvas/components/text_table.rs index 20b956de..fe94ffa5 100644 --- a/src/canvas/components/text_table.rs +++ b/src/canvas/components/text_table.rs @@ -440,7 +440,6 @@ mod test { use crate::app::ScrollDirection::{self, Down, Up}; #[track_caller] - fn test_get( bar: usize, rows: usize, direction: ScrollDirection, selected: usize, force: bool, expected_posn: usize, expected_bar: usize, diff --git a/src/canvas/widgets/process_table.rs b/src/canvas/widgets/process_table.rs index a5f28f5e..306aac20 100644 --- a/src/canvas/widgets/process_table.rs +++ b/src/canvas/widgets/process_table.rs @@ -81,6 +81,7 @@ impl Painter { ) { let should_get_widget_bounds = app_state.should_get_widget_bounds(); if let Some(proc_widget_state) = app_state.proc_state.widget_states.get_mut(&widget_id) { + // TODO: [PROC] this might be too aggressive... let recalculate_column_widths = should_get_widget_bounds || proc_widget_state.force_update; @@ -191,8 +192,8 @@ impl Painter { let start_position: usize = get_search_start_position( num_columns - num_chars_for_text - 5, - &proc_widget_state.search_state.search_state.cursor_direction, - &mut proc_widget_state.search_state.search_state.cursor_bar, + &proc_widget_state.proc_search.search_state.cursor_direction, + &mut proc_widget_state.proc_search.search_state.cursor_bar, current_cursor_position, app_state.is_force_redraw, ); @@ -227,19 +228,19 @@ impl Painter { })]; // Text options shamelessly stolen from VS Code. - let case_style = if !proc_widget_state.search_state.is_ignoring_case { + let case_style = if !proc_widget_state.proc_search.is_ignoring_case { self.colours.currently_selected_text_style } else { self.colours.text_style }; - let whole_word_style = if proc_widget_state.search_state.is_searching_whole_word { + let whole_word_style = if proc_widget_state.proc_search.is_searching_whole_word { self.colours.currently_selected_text_style } else { self.colours.text_style }; - let regex_style = if proc_widget_state.search_state.is_searching_with_regex { + let regex_style = if proc_widget_state.proc_search.is_searching_with_regex { self.colours.currently_selected_text_style } else { self.colours.text_style @@ -265,7 +266,7 @@ impl Painter { ]); search_text.push(Spans::from(Span::styled( - if let Some(err) = &proc_widget_state.search_state.search_state.error_message { + if let Some(err) = &proc_widget_state.proc_search.search_state.error_message { err.as_str() } else { "" @@ -274,17 +275,14 @@ impl Painter { ))); search_text.push(option_text); - let current_border_style = if proc_widget_state - .search_state - .search_state - .is_invalid_search - { - self.colours.invalid_query_style - } else if is_on_widget { - self.colours.highlighted_border_style - } else { - self.colours.border_style - }; + let current_border_style = + if proc_widget_state.proc_search.search_state.is_invalid_search { + self.colours.invalid_query_style + } else if is_on_widget { + self.colours.highlighted_border_style + } else { + self.colours.border_style + }; let title = Span::styled( if draw_border { diff --git a/src/options.rs b/src/options.rs index 3ff77920..2ff82be9 100644 --- a/src/options.rs +++ b/src/options.rs @@ -474,7 +474,7 @@ pub fn build_app( let mapping = HashMap::new(); for widget in search_case_enabled_widgets { if let Some(proc_widget) = proc_state_map.get_mut(&widget.id) { - proc_widget.search_state.is_ignoring_case = !widget.enabled; + proc_widget.proc_search.is_ignoring_case = !widget.enabled; } } flags.search_case_enabled_widgets_map = Some(mapping); @@ -488,7 +488,7 @@ pub fn build_app( let mapping = HashMap::new(); for widget in search_whole_word_enabled_widgets { if let Some(proc_widget) = proc_state_map.get_mut(&widget.id) { - proc_widget.search_state.is_searching_whole_word = widget.enabled; + proc_widget.proc_search.is_searching_whole_word = widget.enabled; } } flags.search_whole_word_enabled_widgets_map = Some(mapping); @@ -500,7 +500,7 @@ pub fn build_app( let mapping = HashMap::new(); for widget in search_regex_enabled_widgets { if let Some(proc_widget) = proc_state_map.get_mut(&widget.id) { - proc_widget.search_state.is_searching_with_regex = widget.enabled; + proc_widget.proc_search.is_searching_with_regex = widget.enabled; } } flags.search_regex_enabled_widgets_map = Some(mapping); diff --git a/src/utils/gen_util.rs b/src/utils/gen_util.rs index 573d32af..c91a6852 100644 --- a/src/utils/gen_util.rs +++ b/src/utils/gen_util.rs @@ -92,6 +92,7 @@ pub fn get_decimal_prefix(quantity: u64, unit: &str) -> (f64, String) { } } +#[inline] pub fn sort_partial_fn<T: std::cmp::PartialOrd>(is_reverse: bool) -> fn(T, T) -> Ordering { if is_reverse { partial_ordering_rev @@ -101,15 +102,19 @@ pub fn sort_partial_fn<T: std::cmp::PartialOrd>(is_reverse: bool) -> fn(T, T) -> } /// Returns an [`Ordering`] between two [`PartialOrd`]s. +#[inline] pub fn partial_ordering<T: std::cmp::PartialOrd>(a: T, b: T) -> Ordering { // TODO: Switch to `total_cmp` on 1.62 a.partial_cmp(&b).unwrap_or(Ordering::Equal) } /// Returns a reversed [`Ordering`] between two [`PartialOrd`]s. +/// +/// This is simply a wrapper function around [`partial_ordering`] that reverses +/// the result. +#[inline] pub fn partial_ordering_rev<T: std::cmp::PartialOrd>(a: T, b: T) -> Ordering { - // TODO: Switch to `total_cmp` on 1.62 - a.partial_cmp(&b).unwrap_or(Ordering::Equal).reverse() + partial_ordering(a, b).reverse() } #[cfg(test)]