diff options
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/app.rs | 814 | ||||
-rw-r--r-- | src/app/data_harvester/processes/mod.rs | 33 | ||||
-rw-r--r-- | src/app/query.rs | 11 | ||||
-rw-r--r-- | src/app/states.rs | 841 | ||||
-rw-r--r-- | src/app/states/table_state.rs | 455 | ||||
-rw-r--r-- | src/app/widgets.rs | 2 | ||||
-rw-r--r-- | src/app/widgets/process.rs | 320 | ||||
-rw-r--r-- | src/canvas.rs | 11 | ||||
-rw-r--r-- | src/canvas/components/text_table.rs | 206 | ||||
-rw-r--r-- | src/canvas/dialogs/dd_dialog.rs | 10 | ||||
-rw-r--r-- | src/canvas/drawing_utils.rs | 256 | ||||
-rw-r--r-- | src/canvas/widgets/cpu_graph.rs | 4 | ||||
-rw-r--r-- | src/canvas/widgets/process_table.rs | 703 | ||||
-rw-r--r-- | src/data_conversion.rs | 37 | ||||
-rw-r--r-- | src/lib.rs | 72 | ||||
-rw-r--r-- | src/options.rs | 27 |
17 files changed, 1615 insertions, 2190 deletions
@@ -40,11 +40,12 @@ nvidia = ["nvml-wrapper"] [dependencies] anyhow = "1.0.57" backtrace = "0.3.65" +cfg-if = "1.0.0" crossterm = "0.18.2" ctrlc = { version = "3.1.9", features = ["termination"] } clap = { version = "3.1.12", features = ["default", "cargo", "wrap_help"] } -cfg-if = "1.0.0" concat-string = "1.0.1" +# const_format = "0.2.23" dirs = "4.0.0" futures = "0.3.21" futures-timer = "3.0.2" @@ -1,7 +1,6 @@ use std::{ cmp::{max, min}, collections::HashMap, - convert::TryInto, path::PathBuf, time::Instant, }; @@ -32,6 +31,7 @@ pub mod layout_manager; mod process_killer; pub mod query; pub mod states; +pub mod widgets; const MAX_SEARCH_LENGTH: usize = 200; @@ -127,9 +127,6 @@ pub struct App { #[builder(default = false, setter(skip))] pub basic_mode_use_percent: bool, - #[builder(default = false, setter(skip))] - pub did_config_fail_to_save: bool, - #[cfg(target_family = "unix")] #[builder(default, setter(skip))] pub user_table: processes::UserTable, @@ -172,9 +169,8 @@ impl App { .widget_states .values_mut() .for_each(|state| { - state.process_search_state.search_state.reset(); + state.search_state.search_state.reset(); }); - self.proc_state.force_update_all = true; // Clear current delete list self.to_delete_process_list = None; @@ -224,10 +220,7 @@ impl App { { if current_proc_state.is_search_enabled() || current_proc_state.is_sort_open { - current_proc_state - .process_search_state - .search_state - .is_enabled = false; + current_proc_state.search_state.search_state.is_enabled = false; current_proc_state.is_sort_open = false; self.is_force_redraw = true; return; @@ -240,10 +233,7 @@ impl App { .get_mut_widget_state(self.current_widget.widget_id - 1) { if current_proc_state.is_search_enabled() { - current_proc_state - .process_search_state - .search_state - .is_enabled = false; + current_proc_state.search_state.search_state.is_enabled = false; self.move_widget_selection(&WidgetDirection::Up); self.is_force_redraw = true; return; @@ -256,8 +246,6 @@ impl App { .get_mut_widget_state(self.current_widget.widget_id - 2) { if current_proc_state.is_sort_open { - current_proc_state.columns.current_scroll_position = - current_proc_state.columns.backup_prev_scroll_position; current_proc_state.is_sort_open = false; self.move_widget_selection(&WidgetDirection::Right); self.is_force_redraw = true; @@ -314,53 +302,55 @@ impl App { .proc_state .get_mut_widget_state(self.current_widget.widget_id) { - // Do NOT allow when in tree mode! - if !proc_widget_state.is_tree_mode { - // Toggles process widget grouping state - proc_widget_state.is_grouped = !(proc_widget_state.is_grouped); - - // Forcefully switch off column if we were on it... - if (proc_widget_state.is_grouped - && (proc_widget_state.process_sorting_type - == processes::ProcessSorting::Pid - || proc_widget_state.process_sorting_type - == processes::ProcessSorting::User - || proc_widget_state.process_sorting_type - == processes::ProcessSorting::State)) - || (!proc_widget_state.is_grouped - && proc_widget_state.process_sorting_type - == processes::ProcessSorting::Count) - { - proc_widget_state.process_sorting_type = - processes::ProcessSorting::CpuPercent; // Go back to default, negate PID for group - proc_widget_state.is_process_sort_descending = true; - } - - proc_widget_state.columns.set_to_sorted_index_from_type( - &proc_widget_state.process_sorting_type, - ); - - proc_widget_state.columns.try_set( - &processes::ProcessSorting::State, - !(proc_widget_state.is_grouped), - ); - - #[cfg(target_family = "unix")] - proc_widget_state.columns.try_set( - &processes::ProcessSorting::User, - !(proc_widget_state.is_grouped), - ); - - proc_widget_state - .columns - .toggle(&processes::ProcessSorting::Count); - proc_widget_state - .columns - .toggle(&processes::ProcessSorting::Pid); - - proc_widget_state.requires_redraw = true; - self.proc_state.force_update = Some(self.current_widget.widget_id); - } + todo!() + // FIXME: [Proc] Fix this. + // // Do NOT allow when in tree mode! + // if !proc_widget_state.is_tree_mode { + // // Toggles process widget grouping state + // proc_widget_state.is_grouped = !(proc_widget_state.is_grouped); + + // // Forcefully switch off column if we were on it... + // if (proc_widget_state.is_grouped + // && (proc_widget_state.process_sorting_type + // == processes::ProcessSorting::Pid + // || proc_widget_state.process_sorting_type + // == processes::ProcessSorting::User + // || proc_widget_state.process_sorting_type + // == processes::ProcessSorting::State)) + // || (!proc_widget_state.is_grouped + // && proc_widget_state.process_sorting_type + // == processes::ProcessSorting::Count) + // { + // proc_widget_state.process_sorting_type = + // processes::ProcessSorting::CpuPercent; // Go back to default, negate PID for group + // proc_widget_state.is_process_sort_descending = true; + // } + + // proc_widget_state.columns.set_to_sorted_index_from_type( + // &proc_widget_state.process_sorting_type, + // ); + + // proc_widget_state.columns.try_set( + // &processes::ProcessSorting::State, + // !(proc_widget_state.is_grouped), + // ); + + // #[cfg(target_family = "unix")] + // proc_widget_state.columns.try_set( + // &processes::ProcessSorting::User, + // !(proc_widget_state.is_grouped), + // ); + + // proc_widget_state + // .columns + // .toggle(&processes::ProcessSorting::Count); + // proc_widget_state + // .columns + // .toggle(&processes::ProcessSorting::Pid); + + // proc_widget_state.requires_redraw = true; + // self.proc_state.force_update = Some(self.current_widget.widget_id); + // } } } _ => {} @@ -368,16 +358,6 @@ impl App { } } - /// I don't like this, but removing it causes a bunch of breakage. - /// Use ``proc_widget_state.is_grouped`` if possible! - pub fn is_grouped(&self, widget_id: u64) -> bool { - if let Some(proc_widget_state) = self.proc_state.widget_states.get(&widget_id) { - proc_widget_state.is_grouped - } else { - false - } - } - pub fn on_slash(&mut self) { if !self.ignore_normal_keybinds() { match &self.current_widget.widget_type { @@ -390,10 +370,7 @@ impl App { _ => 0, }, ) { - proc_widget_state - .process_search_state - .search_state - .is_enabled = true; + proc_widget_state.search_state.search_state.is_enabled = true; self.move_widget_selection(&WidgetDirection::Down); self.is_force_redraw = true; } @@ -404,37 +381,22 @@ impl App { } pub fn toggle_sort(&mut self) { - match &self.current_widget.widget_type { - BottomWidgetType::Proc | BottomWidgetType::ProcSort => { - let widget_id = self.current_widget.widget_id - - match &self.current_widget.widget_type { - BottomWidgetType::Proc => 0, - BottomWidgetType::ProcSort => 2, - _ => 0, - }; - - if let Some(proc_widget_state) = self.proc_state.get_mut_widget_state(widget_id) { - // Open up sorting dialog for that specific proc widget. - // TODO: It might be a decent idea to allow sorting ALL? I dunno. + let widget_id = self.current_widget.widget_id + - match &self.current_widget.widget_type { + BottomWidgetType::Proc => 0, + BottomWidgetType::ProcSort => 2, + _ => 0, + }; - proc_widget_state.is_sort_open = !proc_widget_state.is_sort_open; - if proc_widget_state.is_sort_open { - // If it just opened, move left - proc_widget_state - .columns - .set_to_sorted_index_from_type(&proc_widget_state.process_sorting_type); - self.move_widget_selection(&WidgetDirection::Left); - } else { - // Otherwise, move right if currently on the sort widget - if let BottomWidgetType::ProcSort = self.current_widget.widget_type { - self.move_widget_selection(&WidgetDirection::Right); - } - } - } + if let Some(proc_widget_state) = self.proc_state.get_mut_widget_state(widget_id) { + proc_widget_state.is_sort_open = !proc_widget_state.is_sort_open; - self.is_force_redraw = true; + // If the sort is now open, move left. Otherwise, if the proc sort was selected, force move right. + if proc_widget_state.is_sort_open { + self.move_widget_selection(&WidgetDirection::Left); + } else if let BottomWidgetType::ProcSort = self.current_widget.widget_type { + self.move_widget_selection(&WidgetDirection::Right); } - _ => {} } } @@ -452,7 +414,7 @@ impl App { proc_widget_state.is_process_sort_descending = !proc_widget_state.is_process_sort_descending; - self.proc_state.force_update = Some(widget_id); + proc_widget_state.force_update = true; } } _ => {} @@ -470,30 +432,10 @@ impl App { .widget_states .get_mut(&self.current_widget.widget_id) { - proc_widget_state - .columns - .toggle(&processes::ProcessSorting::Mem); - if let Some(mem_percent_state) = proc_widget_state - .columns - .toggle(&processes::ProcessSorting::MemPercent) - { - if proc_widget_state.process_sorting_type - == processes::ProcessSorting::MemPercent - || proc_widget_state.process_sorting_type - == processes::ProcessSorting::Mem - { - if mem_percent_state { - proc_widget_state.process_sorting_type = - processes::ProcessSorting::MemPercent; - } else { - proc_widget_state.process_sorting_type = - processes::ProcessSorting::Mem; - } - } - } + // FIXME: [Proc]Handle this! + todo!(); - proc_widget_state.requires_redraw = true; - self.proc_state.force_update = Some(self.current_widget.widget_id); + proc_widget_state.force_update = true; } } _ => {} @@ -509,14 +451,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 - .process_search_state - .search_toggle_ignore_case(); + proc_widget_state.search_state.search_toggle_ignore_case(); proc_widget_state.update_query(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); + proc_widget_state.force_update = true; // Remember, it's the opposite (ignoring case is case "in"sensitive) - is_case_sensitive = Some(!proc_widget_state.process_search_state.is_ignoring_case); + is_case_sensitive = Some(!proc_widget_state.search_state.is_ignoring_case); } } @@ -550,8 +490,6 @@ impl App { .build(), ); } - - // self.did_config_fail_to_save = self.update_config_file().is_err(); } } @@ -564,17 +502,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 - .process_search_state - .search_toggle_whole_word(); + proc_widget_state.search_state.search_toggle_whole_word(); proc_widget_state.update_query(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); + proc_widget_state.force_update = true; - is_searching_whole_word = Some( - proc_widget_state - .process_search_state - .is_searching_whole_word, - ); + is_searching_whole_word = + Some(proc_widget_state.search_state.is_searching_whole_word); } } @@ -624,15 +557,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.process_search_state.search_toggle_regex(); + proc_widget_state.search_state.search_toggle_regex(); proc_widget_state.update_query(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); + proc_widget_state.force_update = true; - is_searching_with_regex = Some( - proc_widget_state - .process_search_state - .is_searching_with_regex, - ); + is_searching_with_regex = + Some(proc_widget_state.search_state.is_searching_with_regex); } } @@ -666,8 +596,6 @@ impl App { .build(), ); } - - // self.did_config_fail_to_save = self.update_config_file().is_err(); } } @@ -677,37 +605,37 @@ impl App { .widget_states .get_mut(&(self.current_widget.widget_id)) { - proc_widget_state.is_tree_mode = !proc_widget_state.is_tree_mode; + // proc_widget_state.is_tree_mode = !proc_widget_state.is_tree_mode; - // FIXME: For consistency, either disable tree mode if grouped, or allow grouped mode if in tree mode. - if proc_widget_state.is_tree_mode { - // Disable grouping if so! - proc_widget_state.is_grouped = false; + // // FIXME: For consistency, either disable tree mode if grouped, or allow grouped mode if in tree mode. + // if proc_widget_state.is_tree_mode { + // // Disable grouping if so! + // proc_widget_state.is_grouped = false; - proc_widget_state - .columns - .try_enable(&processes::ProcessSorting::State); + // proc_widget_state + // .columns + // .try_enable(&processes::ProcessSorting::State); - #[cfg(target_family = "unix")] - proc_widget_state - .columns - .try_enable(&processes::ProcessSorting::User); + // #[cfg(target_family = "unix")] + // proc_widget_state + // .columns + // .try_enable(&processes::ProcessSorting::User); - proc_widget_state - .columns - .try_disable(&processes::ProcessSorting::Count); + // proc_widget_state + // .columns + // .try_disable(&processes::ProcessSorting::Count); - proc_widget_state - .columns - .try_enable(&processes::ProcessSorting::Pid); + // proc_widget_state + // .columns + // .try_enable(&processes::ProcessSorting::Pid); - // We enabled... set PID sort type to ascending. - proc_widget_state.process_sorting_type = processes::ProcessSorting::Pid; - proc_widget_state.is_process_sort_descending = false; - } + // // We enabled... set PID sort type to ascending. + // proc_widget_state.process_sorting_type = processes::ProcessSorting::Pid; + // proc_widget_state.is_process_sort_descending = false; + // } - self.proc_state.force_update = Some(self.current_widget.widget_id); - proc_widget_state.requires_redraw = true; + // self.proc_state.force_update = Some(self.current_widget.widget_id); + // proc_widget_state.requires_redraw = true; } } @@ -744,9 +672,8 @@ impl App { .widget_states .get_mut(&(self.current_widget.widget_id - 2)) { - proc_widget_state.update_sorting_with_columns(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 2); - self.toggle_sort(); + // TODO: [Proc] Handle this + proc_widget_state.force_update = true; } } } @@ -761,13 +688,10 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget { - if proc_widget_state - .process_search_state - .search_state - .is_enabled + if proc_widget_state.search_state.search_state.is_enabled && proc_widget_state.get_search_cursor_position() < proc_widget_state - .process_search_state + .search_state .search_state .current_search_query .len() @@ -777,27 +701,25 @@ impl App { .search_walk_forward(proc_widget_state.get_search_cursor_position()); let _removed_chars: String = proc_widget_state - .process_search_state + .search_state .search_state .current_search_query .drain(current_cursor..proc_widget_state.get_search_cursor_position()) .collect(); - proc_widget_state - .process_search_state - .search_state - .grapheme_cursor = GraphemeCursor::new( - current_cursor, - proc_widget_state - .process_search_state - .search_state - .current_search_query - .len(), - true, - ); + proc_widget_state.search_state.search_state.grapheme_cursor = + GraphemeCursor::new( + current_cursor, + proc_widget_state + .search_state + .search_state + .current_search_query + .len(), + true, + ); proc_widget_state.update_query(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); + proc_widget_state.force_update = true; } } else { self.start_killing_process() @@ -815,10 +737,7 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget - && proc_widget_state - .process_search_state - .search_state - .is_enabled + && proc_widget_state.search_state.search_state.is_enabled && proc_widget_state.get_search_cursor_position() > 0 { let current_cursor = proc_widget_state.get_search_cursor_position(); @@ -826,37 +745,33 @@ impl App { .search_walk_back(proc_widget_state.get_search_cursor_position()); let removed_chars: String = proc_widget_state - .process_search_state + .search_state .search_state .current_search_query .drain(proc_widget_state.get_search_cursor_position()..current_cursor) .collect(); - proc_widget_state - .process_search_state - .search_state - .grapheme_cursor = GraphemeCursor::new( - proc_widget_state.get_search_cursor_position(), - proc_widget_state - .process_search_state - .search_state - .current_search_query - .len(), - true, - ); + proc_widget_state.search_state.search_state.grapheme_cursor = + GraphemeCursor::new( + proc_widget_state.get_search_cursor_position(), + proc_widget_state + .search_state + .search_state + .current_search_query + .len(), + true, + ); proc_widget_state - .process_search_state + .search_state .search_state .char_cursor_position -= UnicodeWidthStr::width(removed_chars.as_str()); - proc_widget_state - .process_search_state - .search_state - .cursor_direction = CursorDirection::Left; + proc_widget_state.search_state.search_state.cursor_direction = + CursorDirection::Left; proc_widget_state.update_query(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); + proc_widget_state.force_update = true; } } } @@ -864,7 +779,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.process_search_state.search_state.query + &process_widget_state.search_state.search_state.query } else { &None } @@ -961,18 +876,16 @@ 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 - .process_search_state + .search_state .search_state .current_search_query [proc_widget_state.get_search_cursor_position()..prev_cursor]; proc_widget_state - .process_search_state .search_state - .char_cursor_position -= UnicodeWidthStr::width(str_slice); - proc_widget_state - .process_search_state .search_state - .cursor_direction = CursorDirection::Left; + .char_cursor_position -= UnicodeWidthStr::width(str_slice); + proc_widget_state.search_state.search_state.cursor_direction = + CursorDirection::Left; } } } @@ -1033,18 +946,16 @@ impl App { ); if proc_widget_state.get_search_cursor_position() > prev_cursor { let str_slice = &proc_widget_state - .process_search_state + .search_state .search_state .current_search_query [prev_cursor..proc_widget_state.get_search_cursor_position()]; proc_widget_state - .process_search_state .search_state - .char_cursor_position += UnicodeWidthStr::width(str_slice); - proc_widget_state - .process_search_state .search_state - .cursor_direction = CursorDirection::Right; + .char_cursor_position += UnicodeWidthStr::width(str_slice); + proc_widget_state.search_state.search_state.cursor_direction = + CursorDirection::Right; } } } @@ -1151,26 +1062,22 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget { + proc_widget_state.search_state.search_state.grapheme_cursor = + GraphemeCursor::new( + 0, + proc_widget_state + .search_state + .search_state + .current_search_query + .len(), + true, + ); proc_widget_state - .process_search_state .search_state - .grapheme_cursor = GraphemeCursor::new( - 0, - proc_widget_state - .process_search_state - .search_state - .current_search_query - .len(), - true, - ); - proc_widget_state - .process_search_state .search_state .char_cursor_position = 0; - proc_widget_state - .process_search_state - .search_state - .cursor_direction = CursorDirection::Left; + proc_widget_state.search_state.search_state.cursor_direction = + CursorDirection::Left; } } } @@ -1187,36 +1094,32 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { if is_in_search_widget { + proc_widget_state.search_state.search_state.grapheme_cursor = + GraphemeCursor::new( + proc_widget_state + .search_state + .search_state + .current_search_query + .len(), + proc_widget_state + .search_state + .search_state + .current_search_query + .len(), + true, + ); proc_widget_state - .process_search_state .search_state - .grapheme_cursor = GraphemeCursor::new( - proc_widget_state - .process_search_state - .search_state - .current_search_query - .len(), - proc_widget_state - .process_search_state - .search_state - .current_search_query - .len(), - true, - ); - proc_widget_state - .process_search_state .search_state .char_cursor_position = UnicodeWidthStr::width( proc_widget_state - .process_search_state + .search_state .search_state .current_search_query .as_str(), ); - proc_widget_state - .process_search_state - .search_state - .cursor_direction = CursorDirection::Right; + proc_widget_state.search_state.search_state.cursor_direction = + CursorDirection::Right; } } } @@ -1231,7 +1134,7 @@ impl App { .get_mut(&(self.current_widget.widget_id - 1)) { proc_widget_state.clear_search(); - self.proc_state.force_update = Some(self.current_widget.widget_id - 1); + proc_widget_state.force_update = true; } } } @@ -1271,19 +1174,16 @@ impl App { } let removed_chars: String = proc_widget_state - .process_search_state + .search_state .search_state |