This implements a feature I miss from bash. What I care about:
- not clog the history with repeated commands
- easily prevent some commands to go in the history
The diff below implements HISTCONTROL for this, user-facing behavior
based on bash. The default ksh behavior doesn't change.
I did not implement:
- "ignoreboth", which is a shorthand for "ignoredups:ignorespace";
trivial, but not really useful
- "erasedups", I have no use for this and it's not as trivial
I have yet to put this in an mkr (dunno yet if the space savings of the
setlocale removal positively affects the ramdisks).
Thoughts? ok?
Index: history.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/history.c,v
retrieving revision 1.68
diff -u -p -r1.68 history.c
--- history.c 28 Aug 2017 19:41:55 -0000 1.68
+++ history.c 30 Aug 2017 10:38:43 -0000
@@ -42,6 +42,8 @@ static FILE *histfh;
static char **current; /* current position in history[] */
static char *hname; /* current name of history file */
static int hstarted; /* set after hist_init() called */
+static int ignoredups; /* ditch duplicated history lines? */
+static int ignorespace; /* ditch lines starting with a space? */
static Source *hist_source;
static uint32_t line_co;
@@ -513,6 +515,28 @@ findhistrel(const char *str)
return start + rec + 1;
}
+void
+sethistcontrol(const char *str)
+{
+ char *spec, *tok, *state;
+
+ ignorespace = 0;
+ ignoredups = 0;
+
+ if (str == NULL)
+ return;
+
+ spec = str_save(str, ATEMP);
+ for (tok = strtok_r(spec, ":", &state); tok != NULL;
+ tok = strtok_r(NULL, ":", &state)) {
+ if (strcmp(tok, "ignoredups") == 0)
+ ignoredups = 1;
+ else if (strcmp(tok, "ignorespace") == 0)
+ ignorespace = 1;
+ }
+ afree(spec, ATEMP);
+}
+
/*
* set history
* this means reallocating the dataspace
@@ -608,6 +632,18 @@ histsave(int lno, const char *cmd, int d
{
char *c, *cp;
+ if (ignorespace && cmd[0] == ' ')
+ return;
+
+ c = str_save(cmd, APERM);
+ if ((cp = strrchr(c, '\n')) != NULL)
+ *cp = '\0';
+
+ if (ignoredups && histptr >= history && strcmp(*histptr, c) == 0) {
+ afree(c, APERM);
+ return;
+ }
+
if (dowrite && histfh) {
#ifndef SMALL
struct stat sb;
@@ -623,10 +659,6 @@ histsave(int lno, const char *cmd, int d
}
#endif
}
-
- c = str_save(cmd, APERM);
- if ((cp = strrchr(c, '\n')) != NULL)
- *cp = '\0';
if (histptr < history + histsize - 1)
histptr++;
Index: ksh.1
===================================================================
RCS file: /d/cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.193
diff -u -p -r1.193 ksh.1
--- ksh.1 19 Aug 2017 06:19:42 -0000 1.193
+++ ksh.1 30 Aug 2017 10:38:43 -0000
@@ -1407,6 +1407,15 @@ It is also searched when a command can't
See
.Sx Functions
below for more information.
+.It Ev HISTCONTROL
+A colon separated list of history settings.
+If
+.Li ignoredups
+is present, lines identical to the previous history line will not be saved.
+If
+.Li ignorespace
+is present, lines starting with a space will not be saved.
+Unknown settings are ignored.
.It Ev HISTFILE
The name of the file used to store command history.
When assigned to, history is loaded from the specified file.
Index: sh.h
===================================================================
RCS file: /d/cvs/src/bin/ksh/sh.h,v
retrieving revision 1.61
diff -u -p -r1.61 sh.h
--- sh.h 4 Jul 2017 11:46:15 -0000 1.61
+++ sh.h 30 Aug 2017 10:38:43 -0000
@@ -457,6 +457,7 @@ void hist_finish(void);
void histsave(int, const char *, int);
#ifdef HISTORY
int c_fc(char **);
+void sethistcontrol(const char *);
void sethistsize(int);
void sethistfile(const char *);
char ** histpos(void);
Index: table.h
===================================================================
RCS file: /d/cvs/src/bin/ksh/table.h,v
retrieving revision 1.11
diff -u -p -r1.11 table.h
--- table.h 10 Oct 2015 07:35:16 -0000 1.11
+++ table.h 30 Aug 2017 10:38:43 -0000
@@ -160,15 +160,16 @@ extern const struct builtin shbuiltins [
#define V_MAILPATH 6
#define V_MAILCHECK 7
#define V_RANDOM 8
-#define V_HISTSIZE 9
-#define V_HISTFILE 10
-#define V_VISUAL 11
-#define V_EDITOR 12
-#define V_COLUMNS 13
-#define V_POSIXLY_CORRECT 14
-#define V_TMOUT 15
-#define V_TMPDIR 16
-#define V_LINENO 17
+#define V_HISTCONTROL 9
+#define V_HISTSIZE 10
+#define V_HISTFILE 11
+#define V_VISUAL 12
+#define V_EDITOR 13
+#define V_COLUMNS 14
+#define V_POSIXLY_CORRECT 15
+#define V_TMOUT 16
+#define V_TMPDIR 17
+#define V_LINENO 18
/* values for set_prompt() */
#define PS1 0 /* command */
Index: var.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/var.c,v
retrieving revision 1.57
diff -u -p -r1.57 var.c
--- var.c 8 Sep 2016 15:50:50 -0000 1.57
+++ var.c 30 Aug 2017 10:38:43 -0000
@@ -98,6 +98,7 @@ initvar(void)
{ "POSIXLY_CORRECT", V_POSIXLY_CORRECT },
{ "TMPDIR", V_TMPDIR },
#ifdef HISTORY
+ { "HISTCONTROL", V_HISTCONTROL },
{ "HISTFILE", V_HISTFILE },
{ "HISTSIZE", V_HISTSIZE },
#endif /* HISTORY */
@@ -993,6 +994,9 @@ setspec(struct tbl *vp)
}
break;
#ifdef HISTORY
+ case V_HISTCONTROL:
+ sethistcontrol(str_val(vp));
+ break;
case V_HISTSIZE:
vp->flag &= ~SPECIAL;
sethistsize((int) intval(vp));
@@ -1086,6 +1090,11 @@ unsetspec(struct tbl *vp)
case V_MAILPATH:
mpset(NULL);
break;
+#ifdef HISTORY
+ case V_HISTCONTROL:
+ sethistcontrol(NULL);
+ break;
+#endif
case V_LINENO:
case V_MAILCHECK: /* at&t ksh leaves previous value in place */
case V_RANDOM:
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE