zsh-workers
 help / color / mirror / code / Atom feed
* histignoredups done properly
@ 1996-08-12 12:56 Peter Stephenson
  1996-08-12 19:17 ` hist_strip_spaces (was Re: histignoredups done properly) Wayne Davison
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Stephenson @ 1996-08-12 12:56 UTC (permalink / raw)
  To: Zsh hackers list

Here's another largely cosmetic patch, though this one is more likely
to have unpleasant side effects I haven't noticed and should now
probably be delayed until after 3.0 is released.  (I don't think it
*does*, but virtually any code with pointers and history lists
*might*.)

This fixes histignoredups so that only lines which are really
different are stored; insignificant changes in whitespace are not
treated as differences.  Significant whitespace changes, for example
inside quotation marks, are treated as a difference.  The code simply
uses the extent of command line words which is already recorded.

There is one subtlety:  since you may deliberately alter just the
whitespace on a line, for example pruning a space at the end which
resulted from completion, it is the more recent version which is
stored in the history list, replacing the older one.

One consequent change is that the start time in the extended history
now always reflects the start time of the last command, rather than
the start time of the first command of a repeated sequence.  The
previous behaviour is easy to restore if that seems better (it doesn't
to me, but I can see possible arguments for it).

*** Src/hist.c.id	Fri Aug  2 15:07:29 1996
--- Src/hist.c	Mon Aug 12 14:26:51 1996
***************
*** 627,632 ****
--- 627,653 ----
  	histremmed = 1;
  }
  
+ /* compare current line with history entry using only text in words */
+ 
+ /**/
+ int
+ histcmp(Histent he)
+ {
+     int iword, lword;
+     int nwords = chwordpos/2;
+ 
+     if (nwords != he->nwords)
+ 	return 1;
+ 
+     for (iword = 0; iword < 2*nwords; iword += 2)
+ 	if ((lword = chwords[iword+1]-chwords[iword])
+ 	    != he->words[iword+1]-he->words[iword] ||
+ 	    memcmp(he->text+he->words[iword], chline+chwords[iword], lword))
+ 	    return 1;
+ 
+     return 0;
+ }
+ 
  /* say we're done using the history mechanism */
  
  /**/
***************
*** 634,640 ****
  hend(void)
  {
      int flag, save = 1;
!     Histent he;
  
      if (!chline)
  	return 1;
--- 655,661 ----
  hend(void)
  {
      int flag, save = 1;
!     Histent he = NULL;
  
      if (!chline)
  	return 1;
***************
*** 655,665 ****
  		*--hptr = '\0';
  	    } else
  		save = 0;
- 	he = gethistent(curhist - 1);
  	if (!*chline || !strcmp(chline, "\n") ||
- 	    (isset(HISTIGNOREDUPS) && he->text && !strcmp(he->text, chline)) ||
  	    (isset(HISTIGNORESPACE) && spaceflag))
  	    save = 0;
      }
      if (flag & (HISTFLAG_DONE | HISTFLAG_RECALL)) {
  	char *ptr;
--- 676,701 ----
  		*--hptr = '\0';
  	    } else
  		save = 0;
  	if (!*chline || !strcmp(chline, "\n") ||
  	    (isset(HISTIGNORESPACE) && spaceflag))
  	    save = 0;
+ 	else if (save) {
+ #ifdef DEBUG
+ 	    /* debugging only */
+ 	    if (chwordpos%2) {
+ 		hwend();
+ 		DPUTS(1, "internal:  uncompleted line in history");
+ 	    }
+ #endif
+ 	    /* get rid of pesky \n which we've nulled out:
+ 	     * needed here by HISTIGNOREDUPS code, but needed anyway.
+ 	     */
+ 	    if (!chline[chwords[chwordpos-2]])
+ 		chwordpos -= 2;
+ 	    he = gethistent(curhist - 1);
+ 	    if (isset(HISTIGNOREDUPS) && he->text && !histcmp(he))
+ 		save = 2;
+ 	}
      }
      if (flag & (HISTFLAG_DONE | HISTFLAG_RECALL)) {
  	char *ptr;
***************
*** 682,697 ****
      curhistent->ftim = 0L;
      curhistent->flags = 0;
      if (save) {
! #ifdef DEBUG
! 	/* debugging only */
! 	if (chwordpos%2) {
! 	    hwend();
! 	    DPUTS(1, "internal:  uncompleted line in history");
  	}
- #endif
- 	/* get rid of pesky \n which we've already nulled out */
- 	if (!chline[chwords[chwordpos-2]])
- 	    chwordpos -= 2;
  	if ((curhistent->nwords = chwordpos/2)) {
  	    curhistent->words =
  		(short *)zalloc(curhistent->nwords*2*sizeof(short));
--- 718,736 ----
      curhistent->ftim = 0L;
      curhistent->flags = 0;
      if (save) {
! 	if (save == 2) {
! 	    /* Don't duplicate history entry, but use the current rather than
! 	     * the previous one, in case minor changes were made to it.
! 	     */
! 	    Histent hold = curhistent;
! 	    zsfree(he->text);
! 	    if (he->nwords)
! 		zfree(he->words, he->nwords*2*sizeof(short));
! 	    curhist--;
! 	    *he = *curhistent;
! 	    curhistent = he;
! 	    hold->text = NULL;
  	}
  	if ((curhistent->nwords = chwordpos/2)) {
  	    curhistent->words =
  		(short *)zalloc(curhistent->nwords*2*sizeof(short));

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77330
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* hist_strip_spaces (was Re: histignoredups done properly)
  1996-08-12 12:56 histignoredups done properly Peter Stephenson
@ 1996-08-12 19:17 ` Wayne Davison
  1996-08-12 21:13   ` hist_strip_spaces Wayne Davison
  1996-08-13  5:48   ` hist_strip_spaces (was Re: histignoredups done properly) Andrej Borsenkow
  0 siblings, 2 replies; 5+ messages in thread
From: Wayne Davison @ 1996-08-12 19:17 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh hackers list

Peter Stephenson writes:
> This fixes histignoredups so that only lines which are really
> different are stored; insignificant changes in whitespace are not
> treated as differences.

Nice change.  I was working on something similar over the weekend:  the
removal of insignificant spaces from history lines.  Since I think my
change complements your patch, I've based this diff on previously
applying your histignoredups patch.

Since it may be that not everyone will want this, I made it depend on a
new option, HIST_STRIP_SPACES.  I haven't modified the documentation yet,
however.

Note that since the histstrip() routine may change curhistent->text, I
had to change the cleanup code that frees chline.  The new code has the
additional benefit of being much clearer in what it is trying to do (it
took me a while to figure out what the old code was for).

..wayne..
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: Src/globals.h
@@ -720,6 +720,7 @@
     {"histignoredups", 		'h',  0,    0},
     {"histignorespace", 	'g',  0,    0},
     {"histnostore", 		0,    0,    0},
+    {"histstripspaces",		0,    0,    0},
     {"histverify", 		0,    0,    0},
     {"hup", 			0,    0,    OPT_EMULATE|OPT_ZSH},
     {"ignorebraces", 		'I',  0,    OPT_EMULATE|OPT_SH},
Index: Src/hist.c
@@ -648,6 +648,36 @@
     return 0;
 }
 
+/**/
+void
+histstrip(Histent he)
+{
+    int i, len;
+    int limit = he->nwords*2;
+    char *str, *s;
+
+    for (i = 0, len = he->nwords-1; i < limit; i += 2)
+	len += he->words[i+1] - he->words[i];
+    if (len == he->words[limit-1])
+	return;
+
+    str = zalloc(len+1);
+
+    for (i = 0, s = str; i < limit; i += 2) {
+	len = he->words[i+1] - he->words[i];
+	memcpy(s, he->text + he->words[i], len);
+	he->words[i] = s - str;
+	he->words[i+1] = he->words[i] + len;
+	s += len;
+	*s++ = ' ';
+    }
+    s[-1] = '\0';
+
+    if (he->text != chline)
+	zsfree(he->text);
+    he->text = str;
+}
+
 /* say we're done using the history mechanism */
 
 /**/
@@ -694,7 +724,7 @@
 		chwordpos -= 2;
 	    he = gethistent(curhist - 1);
 	    if (isset(HISTIGNOREDUPS) && he->text && !histcmp(he))
-		save = 2;
+		save = isset(HISTSTRIPSPACES)? 0 : 2;
 	}
     }
     if (flag & (HISTFLAG_DONE | HISTFLAG_RECALL)) {
@@ -737,16 +767,13 @@
 	    memcpy(curhistent->words, chwords,
 		   curhistent->nwords*2*sizeof(short));
 	}
+	if (isset(HISTSTRIPSPACES))
+	    histstrip(curhistent);
     } else
 	remhist();
-    if (chline && !curhistent->text)
-	zfree(chline, hlinesz);
-    if (curhistent->text) {
-	char *s = ztrdup(curhistent->text);
-
-	zfree(curhistent->text, hlinesz);
-	curhistent->text = s;
-    }
+    if (curhistent->text == chline)
+	curhistent->text = ztrdup(chline);
+    zfree(chline, hlinesz);
     zfree(chwords, chwordlen*sizeof(short));
     chline = NULL;
     return !(flag & HISTFLAG_NOEXEC || errflag);
Index: Src/zsh.h
@@ -1102,6 +1102,7 @@
     HISTIGNOREDUPS,
     HISTIGNORESPACE,
     HISTNOSTORE,
+    HISTSTRIPSPACES,
     HISTVERIFY,
     HUP,
     IGNOREBRACES,
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: hist_strip_spaces
  1996-08-12 19:17 ` hist_strip_spaces (was Re: histignoredups done properly) Wayne Davison
@ 1996-08-12 21:13   ` Wayne Davison
  1996-08-13  9:22     ` hist_strip_spaces Wayne Davison
  1996-08-13  5:48   ` hist_strip_spaces (was Re: histignoredups done properly) Andrej Borsenkow
  1 sibling, 1 reply; 5+ messages in thread
From: Wayne Davison @ 1996-08-12 21:13 UTC (permalink / raw)
  To: Zsh hackers list

One problem with my patch is an optimization I added to check if
the line really needs to be rewritten -- it didn't properly handle
trailing spaces.  The following patch fixes this.

..wayne..
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: Src/hist.c
@@ -658,7 +658,7 @@
 
     for (i = 0, len = he->nwords-1; i < limit; i += 2)
 	len += he->words[i+1] - he->words[i];
-    if (len == he->words[limit-1])
+    if (he->text[len] == '\0')
 	return;
 
     str = zalloc(len+1);
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: hist_strip_spaces (was Re: histignoredups done properly)
  1996-08-12 19:17 ` hist_strip_spaces (was Re: histignoredups done properly) Wayne Davison
  1996-08-12 21:13   ` hist_strip_spaces Wayne Davison
@ 1996-08-13  5:48   ` Andrej Borsenkow
  1 sibling, 0 replies; 5+ messages in thread
From: Andrej Borsenkow @ 1996-08-13  5:48 UTC (permalink / raw)
  To: Wayne Davison; +Cc: Peter Stephenson, Zsh hackers list

On Mon, 12 Aug 1996, Wayne Davison wrote:

> Peter Stephenson writes:
> > This fixes histignoredups so that only lines which are really
> > different are stored; insignificant changes in whitespace are not
> > treated as differences.
> 

[ snipped ]

> Since it may be that not everyone will want this, I made it depend on a
> new option, HIST_STRIP_SPACES.  I haven't modified the documentation yet,
> however.
> 

The idea is really nice. Here is another one:

I often find itself in a position, where I use several command in a loop;
e.g. (simplified)

% vi
% cc
% ./a.out

or like. What about "HIST_IGNORE_ALL_DUPS" option, which would keep only
globally unique command line? It would be very easy to add this (now it
shold probably be combined with strip_spaces as well).

Any comments?

greetings

-------------------------------------------------------------------------
Andrej Borsenkow 		Fax:   +7 (095) 252 01 05
SNI ITS Moscow			Tel:   +7 (095) 252 13 88

NERV:  borsenkow.msk		E-Mail: borsenkow.msk@sni.de
-------------------------------------------------------------------------



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: hist_strip_spaces
  1996-08-12 21:13   ` hist_strip_spaces Wayne Davison
@ 1996-08-13  9:22     ` Wayne Davison
  0 siblings, 0 replies; 5+ messages in thread
From: Wayne Davison @ 1996-08-13  9:22 UTC (permalink / raw)
  To: Zsh hackers list

One last(?) problem with my too-hurried patch -- it sometimes adds
spaces between tokens that don't need them (like ';' and '>').  This
diff takes care of it.

..wayne..
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---
Index: Src/hist.c
@@ -652,12 +652,14 @@
 void
 histstrip(Histent he)
 {
-    int i, len;
+    int i, len, needspace;
     int limit = he->nwords*2;
     char *str, *s;
 
-    for (i = 0, len = he->nwords-1; i < limit; i += 2)
-	len += he->words[i+1] - he->words[i];
+    for (i = 0, len = 0; i < limit; i += 2) {
+	len += he->words[i+1] - he->words[i]
+	     + (i > 0 && he->words[i] > he->words[i-1]);
+    }
     if (he->text[len] == '\0')
 	return;
 
@@ -665,13 +667,13 @@
 
     for (i = 0, s = str; i < limit; i += 2) {
 	len = he->words[i+1] - he->words[i];
-	memcpy(s, he->text + he->words[i], len);
+	needspace = (i < limit-2 && he->words[i+2] > he->words[i+1]);
+	memcpy(s, he->text + he->words[i], len + needspace);
 	he->words[i] = s - str;
 	he->words[i+1] = he->words[i] + len;
-	s += len;
-	*s++ = ' ';
+	s += len + needspace;
     }
-    s[-1] = '\0';
+    *s = '\0';
 
     if (he->text != chline)
 	zsfree(he->text);
---8<------8<------8<------8<---cut here--->8------>8------>8------>8---


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1996-08-13  9:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-08-12 12:56 histignoredups done properly Peter Stephenson
1996-08-12 19:17 ` hist_strip_spaces (was Re: histignoredups done properly) Wayne Davison
1996-08-12 21:13   ` hist_strip_spaces Wayne Davison
1996-08-13  9:22     ` hist_strip_spaces Wayne Davison
1996-08-13  5:48   ` hist_strip_spaces (was Re: histignoredups done properly) Andrej Borsenkow

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).