1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01:00

38929: new vim style text object using match-words-by-style mechanism

This commit is contained in:
Oliver Kiddle 2016-07-24 22:18:34 +02:00
parent dfd8b1da4f
commit 932ff2b6f8
3 changed files with 132 additions and 4 deletions

View file

@ -1,5 +1,8 @@
2016-07-24 Oliver Kiddle <opk@zsh.org>
* 38929: Doc/Zsh/contrib.yo, Functions/Zle/select-word-match:
new vim style text object using match-words-by-style mechanism
* 38935: Matthew Martin: Completion/Unix/Command/_tcpdump:
update for Free and Open BSD

View file

@ -1940,6 +1940,8 @@ tindex(transpose-words-match)
tindex(capitalize-word-match)
tindex(up-case-word-match)
tindex(down-case-word-match)
tindex(delete-whole-word-match)
tindex(select-word-match)
tindex(select-word-style)
tindex(match-word-context)
tindex(match-words-by-style)
@ -1947,12 +1949,14 @@ 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))
xitem(tt(delete-whole-word-match), tt(select-word-match))
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
The first 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. For comparison, the widgets
described in ifzman(zmanref(zshzle) under Text Objects)\
the way words are matched can be altered. tt(select-word-match) is intended
to be used as a text object in vi mode but with custom word styles. For
comparison, the widgets described in ifzman(zmanref(zshzle) under Text Objects)\
ifnzman(noderef(Text Objects)) use fixed definitions of words, compatible
with the tt(vim) editor.
@ -1960,7 +1964,7 @@ 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
time it is invoked, the first 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

View file

@ -0,0 +1,121 @@
# Select the entire word around the cursor. Intended for use as
# a vim-style text object in vi mode but with customisable
# word boundaries.
#
# For example:
# autoload -U select-word-match
# zle -N select-in-camel select-word-match
# bindkey -M viopp ic select-in-camel
# zstyle ':zle:*-camel' word-style normal-subword
emulate -L zsh
setopt extendedglob
local curcontext=:zle:$WIDGET
local -a matched_words
# Start and end of range of characters
integer pos1 pos2 num=${NUMERIC:-1}
local style word
# choose between inner word or a word style of widget
for style in $1 ${${WIDGET#*-}[1]} $KEYS[1] "i"; do
[[ $style = [ai] ]] && break
done
autoload -Uz match-words-by-style
while (( num-- )); do
if (( MARK > CURSOR )); then
# if cursor is at the start of the selection, just move back a word
match-words-by-style
if [[ $style = i && -n $matched_words[3] ]]; then
word=$matched_words[3]
else
word=$matched_words[2]$matched_words[3]
fi
if [[ -n $word ]]; then
(( CURSOR -= ${#word} ))
else
return 1
fi
elif (( MARK >= 0 && MARK < CURSOR )); then
# cursor at the end, move forward a word
(( CURSOR+1 == $#BUFFER )) && return 1
(( CURSOR++ ))
match-words-by-style
if [[ -n $matched_words[4] ]]; then
if [[ $style = i ]]; then
# just skip the whitespace
word=$matched_words[4]
else
# skip the whitespace plus word
word=$matched_words[4]$matched_words[5]
fi
else
if [[ $style = i ]]; then
# skip the word
word=$matched_words[5]
else
# skip word and following whitespace
word=$matched_words[5]$matched_words[6]
fi
fi
(( CURSOR += ${#word} - 1 ))
else
match-words-by-style
if [[ -n "${matched_words[3]}" ]]; then
# There's whitespace before the cursor, so the word we are selecting
# starts at the cursor position.
pos1=$CURSOR
else
# No whitespace before us, so select any wordcharacters there.
pos1="${#matched_words[1]}"
fi
if [[ -n "${matched_words[4]}" ]]; then
if [[ -n "${matched_words[3]}" ]] || (( CURSOR == 0 )); then
# whitespace either side, select it
(( pos1 = CURSOR - ${#matched_words[3]} ))
(( pos2 = CURSOR + ${#matched_words[4]} ))
else
# There's whitespace at the cursor position, so only select
# up to the cursor position.
(( pos2 = CURSOR + 1 ))
fi
else
# No whitespace at the cursor position, so select the
# current character and any following wordcharacters.
(( pos2 = CURSOR + ${#matched_words[5]} ))
fi
if [[ $style = a ]]; then
if [[ -n "${matched_words[4]}" && ( -n "${matched_words[3]}" || CURSOR -eq 0 ) ]]; then
# in the middle of whitespace so grab a word
if [[ -n "${matched_words[5]}" ]]; then
(( pos2 += ${#matched_words[5]} )) # preferably the one after
else
(( pos1 -= ${#matched_words[2]} )) # otherwise the one before
fi
elif [[ -n "${matched_words[6]}" ]]; then
(( pos2 += ${#matched_words[6]} ))
elif [[ -n "${matched_words[3]}" ]]; then
# couldn't grab whitespace forwards so try backwards
(( pos1 -= ${#matched_words[3]} ))
elif (( pos1 > 0 )); then
# There might have been whitespace before the word
(( CURSOR = pos1 ))
match-words-by-style
if [[ -n "${matched_words[3]}" ]]; then
(( pos1 -= ${#matched_words[3]} ))
fi
fi
fi
(( MARK = pos1, CURSOR = pos2-1 ))
fi
done
if [[ $KEYMAP == vicmd ]] && (( !REGION_ACTIVE )); then
(( CURSOR++ )) # Need to include cursor position for operators
fi