From de22afc4c245b1eff2f37c3136753dedd27d1560 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Thu, 12 May 2022 00:00:00 -0500 Subject: [PATCH] top: extend 'Ctrl' bottom window for focus via tab key This commit introduces the 'tab' key which can be used to highlight individual elements in that bottom 'Ctrl' window. This can really help when reviewing such data. [ note, normal ongoing monitoring continues unabated ] Signed-off-by: Jim Warner --- top/top.c | 153 ++++++++++++++++++++++++++++++++++++++---------------- top/top.h | 8 +-- 2 files changed, 112 insertions(+), 49 deletions(-) diff --git a/top/top.c b/top/top.c index ed1792cb..2e45199f 100644 --- a/top/top.c +++ b/top/top.c @@ -104,20 +104,25 @@ static int Screen_cols, Screen_rows, Max_lines; // these are for the special separate bottom 'window' #define SCREEN_ROWS ( Screen_rows - Bot_rsvd ) -#define BOT_MAXIMUM 10 -#define BOT_DELIMIT -1 -#define BOT_MISC_NS +1 +#define BOT_MAXIMUM 10 // size of tagged item array +#define BOT_DELIMIT -1 // fenchpost with item array +#define BOT_UNFOCUS -1 // tab focus not established +#define BOT_TAB_YES -1 // tab focus could be active +#define BOT_MISC_NS +1 // data for namespaces req'd // 1 for horizontal separator #define BOT_RSVD 1 #define BOT_KEEP Bot_func = NULL #define BOT_TOSS do { Bot_func = NULL; Bot_item[0] = BOT_DELIMIT; \ - Bot_task = Bot_rsvd = Bot_misc = 0; \ + Bot_task = Bot_rsvd = Bot_what = 0; \ + Bot_indx = BOT_UNFOCUS; \ } while(0) static int Bot_task, - Bot_misc, + Bot_what, Bot_rsvd, + Bot_indx = BOT_UNFOCUS, Bot_item[BOT_MAXIMUM] = { BOT_DELIMIT }; -static char *Bot_name; +static char *Bot_name, + Bot_sep; static void(*Bot_func)(void); /* This is really the number of lines needed to display the summary @@ -4897,29 +4902,65 @@ static inline const char *forest_display (const WIN_t *q, int idx) { /*###### Special Separate Bottom Window support ########################*/ /* - * This guy actually draws the bottom window, | - * including the contents passed as a string. | */ -static void bot_do_see (const char *str, const char *pgm) { - #define maxRSVD ( Screen_rows - 1 ) - char buf[SMLBUFSIZ]; - - snprintf(buf, sizeof(buf), "%s for pid %d, %s" - , Bot_name, Bot_task, pgm); - if (!str || !*str || !strcmp(str, "-")) str = "n/a"; - Bot_rsvd = 1 + BOT_RSVD + (strlen(str) / Screen_cols); - if (Bot_rsvd > maxRSVD) Bot_rsvd = maxRSVD; - putp(fmtmk("%s%s%-*s", tg2(0, SCREEN_ROWS), Curwin->capclr_hdr, Screen_cols, buf)); - putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_clr_eos)); - putp(fmtmk("%s%s", tg2(0, SCREEN_ROWS + 1), Cap_norm)); - fputs(str, stdout); - #undef maxRSVD -} // end: bot_do_see + * This guy actually draws the parsed strings | + * including adding a highlight if necessary. | */ +static void bot_do (const char *str, int focus) { + while (*str == ' ') putchar(*(str++)); + putp(fmtmk("%s%s%s" + , focus ? Cap_reverse : Cap_norm + , str + , Cap_norm)); +} // end: bot_do /* - * This guy manages the bottom margin window, | + * This guy draws that bottom window's header | + * then parses/arranges to show the contents. | + * ( returns the number of elements printed ) | */ +static int bot_focus (const char *hdr, const char *str) { + #define maxRSVD ( Screen_rows - 1 ) + static char sav[BIGBUFSIZ*2]; + const char *end, *beg; + char tmp[SCREENMAX]; + int n, x; + + if (str) { + if (!*str || !strcmp(str, "-")) strcpy(sav, "n/a"); + else memccpy(sav, str, '\0', sizeof(sav) - 1); + Bot_rsvd = 1 + BOT_RSVD + (strlen(sav) / Screen_cols); + if (Bot_rsvd > maxRSVD) Bot_rsvd = maxRSVD; + // caller itself may have used fmtmk, so we'll old school it ... + snprintf(tmp, sizeof(tmp), "%s%s%-*s", tg2(0, SCREEN_ROWS), Curwin->capclr_hdr, Screen_cols, hdr); + putp(tmp); + } + // now fmtmk is safe to use ... + putp(fmtmk("%s%s%s", tg2(0, SCREEN_ROWS + 1), Cap_clr_eos, Cap_norm)); + + beg = &sav[0]; + x = BOT_UNFOCUS; + + while (*beg) { + if (!(end = strchr(beg, Bot_sep))) + end = beg + strlen(beg); + if ((n = end - beg) >= sizeof(tmp)) + n = sizeof(tmp) - 1; + memccpy(tmp, beg, '\0', n); + tmp[n] = '\0'; + bot_do(tmp, (++x == Bot_indx)); + if (*(beg += n)) + putchar(*(beg++)); + while (*beg == ' ') putchar(*(beg++)); + } + return x; + #undef maxRSVD +} // end: bot_focus + + + /* + * This guy manages that bottom margin window | * showing misc stuff based on a single item. | */ static void bot_item_show (void) { + #define mkHDR fmtmk("%s for pid %d, %s", Bot_name, Bot_task, PID_VAL(EU_CMD, str, p)) struct pids_stack *p; int i; @@ -4929,7 +4970,7 @@ static void bot_item_show (void) { break; } if (i < PIDSmaxt) { - bot_do_see(PID_VAL(Bot_item[0], str, p), PID_VAL(EU_CMD, str, p)); + bot_focus(mkHDR, PID_VAL(Bot_item[0], str, p)); } #ifdef BOT_DEAD_ZAP else @@ -4937,18 +4978,21 @@ static void bot_item_show (void) { #else BOT_KEEP; #endif + #undef mkHDR } // end: bot_item_show /* - * This guy toggles between displaying a Ctrl | + * This guy can toggle between displaying the | * bottom window or arranging to turn it off. | */ -static void bot_item_toggle (enum pflag item, const char *name) { +static void bot_item_toggle (enum pflag item, const char *name, char sep) { // if already targeted, assume user wants to turn it off ... if (Bot_item[0] == item) { BOT_TOSS; } else { - Bot_misc = 0; + Bot_sep = sep; + Bot_what = BOT_TAB_YES; + Bot_indx = BOT_UNFOCUS; Bot_item[0] = item; Bot_item[1] = BOT_DELIMIT; Bot_name = (char*)name; @@ -4968,20 +5012,26 @@ static struct { { EU_NS5, PROCPS_NS_USER }, { EU_NS6, PROCPS_NS_UTS } }; + /* * A helper function that will gather various | * stuff for dislay by the bot_misc_show guy. | */ static char *bot_misc_hlp (struct pids_stack *p) { - static char buf[BIGBUFSIZ], *b; + static char tmp[SMLBUFSIZ], buf[BIGBUFSIZ], *b; int i; buf[0] = '\0'; - switch (Bot_misc) { + switch (Bot_what) { case BOT_MISC_NS: b = &buf[0]; - for (i = 0; i < MAXTBL(ns_tab); i++) - b = scat(b, fmtmk("%s: %-10lu " - , procps_ns_get_name(ns_tab[i].that), PID_VAL(ns_tab[i].this, ul_int, p))); + for (i = 0; i < MAXTBL(ns_tab); i++) { + // caller itself may have used fmtmk, so we'll old school it ... + snprintf(tmp, sizeof(tmp), "%s: %-10lu" + , procps_ns_get_name(ns_tab[i].that) + , PID_VAL(ns_tab[i].this, ul_int, p)); + b = scat(b, tmp); + if (i < (MAXTBL(ns_tab) - 1)) b = scat(b, ", "); + } break; default: break; @@ -4991,9 +5041,10 @@ static char *bot_misc_hlp (struct pids_stack *p) { /* - * This guy manages the bottom margin window, | + * This guy manages that bottom margin window | * showing misc data based on multiple items. | */ static void bot_misc_show (void) { + #define mkHDR fmtmk("%s for pid %d, %s", Bot_name, Bot_task, PID_VAL(EU_CMD, str, p)) struct pids_stack *p; int i; @@ -5003,25 +5054,26 @@ static void bot_misc_show (void) { break; } if (i < PIDSmaxt) { - bot_do_see(bot_misc_hlp(p), PID_VAL(EU_CMD, str, p)); + bot_focus(mkHDR, bot_misc_hlp(p)); } -#ifdef BOT_DEATH +#ifdef BOT_DEAD_ZAP else BOT_TOSS; #else BOT_KEEP; #endif + #undef mkHDR } // end: bot_misc_show /* - * This guy toggles between displaying a Ctrl | + * This guy can toggle between displaying the | * bottom window or arranging to turn it off. | */ -static void bot_misc_toggle (int what) { +static void bot_misc_toggle (int what, char sep) { int i; // if already targeted, assume user wants to turn it off ... - if (Bot_misc == what) { + if (Bot_what == what) { BOT_TOSS; } else { switch (what) { @@ -5034,7 +5086,9 @@ static void bot_misc_toggle (int what) { default: break; } - Bot_misc = what; + Bot_sep = sep; + Bot_what = what; + Bot_indx = BOT_UNFOCUS; Bot_func = bot_misc_show; Bot_task = PID_VAL(EU_PID, s_int, Curwin->ppt[Curwin->begtask]); } @@ -5415,16 +5469,23 @@ static void keys_global (int ch) { #endif break; case kbd_CtrlG: - bot_item_toggle(EU_CGR, "control groups"); + bot_item_toggle(EU_CGR, "control groups", '/'); + break; + case kbd_CtrlI: + if (Bot_what) { + ++Bot_indx; + if (Bot_indx > bot_focus(NULL, NULL)) + Bot_indx = BOT_UNFOCUS; + } break; case kbd_CtrlK: - bot_item_toggle(eu_CMDLINE, "command line"); + bot_item_toggle(eu_CMDLINE, "command line", ' '); break; case kbd_CtrlN: - bot_item_toggle(EU_ENV, "environment"); + bot_item_toggle(EU_ENV, "environment", ' '); break; case kbd_CtrlP: - bot_misc_toggle(BOT_MISC_NS); + bot_misc_toggle(BOT_MISC_NS, ','); break; case kbd_CtrlR: if (Secure_mode) @@ -5453,7 +5514,7 @@ static void keys_global (int ch) { } break; case kbd_CtrlU: - bot_item_toggle(EU_SGN, "supplementary groups"); + bot_item_toggle(EU_SGN, "supplementary groups", ','); break; case kbd_ENTER: // these two have the effect of waking us case kbd_SPACE: // from 'pselect', refreshing the display @@ -6295,7 +6356,7 @@ static void do_key (int ch) { { keys_global, { '?', 'B', 'd', 'E', 'e', 'f', 'g', 'H', 'h' , 'I', 'k', 'r', 's', 'X', 'Y', 'Z', '0' - , kbd_CtrlE, kbd_CtrlG, kbd_CtrlK, kbd_CtrlN, kbd_CtrlP, kbd_CtrlR, kbd_CtrlU + , kbd_CtrlE, kbd_CtrlG, kbd_CtrlI, kbd_CtrlK, kbd_CtrlN, kbd_CtrlP, kbd_CtrlR, kbd_CtrlU , kbd_ENTER, kbd_SPACE, '\0' } }, { keys_summary, { '!', '1', '2', '3', '4', 'C', 'l', 'm', 't', '\0' } }, diff --git a/top/top.h b/top/top.h index bbee25fa..3299dd3d 100644 --- a/top/top.h +++ b/top/top.h @@ -173,6 +173,7 @@ char *strcasestr(const char *haystack, const char *needle); #define kbd_DEL 139 #define kbd_CtrlE '\005' #define kbd_CtrlG '\007' +#define kbd_CtrlI '\011' #define kbd_CtrlK '\013' #define kbd_CtrlN '\016' #define kbd_CtrlO '\017' @@ -735,12 +736,13 @@ typedef struct WIN_t { //atic void forest_config (WIN_t *q); //atic inline const char *forest_display (const WIN_t *q, int idx); /*------ Special Separate Bottom Window support ------------------------*/ -//atic void bot_do_see (const char *str, const char *pgm); +//atic void bot_do (const char *str, int focus); +//atic int bot_focus (const char *hdr, const char *str); //atic void bot_item_show (void); -//atic void bot_item_toggle (enum pflag item, const char *name); +//atic void bot_item_toggle (enum pflag item, const char *name, char sep); //atic char *bot_misc_hlp (struct pids_stack *p); //atic void bot_misc_show (void); -//atic void bot_misc_toggle (int what); +//atic void bot_misc_toggle (int what, char sep); /*------ Interactive Input Tertiary support ----------------------------*/ //atic inline int find_ofs (const WIN_t *q, const char *buf); //atic void find_string (int ch);