summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Doc/Zsh/zle.yo12
-rw-r--r--Src/Zle/zle.h2
-rw-r--r--Src/Zle/zle_main.c7
-rw-r--r--Src/Zle/zle_misc.c69
-rw-r--r--Src/Zle/zle_params.c73
-rw-r--r--Src/Zle/zle_utils.c18
7 files changed, 129 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index fbf03cb32..b40c631fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2003-01-27 Peter Stephenson <pws@csr.com>
+
+ * 18139: Doc/Zsh/zle.yo, Src/Zle/zle.h, Src/Zle/zle_main.c,
+ Src/Zle/zle_misc.c, Src/Zle/zle_params.c, Src/Zle/zle_utils.c:
+ Improve $killring interface; can now change length. Empty
+ strings in $killring are ignored when yank-popping. Yank-popping
+ is more consistent about looping and using the original cutbuffer.
+
2003-01-27 Oliver Kiddle <opk@zsh.org>
* Doug Kearns: 18141: Completion/Unix/Command/_elinks:
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 771ff4d18..75d3faadf 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -622,10 +622,14 @@ vindex(killring)
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)
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index a611fd58b..e636073c8 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -142,7 +142,7 @@ typedef struct cutbuffer *Cutbuffer;
#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. */
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 1c45d120c..0e63bf5b1 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -1406,8 +1406,11 @@ finish_(Module m)
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);
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 592a590b5..d63b52caa 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -331,28 +331,35 @@ copyregionaskill(char **args)
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 @@ yank(char **args)
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;
}
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index c8b518cbf..e5277d64d 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -391,43 +391,41 @@ unset_cutbuffer(Param pm, int exp)
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 @@ get_killring(Param pm)
{
/*
* 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;
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 107ff37ec..28f5647bd 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -38,9 +38,9 @@ struct cutbuffer cutbuf;
/* 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 @@ cut(int i, int ct, int dir)
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;
}