-
Notifications
You must be signed in to change notification settings - Fork 0
/
wsdialog.zsh
240 lines (203 loc) · 6.86 KB
/
wsdialog.zsh
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# prepare dialogs
wsdialog-add() {
local dialog=$1
local mname=wsdialog_${dialog}_line
# ws-debug WSDIALOG_ADD: \"$dialog\"
local modesvar=wsdialog_${dialog}_modes
local modes=(${(P)modesvar})
for l4mode in $modes; do
local l4mname=wsdialog_${dialog}_${l4mode}_l4
bindkey -N "$l4mname"
# ws-debug WSDIALOG_ADD: create l4mode: \"$l4mname\"
# bind cancel line4 function
zle -N wsdialog_${dialog}-ret-dial
bindkey -M $l4mname "^U" "wsdialog_${dialog}-ret-dial"
bindkey -M $l4mname "^M" "wsdialog_${dialog}-ret-dial"
# bind user defined keys
local funcsvar=wsdialog_${dialog}_${l4mode}_funcs
declare -A funcs
funcs=(${(@Pkv)funcsvar})
for key func in "${(@kv)funcs}"; do
local funname=wsdialog_${dialog}_${l4mode}_${func}
zle -N $funname
bindkey -M $l4mname $key $funname
eval "$funname() { wsdialog-l4keyfn $dialog $func }"
done
done
eval "wsdialog-${dialog}-run() { wsdialog-run $dialog \"\$@\" }"
eval "wsdialog_${dialog}-ret-dial() { wsdialog-ret-dial $dialog }"
eval "wsline-wsdialog_${dialog}-accept() { wsdialog-acceptfn $dialog }"
eval "wsline-wsdialog_${dialog}-cancel() { wsdialog-cancelfn $dialog }"
}
wsdialog-l4keyfn() {
local dialog=$1
local l4keyfn=$2
$l4keyfn # defines $wsdialog_l4mode
# ws-debug WSDIALOG_L4KEYFN: dialog=$dialog l4keyfn=$l4keyfn m=$wsdialog_l4mode
if [[ -z "$wsdialog_l4mode" ]]; then
wsdialog-ret-dial $dialog
elif [[ "$wsdialog_l4mode" == "<accept>" ]]; then
wsdialog-close $dialog "OK"
elif [[ "$wsdialog_l4mode" == "<cancel>" ]]; then
unset wsdialog_text
wsdialog-close $dialog "NO"
else
wsdialog-rml4 $dialog
# ws-debug WSDIALOG_L4KEYFN: l4mode=$wsdialog_l4mode
wsdialog-l4run $dialog $wsdialog_l4mode
fi
}
# removes line 1-3 and line4 if present
wsdialog-del() {
local bufsz=${#BUFFER}
local end=$((wsdialog_start+wsdialog_len+wsdialog_l4len))
local str1=$BUFFER[1,wsdialog_start-1]
local str2=$BUFFER[end,bufsz]
BUFFER=$str1$str2
}
# exit dialog and restore variables
wsdialog-close() {
local dialog=$1
# status in $2
ws-debug WSDIALOG_CLOSE dialog="\"$1\"" status="\"$2\""
local do_restore=wsdialog_${dialog}_restore
wsline-exit "wsdialog_${dialog}"
#restore text, cursor and region_highlight
wsdialog-del
CURSOR=$wsdialog_savecurs
region_highlight=$wsdialog_init_highlight
wstext_textvar=$wsdialog_oldtextvar
wstext_updfnvar=$wsdialog_oldupdfnvar
wstext_posvar=$wsdialog_oldposvar
wstext_marksvar=$wsdialog_oldmarksvar
wstext_blockvisvar=$wsdialog_oldblockvisvar
wstext_blockcolmodevar=$wsdialog_oldblockcolmodevar
zle -K $wsdialog_savemode
# unset variables
wsdialog-unsetvars
# call restore function
${(P)do_restore} $2
}
wsdialog-unsetvars() {
unset wsdialog_savecurs
unset wsdialog_start
unset wsdialog_init_highlight
unset wsdialog_text
unset wsdialog_maxlen
unset wsdialog_savemode
unset wsdialog_len
unset wsdialog_l4len
unset wsdialog_l4start
unset wsdialog_oldtextvar
unset wsdialog_oldupdfnvar
unset wsdialog_oldposvar
unset wsdialog_oldmarksvar
unset wsdialog_oldblockvisvar
unset wsdialog_oldblockcolmodevar
}
# display line4 and enter l4 mode
wsdialog-l4run() {
local dialog=$1
local l4mode=$2
local end=$((wsdialog_start+wsdialog_len))
# ws-debug WSDIALOG_L4RUN: l4mode=$l4mode
wsdialog_prel4save_cursor=$CURSOR
wsdialog_prel4save_highlight=($region_highlight)
# ws-debug WSDIALOG_L4RUN: save prel4-highlight=$region_highlight
# display line4 and move cursor
local l4rtv=wsdialog_${dialog}_${l4mode}_msg
local l4rt="${(P)l4rtv}"
ws-insert-formatted-at $wsdialog_l4start "$l4rt"
wsdialog_l4len=${#ws_pft}
CURSOR=$((wsdialog_l4start+wsdialog_l4len))
# enter l4mode
local l4mname=wsdialog_${dialog}_${l4mode}_l4
zle -K "$l4mname"
}
# ask caller what to do
wsdialog-acceptfn() {
local dialog=$1
local do_accept=wsdialog_${dialog}_accept
local textvar=wsline_wsdialog_${dialog}_text
# ws-debug WSDIALOG_ACCEPTFN: dialog=$dialog
wsdialog_text="${(P)textvar}"
${(P)do_accept} # defines $wsdialog_l4mode
if [[ -n $wsdialog_l4mode ]]; then
wsdialog-l4run $dialog $wsdialog_l4mode
else
wsdialog-close $dialog "OK"
fi
}
# close everything and call restore
wsdialog-cancelfn() {
local dialog=$1
ws-debug WSDIALOG_CANCELFN: dialog=$dialog
unset wsdialog_text
wsdialog-close $dialog "NO"
}
# !!!cursor & highlight state save/restore by caller!!!
# display dialog
wsdialog-run() {
local dialog=$1
local text="$2"
ws-debug WSDIALOG_RUN: dialog="$dialog" text="$text"
local msgvar=wsdialog_${dialog}_msg
local msg=${(P)msgvar}
wsdialog_savecurs=$CURSOR
wsdialog_savemode=$KEYMAP
wsdialog_oldtextvar=$wstext_textvar
wsdialog_oldupdfnvar=$wstext_updfnvar
wsdialog_oldposvar=$wstext_posvar
wsdialog_oldmarksvar=$wstext_marksvar
wsdialog_oldblockvisvar=$wstext_blockvisvar
wsdialog_oldblockcolmodevar=$wstext_blockcolmodevar
zle end-of-line
LBUFFER+=$'\n'
wsdialog_start=$CURSOR
wsdialog_init_highlight=$region_highlight
local line1=$msg
local line2=" *RETURN* done | *Backspace* or *^H* erase left"$'\n'
local line3=" *^U* cancel | *Del* or *^G* erase char"$'\n'
ws-insert-formatted-at $CURSOR "$line1"
l1len=${#ws_pft}
# wsdialog_line1_fmt=($ws_pff)
# insert wsline
local cols=$(tput cols)
local len=$((cols-l1len-1))
wsline-init wsdialog_$dialog $CURSOR $len $wstext_marksvar \
$wstext_blockvisvar "$text"
local l2start=$((wsdialog_start+l1len+len))
ws-insert-formatted-at $l2start $'\n'"$line2"
local l2len=${#ws_pft}
# wsdialog_line2_fmt=($ws_pff)
local l3start=$((l2start+l2len))
ws-insert-formatted-at $l3start "$line3"
local l3len=${#ws_pft}
# wsdialog_line3_fmt=($ws_pff)
wsdialog_len=$((l1len+len+1+l2len+l3len))
wsdialog_l4start=$((l3start+l3len))
wsdialog_l4len=0
CURSOR=$((l2start-1))
# enter wsline
wsline-activate wsdialog_$dialog
}
# remove dialog l4
wsdialog-rml4() {
local dialog=$1
# ws-debug WSDIALOG_RML4: dialog=\"$dialog\"
# remove old line4
BUFFER[wsdialog_l4start+1,wsdialog_l4start+wsdialog_l4len+1]=""
# restore region highlight
# ws-debug WSDIALOG_RML4: prel4-highlight=$wsdialog_prel4save_highlight
region_highlight=($wsdialog_prel4save_highlight)
# restores dialog cursor
CURSOR=$wsdialog_prel4save_cursor
}
# remove line4, restore state
wsdialog-ret-dial() {
local dialog=$1
wsdialog-rml4 $dialog
# remove line4 marker
unset wsdialog_l4mode
wsline-activate wsdialog_$dialog
}