Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Finer control over what gets written to the history file



On Wed, 16 Oct 2013 09:55:24 +0100
Peter Stephenson <p.stephenson@xxxxxxxxxxx> wrote:
> We could unify the approaches and add a flag for this to histent (we've
> got plenty of spare bits at the moment).  So e.g. zshaddhistory could
> return 2 to say "keep this internally but don't save it".  I haven't
> looked, but it shouldn't be too hard to combine with the HIST_FOREIGN
> and HIST_TMPSTORE logic.

It turns out this is indeed extremely easy, even if it doesn't solve
Bart's problem without an extra measure of clairvoyance.  So there might
be some merit in having it available.

I'm guessing that anyone already using this mechanism would naturally
return status 1, so making 2 special isn't a big incompatibility, but
I've noted it anyway.

diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo
index 1f58df8..6e9cfee 100644
--- a/Doc/Zsh/func.yo
+++ b/Doc/Zsh/func.yo
@@ -264,9 +264,16 @@ Executed when a history line has been read interactively, but
 before it is executed.  The sole argument is the complete history
 line (so that any terminating newline will still be present).
 
-If any of the hook functions return a non-zero value the history
-line will not be saved, although it lingers in the history until the
-next line is executed, allowing you to reuse or edit it immediately.
+If any of the hook functions returns status 1 (or any non-zero value
+other than 2, though this is not guaranteed for future versions of the
+shell) the history line will not be saved, although it lingers in the
+history until the next line is executed, allowing you to reuse or edit
+it immediately.
+
+If any of the hook functions returns status 2 the history line
+will be saved on the internal history list, but not written to
+the history file.  In case of a conflict, the first non-zero status
+value is taken.
 
 A hook function may call `tt(fc -p) var(...)' to switch the history
 context so that the history is saved in a different file from the
diff --git a/README b/README
index 2a22f42..8ddad6e 100644
--- a/README
+++ b/README
@@ -28,6 +28,17 @@ Zsh is a shell with lots of features.  For a list of some of these, see the
 file FEATURES, and for the latest changes see NEWS.  For more
 details, see the documentation.
 
+Incompatibilities between 5.0.2 and 5.0.3
+-----------------------------------------
+
+The "zshaddhistory" hook mechanism documented in the zshmisc manual page
+has been upgraded so that a hook returning status 2 causes a history
+line to be saved on the internal history list but not written to the
+history file.  Previously any non-zero status return would cause
+the line not to be saved on the history at all.  It is recommended
+to use status 1 for this (indeed most shell users would naturally do
+so).
+
 Incompatibilities between 5.0.0 and 5.0.2
 -----------------------------------------
 
diff --git a/Src/hist.c b/Src/hist.c
index ed95609..fa5bdbb 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -1226,7 +1226,15 @@ mod_export int
 hend(Eprog prog)
 {
     LinkList hookargs = newlinklist();
-    int flag, save = 1, hookret, stack_pos = histsave_stack_pos;
+    int flag, hookret, stack_pos = histsave_stack_pos;
+    /*
+     * save:
+     * 0: don't save
+     * 1: save normally
+     * -1: save temporarily, delete after next line
+     * -2: save internally but mark for not writing
+     */
+    int save = 1;
     char *hf;
 
     DPUTS(stophist != 2 && !(inbufflags & INP_ALIAS) && !chline,
@@ -1279,7 +1287,11 @@ hend(Eprog prog)
 	}
 	if (chwordpos <= 2)
 	    save = 0;
-	else if (hookret || should_ignore_line(prog))
+	else if (should_ignore_line(prog))
+	    save = -1;
+	else if (hookret == 2)
+	    save = -2;
+	else if (hookret)
 	    save = -1;
     }
     if (flag & (HISTFLAG_DONE | HISTFLAG_RECALL)) {
@@ -1325,7 +1337,12 @@ hend(Eprog prog)
 	    if (isset(HISTREDUCEBLANKS))
 		histreduceblanks();
 	}
-	newflags = save > 0? 0 : HIST_TMPSTORE;
+	if (save == -1)
+	    newflags = HIST_TMPSTORE;
+	else if (save == -2)
+	    newflags = HIST_NOWRITE;
+	else
+	    newflags = 0;
 	if ((isset(HISTIGNOREDUPS) || isset(HISTIGNOREALLDUPS)) && save > 0
 	 && hist_ring && histstrcmp(chline, hist_ring->node.nam) == 0) {
 	    /* This history entry compares the same as the previous.
@@ -2590,7 +2607,7 @@ savehistfile(char *fn, int err, int writeflags)
 	     || he->node.flags & HIST_TMPSTORE)
 		continue;
 	    if (writeflags & HFILE_SKIPOLD) {
-		if (he->node.flags & HIST_OLD)
+		if (he->node.flags & (HIST_OLD|HIST_NOWRITE))
 		    continue;
 		he->node.flags |= HIST_OLD;
 		if (writeflags & HFILE_USE_OPTIONS)
diff --git a/Src/zsh.h b/Src/zsh.h
index a46898d..a935d23 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1894,6 +1894,7 @@ struct histent {
 #define HIST_DUP	0x00000008	/* Command duplicates a later line */
 #define HIST_FOREIGN	0x00000010	/* Command came from another shell */
 #define HIST_TMPSTORE	0x00000020	/* Kill when user enters another cmd */
+#define HIST_NOWRITE	0x00000040	/* Keep internally but don't write */
 
 #define GETHIST_UPWARD  (-1)
 #define GETHIST_DOWNWARD  1

pws



Messages sorted by: Reverse Date, Date, Thread, Author