18139: 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.
This commit is contained in:
Peter Stephenson 2003-01-27 14:54:31 +00:00
parent cd70d2745c
commit 778a73b027
7 changed files with 130 additions and 61 deletions

View file

@ -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:

View file

@ -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)

View file

@ -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. */

View file

@ -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);

View file

@ -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;
}

View file

@ -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 (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.
*/
for (p = x; kcnt < KRINGCT && *p; kcnt++, p++) {
Cutbuffer kptr = kring + kpos;
if (kring) {
for (kptr = kring, kcnt = 0; kcnt < kringsize; kcnt++, kptr++)
if (kptr->buf)
free(kptr->buf);
kptr->buf = (char *)zalloc(strlen(*p));
zfree(kring, kringsize * sizeof(struct cutbuffer));
kring = NULL;
kringsize = kringnum = 0;
}
if (x) {
/*
* Insert the elements into the kill ring.
* Regardless of the old order, we number it with the current
* entry first.
*/
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;

View file

@ -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;
}