Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: history improvements for 3.1.5-pws-17
- X-seq: zsh-workers 6255
- From: Wayne Davison <wayne@xxxxxxxxx>
- To: Peter Stephenson <pws@xxxxxxxxxxxxxxxxx>
- Subject: Re: PATCH: history improvements for 3.1.5-pws-17
- Date: Tue, 11 May 1999 02:39:42 -0700
- Cc: zsh-workers@xxxxxxxxxxxxxx (Zsh hackers list)
- In-reply-to: pws's message of Mon, 10 May 1999 09:53:16 +0200. <9905100753.AA33639@xxxxxxxxxxxxxxxxx>
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Peter Stephenson writes:
> I've applied both the other history patches, and it does exactly
> what I was hoping, thanks.
Unfortunately there's a problem with how the relocated
savehistfile() call interacts with remhist() in that 2-file tweak.
Fortunately, it's easy to fix.
> Hmmm, it might be a good idea to make `zle widget num' override the
> value of $NUMERIC with num when calling a widget.
I like this -- it makes writing an up-line-or-local-history function
much simpler.
Appended is a patch with the following changes (apply it over the
top of my previous 2-file tweak):
+ Added the zle command: set-local-history. If called with a
non-zero numeric argument, it enables the browsing of local-only
history. If called with a zero argument, it turns off local-only
history. If called with no argument, it toggles the current
setting. I didn't add a keybinding for this, but I've got it
bound to Esc-/ in my .zshrc for the moment.
+ Made the history-browsing commands honor the setting of the set-
local-history toggle (including the history up/down commands, and
searching commands, but not ! references -- should they change
too?)
+ Foreign lines no longer get UNmarked as foreign at any time.
+ The history command displays a '*' next to the history number of
foreign lines.
+ You can now call "zle WIDGET NUM" to temporarily set the "zmult"
value for that widget (the old value gets restored after the
widget runs). If you supply a non-numeric argument, the widget
is called without the MOD_MULT flag set (which typically results
in a zmult of '1', but there are other commands that have a
different default).
+ Commands that call remhist() (like "history") once again remove
the right line (this was broken in my 2-file tweak).
+ The sequence of load/save events is now: load the shared history
right before we store the current line, and then we write it out.
This means that most of the time up-history will access the
previous command even when a foreign-history command shows up.
(Of course, if you enter an empty command then there's not current
command to save, so the imported command(s) will be first when you
press up-arrow.)
+ If you don't have hist_ignore_all_dups set, we import all shared
history lines into the buffer, even lines that we already have.
+ The histfilelock() code waits a little longer before breaking a
stale lock file (10 seconds rather than 5). Is that long enough?
I didn't change any option names -- I figure I'll let you decide to
shorten them if you'd like to.
I'm currently using the following code to make Ctrl-P avoid foreign
history, while up-arrow (and other commands) include it:
up-line-or-local-history() {
zle set-local-history 1
zle up-line-or-history
zle set-local-history 0
}
zle -N up-line-or-local-history
down-line-or-local-history() {
zle set-local-history 1
zle down-line-or-history
zle set-local-history 0
}
zle -N down-line-or-local-history
..wayne..
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: Doc/Zsh/options.yo
@@ -831,21 +831,20 @@
cindex(share history)
cindex(history, sharing)
item(tt(SHARE_HISTORY))(
-This option both imports new commands from the history file (ones
-that are not already in your history list), and also causes your
-typed commands to be appended to the history file (like specifiying
-tt(INCREMENTAL_APPEND_HISTORY)). The history lines are also output
-with timestamps (see tt(EXTENDED_HISTORY)) to make it easier to
-find where we were in the file after the file gets re-written.
-In an attempt to avoid confusing the user, most history commands
-avoid these "foreign" commands. They can be found by using an
-incremental or line-prefix history search (not including `tt(^)' or
-`tt(!)'). You can also make them visible to all commands by using a
-command that shows the history (such as `history' or `fc -l') or
-a command that explicitly imports history lines (`fc -RI').
+This option both imports new commands from the history file, and also
+causes your typed commands to be appended to the history file (like
+specifiying tt(INCREMENTAL_APPEND_HISTORY)). The history lines are also
+output with timestamps ala tt(EXTENDED_HISTORY) (which makes it easier to
+find the spot where we left off reading the file after it gets re-written).
-If you find that you want more control over when foreign commands
+By default, history movement commands visit the imported lines as well as
+the local lines, but you can toggle this on and off with the
+set-local-history zle binding. It is also possible to create a zle
+widget that will make some commands ignore imported commands, and some
+include them.
+
+If you find that you want more control over when commands
get imported, you may wish to turn tt(SHARE_HISTORY) off,
tt(INCREMENTAL_APPEND_HISTORY) on, and then manually import
commands whenever you need them using `fc -RI'.
Index: Src/Zle/iwidgets.list
@@ -91,6 +91,7 @@
"send-break", sendbreak, 0
"set-mark-command", setmarkcommand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"spell-word", spellword, 0
+"set-local-history", setlocalhistory, 0
"transpose-chars", transposechars, 0
"transpose-words", transposewords, 0
"undefined-key", undefinedkey, 0
Index: Src/Zle/zle_hist.c
@@ -297,7 +297,8 @@
srch_str = zalloc(histpos);
memcpy(srch_str, line, histpos);
}
- for (he = up_histent(quietgethist(histline)); he; he = up_histent(he)) {
+ he = quietgethist(histline);
+ while ((he = movehistent(he, -1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
@@ -337,7 +338,8 @@
srch_str = zalloc(histpos);
memcpy(srch_str, line, histpos);
}
- for (he=down_histent(quietgethist(histline)); he; he=down_histent(he)) {
+ he = quietgethist(histline);
+ while ((he = movehistent(he, 1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
@@ -452,16 +454,27 @@
mkundoent();
histline = he->histnum;
setline(ZLETEXT(he));
- /*he->flags &= ~HIST_FOREIGN;*/
setlastline();
clearlist = 1;
}
/**/
+void
+setlocalhistory(void)
+{
+ if (zmod.flags & MOD_MULT) {
+ hist_skip_flags = zmult? HIST_FOREIGN : 0;
+ }
+ else {
+ hist_skip_flags ^= HIST_FOREIGN;
+ }
+}
+
+/**/
int
zle_goto_hist(int ev, int n)
{
- Histent he = movehistent(quietgethist(ev), n, 0);
+ Histent he = movehistent(quietgethist(ev), n, hist_skip_flags);
if (!he)
return 0;
zle_setline(he);
@@ -682,7 +695,7 @@
statusline = ibuf + NORM_PROMPT_POS;
break;
}
- if (!(he = dir > 0? down_histent(he) : up_histent(he))) {
+ if (!(he = movehistent(he, dir, hist_skip_flags))) {
if (sbptr == (int)isrch_spots[top_spot-1].len
&& (isrch_spots[top_spot-1].flags & ISS_FAILING))
top_spot--;
@@ -1024,7 +1037,7 @@
}
t0 = strlen(visrchstr);
he = quietgethist(histline);
- while ((he = (visrchsense < 0? up_histent(he) : down_histent(he)))) {
+ while ((he = movehistent(he, visrchsense, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
@@ -1068,7 +1081,8 @@
zmult = n;
return;
}
- for (he = up_histent(quietgethist(histline)); he; he = up_histent(he)) {
+ he = quietgethist(histline);
+ while ((he = movehistent(he, -1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
@@ -1102,7 +1116,8 @@
zmult = n;
return;
}
- for (he=down_histent(quietgethist(histline)); he; he=down_histent(he)) {
+ he = quietgethist(histline);
+ while ((he = movehistent(he, 1, hist_skip_flags))) {
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
continue;
s = ZLETEXT(he);
Index: Src/Zle/zle_thingy.c
@@ -357,7 +357,7 @@
/* check number of arguments */
for(n = 0; args[n]; n++) ;
- if(!op->o && n != 1) {
+ if(!op->o && n != 1 && n != 2) {
zerrnam(name, "wrong number of arguments", NULL, 0);
return 1;
}
@@ -516,17 +516,31 @@
bin_zle_call(char *name, char **args, char *ops, char func)
{
Thingy t;
+ struct modifier modsave;
if(!zleactive || incompctlfunc || incompfunc) {
zerrnam(name, "widgets can only be called when ZLE is active",
NULL, 0);
return 1;
}
+ if (args[1]) {
+ modsave = zmod;
+ if (isdigit(*args[1])) {
+ zmod.mult = atoi(args[1]);
+ zmod.flags |= MOD_MULT;
+ }
+ else {
+ zmod.mult = 1;
+ zmod.flags &= ~MOD_MULT;
+ }
+ }
t = rthingy(args[0]);
PERMALLOC {
execzlefunc(t);
} LASTALLOC;
unrefthingy(t);
+ if (args[1])
+ zmod = modsave;
return 0;
}
Index: Src/builtin.c
@@ -1353,7 +1353,6 @@
}
for (;;) {
- ent->flags &= ~HIST_FOREIGN;
s = dupstring(ent->text);
/* this if does the pattern matching, if required */
if (!com || domatch(s, com, 0)) {
@@ -1361,8 +1360,10 @@
fclistdone |= fcsubs(&s, subs);
/* do numbering */
- if (n)
- fprintf(f, "%5d ", ent->histnum);
+ if (n) {
+ fprintf(f, "%5d%c ", ent->histnum,
+ ent->flags & HIST_FOREIGN? '*' : ' ');
+ }
/* output actual time (and possibly date) of execution of the
command, if required */
if (d) {
Index: Src/hashtable.c
@@ -1323,9 +1323,8 @@
HashNode oldnode = addhashnode2(ht, nam, nodeptr);
Histent he = (Histent)nodeptr;
if (oldnode && oldnode != nodeptr) {
- if (he->flags & HIST_MAKEUNIQUE) {
- if (!(he->flags & HIST_FOREIGN))
- oldnode->flags &= ~HIST_FOREIGN;
+ if (he->flags & HIST_MAKEUNIQUE
+ || (he->flags & HIST_FOREIGN && (Histent)oldnode == he->up)) {
he->flags |= HIST_DUP;
addhashnode(ht, oldnode->nam, oldnode); /* Remove the new dup */
}
Index: Src/hist.c
@@ -96,9 +96,17 @@
/**/
int histactive;
+/* Current setting of the associated option, but sometimes also includes
+ * the setting of the HIST_SAVE_NO_DUPS option. */
+
/**/
int hist_ignore_all_dups;
+/* What flags (if any) we should skip when moving through the history */
+
+/**/
+int hist_skip_flags;
+
/* Bits of histactive variable */
#define HA_ACTIVE (1<<0) /* History mechanism is active */
#define HA_NOSTORE (1<<1) /* Don't store the line when finished */
@@ -854,6 +862,7 @@
hend(void)
{
int flag, save = 1;
+ char *hf = getsparam("HISTFILE");
DPUTS(!chline, "BUG: chline is NULL in hend()");
if (histdone & HISTFLAG_SETTY)
@@ -879,6 +888,9 @@
if (hist_ignore_all_dups != isset(HISTIGNOREALLDUPS)
&& (hist_ignore_all_dups = isset(HISTIGNOREALLDUPS)) != 0)
histremovedups();
+ /* For history sharing, lock history file once for both read and write */
+ if (isset(SHAREHISTORY) && lockhistfile(hf, 0))
+ readhistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST);
flag = histdone;
histdone = 0;
if (hptr < chline + 1)
@@ -916,7 +928,7 @@
Histent he;
int keepflags;
- for (he = hist_ring; he && he->flags & HIST_FOREIGN;
+ for (he = hist_ring; he && he->flags & hist_skip_flags;
he = up_histent(he)) ;
#ifdef DEBUG
/* debugging only */
@@ -961,7 +973,8 @@
chline = NULL;
histactive = 0;
if (isset(SHAREHISTORY) || isset(INCREMENTALAPPENDHISTORY))
- savehistfile(NULL, 1, HFILE_USE_OPTIONS | HFILE_FAST);
+ savehistfile(hf, 1, HFILE_USE_OPTIONS | HFILE_FAST);
+ unlockhistfile(hf); /* It's OK to call this even if we aren't locked */
return !(flag & HISTFLAG_NOEXEC || errflag);
}
@@ -973,9 +986,7 @@
{
if (!(histactive & HA_ACTIVE)) {
if (!(histactive & HA_JUNKED)) {
- /* make sure this doesn't show up when we do firsthist() */
- if (hist_ring->histnum == curhist)
- freehistnode((HashNode)hist_ring);
+ freehistnode((HashNode)hist_ring);
histactive |= HA_JUNKED;
/* curhist-- is delayed until the next hbegin() */
}
@@ -1589,7 +1600,6 @@
return;
lasthist.fsiz = sb.st_size;
lasthist.mtim = sb.st_mtime;
- readflags |= HFILE_SKIPOLD;
}
else if (!lockhistfile(fn, 1))
return;
@@ -1614,7 +1624,8 @@
newflags = HIST_OLD | HIST_READ;
if (readflags & HFILE_FAST)
newflags |= HIST_FOREIGN;
- if (readflags & HFILE_SKIPOLD)
+ if (readflags & HFILE_SKIPOLD
+ || (hist_ignore_all_dups && newflags & hist_skip_flags))
newflags |= HIST_MAKEUNIQUE;
while (fpos = ftell(in), fgets(buf, bufsiz, in)) {
int l = strlen(buf);
@@ -1756,13 +1767,7 @@
lasthist.next_write_ev = he->histnum + 1;
he = down_histent(he);
}
- /* If we have something to write, lock before the (potential)
- * read so that we don't lock twice. */
- if (he && !lockhistfile(fn, 0))
- return;
- if (isset(SHAREHISTORY))
- readhistfile(fn, 0, HFILE_USE_OPTIONS | HFILE_FAST);
- if (!he)
+ if (!he || !lockhistfile(fn, 0))
return;
if (histfile_linect > savehist + savehist / 5)
writeflags &= ~HFILE_FAST;
@@ -1890,7 +1895,7 @@
continue;
}
else if (keep_trying) {
- if (time(NULL) - sb.st_mtime < 5)
+ if (time(NULL) - sb.st_mtime < 10)
sleep(1);
else
unlink(lockfile);
@@ -1906,6 +1911,10 @@
}
return ct != lockhistct;
}
+
+/* Unlock the history file if this corresponds to the last nested lock
+ * request. If we don't have the file locked, just return.
+ */
/**/
void
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Messages sorted by:
Reverse Date,
Date,
Thread,
Author