From 2efe275512f62f1e25fda96ebc8446b52c6882f0 Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Fri, 15 Feb 2013 00:00:00 -0600 Subject: [PATCH] top: enable recall of previous input lines for re-edit With this commit, users can now retrieve previous line input for re-editing and/or re-input using the Up/Down arrow keys (or their aliases). This mirrors the 'bash' or 'less' interface and represents a major enhancement achieved via a somewhat minor impact to our code base. [ 33 lines of code, 5 closing braces & some comments ] [ all in 1 function, when TERMIOS_ONLY isn't defined ] Currently, the upper limit for such recallable strings has been set at 50 but that could be easily increased. (everything is perfectly justified plus right margins) (are completely filled, but of course it must be luck) Signed-off-by: Jim Warner --- top/top.1 | 33 ++++++++++++++++++++++++--------- top/top.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- top/top.h | 3 +++ 3 files changed, 75 insertions(+), 12 deletions(-) diff --git a/top/top.1 b/top/top.1 index ae393fa7..19f1f847 100644 --- a/top/top.1 +++ b/top/top.1 @@ -90,7 +90,7 @@ . .\" Document ///////////////////////////////////////////////////////////// .\" ---------------------------------------------------------------------- -.TH TOP 1 "January 2013" "procps-ng" "User Commands" +.TH TOP 1 "February 2013" "procps-ng" "User Commands" .\" ---------------------------------------------------------------------- .\" ---------------------------------------------------------------------- @@ -208,6 +208,15 @@ Insert this command after \*(We has been suspended but before resuming it. reset restore your \fBterminal settings\fR .Ed +\*(NT the width of \*(We's display will be limited to \*(WX positions. +Displaying all fields requires \*(WF characters. +Remaining screen width is usually allocated to any variable width columns +currently visible. +The variable width columns, such as COMMAND, are noted in topic +3a. DESCRIPTIONS of Fields. +Actual output width may also be influenced by the \-w switch, which is +discussed in topic 1. COMMAND\-LINE Options. + Lastly, some of \*(We's screens or functions require the use of cursor motion keys like the standard \*(KAs plus the Home, End, PgUp and PgDn keys. If your terminal or emulator does not provide those keys, the following @@ -224,14 +233,20 @@ combinations are accepted as alternatives: End alt +\fB Right\fR or alt + ctrl +\fB l \fR .Ed -\*(NT the width of \*(We's display will be limited to \*(WX positions. -Displaying all fields requires \*(WF characters. -Remaining screen width is usually allocated to any variable width columns -currently visible. -The variable width columns, such as COMMAND, are noted in topic -3a. DESCRIPTIONS of Fields. -Actual output width may also be influenced by the \-w switch, which is -discussed in topic 1. COMMAND\-LINE Options. +The \fBUp\fR and \fBDown\fR \*(KAs have special significance when prompted +for line input terminated with the key. +Those keys, or their aliases, can be used to retrieve previous input lines +which can then be edited and re-input. +And there are four additional keys available with line oriented input. +.Bd -literal -compact + \fI key special-significance \fR + Up recall \fBolder\fR strings for re-editing + Down recall \fBnewer\fR strings or \fBerase\fR entire line + Insert toggle between \fBinsert\fR and \fBovertype\fR modes + Delete character \fBremoved\fR at cursor, moving others left + Home jump to \fBbeginning\fR of input line + End jump to \fBend\fR of input line +.Ed .\" ...................................................................... .SS Startup Defaults diff --git a/top/top.c b/top/top.c index 468a48c2..267b7f1e 100644 --- a/top/top.c +++ b/top/top.c @@ -1073,8 +1073,10 @@ static char *ioline (const char *prompt) { * Get line oriented interactive input from the user, * going way beyond native tty support by providing: * . true line editing, not just destructive backspace - * . an input limit sensitive to current screen dimensions */ + * . an input limit sensitive to current screen dimensions + * . ability to recall prior strings for re-input/re-editing */ static char *ioline (const char *prompt) { + #define savMAX 50 // thank goodness memmove allows the two strings to overlap #define sqzSTR { memmove(&buf[pos], &buf[pos+1], bufMAX-pos); \ buf[sizeof(buf)-1] = '\0'; } @@ -1084,8 +1086,19 @@ static char *ioline (const char *prompt) { #define phyCOL (beg+pos+1) #define bufMAX ((int)sizeof(buf)-2) // -1 for '\0' string delimeter static char buf[MEDBUFSIZ+1]; // +1 for '\0' string delimeter - int beg, pos, len, key, ovt; + int beg, pos, len, key, ovt, i; + struct lin_s { + struct lin_s *bkw; // ptr to older saved strs + struct lin_s *fwd; // ptr to newer saved strs + char *str; // the saved string + }; + static struct lin_s *anchor, *plin; + if (!anchor) { + anchor = alloc_c(sizeof(struct lin_s)); + anchor->str = alloc_s(""); // top-of-stack == empty str + } + plin = anchor; pos = ovt = 0; beg = show_pmt(prompt); memset(buf, '\0', sizeof(buf)); @@ -1122,6 +1135,18 @@ static char *ioline (const char *prompt) { case kbd_END: pos = len; break; + case kbd_UP: + if (plin->bkw) { + plin = plin->bkw; + memset(buf, '\0', sizeof(buf)); + pos = snprintf(buf, sizeof(buf), "%s", plin->str); + } + break; + case kbd_DOWN: + memset(buf, '\0', sizeof(buf)); + if (plin->fwd) plin = plin->fwd; + pos = snprintf(buf, sizeof(buf), "%s", plin->str); + break; default: // what we REALLY wanted (maybe) if (isprint(key) && logCOL < bufMAX && phyCOL < Screen_cols) { if (!ovt) expSTR @@ -1133,7 +1158,27 @@ static char *ioline (const char *prompt) { putp(tg2(beg+pos, Msg_row)); } while (key != kbd_ENTER && key != kbd_ESC); - return buf; + // weed out duplicates, including empty strings (top-of-stack)... + for (i = 0, plin = anchor; ; i++) { + if (!STRCMP(plin->str, buf)) return buf; + if (!plin->bkw) break; // let i equal total stacked strings + plin = plin->bkw; // ( with plin representing bottom ) + } + if (i < savMAX) + plin = alloc_c(sizeof(struct lin_s)); + else { // when a new string causes overflow + plin->fwd->bkw = NULL; // make next-to-last string new last + free(plin->str); // and toss copy but keep the struct + } + plin->str = alloc_s(buf); // copy user's new unique input line + plin->bkw = anchor->bkw; // keep empty string as top-of-stack + if (plin->bkw) // did we have some already stacked? + plin->bkw->fwd = plin; // yep, so point prior to new string + plin->fwd = anchor; // and prepare to be a second banana + anchor->bkw = plin; // by sliding it in as new number 2! + + return buf; // protect our copy, return original + #undef savMAX #undef sqzSTR #undef expSTR #undef logCOL diff --git a/top/top.h b/top/top.h index d705a397..d7fe8ff6 100644 --- a/top/top.h +++ b/top/top.h @@ -600,6 +600,9 @@ typedef struct WIN_t { #if (LRGBUFSIZ < SCREENMAX) # error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX' #endif +#if defined(TERMIOS_ONLY) +# warning 'TERMIOS_ONLY' disables input recall and makes man doc incorrect +#endif /*###### Some Prototypes (ha!) #########################################*/