From 2c6222e30a25a833e8554709818e1c378ca46848 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Fri, 12 Feb 2021 18:48:09 +0100 Subject: [PATCH] Option and key ("*") to collapse / expand all branches under PID 1 (and PID 2 if kernel threads are shown) Based on hishamhm/htop#510 by Krishna Chaitanya, B Closes #68 --- Action.c | 14 ++++++++++++-- DisplayOptionsPanel.c | 1 + ProcessList.c | 10 ++++++++++ ProcessList.h | 2 ++ Settings.c | 4 ++++ Settings.h | 1 + htop.1.in | 4 +++- htop.c | 3 +++ 8 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Action.c b/Action.c index a87ca1a8..30f25a1e 100644 --- a/Action.c +++ b/Action.c @@ -227,10 +227,19 @@ static Htop_Reaction actionToggleMergedCommand(State* st) { static Htop_Reaction actionToggleTreeView(State* st) { st->settings->treeView = !st->settings->treeView; - ProcessList_expandTree(st->pl); + if (!st->settings->allBranchesCollapsed) ProcessList_expandTree(st->pl); return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_KEEP_FOLLOWING | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR; } +static Htop_Reaction actionExpandOrCollapseAllBranches(State* st) { + st->settings->allBranchesCollapsed = !st->settings->allBranchesCollapsed; + if (st->settings->allBranchesCollapsed) + ProcessList_collapseAllBranches(st->pl); + else + ProcessList_expandTree(st->pl); + return HTOP_REFRESH | HTOP_SAVE_SETTINGS; +} + static Htop_Reaction actionIncFilter(State* st) { IncSet* inc = (st->mainPanel)->inc; IncSet_activate(inc, INC_FILTER, (Panel*)st->mainPanel); @@ -438,7 +447,7 @@ static const struct { { .key = " H: ", .info = "hide/show user process threads" }, { .key = " K: ", .info = "hide/show kernel threads" }, { .key = " F: ", .info = "cursor follows process" }, - { .key = " + -: ", .info = "expand/collapse tree" }, + { .key = " + - *: ", .info = "expand/collapse tree (* = toggle all)" }, { .key = "N P M T: ", .info = "sort by PID, CPU%, MEM% or TIME" }, { .key = " I: ", .info = "invert sort order" }, { .key = " F6 > .: ", .info = "select sort column" }, @@ -621,6 +630,7 @@ static Htop_Reaction actionShowCommandScreen(State* st) { void Action_setBindings(Htop_Action* keys) { keys[' '] = actionTag; + keys['*'] = actionExpandOrCollapseAllBranches; keys['+'] = actionExpandOrCollapse; keys[','] = actionSetSortColumn; keys['-'] = actionExpandOrCollapse; diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c index 7e02b231..62bee9be 100644 --- a/DisplayOptionsPanel.c +++ b/DisplayOptionsPanel.c @@ -98,6 +98,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* Panel_setHeader(super, "Display options"); Panel_add(super, (Object*) CheckItem_newByRef("Tree view", &(settings->treeView))); Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is always sorted by PID (htop 2 behavior)", &(settings->treeViewAlwaysByPID))); + Panel_add(super, (Object*) CheckItem_newByRef("- Tree view is collapsed by default", &(settings->allBranchesCollapsed))); Panel_add(super, (Object*) CheckItem_newByRef("Shadow other users' processes", &(settings->shadowOtherUsers))); Panel_add(super, (Object*) CheckItem_newByRef("Hide kernel threads", &(settings->hideKernelThreads))); Panel_add(super, (Object*) CheckItem_newByRef("Hide userland process threads", &(settings->hideUserlandThreads))); diff --git a/ProcessList.c b/ProcessList.c index 5e6e917b..dcfa05dc 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -494,6 +494,16 @@ void ProcessList_expandTree(ProcessList* this) { } } +void ProcessList_collapseAllBranches(ProcessList* this) { + int size = Vector_size(this->processes); + for (int i = 0; i < size; i++) { + Process* process = (Process*) Vector_get(this->processes, i); + // FreeBSD has pid 0 = kernel and pid 1 = init, so init has tree_depth = 1 + if (process->tree_depth > 0 && process->pid > 1) + process->showChildren = false; + } +} + void ProcessList_rebuildPanel(ProcessList* this) { const char* incFilter = this->incFilter; diff --git a/ProcessList.h b/ProcessList.h index 3cd10a4e..a58f8028 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -106,6 +106,8 @@ ProcessField ProcessList_keyAt(const ProcessList* this, int at); void ProcessList_expandTree(ProcessList* this); +void ProcessList_collapseAllBranches(ProcessList* this); + void ProcessList_rebuildPanel(ProcessList* this); Process* ProcessList_getProcess(ProcessList* this, pid_t pid, bool* preExisting, Process_New constructor); diff --git a/Settings.c b/Settings.c index f12a51f4..a6ca7935 100644 --- a/Settings.c +++ b/Settings.c @@ -163,6 +163,8 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo this->treeView = atoi(option[1]); } else if (String_eq(option[0], "tree_view_always_by_pid")) { this->treeViewAlwaysByPID = atoi(option[1]); + } else if (String_eq(option[0], "all_branches_collapsed")) { + this->allBranchesCollapsed = atoi(option[1]); } else if (String_eq(option[0], "hide_kernel_threads")) { this->hideKernelThreads = atoi(option[1]); } else if (String_eq(option[0], "hide_userland_threads")) { @@ -314,6 +316,7 @@ bool Settings_write(Settings* this) { fprintf(fd, "show_merged_command=%d\n", (int) this->showMergedCommand); fprintf(fd, "tree_view=%d\n", (int) this->treeView); fprintf(fd, "tree_view_always_by_pid=%d\n", (int) this->treeViewAlwaysByPID); + fprintf(fd, "all_branches_collapsed=%d\n", (int) this->allBranchesCollapsed); fprintf(fd, "header_margin=%d\n", (int) this->headerMargin); fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime); fprintf(fd, "cpu_count_from_one=%d\n", (int) this->countCPUsFromOne); @@ -352,6 +355,7 @@ Settings* Settings_new(int initialCpuCount) { this->hideKernelThreads = false; this->hideUserlandThreads = false; this->treeView = false; + this->allBranchesCollapsed = false; this->highlightBaseName = false; this->highlightMegabytes = false; this->detailedCPUTime = false; diff --git a/Settings.h b/Settings.h index fdaf3e37..80ced433 100644 --- a/Settings.h +++ b/Settings.h @@ -47,6 +47,7 @@ typedef struct Settings_ { #endif bool treeView; bool treeViewAlwaysByPID; + bool allBranchesCollapsed; bool showProgramPath; bool shadowOtherUsers; bool showThreadNames; diff --git a/htop.1.in b/htop.1.in index a587af21..afd882e4 100644 --- a/htop.1.in +++ b/htop.1.in @@ -185,9 +185,11 @@ Quit Invert the sort order: if sort order is increasing, switch to decreasing, and vice-versa. .TP -.B +, \- +.B +, \-, * When in tree view mode, expand or collapse subtree. When a subtree is collapsed a "+" sign shows to the left of the process name. +Pressing "*" will expand or collapse all children of PIDs without parents, so +typically PID 1 (init) and PID 2 (kthreadd on Linux, if kernel threads are shown). .TP .B a (on multiprocessor machines) Set CPU affinity: mark which CPUs a process is allowed to use. diff --git a/htop.c b/htop.c index 65ad21e4..785d4554 100644 --- a/htop.c +++ b/htop.c @@ -469,6 +469,9 @@ int main(int argc, char** argv) { millisleep(75); ProcessList_scan(pl, false); + if (settings->allBranchesCollapsed) + ProcessList_collapseAllBranches(pl); + ScreenManager_run(scr, NULL, NULL); attron(CRT_colors[RESET_COLOR]);