From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8452 invoked from network); 24 Jan 2003 12:21:01 -0000 Received: from sunsite.dk (130.225.247.90) by ns1.primenet.com.au with SMTP; 24 Jan 2003 12:21:01 -0000 Received: (qmail 21846 invoked by alias); 24 Jan 2003 12:20:51 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 18139 Received: (qmail 21837 invoked from network); 24 Jan 2003 12:20:51 -0000 Received: from localhost (HELO sunsite.dk) (127.0.0.1) by localhost with SMTP; 24 Jan 2003 12:20:51 -0000 X-MessageWall-Score: 0 (sunsite.dk) Received: from [62.189.183.235] by sunsite.dk (MessageWall 1.0.8) with SMTP; 24 Jan 2003 12:20:51 -0000 Received: from exchange01.csr.com (unverified) by (Content Technologies SMTPRS 4.2.1) with ESMTP id ; Fri, 24 Jan 2003 12:26:44 +0000 Received: from csr.com (tinky-winky.csr.com [192.168.144.127]) by exchange01.csr.com with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2650.21) id DQ47JH3T; Fri, 24 Jan 2003 12:19:06 -0000 To: zsh-workers@sunsite.dk (Zsh hackers list) Cc: Andy Spiegl Subject: Re: size of kill-ring? In-reply-to: "Peter Stephenson"'s message of "Thu, 23 Jan 2003 17:28:57 GMT." <3412.1043342937@csr.com> Date: Fri, 24 Jan 2003 12:20:47 +0000 Message-ID: <934.1043410847@csr.com> From: Peter Stephenson Peter Stephenson wrote: > Andy Spiegl wrote: > > is there any way I can change the size of the kill-ring? > > Andy. > > Rewrite zle to make the constant KRINGCT dynamic. This looks a fairly > easy project, and (in 4.1) there's already an interface for changing the > size via the new $killring zle parameter. This is the first attempt. I had some crashes in the early stages and although I haven't seen any with the version below it's worth playing around to see if there is anything amiss. A simple inc-kill-ring-size widget looks like: # Increase (or decrease) size of zle kill ring, depending on the # widget name. # zle -N inc-kill-ring-size # zle -N dec-kill-ring-size inc-kill-ring-size emulate -L zsh if [[ $WIDGET = inc* ]]; then killring=(${killring} '') elif (( ${#killring} )); then killring=(${killring[1,-2]}) fi which can be extended in any number of ways --- the fixed size limitation on $killring has gone, so it really does work like a normal array now. Remember, however, that zle parameters are only special in zle widgets, to avoid namespace pollution. I've fixed two existing inconsistencies on the way, the first actually a by-product: 1. Previously, if the kill ring wasn't full, yank-pop got to the last entry and stuck instead of cycling back to the beginning. Now it always cycles even if it's not full. This is partly to get around the fact that with the array there's no distinction between an empty buffer and a buffer with a zero-length string in it --- I am assuming that yanking zero-length text is not useful, so such buffers are always skipped when yank-pop'ing. 2. Previously yank-pop didn't cycle back to the original cut buffer, which should logically appear just before the second time you loop through the kill ring. Now this is part of the sequence. I haven't documented this bit since it seems to me the obvious behaviour anyway. It's certainly what Emacs does. Index: Doc/Zsh/zle.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v retrieving revision 1.27 diff -u -r1.27 zle.yo --- Doc/Zsh/zle.yo 6 Dec 2002 23:24:07 -0000 1.27 +++ Doc/Zsh/zle.yo 24 Jan 2003 12:05:21 -0000 @@ -622,10 +622,14 @@ item(tt(killring) (array))( The array of previously killed items, with the most recently killed first. This gives the items that would be retrieved by a tt(yank-pop) in the -same order, up to eight (which is the maximum stored internally). -Unlike a normal array, only a maximum of eight elements may be written; -any extra are ignored. If fewer than eight elements are given, the -remaining elements of the kill ring will be treated as undefined. +same order. + +The default size for the kill ring is eight, however the length may be +changed by normal array operations. Any empty string in the kill ring is +ignored by the tt(yank-pop) command, hence the size of the array +effectively sets the maximum length of the kill ring, while the number of +non-zero strings gives the current length, both as seen by the user at the +command line. ) vindex(LASTSEARCH) Index: Src/Zle/zle.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle.h,v retrieving revision 1.2 diff -u -r1.2 zle.h --- Src/Zle/zle.h 23 May 2000 08:20:57 -0000 1.2 +++ Src/Zle/zle.h 24 Jan 2003 12:05:21 -0000 @@ -142,7 +142,7 @@ #define CUTBUFFER_LINE 1 /* for vi: buffer contains whole lines of data */ -#define KRINGCT 8 /* number of buffers in the kill ring */ +#define KRINGCTDEF 8 /* default number of buffers in the kill ring */ /* Types of completion. */ Index: Src/Zle/zle_main.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v retrieving revision 1.28 diff -u -r1.28 zle_main.c --- Src/Zle/zle_main.c 27 Aug 2002 21:10:34 -0000 1.28 +++ Src/Zle/zle_main.c 24 Jan 2003 12:05:21 -0000 @@ -1406,8 +1406,11 @@ if (rdstrs) freelinklist(rdstrs, freestr); zfree(cutbuf.buf, cutbuf.len); - for(i = KRINGCT; i--; ) - zfree(kring[i].buf, kring[i].len); + if (kring) { + for(i = kringsize; i--; ) + zfree(kring[i].buf, kring[i].len); + zfree(kring, kringsize * sizeof(struct cutbuffer)); + } for(i = 35; i--; ) zfree(vibuf[i].buf, vibuf[i].len); Index: Src/Zle/zle_misc.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v retrieving revision 1.6 diff -u -r1.6 zle_misc.c --- Src/Zle/zle_misc.c 3 Sep 2001 01:39:20 -0000 1.6 +++ Src/Zle/zle_misc.c 24 Jan 2003 12:05:21 -0000 @@ -331,28 +331,35 @@ return 0; } +/* + * kct: index into kill ring, or -1 for original cutbuffer of yank. + * yankb, yanke: mark the start and end of last yank in editing buffer. + */ static int kct, yankb, yanke; +/* The original cutbuffer, either cutbuf or one of the vi buffers. */ +static Cutbuffer kctbuf; /**/ int yank(char **args) { - Cutbuffer buf = &cutbuf; int n = zmult; if (n < 0) return 1; if (zmod.flags & MOD_VIBUF) - buf = &vibuf[zmod.vibuf]; - if (!buf->buf) + kctbuf = &vibuf[zmod.vibuf]; + else + kctbuf = &cutbuf; + if (!kctbuf->buf) return 1; mark = cs; yankb = cs; while (n--) { - kct = kringnum; - spaceinline(buf->len); - memcpy((char *)line + cs, buf->buf, buf->len); - cs += buf->len; + kct = -1; + spaceinline(kctbuf->len); + memcpy((char *)line + cs, kctbuf->buf, kctbuf->len); + cs += kctbuf->len; yanke = cs; } return 0; @@ -362,18 +369,56 @@ int yankpop(char **args) { - int cc; + int cc, kctstart = kct; + Cutbuffer buf; - if (!(lastcmd & ZLE_YANK) || !kring[kct].buf) + if (!(lastcmd & ZLE_YANK)) return 1; + do { + /* + * This is supposed to make the yankpop loop + * original buffer -> kill ring in order -> original buffer -> ... + * where the original buffer is -1 and the remainder are + * indices into the kill ring, remember that we need to start + * that at kringnum rather than zero. + */ + if (kct == -1) + kct = kringnum; + else { + int kctnew = (kct + kringsize - 1) % kringsize; + if (kctnew == kringnum) + kct = -1; + else + kct = kctnew; + } + if (kct == -1) + buf = kctbuf; /* Use original cutbuffer */ + else + buf = kring+kct; /* Use somewhere in the kill ring */ + /* Careful to prevent infinite looping */ + if (kct == kctstart) + return 1; + /* + * Skip unset buffers instead of stopping as we used to do. + * Also skip zero-length buffers. + * There are two reasons for this: + * 1. We now map the array $killring directly into the + * killring, instead of via some extra size-checking logic. + * When $killring has been set, a buffer will always have + * at least a zero-length string in it. + * 2. The old logic was inconsistent; when the kill ring + * was full, we could loop round and round it, otherwise + * we just stopped when we hit the first empty buffer. + */ + } while (!buf->buf || !*buf->buf); + cs = yankb; foredel(yanke - yankb); - cc = kring[kct].len; + cc = buf->len; spaceinline(cc); - memcpy((char *)line + cs, kring[kct].buf, cc); + memcpy((char *)line + cs, buf->buf, cc); cs += cc; yanke = cs; - kct = (kct + KRINGCT - 1) % KRINGCT; return 0; } Index: Src/Zle/zle_params.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_params.c,v retrieving revision 1.7 diff -u -r1.7 zle_params.c --- Src/Zle/zle_params.c 6 Dec 2002 23:24:07 -0000 1.7 +++ Src/Zle/zle_params.c 24 Jan 2003 12:05:21 -0000 @@ -391,43 +391,41 @@ static void set_killring(Param pm, char **x) { - int kpos, kcnt; + int kcnt; + Cutbuffer kptr; char **p; - kcnt = 0; - kpos = kringnum; - + if (kring) { + for (kptr = kring, kcnt = 0; kcnt < kringsize; kcnt++, kptr++) + if (kptr->buf) + free(kptr->buf); + zfree(kring, kringsize * sizeof(struct cutbuffer)); + kring = NULL; + kringsize = kringnum = 0; + } if (x) { /* - * Insert the elements into the kill ring, up to a maximum - * of KRINGCT. We always handle the ring in the order - * a series of yank-pops would show, i.e. starting with - * the most recently cut and going backwards. + * Insert the elements into the kill ring. + * Regardless of the old order, we number it with the current + * entry first. */ - for (p = x; kcnt < KRINGCT && *p; kcnt++, p++) { - Cutbuffer kptr = kring + kpos; - if (kptr->buf) - free(kptr->buf); - kptr->buf = (char *)zalloc(strlen(*p)); + kringsize = arrlen(x); + kring = (Cutbuffer)zcalloc(kringsize * sizeof(struct cutbuffer)); + for (p = x, kptr = kring; *p; p++, kptr++) { + int len = strlen(*p); + kptr->buf = (char *)zalloc(len); strcpy(kptr->buf, *p); unmetafy(kptr->buf, &kptr->len); - kptr->flags = 0; - kpos = (kpos + KRINGCT - 1) % KRINGCT; + if (len != kptr->len) { + /* Might as well have the lengths consistent. */ + char *p2 = zalloc(kptr->len); + memcpy(p2, kptr->buf, kptr->len); + zfree(kptr->buf, len); + kptr->buf = p2; + } } freearray(x); } - /* - * Any values unsupplied are to be unset. - */ - for (; kcnt < KRINGCT; kcnt++) { - Cutbuffer kptr = kring + kpos; - if (kptr->buf) { - free(kptr->buf); - kptr->buf = NULL; - kptr->flags = kptr->len = 0; - } - kpos = (kpos + KRINGCT - 1) % KRINGCT; - } } /**/ @@ -436,23 +434,28 @@ { /* * Return the kill ring with the most recently killed first. - * Stop as soon as we find something which isn't set, i.e. - * don't fill in bogus entries. + * Since the kill ring is no longer a fixed length, we return + * all entries even if empty. */ int kpos, kcnt; char **ret, **p; - for (kpos = kringnum, kcnt = 0; kcnt < KRINGCT; kcnt++) { + /* Supposed to work even if kring is NULL */ + for (kpos = kringnum, kcnt = 0; kcnt < kringsize; kcnt++) { if (!kring[kpos].buf) break; - kpos = (kpos + KRINGCT - 1) % KRINGCT; + kpos = (kpos + kringsize - 1) % kringsize; } - p = ret = (char **)zhalloc((kcnt+1) * sizeof(char *)); + p = ret = (char **)zhalloc((kringsize+1) * sizeof(char *)); - for (kpos = kringnum; kcnt; kcnt--) { - *p++ = metafy((char *)kring[kpos].buf, kring[kpos].len, META_HEAPDUP); - kpos = (kpos + KRINGCT - 1) % KRINGCT; + for (kpos = kringnum, kcnt = 0; kcnt < kringsize; kcnt++) { + Cutbuffer kptr = kring + kpos; + if (kptr->buf) + *p++ = metafy((char *)kptr->buf, kptr->len, META_HEAPDUP); + else + *p++ = dupstring(""); + kpos = (kpos + kringsize - 1) % kringsize; } *p = NULL; Index: Src/Zle/zle_utils.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_utils.c,v retrieving revision 1.6 diff -u -r1.6 zle_utils.c --- Src/Zle/zle_utils.c 26 Mar 2001 08:58:34 -0000 1.6 +++ Src/Zle/zle_utils.c 24 Jan 2003 12:05:21 -0000 @@ -38,9 +38,9 @@ /* Emacs-style kill buffer ring */ /**/ -struct cutbuffer kring[KRINGCT]; +struct cutbuffer *kring; /**/ -int kringnum; +int kringsize, kringnum; /* Vi named cut buffers. 0-25 are the named buffers "a to "z, and * * 26-34 are the numbered buffer stack "1 to "9. */ @@ -167,10 +167,16 @@ cutbuf.buf = ztrdup(""); cutbuf.len = cutbuf.flags = 0; } else if (!(lastcmd & ZLE_KILL)) { - kringnum = (kringnum + 1) % KRINGCT; - if (kring[kringnum].buf) - free(kring[kringnum].buf); - kring[kringnum] = cutbuf; + Cutbuffer kptr; + if (!kring) { + kringsize = KRINGCTDEF; + kring = (Cutbuffer)zcalloc(kringsize * sizeof(struct cutbuffer)); + } else + kringnum = (kringnum + 1) % kringsize; + kptr = kring + kringnum; + if (kptr->buf) + zfree(kptr->buf, kptr->len); + *kptr = cutbuf; cutbuf.buf = ztrdup(""); cutbuf.len = cutbuf.flags = 0; } -- Peter Stephenson Software Engineer CSR Ltd., Science Park, Milton Road, Cambridge, CB4 0WH, UK Tel: +44 (0)1223 692070 ********************************************************************** The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer. **********************************************************************