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

Re: !!$ unitialized at first prompt



On Fri, 24 Sep 2010 08:10:40 -0700
Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> You can load your own history something like this provided that you
> *don't* use shared or extended history:
> 
>     readhistfile() {
> 	emulate -LR zsh
> 	local histline
> 	local -a histwords
> 	while read -r histline
> 	do
> 	    if [[ $histline = *\\ ]]
> 	    then
> 		histline[-1]=''
> 		histwords+=( ${(z)histline}$'\n' )
> 	    else
> 		histwords+=( ${(z)histline} )
> 		print -s $histwords
> 		histwords=()
> 	    fi
> 	done
>     }

This, we can do internally without the side effects.  I'd forgotten this
already did use the lexer, so I was too pessimistic.

The mechanism for word splitting in the manner of the (z) flag is a bit
iffy.  I've picked up that newlines get turned into semicolons --- there
was a discussion about this recently --- and also that &! turns into &|,
which I didn't know about.  If you have debugging turned on you'll see
warning messages that should be enough to fix any remaining problems.
(I could just assume the words are at least the right length but I'd
rather find out the problems.)

Index: Src/hist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hist.c,v
retrieving revision 1.99
diff -p -u -r1.99 hist.c
--- Src/hist.c	22 Jun 2010 11:00:32 -0000	1.99
+++ Src/hist.c	24 Sep 2010 19:59:41 -0000
@@ -2228,11 +2228,12 @@ readhistfile(char *fn, int err, int read
     Histent he;
     time_t stim, ftim, tim = time(NULL);
     off_t fpos;
-    short *wordlist;
+    short *words;
     struct stat sb;
-    int nwordpos, nwordlist, bufsiz;
+    int nwordpos, nwords, bufsiz;
     int searching, newflags, l, ret;
-
+    LinkList wordlist;
+   
     if (!fn && !(fn = getsparam("HISTFILE")))
 	return;
     if (readflags & HFILE_FAST) {
@@ -2251,8 +2252,8 @@ readhistfile(char *fn, int err, int read
 	}
     }
     if ((in = fopen(unmeta(fn), "r"))) {
-	nwordlist = 64;
-	wordlist = (short *)zalloc(nwordlist*sizeof(short));
+	nwords = 64;
+	words = (short *)zalloc(nwords*sizeof(short));
 	bufsiz = 1024;
 	buf = zalloc(bufsiz);
 
@@ -2334,29 +2335,63 @@ readhistfile(char *fn, int err, int read
 	    else
 		he->ftim = ftim;
 
-	    /* Divide up the words.  We don't know how it lexes,
-	       so just look for white-space.
-	       */
+	    /*
+	     * Divide up the words.  Attempt to do this using the lexer.
+	     */
 	    nwordpos = 0;
 	    start = pt;
-	    do {
+	    wordlist = bufferwords(NULL, pt, NULL);
+	    he->nwords = countlinknodes(wordlist);
+	    if (2*he->nwords > nwords) {
+		nwords = 2*he->nwords;
+		words = (short *)realloc(words, nwords*sizeof(short));
+	    }
+	    while (firstnode(wordlist)) {
+		char *word = uremnode(wordlist, firstnode(wordlist));
+		
 		while (inblank(*pt))
 		    pt++;
-		if (*pt) {
-		    if (nwordpos >= nwordlist)
-			wordlist = (short *) realloc(wordlist,
-					(nwordlist += 64)*sizeof(short));
-		    wordlist[nwordpos++] = pt - start;
-		    while (*pt && !inblank(*pt))
-			pt++;
-		    wordlist[nwordpos++] = pt - start;
+		if (!strpfx(word, pt)) {
+		    int bad = 0;
+		    /*
+		     * Oddity 1: newlines turn into semicolons.
+		     */
+		    if (!strcmp(word, ";"))
+			continue;
+		    /*
+		     * Oddity 2: !'s turn into |'s.
+		     */
+		    while (*pt) {
+			if (!*word) {
+			    bad = 1;
+			    break;
+			}
+			if (*pt == *word ||
+			    (*pt == '!' && *word == '|')) {
+			    pt++;
+			    word++;
+			} else {
+			    bad = 1;
+			    break;
+			}
+		    }
+		    if (bad) {
+#ifdef DEBUG
+			dputs(ERRMSG("bad wordsplit reading history: %s\nat: %s"
+				     "\nword: %s"),
+			      start, pt, word);
+#endif
+			break;
+		    }
 		}
-	    } while (*pt);
+		words[nwordpos++] = pt - start;
+		pt += strlen(word);
+		words[nwordpos++] = pt - start;
+	    }
 
-	    he->nwords = nwordpos/2;
 	    if (he->nwords) {
 		he->words = (short *)zalloc(nwordpos*sizeof(short));
-		memcpy(he->words, wordlist, nwordpos*sizeof(short));
+		memcpy(he->words, words, nwordpos*sizeof(short));
 	    } else
 		he->words = (short *)NULL;
 	    addhistnode(histtab, he->node.nam, he);
@@ -2369,7 +2404,7 @@ readhistfile(char *fn, int err, int read
 	    zsfree(lasthist.text);
 	    lasthist.text = ztrdup(start);
 	}
-	zfree(wordlist, nwordlist*sizeof(short));
+	zfree(words, nwords*sizeof(short));
 	zfree(buf, bufsiz);
 
 	fclose(in);

-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



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