1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-02 22:11:54 +02:00

16767: Src/Zle/zle_hist.c, Doc/Zsh/zle.yo, Doc/Zsh/contrib.yo,

Functions/Zle/copy-earlier-word:  Enhance insert-last-word to
pick different lines from the history (including the current
line) and different words from that line.  Add copy-earlier-word
as suggested by Dominik Vogt to copy words from either the
current line, or (following an insert-last-word) a previous
history line.
This commit is contained in:
Peter Stephenson 2002-03-05 16:33:19 +00:00
parent 15630b234a
commit 849f4068de
5 changed files with 189 additions and 23 deletions

View file

@ -1,3 +1,13 @@
2002-03-05 Peter Stephenson <pws@csr.com>
* 16767: Src/Zle/zle_hist.c, Doc/Zsh/zle.yo, Doc/Zsh/contrib.yo,
Functions/Zle/copy-earlier-word: Enhance insert-last-word to
pick different lines from the history (including the current
line) and different words from that line. Add copy-earlier-word
as suggested by Dominik Vogt to copy words from either the
current line, or (following an insert-last-word) a previous
history line.
2002-03-04 Peter Stephenson <pws@csr.com>
* 16759: Src/builtin.c: from Eric Norum <eric.norum@usask.ca>:

View file

@ -524,6 +524,20 @@ example(zle -N insert-last-assignment smart-insert-last-word
zstyle :insert-last-assignment match '[[:alpha:]][][[:alnum:]]#=*'
bindkey '\e=' insert-last-assignment)
)
findex(copy-earlier-word)
item(tt(copy-earlier-word))(
This widget works like a combination of tt(insert-last-word) and
tt(copy-prev-shell-word). Repeated invocations of the widget retrieve
earlier words on the relevant history line. With a numeric argument
var(N), insert the var(N)th word from the history line; var(N) may be
negative to count from the end of the line.
If tt(insert-last-word) has been used to retrieve the last word on a
previous history line, repeated invocations will replace that word with
earlier words from the same line.
Otherwise, the widget applies to words on the line currently being edited.
)
enditem()
subsect(Styles)

View file

@ -941,6 +941,37 @@ left (zero inserts the previous command word). Repeating this command
replaces the word just inserted with the last word from the
history event prior to the one just used; numeric arguments can be used in
the same way to pick a word from that event.
When called from a shell function invoked from a user-defined widget, the
command can take one to three arguments. The first argument specifies a
history offset which applies to successive calls to this widget: if is -1,
the default behaviour is used, while if it is 1, successive calls will move
forwards through the history. The value 0 can be used to indicate that the
history line examined by the previous execution of the command will be
reexamined. Note that negative numbers should be preceeded with a
`tt(-)tt(-)' argument to avoid confusing them with options.
If two arguments are given, the second specifies the word on the command
line in normal array index notation (as a more natural alternative to the
prefix argument). Hence 1 is the first word, and -1 (the default) is the
last word.
If a third argument is given, its value is ignored, but it is used to
signify that the history offset is relative to the current history line,
rather than the one remembered after the previous invocations of
tt(insert-last-word).
For example, the default behaviour of the command corresponds to
example(zle insert-last-word -- -1 -1)
while the command
example(zle insert-last-word -- -1 1 -)
always copies the first word of the line in the history immediately before
the line being edited. This has the side effect that later invocations of
the widget will be relative to that line.
)
tindex(vi-repeat-search)
item(tt(vi-repeat-search) (unbound) (n) (unbound))(

View file

@ -0,0 +1,19 @@
# Copy the word before the one you last copied --- call repeatedly
# to cycle through the list of words on the history line.
#
# Words in combination with insert-last-word to use the line reached,
# and start from the word before last. Otherwise, it will operate on
# the current line.
if (( ${NUMERIC:-0} )); then
# 1 means last word, 2 second last, etc.
(( __copyword = ${NUMERIC:-0} ))
elif [[ -n $__copyword && $WIDGET = $LASTWIDGET ]]; then
(( __copyword-- ))
elif [[ $LASTWIDGET = *insert-last-word ]]; then
__copyword=-2
else
__copyword=-1
fi
zle .insert-last-word 0 $__copyword

View file

@ -410,46 +410,138 @@ endofhistory(char **args)
int
insertlastword(char **args)
{
int n;
int n, nwords, histstep = -1, wordpos = 0, deleteword = 0;
char *s, *t;
Histent he;
Histent he = NULL;
LinkList l = NULL;
LinkNode node;
/* multiple calls will now search back through the history, pem */
static char *lastinsert;
static int lasthist, lastpos;
int evhist = addhistnum(curhist, -1, HIST_FOREIGN), save;
static int lasthist, lastpos, lastlen;
int evhist, save;
if (lastinsert) {
int lastlen = ztrlen(lastinsert);
int pos = cs;
/*
* If we have at least one argument, the first is the history
* step. The default is -1 (go back). Repeated calls take
* a step in this direction. A value of 0 is allowed and doesn't
* move the line.
*
* If we have two arguments, the second is the position of
* the word to extract, 1..N. The default is to use the
* numeric argument, or the last word if that is not set.
*
* If we have three arguments, we reset the history pointer to
* the current history event before applying the history step.
*/
if (*args)
{
histstep = (int)zstrtol(*args, NULL, 10);
if (*++args)
{
wordpos = (int)zstrtol(*args, NULL, 10);
if (*++args)
lasthist = curhist;
}
}
if (lastpos <= pos &&
lastlen == pos - lastpos &&
memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) {
evhist = addhistnum(lasthist, -1, HIST_FOREIGN);
if (lastinsert && lastlen &&
lastpos <= cs &&
lastlen == cs - lastpos &&
memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0)
deleteword = 1;
else
lasthist = curhist;
evhist = histstep ? addhistnum(lasthist, histstep, HIST_FOREIGN) :
lasthist;
if (evhist == curhist) {
/*
* The line we are currently editing. If we are going to
* replace an existing word, delete the old one now to avoid
* confusion.
*/
if (deleteword) {
int pos = cs;
cs = lastpos;
foredel(pos - cs);
/*
* Mark that this has been deleted.
* For consistency with history lines, we really ought to
* insert it back if the current command later fails. But
* - we can't be bothered
* - the problem that this can screw up going to other
* lines in the history because we don't update
* the history line isn't really relevant
* - you can see what you're copying, dammit, so you
* shouldn't make errors.
* Of course, I could have implemented it in the time
* it took to say why I haven't.
*/
deleteword = 0;
}
zsfree(lastinsert);
lastinsert = NULL;
/*
* Can only happen fail if the line is empty, I hope.
* In that case, we don't need to worry about restoring
* a deleted word, because that can only have come
* from a non-empty line. I think.
*/
if (!(l = bufferwords(NULL, NULL, NULL)))
return 1;
nwords = countlinknodes(l);
} else {
/* Some stored line. */
if (!(he = quietgethist(evhist)) || !he->nwords)
return 1;
nwords = he->nwords;
}
if (!(he = quietgethist(evhist)) || !he->nwords)
return 1;
if (zmult > 0) {
n = he->nwords - (zmult - 1);
if (wordpos) {
n = (wordpos > 0) ? wordpos : nwords + wordpos + 1;
} else if (zmult > 0) {
n = nwords - (zmult - 1);
} else {
n = 1 - zmult;
}
if (n < 1 || n > he->nwords)
if (n < 1 || n > nwords) {
/*
* We can't put in the requested word, but we did find the
* history entry, so we remember the position in the history
* list. This avoids getting stuck on a history line with
* fewer words than expected. The cursor location cs
* has not changed, and lastinsert is still valid.
*/
lasthist = evhist;
return 1;
s = he->text + he->words[2*n-2];
t = he->text + he->words[2*n-1];
}
/*
* Only remove the old word from the command line if we have
* successfully found a new one to insert.
*/
if (deleteword > 0) {
int pos = cs;
cs = lastpos;
foredel(pos - cs);
}
if (lastinsert) {
zfree(lastinsert, lastlen);
lastinsert = NULL;
}
if (l) {
for (node = firstnode(l); --n; incnode(node))
;
s = (char *)getdata(node);
t = s + strlen(s);
} else {
s = he->text + he->words[2*n-2];
t = he->text + he->words[2*n-1];
}
save = *t;
*t = '\0'; /* ignore trailing whitespace */
lasthist = evhist;
lastpos = cs;
lastinsert = ztrdup(s);
lastlen = t - s;
lastinsert = zalloc(t - s);
memcpy(lastinsert, s, lastlen);
n = zmult;
zmult = 1;
doinsert(s);