summaryrefslogtreecommitdiffstats
path: root/sys/ddb
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1996-08-10 13:38:44 +0000
committerjoerg <joerg@FreeBSD.org>1996-08-10 13:38:44 +0000
commit08f9d454e02de3df6c4a926fc9dbbce05efbbce0 (patch)
tree47fdc1668b4cca134e7a9108a13f31e5b130f8b1 /sys/ddb
parent6d942cc83d6307d306f463abfa4a86a64bf4fad9 (diff)
downloadFreeBSD-src-08f9d454e02de3df6c4a926fc9dbbce05efbbce0.zip
FreeBSD-src-08f9d454e02de3df6c4a926fc9dbbce05efbbce0.tar.gz
Finally implement a simple commandline history in DDB.
Emacs-style line editing has already been there (did anybody ever notice this? :), so i `only' had to add ^P and ^N. The approach is fairly minimalistic, with the advantage of keeping the bloat as small as 864 bytes of .text and 16 bytes of .bss, plus 10*120 bytes malloc'ed history buffer at the first use.
Diffstat (limited to 'sys/ddb')
-rw-r--r--sys/ddb/db_input.c73
1 files changed, 71 insertions, 2 deletions
diff --git a/sys/ddb/db_input.c b/sys/ddb/db_input.c
index f71ed8a..5e737ca 100644
--- a/sys/ddb/db_input.c
+++ b/sys/ddb/db_input.c
@@ -23,7 +23,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: db_input.c,v 1.12 1995/12/10 19:07:59 bde Exp $
+ * $Id: db_input.c,v 1.13 1996/05/08 04:28:34 gpalmer Exp $
*/
/*
@@ -32,6 +32,7 @@
*/
#include <sys/param.h>
+#include <sys/malloc.h>
#include <sys/systm.h>
#include <machine/cons.h>
@@ -53,6 +54,13 @@ static char * db_lbuf_end; /* end of input line buffer */
static char * db_lc; /* current character */
static char * db_le; /* one past last character */
+/*
+ * Simple input line history support.
+ */
+static char * db_lhistory;
+static int db_lhistlsize, db_lhistidx, db_lhistcur;
+#define DB_LHIST_NLINES 10
+
#define CTRL(c) ((c) & 0x1f)
#define isspace(c) ((c) == ' ' || (c) == '\t')
#define BLANK ' '
@@ -171,11 +179,46 @@ db_inputchar(c)
break;
case CTRL('r'):
db_putstring("^R\n", 3);
+ redraw:
if (db_le > db_lbuf_start) {
db_putstring(db_lbuf_start, db_le - db_lbuf_start);
db_putnchars(BACKUP, db_le - db_lc);
}
break;
+ case CTRL('p'):
+ /* Make previous history line the active one. */
+ if (db_lhistcur >= 0) {
+ bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
+ db_lbuf_start, db_lhistlsize);
+ db_lhistcur--;
+ goto hist_redraw;
+ }
+ break;
+ case CTRL('n'):
+ /* Make next history line the active one. */
+ if (db_lhistcur < db_lhistidx - 1) {
+ db_lhistcur += 2;
+ bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
+ db_lbuf_start, db_lhistlsize);
+ } else {
+ /*
+ * ^N through tail of history, reset the
+ * buffer to zero length.
+ */
+ *db_lbuf_start = '\0';
+ db_lhistcur = db_lhistidx;
+ }
+
+ hist_redraw:
+ db_putnchars(BACKUP, db_le - db_lbuf_start);
+ db_putnchars(BLANK, db_le - db_lbuf_start);
+ db_putnchars(BACKUP, db_le - db_lbuf_start);
+ db_le = index(db_lbuf_start, '\0');
+ if (db_le[-1] == '\r' || db_le[-1] == '\n')
+ *--db_le = '\0';
+ db_lc = db_le;
+ goto redraw;
+
case '\n':
case '\r':
*db_le++ = c;
@@ -211,6 +254,20 @@ db_readline(lstart, lsize)
char * lstart;
int lsize;
{
+ if (db_lhistory && lsize != db_lhistlsize) {
+ /* Should not happen, but to be sane, throw history away. */
+ FREE(db_lhistory, M_TEMP);
+ db_lhistory = 0;
+ }
+ if (db_lhistory == 0) {
+ /* Initialize input line history. */
+ db_lhistlsize = lsize;
+ db_lhistidx = -1;
+ MALLOC(db_lhistory, char *, lsize * DB_LHIST_NLINES,
+ M_TEMP, M_NOWAIT);
+ }
+ db_lhistcur = db_lhistidx;
+
db_force_whitespace(); /* synch output position */
db_lbuf_start = lstart;
@@ -222,8 +279,20 @@ db_readline(lstart, lsize)
continue;
db_printf("\n"); /* synch output position */
-
*db_le = 0;
+
+ if (db_le - db_lbuf_start > 1) {
+ /* Maintain input line history for non-empty lines. */
+ if (++db_lhistidx == DB_LHIST_NLINES) {
+ /* Rotate history. */
+ ovbcopy(db_lhistory + db_lhistlsize, db_lhistory,
+ db_lhistlsize * (DB_LHIST_NLINES - 1));
+ db_lhistidx--;
+ }
+ bcopy(lstart, db_lhistory + (db_lhistidx * db_lhistlsize),
+ db_lhistlsize);
+ }
+
return (db_le - db_lbuf_start);
}
OpenPOWER on IntegriCloud