From 9174ccb2c0e3d0521d02817fe39cd5f55db92bf9 Mon Sep 17 00:00:00 2001 From: ceres Date: Mon, 18 Nov 2024 13:34:59 +0200 Subject: [PATCH 1/2] Add option to have process tree collapsed by default --- .../configuration/command-line-options.md | 1 + .../configuration/config-file/flags.md | 1 + src/app.rs | 2 + src/options.rs | 3 ++ src/options/args.rs | 7 +++ src/options/config/flags.rs | 1 + src/widgets/process_table.rs | 51 ++++++++++++------- 7 files changed, 48 insertions(+), 18 deletions(-) diff --git a/docs/content/configuration/command-line-options.md b/docs/content/configuration/command-line-options.md index 04c8f7748..47dc4b599 100644 --- a/docs/content/configuration/command-line-options.md +++ b/docs/content/configuration/command-line-options.md @@ -37,6 +37,7 @@ see information on these options by running `btm -h`, or run `btm --help` to dis | `-T, --tree` | Makes the process widget use tree mode by default. | | `-n, --unnormalized_cpu` | Show process CPU% usage without averaging over the number of CPU cores. | | `-W, --whole_word` | Enables whole-word matching by default while searching. | +| `--tree_collapse` | Collapse process tree by default. | ## Temperature Options diff --git a/docs/content/configuration/config-file/flags.md b/docs/content/configuration/config-file/flags.md index 9dd3edd0f..4a3cb5d37 100644 --- a/docs/content/configuration/config-file/flags.md +++ b/docs/content/configuration/config-file/flags.md @@ -51,3 +51,4 @@ each time: | `memory_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the memory widget. | | `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the network widget. | | `average_cpu_row` | Boolean | Moves the average CPU usage entry to its own row when using basic mode. | +| `tree_collapse` | Boolean | Collapse process tree by default. | diff --git a/src/app.rs b/src/app.rs index 3b3b28a7e..b2c0d1c77 100644 --- a/src/app.rs +++ b/src/app.rs @@ -68,6 +68,7 @@ pub struct AppConfigFields { pub network_use_binary_prefix: bool, pub retention_ms: u64, pub dedicated_average_row: bool, + pub tree_collapse: bool, } /// For filtering out information @@ -530,6 +531,7 @@ impl App { ProcWidgetMode::Normal => { proc_widget_state.mode = ProcWidgetMode::Tree { collapsed_pids: Default::default(), + collapse: self.app_config_fields.tree_collapse, }; proc_widget_state.force_rerender_and_update(); } diff --git a/src/options.rs b/src/options.rs index a0d3119ba..521d6de31 100644 --- a/src/options.rs +++ b/src/options.rs @@ -227,6 +227,7 @@ pub(crate) fn init_app( let is_default_command = is_flag_enabled!(process_command, args.process, config); let is_advanced_kill = !(is_flag_enabled!(disable_advanced_kill, args.process, config)); let process_memory_as_value = is_flag_enabled!(process_memory_as_value, args.process, config); + let tree_collapse = is_flag_enabled!(tree_collapse, args.process, config); // For CPU let default_cpu_selection = get_default_cpu_selection(args, config); @@ -305,6 +306,7 @@ pub(crate) fn init_app( network_use_binary_prefix, retention_ms, dedicated_average_row: get_dedicated_avg_row(config), + tree_collapse, }; let table_config = ProcTableConfig { @@ -384,6 +386,7 @@ pub(crate) fn init_app( } else if is_default_tree { ProcWidgetMode::Tree { collapsed_pids: Default::default(), + collapse: tree_collapse, } } else { ProcWidgetMode::Normal diff --git a/src/options/args.rs b/src/options/args.rs index e49cf16dd..eba741701 100644 --- a/src/options/args.rs +++ b/src/options/args.rs @@ -346,6 +346,13 @@ pub struct ProcessArgs { help = "Enables whole-word matching by default while searching." )] pub whole_word: bool, + + #[arg( + long, + action = ArgAction::SetTrue, + help = "Collapse process tree by default." + )] + pub tree_collapse: bool, } /// Temperature arguments/config options. diff --git a/src/options/config/flags.rs b/src/options/config/flags.rs index 1d020e016..784a031bc 100644 --- a/src/options/config/flags.rs +++ b/src/options/config/flags.rs @@ -44,4 +44,5 @@ pub(crate) struct FlagConfig { pub(crate) enable_cache_memory: Option, pub(crate) retention: Option, pub(crate) average_cpu_row: Option, + pub(crate) tree_collapse: Option, } diff --git a/src/widgets/process_table.rs b/src/widgets/process_table.rs index 6e620eaa1..4a56b2c12 100644 --- a/src/widgets/process_table.rs +++ b/src/widgets/process_table.rs @@ -62,7 +62,10 @@ impl ProcessSearchState { #[derive(Clone, Debug, Eq, PartialEq)] pub enum ProcWidgetMode { - Tree { collapsed_pids: HashSet }, + Tree { + collapsed_pids: HashSet, + collapse: bool, + }, Grouped, Normal, } @@ -400,15 +403,16 @@ impl ProcWidgetState { ProcWidgetMode::Grouped | ProcWidgetMode::Normal => { self.get_normal_data(&data_collection.process_data.process_harvest) } - ProcWidgetMode::Tree { collapsed_pids } => { - self.get_tree_data(collapsed_pids, data_collection) - } + ProcWidgetMode::Tree { + collapsed_pids, + collapse, + } => self.get_tree_data(collapsed_pids, data_collection, collapse), }; self.table.set_data(data); } fn get_tree_data( - &self, collapsed_pids: &HashSet, data_collection: &DataCollection, + &self, collapsed_pids: &HashSet, data_collection: &DataCollection, collapse: &bool, ) -> Vec { const BRANCH_END: char = '└'; const BRANCH_SPLIT: char = '├'; @@ -567,8 +571,18 @@ impl ProcWidgetState { let disabled = !kept_pids.contains(&process.pid); let is_last = *siblings_left == 0; - if collapsed_pids.contains(&process.pid) { + if !collapsed_pids.contains(&process.pid) & collapse { let mut summed_process = process.clone(); + let mut prefix = if prefixes.is_empty() { + String::default() + } else { + format!( + "{}{}{} ", + prefixes.join(""), + if is_last { BRANCH_END } else { BRANCH_SPLIT }, + BRANCH_HORIZONTAL + ) + }; if let Some(children_pids) = filtered_tree.get(&process.pid) { let mut sum_queue = children_pids @@ -591,19 +605,20 @@ impl ProcWidgetState { })); } } + if !children_pids.is_empty() { + prefix = if prefixes.is_empty() { + "+ ".to_string() + } else { + format!( + "{}{}{} + ", + prefixes.join(""), + if is_last { BRANCH_END } else { BRANCH_SPLIT }, + BRANCH_HORIZONTAL + ) + }; + } } - let prefix = if prefixes.is_empty() { - "+ ".to_string() - } else { - format!( - "{}{}{} + ", - prefixes.join(""), - if is_last { BRANCH_END } else { BRANCH_SPLIT }, - BRANCH_HORIZONTAL - ) - }; - data.push(summed_process.prefix(Some(prefix)).disabled(disabled)); } else { let prefix = if prefixes.is_empty() { @@ -817,7 +832,7 @@ impl ProcWidgetState { } pub fn toggle_current_tree_branch_entry(&mut self) { - if let ProcWidgetMode::Tree { collapsed_pids } = &mut self.mode { + if let ProcWidgetMode::Tree { collapsed_pids, .. } = &mut self.mode { if let Some(process) = self.table.current_item() { let pid = process.pid; From ca0abc81bfb4de868d7d59f8e268f9e8d9c25328 Mon Sep 17 00:00:00 2001 From: ceres Date: Tue, 19 Nov 2024 09:14:56 +0200 Subject: [PATCH 2/2] Fix collapse logic --- src/widgets/process_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/process_table.rs b/src/widgets/process_table.rs index 4a56b2c12..1434cc0e1 100644 --- a/src/widgets/process_table.rs +++ b/src/widgets/process_table.rs @@ -571,7 +571,7 @@ impl ProcWidgetState { let disabled = !kept_pids.contains(&process.pid); let is_last = *siblings_left == 0; - if !collapsed_pids.contains(&process.pid) & collapse { + if collapsed_pids.contains(&process.pid).eq(&!collapse) { let mut summed_process = process.clone(); let mut prefix = if prefixes.is_empty() { String::default()