mirrored from git://git.code.sf.net/p/zsh/code
-
Notifications
You must be signed in to change notification settings - Fork 442
/
select-bracketed
58 lines (49 loc) · 1.66 KB
/
select-bracketed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Text object for matching characters between matching pairs of brackets
#
# So for example, given (( i+1 )), the vi command ci( will change
# all the text between matching colons.
#
# The following is an example of how to enable this:
# autoload -U select-bracketed
# zle -N select-bracketed
# for m in visual viopp; do
# for c in {a,i}${(s..)^:-'()[]{}<>bB'}; do
# bindkey -M $m $c select-bracketed
# done
# done
setopt localoptions noksharrays
local style=${${1:-$KEYS}[1]} matching="(){}[]<>bbBB"
local -i find=${NUMERIC:-1} idx=${matching[(I)[${${1:-$KEYS}[2]}]]}%9
(( idx )) || return 1 # no corresponding closing bracket
local lmatch=${matching[1 + ((idx-1) & ~1)]}
local rmatch=${matching[1 + ((idx-1) | 1)]}
local -i start=CURSOR+1 end=CURSOR+1 rfind=find
[[ $BUFFER[start] = "$rmatch" ]] && (( start--, end-- ))
if (( REGION_ACTIVE && MARK != CURSOR)); then
(( MARK < CURSOR && (start=end=MARK+1) ))
local -i origstart=start-1
[[ $style = i ]] && (( origstart-- ))
fi
while (( find )); do
for (( ; find && start; --start )); do
case $BUFFER[start] in
"$lmatch") (( find-- )) ;;
"$rmatch") (( find++ )) ;;
esac
done
(( find )) && return 1 # opening bracket not found
while (( rfind && end++ < $#BUFFER )); do
case $BUFFER[end] in
"$lmatch") (( rfind++ )) ;;
"$rmatch") (( rfind-- )) ;;
esac
done
(( rfind )) && return 1 # closing bracket not found
(( REGION_ACTIVE && MARK != CURSOR && start >= origstart &&
( find=rfind=${NUMERIC:-1} ) ))
done
[[ $style = i ]] && (( start++, end-- ))
(( REGION_ACTIVE = !!REGION_ACTIVE ))
[[ $KEYMAP = vicmd ]] && (( REGION_ACTIVE && end-- ))
MARK=$start
CURSOR=$end