mirror of
https://github.com/zsh-users/zsh
synced 2024-07-21 18:24:18 +00:00
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:
parent
cd70d2745c
commit
778a73b027
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue