top: introduced new focus toggle ('F'), program source
Sometimes, it might be useful to isolate a parent task and its forked children from other system activity. As an example, a user might want to examine workload in a specific lxc container. Or maybe there is some need to question what's happening under the same tmux session. Since forest view mode tends to be a relatively stable display, it will sometimes satisfy the above need. But that mode can't currently guarantee the target process always remains as the topmost task or even is visible. So, this patch will enable focusing on any parent task and keeping it as the topmost process while displaying it and its forked children only. It then appears as if there is no other activity in that system by virtue of the blank lines which follow that final child process. To implement this new feature, top's redundant 'F' key has been repurposed. It made little sense devoting two keys to the Fields Management screen (especially since the key we've taken required two separate keystrokes). [ and while we're at it, i also added punctuation to ] [ that prologue for 'forest_display' since all other ] [ forest functions used punctuation. And, instead of ] [ a pointer to a proc_t he will now get a ppt index. ] Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
37f1060299
commit
bdd50fa2fc
88
top/top.c
88
top/top.c
@ -4443,9 +4443,9 @@ static void win_names (WIN_t *q, const char *name) {
|
|||||||
static void win_reset (WIN_t *q) {
|
static void win_reset (WIN_t *q) {
|
||||||
SETw(q, Show_IDLEPS | Show_TASKON);
|
SETw(q, Show_IDLEPS | Show_TASKON);
|
||||||
#ifndef SCROLLVAR_NO
|
#ifndef SCROLLVAR_NO
|
||||||
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->varcolbeg = 0;
|
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->varcolbeg = q->focus_pid = 0;
|
||||||
#else
|
#else
|
||||||
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = 0;
|
q->rc.maxtasks = q->usrseltyp = q->begpflg = q->begtask = q->begnext = q->focus_pid = 0;
|
||||||
#endif
|
#endif
|
||||||
Monpidsidx = 0;
|
Monpidsidx = 0;
|
||||||
osel_clear(q);
|
osel_clear(q);
|
||||||
@ -4764,7 +4764,7 @@ static inline int wins_usrselect (const WIN_t *q, const int idx) {
|
|||||||
/*
|
/*
|
||||||
* We try keeping most existing code unaware of these activities |
|
* We try keeping most existing code unaware of these activities |
|
||||||
* ( plus, maintain alphabetical order within carefully chosen ) |
|
* ( plus, maintain alphabetical order within carefully chosen ) |
|
||||||
* ( names beginning forest_a, forest_b, forest_c and forest_d ) |
|
* ( names beginning with 'forest' & ending with a, b, c, d, e ) |
|
||||||
* ( with each name exactly 1 letter more than its predecessor ) | */
|
* ( with each name exactly 1 letter more than its predecessor ) | */
|
||||||
static proc_t **Seed_ppt; // temporary win ppt pointer |
|
static proc_t **Seed_ppt; // temporary win ppt pointer |
|
||||||
static proc_t **Tree_ppt; // forest_create will resize |
|
static proc_t **Tree_ppt; // forest_create will resize |
|
||||||
@ -4886,13 +4886,14 @@ static void forest_create (WIN_t *q) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This guy adds the artwork to either 'cmd' or 'cmdline' values |
|
* This guy adds the artwork to either 'cmd' or 'cmdline' values |
|
||||||
* when we're in forest view mode otherwise he just returns them | */
|
* if we are in forest view mode otherwise he just returns them. | */
|
||||||
static inline const char *forest_display (const WIN_t *q, const proc_t *p) {
|
static inline const char *forest_display (const WIN_t *q, int idx) {
|
||||||
#ifndef SCROLLVAR_NO
|
#ifndef SCROLLVAR_NO
|
||||||
static char buf[1024*64*2]; // the same as readproc's MAX_BUFSZ
|
static char buf[1024*64*2]; // the same as readproc's MAX_BUFSZ
|
||||||
#else
|
#else
|
||||||
static char buf[ROWMINSIZ];
|
static char buf[ROWMINSIZ];
|
||||||
#endif
|
#endif
|
||||||
|
const proc_t *p = q->ppt[idx];
|
||||||
const char *which = (CHKw(q, Show_CMDLIN)) ? *p->cmdline : p->cmd;
|
const char *which = (CHKw(q, Show_CMDLIN)) ? *p->cmdline : p->cmd;
|
||||||
|
|
||||||
if (!CHKw(q, Show_FOREST) || !p->pad_3) return which;
|
if (!CHKw(q, Show_FOREST) || !p->pad_3) return which;
|
||||||
@ -4911,6 +4912,30 @@ static inline const char *forest_display (const WIN_t *q, const proc_t *p) {
|
|||||||
else snprintf(buf, sizeof(buf), "%*s%s", (4 * p->pad_3), " `- ", which);
|
else snprintf(buf, sizeof(buf), "%*s%s", (4 * p->pad_3), " `- ", which);
|
||||||
return buf;
|
return buf;
|
||||||
} // end: forest_display
|
} // end: forest_display
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there's a 'focus_pid' established for a window, this guy |
|
||||||
|
* determines that window's 'focus_beg' plus 'focus_end' values. |
|
||||||
|
* But, if the pid can no longer be found, he'll turn off focus! | */
|
||||||
|
static void forest_excluded (WIN_t *q) {
|
||||||
|
int i, level;
|
||||||
|
|
||||||
|
for (i = 0; i < Frame_maxtask; i++) {
|
||||||
|
if (q->focus_pid == q->ppt[i]->tid) {
|
||||||
|
level = q->ppt[i]->pad_3;
|
||||||
|
q->focus_beg = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == Frame_maxtask)
|
||||||
|
q->focus_pid = q->begtask = 0;
|
||||||
|
else {
|
||||||
|
while (i+1 < Frame_maxtask && q->ppt[i+1]->pad_3 > level)
|
||||||
|
++i;
|
||||||
|
q->focus_end = i + 1; // make 'focus_end' a proper fencpost
|
||||||
|
}
|
||||||
|
} // end: forest_excluded
|
||||||
|
|
||||||
/*###### Interactive Input Tertiary support ############################*/
|
/*###### Interactive Input Tertiary support ############################*/
|
||||||
|
|
||||||
@ -5177,7 +5202,6 @@ static void keys_global (int ch) {
|
|||||||
case 'e':
|
case 'e':
|
||||||
if (++Rc.task_mscale > SK_Pb) Rc.task_mscale = SK_Kb;
|
if (++Rc.task_mscale > SK_Pb) Rc.task_mscale = SK_Kb;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
|
||||||
case 'f':
|
case 'f':
|
||||||
fields_utility();
|
fields_utility();
|
||||||
break;
|
break;
|
||||||
@ -5430,6 +5454,15 @@ static void keys_task (int ch) {
|
|||||||
case 'c':
|
case 'c':
|
||||||
VIZTOGw(w, Show_CMDLIN);
|
VIZTOGw(w, Show_CMDLIN);
|
||||||
break;
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (VIZCHKw(w)) {
|
||||||
|
if (CHKw(w, Show_FOREST)) {
|
||||||
|
int n = w->ppt[w->begtask]->tid;
|
||||||
|
if (w->focus_pid == n) w->focus_pid = 0;
|
||||||
|
else w->focus_pid = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
{ static WIN_t *w_sav;
|
{ static WIN_t *w_sav;
|
||||||
static int beg_sav;
|
static int beg_sav;
|
||||||
@ -5486,6 +5519,7 @@ static void keys_task (int ch) {
|
|||||||
if (!ENUviz(w, EU_CMD))
|
if (!ENUviz(w, EU_CMD))
|
||||||
show_msg(fmtmk(N_fmt(FOREST_modes_fmt) , CHKw(w, Show_FOREST)
|
show_msg(fmtmk(N_fmt(FOREST_modes_fmt) , CHKw(w, Show_FOREST)
|
||||||
? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
|
? N_txt(ON_word_only_txt) : N_txt(OFF_one_word_txt)));
|
||||||
|
if (!CHKw(w, Show_FOREST)) w->focus_pid = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -5886,13 +5920,13 @@ static void do_key (int ch) {
|
|||||||
char keys[SMLBUFSIZ];
|
char keys[SMLBUFSIZ];
|
||||||
} key_tab[] = {
|
} key_tab[] = {
|
||||||
{ keys_global,
|
{ keys_global,
|
||||||
{ '?', 'B', 'd', 'E', 'e', 'F', 'f', 'g', 'H', 'h'
|
{ '?', 'B', 'd', 'E', 'e', 'f', 'g', 'H', 'h'
|
||||||
, 'I', 'k', 'r', 's', 'X', 'Y', 'Z', '0'
|
, 'I', 'k', 'r', 's', 'X', 'Y', 'Z', '0'
|
||||||
, kbd_ENTER, kbd_SPACE, '\0' } },
|
, kbd_ENTER, kbd_SPACE, '\0' } },
|
||||||
{ keys_summary,
|
{ keys_summary,
|
||||||
{ '!', '1', '2', '3', '4', 'C', 'l', 'm', 't', '\0' } },
|
{ '!', '1', '2', '3', '4', 'C', 'l', 'm', 't', '\0' } },
|
||||||
{ keys_task,
|
{ keys_task,
|
||||||
{ '#', '<', '>', 'b', 'c', 'i', 'J', 'j', 'n', 'O', 'o'
|
{ '#', '<', '>', 'b', 'c', 'F', 'i', 'J', 'j', 'n', 'O', 'o'
|
||||||
, 'R', 'S', 'U', 'u', 'V', 'v', 'x', 'y', 'z'
|
, 'R', 'S', 'U', 'u', 'V', 'v', 'x', 'y', 'z'
|
||||||
, kbd_CtrlO, '\0' } },
|
, kbd_CtrlO, '\0' } },
|
||||||
{ keys_window,
|
{ keys_window,
|
||||||
@ -6209,9 +6243,9 @@ static const char *task_show (const WIN_t *q, const int idx) {
|
|||||||
break;
|
break;
|
||||||
case EU_CMD:
|
case EU_CMD:
|
||||||
if (CHKw(q, Show_CMDLIN))
|
if (CHKw(q, Show_CMDLIN))
|
||||||
varUTF8(forest_display(q, p))
|
varUTF8(forest_display(q, idx))
|
||||||
else
|
else
|
||||||
makeVAR(forest_display(q, p));
|
makeVAR(forest_display(q, idx));
|
||||||
break;
|
break;
|
||||||
case EU_COD:
|
case EU_COD:
|
||||||
cp = scale_mem(S, pages2K(p->trs), W, Jn);
|
cp = scale_mem(S, pages2K(p->trs), W, Jn);
|
||||||
@ -6451,32 +6485,34 @@ static const char *task_show (const WIN_t *q, const int idx) {
|
|||||||
static void window_hlp (void) {
|
static void window_hlp (void) {
|
||||||
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
|
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
|
||||||
int i, reversed;
|
int i, reversed;
|
||||||
|
int beg = w->focus_pid ? w->focus_beg : 0;
|
||||||
|
int end = w->focus_pid ? w->focus_end : Frame_maxtask;
|
||||||
|
|
||||||
SETw(w, NOPRINT_xxx);
|
SETw(w, NOPRINT_xxx);
|
||||||
w->begtask += w->begnext;
|
w->begtask += w->begnext;
|
||||||
// next 'if' will force a forward scan ...
|
// next 'if' will force a forward scan ...
|
||||||
if (w->begtask <= 0) { w->begtask = 0; w->begnext = +1; }
|
if (w->begtask <= beg) { w->begtask = beg; w->begnext = +1; }
|
||||||
else if (w->begtask >= Frame_maxtask) w->begtask = Frame_maxtask - 1;
|
else if (w->begtask >= end) w->begtask = end - 1;
|
||||||
|
|
||||||
reversed = 0;
|
reversed = 0;
|
||||||
// potentially scroll forward ...
|
// potentially scroll forward ...
|
||||||
if (w->begnext > 0) {
|
if (w->begnext > beg) {
|
||||||
fwd_redux:
|
fwd_redux:
|
||||||
for (i = w->begtask; i < Frame_maxtask; i++) {
|
for (i = w->begtask; i < end; i++) {
|
||||||
if (wins_usrselect(w, i)
|
if (wins_usrselect(w, i)
|
||||||
&& (*task_show(w, i)))
|
&& (*task_show(w, i)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i < Frame_maxtask) {
|
if (i < end) {
|
||||||
w->begtask = i;
|
w->begtask = i;
|
||||||
goto wrap_up;
|
goto wrap_up;
|
||||||
}
|
}
|
||||||
// no luck forward, so let's try backward
|
// no luck forward, so let's try backward
|
||||||
w->begtask = Frame_maxtask - 1;
|
w->begtask = end - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// potentially scroll backward ...
|
// potentially scroll backward ...
|
||||||
for (i = w->begtask; i > 0; i--) {
|
for (i = w->begtask; i > beg; i--) {
|
||||||
if (wins_usrselect(w, i)
|
if (wins_usrselect(w, i)
|
||||||
&& (*task_show(w, i)))
|
&& (*task_show(w, i)))
|
||||||
break;
|
break;
|
||||||
@ -6484,9 +6520,9 @@ fwd_redux:
|
|||||||
w->begtask = i;
|
w->begtask = i;
|
||||||
|
|
||||||
// reached the top, but maybe this guy ain't visible
|
// reached the top, but maybe this guy ain't visible
|
||||||
if (!w->begtask && !reversed) {
|
if (w->begtask == beg && !reversed) {
|
||||||
if (!(wins_usrselect(w, 0))
|
if (!(wins_usrselect(w, beg))
|
||||||
|| (!(*task_show(w, 0)))) {
|
|| (!(*task_show(w, beg)))) {
|
||||||
reversed = 1;
|
reversed = 1;
|
||||||
goto fwd_redux;
|
goto fwd_redux;
|
||||||
}
|
}
|
||||||
@ -6507,16 +6543,17 @@ static int window_show (WIN_t *q, int wmax) {
|
|||||||
( actual 'running' tasks will be a subset of those selected ) */
|
( actual 'running' tasks will be a subset of those selected ) */
|
||||||
#define isBUSY(x) (0 < (x)->pcpu)
|
#define isBUSY(x) (0 < (x)->pcpu)
|
||||||
#define winMIN(a,b) (((a) < (b)) ? (a) : (b))
|
#define winMIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
int i, lwin;
|
int i, lwin, numtasks;
|
||||||
|
|
||||||
// Display Column Headings -- and distract 'em while we sort (maybe)
|
// Display Column Headings -- and distract 'em while we sort (maybe)
|
||||||
PUFF("\n%s%s%s", q->capclr_hdr, q->columnhdr, Caps_endline);
|
PUFF("\n%s%s%s", q->capclr_hdr, q->columnhdr, Caps_endline);
|
||||||
// and just in case 'Monpids' is active but matched no processes ...
|
// and just in case 'Monpids' is active but matched no processes ...
|
||||||
if (!Frame_maxtask) return 1; // 1 for the column header
|
if (!Frame_maxtask) return 1; // 1 for the column header
|
||||||
|
|
||||||
if (CHKw(q, Show_FOREST))
|
if (CHKw(q, Show_FOREST)) {
|
||||||
forest_create(q);
|
forest_create(q);
|
||||||
else {
|
if (q->focus_pid) forest_excluded(q);
|
||||||
|
} else {
|
||||||
if (CHKw(q, Qsrt_NORMAL)) Frame_srtflg = 1; // this is always needed!
|
if (CHKw(q, Qsrt_NORMAL)) Frame_srtflg = 1; // this is always needed!
|
||||||
else Frame_srtflg = -1;
|
else Frame_srtflg = -1;
|
||||||
Frame_ctimes = CHKw(q, Show_CTIMES); // this & next, only maybe
|
Frame_ctimes = CHKw(q, Show_CTIMES); // this & next, only maybe
|
||||||
@ -6530,16 +6567,17 @@ static int window_show (WIN_t *q, int wmax) {
|
|||||||
i = q->begtask;
|
i = q->begtask;
|
||||||
lwin = 1; // 1 for the column header
|
lwin = 1; // 1 for the column header
|
||||||
wmax = winMIN(wmax, q->winlines + 1); // ditto for winlines, too
|
wmax = winMIN(wmax, q->winlines + 1); // ditto for winlines, too
|
||||||
|
numtasks = q->focus_pid ? winMIN(q->focus_end, Frame_maxtask) : Frame_maxtask;
|
||||||
|
|
||||||
/* the least likely scenario is also the most costly, so we'll try to avoid
|
/* the least likely scenario is also the most costly, so we'll try to avoid
|
||||||
checking some stuff with each iteration and check it just once... */
|
checking some stuff with each iteration and check it just once... */
|
||||||
if (CHKw(q, Show_IDLEPS) && !q->usrseltyp)
|
if (CHKw(q, Show_IDLEPS) && !q->usrseltyp)
|
||||||
while (i < Frame_maxtask && lwin < wmax) {
|
while (i < numtasks && lwin < wmax) {
|
||||||
if (*task_show(q, i++))
|
if (*task_show(q, i++))
|
||||||
++lwin;
|
++lwin;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
while (i < Frame_maxtask && lwin < wmax) {
|
while (i < numtasks && lwin < wmax) {
|
||||||
if ((CHKw(q, Show_IDLEPS) || isBUSY(q->ppt[i]))
|
if ((CHKw(q, Show_IDLEPS) || isBUSY(q->ppt[i]))
|
||||||
&& wins_usrselect(q, i)
|
&& wins_usrselect(q, i)
|
||||||
&& *task_show(q, i))
|
&& *task_show(q, i))
|
||||||
|
@ -438,6 +438,9 @@ typedef struct WIN_t {
|
|||||||
int osel_tot; // total of other selection criteria
|
int osel_tot; // total of other selection criteria
|
||||||
char *findstr; // window's current/active search string
|
char *findstr; // window's current/active search string
|
||||||
int findlen; // above's strlen, without call overhead
|
int findlen; // above's strlen, without call overhead
|
||||||
|
int focus_pid; // target pid when 'F' toggle is active
|
||||||
|
int focus_beg; // ppt index where 'F' toggle has begun
|
||||||
|
int focus_end; // ppt index where 'F' toggle has ended
|
||||||
proc_t **ppt; // this window's proc_t ptr array
|
proc_t **ppt; // this window's proc_t ptr array
|
||||||
struct WIN_t *next, // next window in window stack
|
struct WIN_t *next, // next window in window stack
|
||||||
*prev; // prior window in window stack
|
*prev; // prior window in window stack
|
||||||
@ -789,7 +792,8 @@ typedef struct WIN_t {
|
|||||||
//atic int forest_based (const proc_t **x, const proc_t **y);
|
//atic int forest_based (const proc_t **x, const proc_t **y);
|
||||||
#endif
|
#endif
|
||||||
//atic void forest_create (WIN_t *q);
|
//atic void forest_create (WIN_t *q);
|
||||||
//atic inline const char *forest_display (const WIN_t *q, const proc_t *p);
|
//atic inline const char *forest_display (const WIN_t *q, int idx);
|
||||||
|
//atic void forest_excluded (WIN_t *q);
|
||||||
/*------ Interactive Input Tertiary support ----------------------------*/
|
/*------ Interactive Input Tertiary support ----------------------------*/
|
||||||
//atic inline int find_ofs (const WIN_t *q, const char *buf);
|
//atic inline int find_ofs (const WIN_t *q, const char *buf);
|
||||||
//atic void find_string (int ch);
|
//atic void find_string (int ch);
|
||||||
|
@ -555,7 +555,7 @@ static void build_uniq_nlstab (void) {
|
|||||||
" Z~5,~1B~5,E,e Global: '~1Z~2' colors; '~1B~2' bold; '~1E~2'/'~1e~2' summary/task memory scale\n"
|
" Z~5,~1B~5,E,e Global: '~1Z~2' colors; '~1B~2' bold; '~1E~2'/'~1e~2' summary/task memory scale\n"
|
||||||
" l,t,m,I Toggle: '~1l~2' load avg; '~1t~2' task/cpu; '~1m~2' memory; '~1I~2' Irix mode\n"
|
" l,t,m,I Toggle: '~1l~2' load avg; '~1t~2' task/cpu; '~1m~2' memory; '~1I~2' Irix mode\n"
|
||||||
" 0,1,2,3,4 Toggle: '~10~2' zeros; '~11~2/~12~2/~13~2' cpu/numa views; '~14~2' cpus two abreast\n"
|
" 0,1,2,3,4 Toggle: '~10~2' zeros; '~11~2/~12~2/~13~2' cpu/numa views; '~14~2' cpus two abreast\n"
|
||||||
" f,F,X Fields: '~1f~2'/'~1F~2' add/remove/order/sort; '~1X~2' increase fixed-width\n"
|
" f,X Fields: '~1f~2' add/remove/order/sort; '~1X~2' increase fixed-width fields\n"
|
||||||
"\n"
|
"\n"
|
||||||
" L,&,<,> . Locate: '~1L~2'/'~1&~2' find/again; Move sort column: '~1<~2'/'~1>~2' left/right\n"
|
" L,&,<,> . Locate: '~1L~2'/'~1&~2' find/again; Move sort column: '~1<~2'/'~1>~2' left/right\n"
|
||||||
" R,H,J,C . Toggle: '~1R~2' Sort; '~1H~2' Threads; '~1J~2' Num justify; '~1C~2' Coordinates\n"
|
" R,H,J,C . Toggle: '~1R~2' Sort; '~1H~2' Threads; '~1J~2' Num justify; '~1C~2' Coordinates\n"
|
||||||
@ -564,7 +564,7 @@ static void build_uniq_nlstab (void) {
|
|||||||
" z~5,~1b~5 . Toggle: '~1z~2' color/mono; '~1b~2' bold/reverse (only if 'x' or 'y')\n"
|
" z~5,~1b~5 . Toggle: '~1z~2' color/mono; '~1b~2' bold/reverse (only if 'x' or 'y')\n"
|
||||||
" u,U,o,O . Filter by: '~1u~2'/'~1U~2' effective/any user; '~1o~2'/'~1O~2' other criteria\n"
|
" u,U,o,O . Filter by: '~1u~2'/'~1U~2' effective/any user; '~1o~2'/'~1O~2' other criteria\n"
|
||||||
" n,#,^O . Set: '~1n~2'/'~1#~2' max tasks displayed; Show: ~1Ctrl~2+'~1O~2' other filter(s)\n"
|
" n,#,^O . Set: '~1n~2'/'~1#~2' max tasks displayed; Show: ~1Ctrl~2+'~1O~2' other filter(s)\n"
|
||||||
" V,v . Toggle: '~1V~2' forest view; '~1v~2' hide/show forest view children\n"
|
" V,v,F . Toggle: '~1V~2' forest view; '~1v~2' hide/show children; '~1F~2' keep focused\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%s"
|
"%s"
|
||||||
" W,Y,! Write config file '~1W~2'; Inspect other output '~1Y~2'; Combine Cpus '~1!~2'\n"
|
" W,Y,! Write config file '~1W~2'; Inspect other output '~1Y~2'; Combine Cpus '~1!~2'\n"
|
||||||
|
Loading…
Reference in New Issue
Block a user