zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Zsh Workers <zsh-workers@zsh.org>
Subject: Re: !!$ unitialized at first prompt
Date: Fri, 24 Sep 2010 21:12:47 +0100	[thread overview]
Message-ID: <20100924211247.626449fb@pws-pc> (raw)
In-Reply-To: <100924081042.ZM4496@torch.brasslantern.com>

On Fri, 24 Sep 2010 08:10:40 -0700
Bart Schaefer <schaefer@brasslantern.com> 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@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


  parent reply	other threads:[~2010-09-24 21:18 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-24  4:36 Benjamin R. Haskell
2010-09-24  4:43 ` Benjamin R. Haskell
2010-09-24 11:48   ` Mikael Magnusson
2010-09-24 12:39     ` Peter Stephenson
2010-09-24 14:18       ` Benjamin R. Haskell
2010-09-24 14:26         ` Peter Stephenson
2010-09-24 15:30           ` Bart Schaefer
2010-09-24 15:10       ` Bart Schaefer
2010-09-24 15:20         ` Mikael Magnusson
2010-09-24 20:12         ` Peter Stephenson [this message]
2010-09-25  6:53           ` Bart Schaefer
2010-09-25 17:26             ` Wayne Davison
2010-09-25 18:49               ` Peter Stephenson
2010-09-26  1:14                 ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100924211247.626449fb@pws-pc \
    --to=p.w.stephenson@ntlworld.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).