mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
18394: New word movement and editing widgets.
This commit is contained in:
parent
2941469f61
commit
1e57c42f47
13 changed files with 678 additions and 26 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
2003-03-28 Peter Stephenson <pws@csr.com>
|
||||
|
||||
* 18394: Doc/Zsh/contrib.yo,
|
||||
Functions/Zle/backward-kill-word-match,
|
||||
Functions/Zle/backward-word-match,
|
||||
Functions/Zle/capitalize-word-match,
|
||||
Functions/Zle/down-case-word-match,
|
||||
Functions/Zle/forward-word-match, Functions/Zle/kill-word-match,
|
||||
Functions/Zle/match-words-by-style,
|
||||
Functions/Zle/read-from-minibuffer,
|
||||
Functions/Zle/select-word-style,
|
||||
Functions/Zle/transpose-words-match,
|
||||
Functions/Zle/up-case-word-match: Replacement widgets for
|
||||
word movement and editing, controlled by style and by
|
||||
select-word-style widget/function.
|
||||
|
||||
2003-03-26 Peter Stephenson <pws@csr.com>
|
||||
|
||||
* 18392: Src/builtin.c: read with -p and -t options crashed
|
||||
|
|
|
@ -362,29 +362,141 @@ followed by an appropriate tt(bindkey) command to associate the function
|
|||
with a key sequence. Suggested bindings are described below.
|
||||
|
||||
startitem()
|
||||
tindex(bash-forward-word)
|
||||
tindex(bash-backward-word)
|
||||
tindex(bash-kill-word)
|
||||
tindex(bash-backward-kill-word)
|
||||
tindex(bash-transpose-words)
|
||||
tindex(bash-up-case-word)
|
||||
tindex(bash-down-case-word)
|
||||
xitem(tt(bash-forward-word), tt(bash-backward-word))
|
||||
xitem(tt(bash-kill-word), tt(bash-backward-kill-word))
|
||||
xitem(tt(bash-up-case-word), tt(bash-down-case-word))
|
||||
item(tt(bash-transpose-words))(
|
||||
These work similarly to the corresponding builtin zle functions without the
|
||||
`tt(bash-)' prefix, but a word is considered to consist of alphanumeric
|
||||
characters only. If you wish to replace your existing bindings with these
|
||||
four widgets, the following is sufficient:
|
||||
item(bash-style word functions)(
|
||||
If you are looking for functions to implement moving over and editing
|
||||
words in the manner of bash, where only alphanumeric characters are
|
||||
considered word characters, you can use the functions described in
|
||||
the next section. The following is sufficient:
|
||||
|
||||
example(for widget in kill-word backward-kill-word \
|
||||
forward-word backward-word \
|
||||
up-case-word down-case-word \
|
||||
transpose-words; do
|
||||
autoload bash-$widget
|
||||
zle -N $widget bash-$widget
|
||||
done)
|
||||
example(autoload -U select-word-style
|
||||
select-word-style bash)
|
||||
|
||||
)
|
||||
tindex(forward-word-match)
|
||||
tindex(backward-word-match)
|
||||
tindex(kill-word-match)
|
||||
tindex(backward-kill-word-match)
|
||||
tindex(transpose-words-match)
|
||||
tindex(capitalize-word-match)
|
||||
tindex(up-case-word-match)
|
||||
tindex(down-case-word-match)
|
||||
tindex(select-word-style)
|
||||
tindex(match-word-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-word-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),
|
||||
the way words are matched can be altered.
|
||||
|
||||
The simplest way of configuring the functions is to use
|
||||
tt(select-word-style), which can either be called as a normal function with
|
||||
the appropriate argument, or invoked as a user-defined widget that will
|
||||
prompt for the first character of the word style to be used. The first
|
||||
time it is invoked, the eight tt(-match) functions will automatically
|
||||
replace the builtin versions, so they do not need to be loaded explicitly.
|
||||
|
||||
The word styles available are as follows. Only the first character
|
||||
is examined.
|
||||
|
||||
startitem()
|
||||
item(tt(bash))(
|
||||
Word characters are alphanumeric characters only.
|
||||
)
|
||||
item(tt(normal))(
|
||||
As in normal shell operation: word characters are alphanumeric characters
|
||||
plus any characters present in the string given by the parameter
|
||||
tt($WORDCHARS).
|
||||
)
|
||||
item(tt(shell))(
|
||||
Words are complete shell command arguments, possibly including complete
|
||||
quoted strings, or any tokens special to the shell.
|
||||
)
|
||||
item(tt(whitespace))(
|
||||
Words are any set of characters delimited by whitespace.
|
||||
)
|
||||
item(tt(default))(
|
||||
Restore the default settings; this is usually the same as `tt(normal)'.
|
||||
)
|
||||
enditem()
|
||||
|
||||
More control can be obtained using the tt(zstyle) command, as described in
|
||||
ifzman(zmanref(zshmodules))\
|
||||
ifnzman(noderef(The zsh/zutil Module)). Each style is looked up in the
|
||||
context tt(:zle:)var(widget) where var(widget) is the name of the
|
||||
user-defined widget, not the name of the function implementing it, so in
|
||||
the case of the definitions supplied by tt(select-word-style) the
|
||||
appropriate contexts are tt(:zle:forward-word), and so on. The function
|
||||
tt(select-word-style) itself always defines styles for the context
|
||||
`tt(:zle:*)' which can be overridden by more specific (longer) patterns as
|
||||
well as explicit contexts.
|
||||
|
||||
The style tt(word-style) specifies the rules to use. This may have the
|
||||
following values.
|
||||
|
||||
startitem()
|
||||
item(tt(normal))(
|
||||
Use the standard shell rules, i.e. alphanumerics and tt($WORDCHARS), unless
|
||||
overridden by the styles tt(word-chars) or tt(word-class).
|
||||
)
|
||||
item(tt(specified))(
|
||||
Similar to tt(normal), but em(only) the specified characters, and not also
|
||||
alphanumerics, are considered word characters.
|
||||
)
|
||||
item(tt(unspecified))(
|
||||
The negation of specified. The given characters are those which will
|
||||
em(not) be considered part of a word.
|
||||
)
|
||||
item(tt(shell))(
|
||||
Words are obtained by using the syntactic rules for generating shell
|
||||
command arguments. In addition, special tokens which are never command
|
||||
arguments such as `tt(())' are also treated as words.
|
||||
)
|
||||
item(tt(whitespace))(
|
||||
Words are whitespace-delimited strings of characters.
|
||||
)
|
||||
enditem()
|
||||
|
||||
The first three of those styles 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
|
||||
precedence over tt(word-chars) if both are set. The tt(word-class) style
|
||||
does not include the surrounding brackets of the character class; for
|
||||
example, `tt(-:[:alnum:])' is a valid tt(word-class) to include all
|
||||
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
|
||||
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
|
||||
are. For example, if
|
||||
|
||||
example(zstyle ':zle:transpose-words' skip-chars 1)
|
||||
|
||||
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).
|
||||
|
||||
The word matching and all the handling of tt(zstyle) settings is actually
|
||||
implemented by the function tt(match-word-by-style). This can be used to
|
||||
create new user-defined widgets. The calling function should set the local
|
||||
parameter tt(curcontext) to tt(:zle:)var(widget), create the local
|
||||
parameter tt(matched_words) and call tt(match-word-by-style) with no
|
||||
arguments. On return, tt(matched_words) will be set to an array with the
|
||||
elements: (1) the start of the line (2) the word before the cursor (3) any
|
||||
non-word characters between that word and the cursor (4) any non-word
|
||||
character at the cursor position plus any remaining non-word characters
|
||||
before the next word, including all characters specified by the
|
||||
tt(skip-chars) style, (5) the word at or following the cursor (6) any
|
||||
non-word characters following that word (7) the remainder of the line. Any
|
||||
of the elements may be an empty string; the calling function should test
|
||||
for this to decide whether it can perform its function.
|
||||
)
|
||||
tindex(copy-earlier-word)
|
||||
item(tt(copy-earlier-word))(
|
||||
|
@ -601,6 +713,11 @@ by a keyboard break (typically tt(^G)), the function returns status 1
|
|||
and tt($REPLY) is not set. If an argument is supplied to the function
|
||||
it is taken as a prompt, otherwise `tt(? )' is used.
|
||||
|
||||
One option is available: `tt(-k) var(num)' specifies that var(num)
|
||||
characters are to be read instead of a whole line. The line editor is not
|
||||
invoked recursively in this case. Note that unlike the tt(read) builtin
|
||||
var(num) must be given; there is no default.
|
||||
|
||||
The name is a slight misnomer, as in fact the shell's own minibuffer is
|
||||
not used. Hence it is still possible to call tt(executed-named-cmd) and
|
||||
similar functions while reading a value.
|
||||
|
|
36
Functions/Zle/backward-kill-word-match
Normal file
36
Functions/Zle/backward-kill-word-match
Normal file
|
@ -0,0 +1,36 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word done
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
if (( count < 0 )); then
|
||||
(( NUMERIC = -count ))
|
||||
zle ${WIDGET##backward-}
|
||||
return
|
||||
fi
|
||||
|
||||
while (( count-- )); do
|
||||
|
||||
match-words-by-style
|
||||
|
||||
word="$matched_words[2]$matched_words[3]"
|
||||
|
||||
if [[ -n $word ]]; then
|
||||
if [[ -n $done || $LASTWIDGET = *kill* ]]; then
|
||||
CUTBUFFER="$word$CUTBUFFER"
|
||||
else
|
||||
killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
|
||||
CUTBUFFER=$word
|
||||
fi
|
||||
LBUFFER=$matched_words[1]
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done=1
|
||||
done
|
||||
|
||||
return 0
|
29
Functions/Zle/backward-word-match
Normal file
29
Functions/Zle/backward-word-match
Normal file
|
@ -0,0 +1,29 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
if (( count < 0 )); then
|
||||
(( NUMERIC = - count ))
|
||||
zle ${WIDGET/backward/forward}
|
||||
return
|
||||
fi
|
||||
|
||||
while (( count-- )); do
|
||||
|
||||
match-words-by-style
|
||||
|
||||
word=$matched_words[2]$matched_words[3]
|
||||
|
||||
if [[ -n $word ]]; then
|
||||
(( CURSOR -= ${#word} ))
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
23
Functions/Zle/capitalize-word-match
Normal file
23
Functions/Zle/capitalize-word-match
Normal file
|
@ -0,0 +1,23 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
while (( count-- > 0 )); do
|
||||
match-words-by-style
|
||||
|
||||
word=${(j..)matched_words[4,5]}
|
||||
|
||||
if [[ -n $word ]]; then
|
||||
LBUFFER+=${(C)word}
|
||||
RBUFFER=${(j..)matched_words[6,7]}
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
23
Functions/Zle/down-case-word-match
Normal file
23
Functions/Zle/down-case-word-match
Normal file
|
@ -0,0 +1,23 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
while (( count-- > 0 )); do
|
||||
match-words-by-style
|
||||
|
||||
word=${(j..)matched_words[4,5]}
|
||||
|
||||
if [[ -n word ]]; then
|
||||
LBUFFER+=${(L)word}
|
||||
RBUFFER=${(j..)matched_words[6,7]}
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
39
Functions/Zle/forward-word-match
Normal file
39
Functions/Zle/forward-word-match
Normal file
|
@ -0,0 +1,39 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
if (( count < 0 )); then
|
||||
(( NUMERIC = -count ))
|
||||
zle ${WIDGET/forward/backward}
|
||||
return
|
||||
fi
|
||||
|
||||
while (( count-- )); do
|
||||
|
||||
match-words-by-style
|
||||
|
||||
# For some reason forward-word doesn't work like the other word
|
||||
# word commnds; it skips whitespace only after any matched word
|
||||
# characters.
|
||||
|
||||
if [[ -n $matched_words[4] ]]; then
|
||||
# just skip the whitespace
|
||||
word=$matched_words[4]
|
||||
else
|
||||
# skip the word and trailing whitespace
|
||||
word=$matched_words[5]$matched_words[6]
|
||||
fi
|
||||
|
||||
if [[ -n $word ]]; then
|
||||
(( CURSOR += ${#word} ))
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
36
Functions/Zle/kill-word-match
Normal file
36
Functions/Zle/kill-word-match
Normal file
|
@ -0,0 +1,36 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word done
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
if (( count < 0 )); then
|
||||
(( NUMERIC = -count ))
|
||||
zle backward-$WIDGET
|
||||
return
|
||||
fi
|
||||
|
||||
while (( count-- )); do
|
||||
|
||||
match-words-by-style
|
||||
|
||||
word="${(j..)matched_words[4,5]}"
|
||||
|
||||
if [[ -n $word ]]; then
|
||||
if [[ -n $done || $LASTWIDGET = *kill* ]]; then
|
||||
CUTBUFFER="$CUTBUFFER$word"
|
||||
else
|
||||
killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
|
||||
CUTBUFFER=$word
|
||||
fi
|
||||
RBUFFER=$matched_words[6]
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done=1
|
||||
done
|
||||
|
||||
return 0
|
167
Functions/Zle/match-words-by-style
Normal file
167
Functions/Zle/match-words-by-style
Normal file
|
@ -0,0 +1,167 @@
|
|||
# Match words by the style given below. The matching depends on the
|
||||
# cursor position. The matched_words array is set to the matched portions
|
||||
# separately. These look like:
|
||||
# <stuff-at-start> <word-before-cursor> <whitespace-before-cursor>
|
||||
# <whitespace-after-cursor> <word-after-cursor> <whitespace-after-word>
|
||||
# <stuff-at-end>
|
||||
# where the cursor position is always after the third item and `after'
|
||||
# is to be interpreted as `after or on'. Some
|
||||
# of the array elements will be empty; this depends on the style.
|
||||
# For example
|
||||
# foo bar rod stick
|
||||
# ^
|
||||
# with the cursor where indicated whill with typical settings produce the
|
||||
# elements `foo ', `bar', ` ', ` ', `rod', ` ' and `stick'.
|
||||
#
|
||||
# The style word-style can be set to indicate what a word is.
|
||||
# The three possibilities are:
|
||||
#
|
||||
# shell Words are shell words, i.e. elements of a command line.
|
||||
# whitespace Words are space delimited words; only space or tab characters
|
||||
# are considered to terminated a word.
|
||||
# normal (the default): the usual zle logic is applied, with all
|
||||
# alphanumeric characters plus any characters in $WORDCHARS
|
||||
# considered parts of a word. The style word-chars overrides
|
||||
# the parameter. (Any currently undefined value will be
|
||||
# treated as `normal', but this should not be relied upon.)
|
||||
# specified Similar to normal, except that only the words given
|
||||
# in the string (and not also alphanumeric characters)
|
||||
# are to be considerd parts of words.
|
||||
# unspecified The negation of `specified': the characters given
|
||||
# are those that aren't to be considered parts of a word.
|
||||
# They should probably include white space.
|
||||
#
|
||||
# In the case of the `normal' or `(un)specified', more control on the
|
||||
# behaviour can be obtained by setting the style `word-chars' for the
|
||||
# current context. The value is used to override $WORDCHARS locally.
|
||||
# Hence,
|
||||
# zstyle ':zle:transpose-words*' word-style normal
|
||||
# zstyle ':zle:transpose-words*' word-chars ''
|
||||
# will force bash-style word recognition, i.e only alphanumeric characters
|
||||
# are considerd parts of a word. It is up to the function which calls
|
||||
# match-words-by-style to set the context in the variable curcontext,
|
||||
# else a default context will be used (not recommended).
|
||||
#
|
||||
# You can override the use of word-chars with the style word-class.
|
||||
# This specifies the same information, but as a character class.
|
||||
# The surrounding square brackets shouldn't be given, but anything
|
||||
# which can appear inside is allowed. For example,
|
||||
# zstyle ':zle:*' word-class '-:[:alnum:]'
|
||||
# is valid. Note the usual care with `]' , `^' and `-' must be taken if
|
||||
# they need to appear as individual characters rather than for grouping.
|
||||
#
|
||||
# The final style is `skip-chars'. This is an integer; that many
|
||||
# characters counting the one under the cursor will be treated as
|
||||
# whitespace regardless and added to the front of the fourth element of
|
||||
# matched_words. The default is zero, i.e. the character under the cursor
|
||||
# will appear in <whitespace-after-cursor> if it is whitespace, else in
|
||||
# <word-after-cursor>. This style is mostly useful for forcing
|
||||
# transposition to ignore the current character.
|
||||
|
||||
|
||||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
local wordstyle spacepat wordpat1 wordpat2 opt charskip
|
||||
local match mbegin mend pat1 pat2 word1 word2 ws1 ws2 ws3 skip
|
||||
local MATCH MBEGIN MEND
|
||||
|
||||
if [[ -z $curcontext ]]; then
|
||||
local curcontext=:zle:match-words-by-style
|
||||
fi
|
||||
|
||||
zstyle -s $curcontext word-style wordstyle
|
||||
zstyle -s $curcontext skip-chars skip
|
||||
[[ -z $skip ]] && skip=0
|
||||
|
||||
case $wordstyle in
|
||||
(shell) local bufwords
|
||||
# This splits the line into words as the shell understands them.
|
||||
bufwords=(${(z)LBUFFER})
|
||||
# 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
|
||||
|
||||
# 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
|
||||
spacepat='[[:space:]]#'
|
||||
;;
|
||||
(*space) spacepat='[[:space:]]#'
|
||||
wordpat1='[^[:space:]]##'
|
||||
wordpat2=$wordpat1
|
||||
;;
|
||||
(*) local wc
|
||||
# See if there is a character class.
|
||||
if zstyle -s $curcontext word-class wc; then
|
||||
# Treat as a character class: do minimal quoting.
|
||||
wc=${wc//(#m)[\'\"\`\$\(\)\^]/\\$MATCH}
|
||||
else
|
||||
# See if there is a local version of $WORDCHARS.
|
||||
zstyle -s $curcontext word-chars wc ||
|
||||
wc=$WORDCHARS
|
||||
if [[ $wc = (#b)(?*)-(*) ]]; then
|
||||
# We need to bring any `-' to the front to avoid confusing
|
||||
# character classes... we get away with `]' since in zsh
|
||||
# this isn't a pattern character if it's quoted.
|
||||
wc=-$match[1]$match[2]
|
||||
fi
|
||||
wc="${(q)wc}"
|
||||
fi
|
||||
# Quote $wc where necessary, because we don't want those
|
||||
# characters to be considered as pattern characters later on.
|
||||
if [[ $wordstyle = *specified ]]; then
|
||||
if [[ $wordstyle != un* ]]; then
|
||||
# The given set of characters are the word characters, nothing else
|
||||
wordpat1="[${wc}]##"
|
||||
# anything else is a space.
|
||||
spacepat="[^${wc}]#"
|
||||
else
|
||||
# The other way round.
|
||||
wordpat1="[^${wc}]##"
|
||||
spacepat="[${wc}]#"
|
||||
fi
|
||||
else
|
||||
# Normal: similar, but add alphanumerics.
|
||||
wordpat1="[${wc}[:alnum:]]##"
|
||||
spacepat="[^${wc}[:alnum:]]#"
|
||||
fi
|
||||
wordpat2=$wordpat1
|
||||
;;
|
||||
esac
|
||||
|
||||
# The eval makes any special characters in the parameters active.
|
||||
# In particular, we need the surrounding `[' s to be `real'.
|
||||
# This is why we quoted the wordpats in the `shell' option, where
|
||||
# they have to be treated as literal strings at this point.
|
||||
match=()
|
||||
eval pat1='${LBUFFER%%(#b)('${wordpat1}')('${spacepat}')}'
|
||||
word1=$match[1]
|
||||
ws1=$match[2]
|
||||
|
||||
match=()
|
||||
charskip=
|
||||
repeat $skip charskip+=\?
|
||||
|
||||
eval pat2='${RBUFFER##(#b)('${charskip}${spacepat}')('\
|
||||
${wordpat2}')('${spacepat}')}'
|
||||
|
||||
ws2=$match[1]
|
||||
word2=$match[2]
|
||||
ws3=$match[3]
|
||||
|
||||
matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2")
|
|
@ -1,3 +1,22 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
local opt keys
|
||||
integer stat
|
||||
|
||||
while getopts "k:" opt; do
|
||||
case $opt in
|
||||
(k)
|
||||
keys=$OPTARG
|
||||
;;
|
||||
|
||||
(*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
|
||||
|
||||
local savelbuffer=$LBUFFER saverbuffer=$RBUFFER
|
||||
local savepredisplay=$PREDISPLAY savepostdisplay=$POSTDISPLAY
|
||||
|
||||
|
@ -7,10 +26,15 @@ PREDISPLAY="$PREDISPLAY$savelbuffer$saverbuffer$POSTDISPLAY
|
|||
${1:-? }"
|
||||
POSTDISPLAY=
|
||||
|
||||
zle recursive-edit
|
||||
integer stat=$?
|
||||
|
||||
(( stat )) || REPLY=$BUFFER
|
||||
if [[ -n $keys ]]; then
|
||||
zle -R
|
||||
read -k $keys
|
||||
stat=$?
|
||||
else
|
||||
zle recursive-edit
|
||||
stat=$?
|
||||
(( stat )) || REPLY=$BUFFER
|
||||
fi
|
||||
|
||||
LBUFFER=$savelbuffer
|
||||
RBUFFER=$saverbuffer
|
||||
|
|
88
Functions/Zle/select-word-style
Normal file
88
Functions/Zle/select-word-style
Normal file
|
@ -0,0 +1,88 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
local -a word_functions
|
||||
|
||||
word_functions=(backward-kill-word backward-word
|
||||
capitalize-word down-case-word
|
||||
forward-word kill-word
|
||||
transpose-words up-case-word)
|
||||
|
||||
[[ -z $1 ]] && autoload read-from-minibuffer
|
||||
|
||||
local REPLY detail f
|
||||
|
||||
if ! zle -l $word_functions[1]; then
|
||||
for f in $word_functions; do
|
||||
autoload -U $f-match
|
||||
zle -N $f $f-match
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
while true; do
|
||||
|
||||
if [[ -n $WIDGET && -z $1 ]]; then
|
||||
read-from-minibuffer -k1 "Word styles (hit return for more detail):
|
||||
(b)ash (n)ormal (s)hell (w)hitespace (N)one (A)bort
|
||||
${detail}? " || return 1
|
||||
else
|
||||
REPLY=$1
|
||||
fi
|
||||
|
||||
detail=
|
||||
|
||||
case $REPLY in
|
||||
(b*)
|
||||
# bash style
|
||||
zstyle ':zle:*' word-style standard
|
||||
zstyle ':zle:*' word-chars ''
|
||||
;;
|
||||
|
||||
(n*)
|
||||
# normal zsh style
|
||||
zstyle ':zle:*' word-style standard
|
||||
zstyle ':zle:*' word-chars "$WORDCHARS"
|
||||
;;
|
||||
|
||||
(s*)
|
||||
# shell command arguments or special tokens
|
||||
zstyle ':zle:*' word-style shell
|
||||
;;
|
||||
|
||||
(w*)
|
||||
# whitespace-delimited
|
||||
zstyle ':zle:*' word-style space
|
||||
;;
|
||||
|
||||
(d*)
|
||||
# default: could also return widgets to builtins here
|
||||
zstyle -d ':zle:*' word-style
|
||||
zstyle -d ':zle:*' word-chars
|
||||
;;
|
||||
|
||||
(q*)
|
||||
# quit without setting
|
||||
return 1
|
||||
;;
|
||||
|
||||
(*)
|
||||
detail="\
|
||||
(b)ash: Word characters are alphanumerics only
|
||||
(n)ormal: Word characters are alphanumerics plus \$WORDCHARS
|
||||
(s)hell: Words are command arguments using shell syntax
|
||||
(w)hitespace: Words are whitespace-delimited
|
||||
(d)efault: Use default, no special handling (usually same as \`n')
|
||||
(q)uit: Quit without setting a new style
|
||||
"
|
||||
if [[ -z $WIDGET || -n $1 ]]; then
|
||||
print "Usage: $0 word-style
|
||||
where word-style is one of the characters in parentheses:
|
||||
$detail" >&2
|
||||
return 1
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
return
|
||||
done
|
31
Functions/Zle/transpose-words-match
Normal file
31
Functions/Zle/transpose-words-match
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Transpose words, matching the words using match-words-by-style, q.v.
|
||||
# The group of word characters preceeding the cursor (not necessarily
|
||||
# immediately) are transposed with the group of word characters following
|
||||
# the cursor (again, not necessarily immediately).
|
||||
#
|
||||
# Note the style skip-chars, used in the context of the current widget.
|
||||
# This gives a number of character starting from the cursor position
|
||||
# which are never considered part of a word and hence are always left
|
||||
# alone. The default is 0 and typically the only useful alternative
|
||||
# is one. This would have the effect that `fooXbar' with the cursor
|
||||
# on X would be turned into `barXfoo' with the cursor still on the X,
|
||||
# regardless of what the character X is.
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" skip
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
while (( count-- > 0 )); do
|
||||
match-words-by-style
|
||||
|
||||
[[ -z "$matched_words[2]$matched_words[5]" ]] && return 1
|
||||
|
||||
LBUFFER="$matched_words[1]$matched_words[5]${(j..)matched_words[3,4]}\
|
||||
$matched_words[2]"
|
||||
RBUFFER="${(j..)matched_words[6,7]}"
|
||||
|
||||
done
|
||||
|
||||
return 0
|
23
Functions/Zle/up-case-word-match
Normal file
23
Functions/Zle/up-case-word-match
Normal file
|
@ -0,0 +1,23 @@
|
|||
emulate -L zsh
|
||||
setopt extendedglob
|
||||
|
||||
autoload match-words-by-style
|
||||
|
||||
local curcontext=":zle:$WIDGET" word
|
||||
local -a matched_words
|
||||
integer count=${NUMERIC:-1}
|
||||
|
||||
while (( count-- > 0 )); do
|
||||
match-words-by-style
|
||||
|
||||
word=${(j..)matched_words[4,5]}
|
||||
|
||||
if [[ -n $word ]]; then
|
||||
LBUFFER+=${(U)word}
|
||||
RBUFFER=${(j..)matched_words[6,7]}
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
Loading…
Reference in a new issue