top: add variable width data display without scrolling <=== port of newlib fb32021e

______________________________ original newlib message

There are times when one might want to see some task's
particular variable width data. However, prior to this
commit, the only way was to first turn on a field then
scroll through it via repeated right arrow keystrokes.

[ this also required that field to be displayed last ]

Needless to say, given the potential length of some of
that variable data this could be extremely cumbersome.

Now with this patch, a Ctrl keystroke combination will
create a separate window at the bottom of the terminal
screen where such variable width data is seen in full.

[ the targeted task is the 1st task displayed, which ]
[ is a convention employed in some existing commands ]

[ the targeted data was determined by these Ctrl key ]
[ combinations: CtrlG = ctrl group; CtrlK = cmdline; ]
[ CtrlU = supplementary groups; plus CtrlV = environ ]

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2022-06-15 00:00:00 -05:00 committed by Craig Small
parent 673fe994f9
commit 49bb9f9ae4
3 changed files with 150 additions and 16 deletions

151
top/top.c
View File

@ -110,7 +110,18 @@ static int Monpidsidx = 0;
basis (see the WIN_t). Max_lines is the total number of
screen rows after deducting summary information overhead. */
/* Current terminal screen size. */
static int Screen_cols, Screen_rows, Max_lines;
static int Screen_cols, Screen_rows, Max_lines;
// these are used to potentially set aside a bottom 'window'
#define SCREEN_ROWS ( Screen_rows - Tagged_rsvd )
// 1 for horizontal separator
#define TAGGED_RSVD ( 1 )
#define TAGGED_UNDO do { Tagged_task = Tagged_rsvd = Tagged_lflg = 0; } while (0)
static int Tagged_task,
Tagged_rsvd,
Tagged_lflg;
static char *Tagged_name;
static void(*Tagged_func)(void);
/* This is really the number of lines needed to display the summary
information (0 - nn), but is used as the relative row where we
@ -2128,6 +2139,9 @@ static void build_headers (void) {
if (EU_CMD == f && CHKw(w, Show_CMDLIN)) Frames_libflags |= L_CMDLINE;
// for 'U' filtering we need the other user ids too
if (w->usrseltyp == 'U') Frames_libflags |= L_status;
// lastly, accommodate any special non-display 'tagged' needs...
if (Tagged_lflg) Frames_libflags |= Tagged_lflg;
} // end: VIZISw(w)
if (Rc.mode_altscr) w = w->next;
@ -4540,13 +4554,14 @@ static void win_reset (WIN_t *q) {
#else
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->focus_pid = 0;
#endif
// these next two are global, not really windows based
Monpidsidx = 0;
Rc.tics_scaled = 0;
osel_clear(q);
q->findstr[0] = '\0';
q->rc.combine_cpus = 0;
// these next guys are global, not really windows based
Monpidsidx = 0;
Rc.tics_scaled = 0;
TAGGED_UNDO;
} // end: win_reset
@ -4829,6 +4844,70 @@ static void wins_stage_2 (void) {
} // end: wins_stage_2
/*
* This guy manages the bottom margin window |
* & the tagged process command line display | */
static void wins_tag_cmdline (void) {
char buf[SMLBUFSIZ];
const char *p;
int i;
for (i = 0; i < Frame_maxtask; i++) {
if (Tagged_task == Curwin->ppt[i]->tid)
break;
}
if (i < Frame_maxtask) {
snprintf(buf, sizeof(buf), "command line for pid %d:", Tagged_task);
p = *Curwin->ppt[i]->cmdline;
if (!p || !*p) p = "n/a";
Tagged_rsvd = 1 + TAGGED_RSVD + (strlen(p) / Screen_cols);
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(p, stdout);
} else {
TAGGED_UNDO;
}
} // end: wins_tag_cmdline
/*
* This guy manages the bottom margin window |
* showing miscellaneous variable width data | */
static void wins_tag_generic (void) {
char buf[SMLBUFSIZ];
const char *p;
int i;
for (i = 0; i < Frame_maxtask; i++) {
if (Tagged_task == Curwin->ppt[i]->tid)
break;
}
if (i < Frame_maxtask) {
snprintf(buf, sizeof(buf), "%s for pid %d:", Tagged_name, Tagged_task);
switch (Tagged_lflg) {
case (L_CGROUP): // Ctrl-G
p = *Curwin->ppt[i]->cgroup;
break;
case (L_SUPGRP): // Ctrl-U
p = Curwin->ppt[i]->supgrp;
break;
case (L_ENVIRON): // Ctrl-V
p = *Curwin->ppt[i]->environ;
break;
}
if (!p || !*p || !strcmp(p, "-")) p = "n/a";
Tagged_rsvd = 1 + TAGGED_RSVD + (strlen(p) / Screen_cols);
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(p, stdout);
} else {
TAGGED_UNDO;
}
} // end: wins_tag_generic
/*
* Determine if this task matches the 'u/U' selection
* criteria for a given window */
@ -5053,7 +5132,7 @@ static void forest_excluded (WIN_t *q) {
// if some task 'above' us ended, try to maintain focus
// ( but allow scrolling when there are many children )
if (q->begtask > q->focus_beg
&& (Screen_rows > (q->focus_end - q->focus_beg))) {
&& (SCREEN_ROWS > (q->focus_end - q->focus_beg))) {
q->begtask = q->focus_beg;
q->begnext = 0; // as 'mkVIZoff' but in any window
}
@ -5417,6 +5496,53 @@ static void keys_global (int ch) {
Rc.tics_scaled = 0;
#endif
break;
case kbd_CtrlG:
def = w->ppt[w->begtask]->tid;
// if already targeted, assume user wants to turn it off ...
if (Tagged_task && Tagged_lflg == (L_CGROUP)) {
TAGGED_UNDO;
} else {
Tagged_task = def;
Tagged_lflg = L_CGROUP;
Tagged_name = "control groups";
Tagged_func = wins_tag_generic;
}
break;
case kbd_CtrlK:
def = w->ppt[w->begtask]->tid;
// if already targeted, assume user wants to turn it off ...
if (Tagged_task && Tagged_lflg == (L_CMDLINE)) {
TAGGED_UNDO;
} else {
Tagged_task = def;
Tagged_lflg = L_CMDLINE;
Tagged_func = wins_tag_cmdline;
}
break;
case kbd_CtrlU:
def = w->ppt[w->begtask]->tid;
// if already targeted, assume user wants to turn it off ...
if (Tagged_task && Tagged_lflg == (L_SUPGRP)) {
TAGGED_UNDO;
} else {
Tagged_task = def;
Tagged_lflg = L_SUPGRP;
Tagged_name = "supplementary groups";
Tagged_func = wins_tag_generic;
}
break;
case kbd_CtrlV:
def = w->ppt[w->begtask]->tid;
// if already targeted, assume user wants to turn it off ...
if (Tagged_task && Tagged_lflg == (L_ENVIRON)) {
TAGGED_UNDO;
} else {
Tagged_task = def;
Tagged_lflg = L_ENVIRON;
Tagged_name = "environment";
Tagged_func = wins_tag_generic;
}
break;
case kbd_ENTER: // these two have the effect of waking us
case kbd_SPACE: // from 'pselect', refreshing the display
break; // and updating any hot-plugged resources
@ -6040,7 +6166,7 @@ static int sum_unify (CPU_t *cpu, int nobuf) {
* A helper function that displays cpu and/or numa node stuff |
* ( so as to keep the 'summary_show' guy a reasonable size ) | */
static void do_cpus (void) {
#define noMAS (Msg_row + 1 >= Screen_rows - 1)
#define noMAS (Msg_row + 1 >= SCREEN_ROWS - 1)
char tmp[MEDBUFSIZ];
int i;
@ -6230,7 +6356,8 @@ 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_ENTER, kbd_SPACE, '\0' } },
, kbd_CtrlE, kbd_CtrlG, kbd_CtrlK, kbd_CtrlU, kbd_CtrlV
, kbd_ENTER, kbd_SPACE, '\0' } },
{ keys_summary,
{ '!', '1', '2', '3', '4', 'C', 'l', 'm', 't', '\0' } },
{ keys_task,
@ -6300,7 +6427,7 @@ all_done:
* 2) Display task/cpu states (maybe)
* 3) Display memory & swap usage (maybe) */
static void summary_show (void) {
#define isROOM(f,n) (CHKw(Curwin, f) && Msg_row + (n) < Screen_rows - 1)
#define isROOM(f,n) (CHKw(Curwin, f) && Msg_row + (n) < SCREEN_ROWS - 1)
// Display Uptime and Loadavg
if (isROOM(View_LOADAV, 1)) {
@ -6815,7 +6942,7 @@ static void frame_make (void) {
Tree_idx = Pseudo_row = Msg_row = scrlins = 0;
summary_show();
Max_lines = (Screen_rows - Msg_row) - 1;
Max_lines = (SCREEN_ROWS - Msg_row) - 1;
// we're now on Msg_row so clear out any residual messages ...
putp(Cap_clr_eol);
@ -6842,8 +6969,8 @@ static void frame_make (void) {
PSU_CLREOS(Pseudo_row);
}
if (CHKw(w, View_SCROLL) && VIZISw(Curwin))
show_scroll();
if (CHKw(w, View_SCROLL) && VIZISw(Curwin)) show_scroll();
if (Tagged_task) Tagged_func();
fflush(stdout);
/* we'll deem any terminal not supporting tgoto as dumb and disable

View File

@ -61,6 +61,7 @@
//#define SCROLLVAR_NO /* disable intra-column horizontal scrolls */
//#define SCROLLV_BY_1 /* when scrolling left/right do not move 8 */
//#define STRINGCASENO /* case insenstive compare/locate versions */
//#define TAG_CMD_MUST /* CtrlK (cmdline) needs proper 'c' toggle */
//#define TERMIOS_ONLY /* use native input only (just limp along) */
//#define TOG4_NOFORCE /* no force 2 abreast mode with '4' toggle */
//#define TOG4_NOTRUNC /* ensure no truncation for 2 abreast mode */
@ -182,8 +183,12 @@ char *strcasestr(const char *haystack, const char *needle);
#define kbd_BKSP 137
#define kbd_INS 138
#define kbd_DEL 139
#define kbd_CtrlO '\017'
#define kbd_CtrlE '\005'
#define kbd_CtrlG '\007'
#define kbd_CtrlK '\013'
#define kbd_CtrlO '\017'
#define kbd_CtrlU '\025'
#define kbd_CtrlV '\026'
/* Special value in Pseudo_row to force an additional procs refresh
-- used at startup and for task/thread mode transitions */
@ -805,6 +810,8 @@ typedef struct WIN_t {
//atic void wins_reflag (int what, int flg);
//atic void wins_stage_1 (void);
//atic void wins_stage_2 (void);
//atic void wins_tag_cmdline (void);
//atic void wins_tag_generic (void);
//atic inline int wins_usrselect (const WIN_t *q, const int idx);
/*------ Forest View support -------------------------------------------*/
//atic void forest_adds (const int self, int level);

View File

@ -590,7 +590,8 @@ static void build_uniq_nlstab (void) {
" V,v,F . Toggle: '~1V~2' forest view; '~1v~2' hide/show children; '~1F~2' keep focused\n"
"\n"
"%s"
" W,Y,!,^E Write cfg '~1W~2'; Inspect '~1Y~2'; Combine Cpus '~1!~2'; Scale time ~1Ctrl~2+'~1E~2'\n"
" ^G,K,U,V View: ctl groups ~1^g~2; cmdline ~1^k~2; supp groups ~1^u~2; environment ~1^v~2\n"
" W,Y,!,^E Write cfg '~1W~2'; Inspect '~1Y~2'; Combine Cpus '~1!~2'; Scale time ~1^e~2'\n"
" q Quit\n"
" ( commands shown with '.' require a ~1visible~2 task display ~1window~2 ) \n"
"Press '~1h~2' or '~1?~2' for help with ~1Windows~2,\n"
@ -661,8 +662,7 @@ static void build_uniq_nlstab (void) {
. also imbedded in the translatable text (along with escape seqs)
. should never themselves be translated. */
Uniq_nlstab[KEYS_helpext_fmt] = _(""
" k,r Manipulate tasks: '~1k~2' kill; '~1r~2' renice\n"
" d or s Set update interval\n");
" d,k,r,^R, '~1d~2' set delay; '~1k~2' kill; '~1r~2' renice; ~1Ctrl~2+'~1R~2' renice autogroup\n");
/* Translation Hint:
. This Fields Management header should be 3 lines long so as