-
Notifications
You must be signed in to change notification settings - Fork 1
/
zui-process-buffer2
91 lines (75 loc) · 2.62 KB
/
zui-process-buffer2
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Input:
# $1 - optional buffer to process (default is $BUFFER)
#
# Output:
# ZUI_PB2_WORDS - split of "$1" into shell words; array
# ZUI_PB2_QWORDS - shell words when [;|>&] didn't split
# ZUI_PB2_WORDS_BEGINNINGS - indexes of first letters of corresponding words in ZUI_PB2_WORDS
# ZUI_PB2_QWORDS_BEGINNINGS - the same, but in ZUI_PB2_QWORDS
# ZUI_PB2_SPACES - white spaces before corresponding words in ZUI_PB2_WORDS
# ZUI_PB2_QSPACES - the same, but in ZUI_PB2_QWORDS
#
emulate -LR zsh
setopt typesetsilent extendedglob noshortloops
local MBEGIN MEND MATCH mbegin mend match
local buf="${1:-$BUFFER}"
# All output variables are either overwritten or cleared
ZUI_PB2_WORDS=( "${(Z+n+)buf}" )
ZUI_PB2_QWORDS=( )
ZUI_PB2_SPACES=( )
ZUI_PB2_QSPACES=( )
ZUI_PB2_WORDS_BEGINNINGS=( )
ZUI_PB2_QWORDS_BEGINNINGS=( )
# (Z+n+) will return 1 element for buf that is empty or only whitespace
if [[ "$buf" = ( |$'\t')# ]]; then
ZUI_PB2_WORDS=( )
integer nwords=0
else
integer nwords="${#ZUI_PB2_WORDS}"
fi
# Remove ZUI_PB2_WORDS one by one, counting characters,
# computing beginning of each word
local i word wordlen
integer char_count=0 idx=0
# (Z) handles spaces nicely, but we need them for the user
# Also compute words beginnings
for (( i=1; i<=nwords; i++ )); do
idx+=1
# Remove spurious space generated by Z-flag when
# input is an unbound '$(' (happens with zsh < 5.1)
# and also real spaces gathered by an unbound '$(',
# to handle them in a way normal to this loop
ZUI_PB2_WORDS[i]="${ZUI_PB2_WORDS[i]%% ##}"
word="${ZUI_PB2_WORDS[i]}"
# Remove white spaces
buf="${buf##(#m)[^$word[1]]#}"
# Count them
char_count=char_count+"${#MATCH}"
# The beginning of current word
ZUI_PB2_WORDS_BEGINNINGS[i]=$(( char_count + 1 ))
# Remember the spaces
ZUI_PB2_SPACES[i]="$MATCH"
if [[ "$word" = [\;\>\&\|] && -z "$MATCH" && "$idx" -gt "1" ]]; then
idx=idx-1
ZUI_PB2_QWORDS[idx]+="$word"
elif [[ -z "$MATCH" && "$idx" -gt "1" && "${ZUI_PB2_QWORDS[idx-1]}" = *[\;\>\&\|] ]]; then
idx=idx-1
ZUI_PB2_QWORDS[idx]+="$word"
else
ZUI_PB2_QWORDS[idx]="$word"
ZUI_PB2_QWORDS_BEGINNINGS[idx]=$(( char_count + 1 ))
ZUI_PB2_QSPACES[idx]="$MATCH"
fi
# Remove the word
wordlen="${#word}"
[[ "${buf[1,wordlen]}" != "$word" ]] && return 1 # should not happen unless bug in (z)
buf="${buf[wordlen+1,-1]}"
char_count=char_count+"$#word"
done
# What's left in $buf can be only white spaces
char_count=char_count+"${#buf}"
ZUI_PB2_SPACES[i]="$buf"
ZUI_PB2_QSPACES[idx+1]="$buf"
# This function should be tested
return 0
# vim:ft=zsh