22606: add match-word-context.

Remove workaround from match-words-by-style
This commit is contained in:
Peter Stephenson 2006-08-14 16:14:41 +00:00
parent f2dbedcc4f
commit 3a97920199
5 changed files with 94 additions and 23 deletions

View file

@ -1,5 +1,10 @@
2006-08-14 Peter Stephenson <pws@csr.com>
* 22606: Doc/Zsh/contrib.yo, Functions/Zle/match-word-context,
Functions/Zle/match-words-by-style, Functions/Zle/.distfiles: new
word-context style for word matching, remove out-of-date handling
for bug.
* 22605: Src/Zle/complist.c: bug in 22597 noticed by Bart
when not printing.

View file

@ -384,12 +384,13 @@ tindex(capitalize-word-match)
tindex(up-case-word-match)
tindex(down-case-word-match)
tindex(select-word-style)
tindex(match-word-context)
tindex(match-words-by-style)
xitem(tt(forward-word-match), tt(backward-word-match))
xitem(tt(kill-word-match), tt(backward-kill-word-match))
xitem(tt(transpose-words-match), tt(capitalize-word-match))
xitem(tt(up-case-word-match), tt(down-case-word-match))
item(tt(select-word-style), tt(match-words-by-style))(
item(tt(select-word-style), tt(match-word-context), tt(match-words-by-style))(
The eight `tt(-match)' functions are drop-in replacements for the
builtin widgets without the suffix. By default they behave in a similar
way. However, by the use of styles and the function tt(select-word-style),
@ -463,7 +464,7 @@ Words are whitespace-delimited strings of characters.
)
enditem()
The first three of those styles usually use tt($WORDCHARS), but the value
The first three of those rules usually use tt($WORDCHARS), but the value
in the parameter can be overridden by the style tt(word-chars), which works
in exactly the same way as tt($WORDCHARS). In addition, the style
tt(word-class) uses character class syntax to group characters and takes
@ -474,7 +475,7 @@ alphanumerics plus the characters `tt(-)' and `tt(:)'. Be careful
including `tt(])', `tt(^)' and `tt(-)' as these are special inside
character classes.
The final style is tt(skip-chars). This is mostly useful for
The style tt(skip-chars) is mostly useful for
tt(transpose-words) and similar functions. If set, it gives a count of
characters starting at the cursor position which will not be considered
part of the word and are treated as space, regardless of what they actually
@ -486,6 +487,17 @@ has been set, and tt(transpose-words-match) is called with the cursor on
the var(X) of tt(foo)var(X)tt(bar), where var(X) can be any character, then
the resulting expression is tt(bar)var(X)tt(foo).
Finer grained control can be obtained by setting the style
tt(word-context) to an array of pairs of entries. Each pair of entries
consists of a var(pattern) and a var(subcontext). The word the cursor is on is
matched against each var(pattern) in turn until one matches; if it does,
the context is extended by a colon and the corresponding var(subcontext).
Note that the test is made against the original word on the line, with
no stripping of quotes. If the cursor is at the end of the line
the test is maded against an empty string; if it is on whitespace
between words the test is made against a single space. Some examples
are given below.
Here are some examples of use of the styles, actually taken from the
simplified interface in tt(select-word-style):
@ -501,6 +513,21 @@ example(style ':zle:*kill*' word-style space)
Uses space-delimited words for widgets with the word `kill' in the name.
Neither of the styles tt(word-chars) nor tt(word-class) is used in this case.
Here are some examples of use of the tt(word-context) style to extend
the context.
example(zstyle ':zle:*' word-context "[[:space:]]" whitespace "*/*" file
zstyle ':zle:transpose-words:whitespace' word-style shell
zstyle ':zle:transpose-words:filename' word-style normal
zstyle ':zle:transpose-words:filename' word-chars '')
This provides two different ways of using tt(transpose-words) depending on
whether the cursor is on whitespace between words or on a filename, here
any word containing a tt(/). On whitespace, complete arguments as defined
by standard shell rules will be transposed. In a filename, only
alphanumerics will be transposed. Elsewhere, words will be transposed
using the default style for tt(:zle:transpose-words).
The word matching and all the handling of tt(zstyle) settings is actually
implemented by the function tt(match-words-by-style). This can be used to
create new user-defined widgets. The calling function should set the local
@ -527,6 +554,10 @@ endsitem()
For example, tt(match-words-by-style -w shell -c 0) may be used to
extract the command argument around the cursor.
The tt(word-context) style is implemented by the function
tt(match-word-context). This should not usually need to be called
directly.
)
tindex(delete-whole-word-match)
item(tt(delete-whole-word-match))(

View file

@ -11,6 +11,7 @@ incarg incremental-complete-word
insert-composed-char insert-files
insert-unicode-char keeper
keymap+widget kill-word-match
match-word-context
match-words-by-style narrow-to-region
narrow-to-region-invisible predict-on
quote-and-complete-word read-from-minibuffer

View file

@ -0,0 +1,48 @@
# See if we can extend the word context to something more specific.
# curcontext must be set to the base context by this point; it
# will be appended to directly.
emulate -L zsh
setopt extendedglob
local -a worcon bufwords
local pat tag lastword word
integer iword
zstyle -a $curcontext word-context worcon || return 0
if (( ${#worcon} % 2 )); then
zle -M "Bad word-context style in context $curcontext"
return
fi
bufwords=(${(z)LBUFFER})
iword=${#bufwords}
lastword=${bufwords[-1]}
bufwords=(${(z)BUFFER})
if [[ $lastword = ${bufwords[iword]} ]]; then
# If the word immediately left of the cursor is complete,
# we're not on it. Either we're on unquoted whitespace, or
# the start of a new word. Test the latter.
if [[ -z $RBUFFER ]]; then
# Nothing there, so not in a word.
word=''
elif [[ $RBUFFER[1] = [[:space:]] ]]; then
# Whitespace, so not in a word.
word=' '
else
# We want the next word along.
word=${bufwords[iword+1]}
fi
else
# We're on a word.
word=${bufwords[iword]}
fi
for pat tag in "${worcon[@]}"; do
if [[ $word = ${~pat} ]]; then
curcontext+=":$tag"
return
fi
done

View file

@ -71,9 +71,10 @@ local wordstyle spacepat wordpat1 wordpat2 opt charskip wordchars wordclass
local match mbegin mend pat1 pat2 word1 word2 ws1 ws2 ws3 skip
local nwords MATCH MBEGIN MEND
if [[ -z $curcontext ]]; then
local curcontext=:zle:match-words-by-style
fi
local curcontext=${curcontext:-:zle:match-words-by-style}
autoload -U match-word-context
match-word-context
while getopts "w:s:c:C:" opt; do
case $opt in
@ -108,27 +109,12 @@ case $wordstyle in
# This splits the line into words as the shell understands them.
bufwords=(${(z)LBUFFER})
nwords=${#bufwords}
# Work around bug: if stripping quotes failed, a bogus
# space is appended. Not a good test, since this may
# be a quoted space, but it's hard to get right.
wordpat1=${bufwords[-1]}
if [[ ${wordpat1[-1]} = ' ' ]]; then
wordpat1=${(q)wordpat1[1,-2]}
else
wordpat1="${(q)wordpat1}"
fi
wordpat1="${(q)bufwords[-1]}"
# Take substring of RBUFFER to skip over $skip characters
# from the cursor position.
bufwords=(${(z)RBUFFER[1+$skip,-1]})
# Work around bug again.
wordpat2=${bufwords[1]}
if [[ ${wordpat2[-1]} = ' ' ]]
then
wordpat2=${(q)wordpat2[1,-2]}
else
wordpat2="${(q)wordpat2}"
fi
wordpat2="${(q)bufwords[1]}"
spacepat='[[:space:]]#'
# Assume the words are at the top level, i.e. if we are inside