-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathzca
More file actions
349 lines (297 loc) · 11.9 KB
/
zca
File metadata and controls
349 lines (297 loc) · 11.9 KB
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# Uses h-list
emulate -LR zsh
setopt extendedglob
_zca_has_terminfo=0
zmodload zsh/curses
zmodload zsh/parameter
zmodload zsh/terminfo 2>/dev/null && _zca_has_terminfo=1
trap "_zca_exit" EXIT
local IFS="
"
local one_HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
local one_HLIST_CURRENT_IDX
local one_HLIST_IS_SEARCH_MODE
local one_HLIST_SEARCH_BUFFER
local one_HLIST_TEXT_OFFSET
local one_HLIST_IS_UNIQ_MODE
local one_HLIST_CURRENT_SEGMENT
local -a one_HLIST_ENABLED_EVENTS
local -A one_HLIST_ACTIVE_SEGMENTS
local one_HLIST_TRACK_SEGMENTS
local two_HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
local two_HLIST_CURRENT_IDX
local two_HLIST_IS_SEARCH_MODE
local two_HLIST_SEARCH_BUFFER
local two_HLIST_TEXT_OFFSET
local two_HLIST_IS_UNIQ_MODE
local two_HLIST_CURRENT_SEGMENT
local -a two_HLIST_ENABLED_EVENTS
local -A two_HLIST_ACTIVE_SEGMENTS
local two_HLIST_TRACK_SEGMENTS
# Cleanup before any exit
_zca_exit() {
setopt localoptions
setopt extendedglob
zcurses 2>/dev/null delwin main
zcurses 2>/dev/null delwin status
zcurses 2>/dev/null refresh
zcurses end
_zca_alternate_screen 0
unset _zca_has_terminfo
_hlist_cursor_visibility "plain" 1
unset _hlist_has_terminfo
}
_zca_init_windows() {
_zca_alternate_screen 1
zcurses init
zcurses delwin cmd 2>/dev/null
zcurses delwin main 2>/dev/null
zcurses delwin status 2>/dev/null
zcurses addwin cmd 4 "$term_width" 0 0
zcurses addwin main $(( term_height - 7 )) "$term_width" 4 0
zcurses addwin status "3" "$term_width" $(( term_height - 3 )) 0
}
# Reason for this function is that on some systems
# smcup and rmcup are not knowing why left empty
_zca_alternate_screen() {
[ "$_zca_has_terminfo" -ne "1" ] && return
[[ "$1" = "1" && -n "$terminfo[smcup]" ]] && return
[[ "$1" = "0" && -n "$terminfo[rmcup]" ]] && return
case "$TERM" in
*rxvt*)
[ "$1" = "1" ] && echo -n $'\x1b7\x1b[?47h'
[ "$1" = "0" ] && echo -n $'\x1b[2J\x1b[?47l\x1b8'
;;
*)
[ "$1" = "1" ] && echo -n $'\x1b[?1049h'
[ "$1" = "0" ] && echo -n $'\x1b[?1049l'
# just to remember two other that work: $'\x1b7\x1b[r\x1b[?47h', $'\x1b[?47l\x1b8'
;;
esac
}
_zca_switch_lists_states() {
# First argument is current list, i.e. $active_window
# This implies that we are switching from 1-$active_window
if [ "$1" = "0" ]; then
# Switched to 1st list, save 2nd list's state
two_HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
two_HLIST_CURRENT_IDX=$HLIST_CURRENT_IDX
two_HLIST_IS_SEARCH_MODE=$HLIST_IS_SEARCH_MODE
two_HLIST_SEARCH_BUFFER=$HLIST_SEARCH_BUFFER
two_HLIST_TEXT_OFFSET=$HLIST_TEXT_OFFSET
two_HLIST_IS_UNIQ_MODE=$HLIST_IS_UNIQ_MODE
two_HLIST_CURRENT_SEGMENT=$HLIST_CURRENT_SEGMENT
two_HLIST_ENABLED_EVENTS=( ${HLIST_ENABLED_EVENTS[@]} )
two_HLIST_ACTIVE_SEGMENTS=( ${(kv)HLIST_ACTIVE_SEGMENTS[@]} )
two_HLIST_TRACK_SEGMENTS=$HLIST_TRACK_SEGMENTS
# ..and restore 1st list's state
HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$one_HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
HLIST_CURRENT_IDX=$one_HLIST_CURRENT_IDX
HLIST_IS_SEARCH_MODE=$one_HLIST_IS_SEARCH_MODE
HLIST_SEARCH_BUFFER=$one_HLIST_SEARCH_BUFFER
HLIST_TEXT_OFFSET=$one_HLIST_TEXT_OFFSET
HLIST_IS_UNIQ_MODE=$one_HLIST_IS_UNIQ_MODE
HLIST_CURRENT_SEGMENT=$one_HLIST_CURRENT_SEGMENT
HLIST_ENABLED_EVENTS=( ${one_HLIST_ENABLED_EVENTS[@]} )
HLIST_ACTIVE_SEGMENTS=( ${(kv)one_HLIST_ACTIVE_SEGMENTS[@]} )
HLIST_TRACK_SEGMENTS=$one_HLIST_TRACK_SEGMENTS
else
# Switched to 2st list, save 1st list's state
one_HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
one_HLIST_CURRENT_IDX=$HLIST_CURRENT_IDX
one_HLIST_IS_SEARCH_MODE=$HLIST_IS_SEARCH_MODE
one_HLIST_SEARCH_BUFFER=$HLIST_SEARCH_BUFFER
one_HLIST_TEXT_OFFSET=$HLIST_TEXT_OFFSET
one_HLIST_IS_UNIQ_MODE=$HLIST_IS_UNIQ_MODE
one_HLIST_CURRENT_SEGMENT=$HLIST_CURRENT_SEGMENT
one_HLIST_ENABLED_EVENTS=( ${HLIST_ENABLED_EVENTS[@]} )
one_HLIST_ACTIVE_SEGMENTS=( ${(kv)HLIST_ACTIVE_SEGMENTS[@]} )
one_HLIST_TRACK_SEGMENTS=$HLIST_TRACK_SEGMENTS
# ..and restore 2nd list's state
HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=$two_HLIST_FROM_WHAT_IDX_LIST_IS_SHOWN
HLIST_CURRENT_IDX=$two_HLIST_CURRENT_IDX
HLIST_IS_SEARCH_MODE=$two_HLIST_IS_SEARCH_MODE
HLIST_SEARCH_BUFFER=$two_HLIST_SEARCH_BUFFER
HLIST_TEXT_OFFSET=$two_HLIST_TEXT_OFFSET
HLIST_IS_UNIQ_MODE=$two_HLIST_IS_UNIQ_MODE
HLIST_CURRENT_SEGMENT=$two_HLIST_CURRENT_SEGMENT
HLIST_ENABLED_EVENTS=( ${two_HLIST_ENABLED_EVENTS[@]} )
HLIST_ACTIVE_SEGMENTS=( ${(kv)two_HLIST_ACTIVE_SEGMENTS[@]} )
HLIST_TRACK_SEGMENTS=$two_HLIST_TRACK_SEGMENTS
fi
}
unset HLIST_COLORING_PATTERN
[ -f ~/.config/zca/h-list.conf ] && builtin source ~/.config/zca/h-list.conf
[ -f ~/.config/zca/zca.conf ] && builtin source ~/.config/zca/zca.conf
typeset -a list1 undolist
local answer active_window=1
local boldattr
integer cur_bkp
[ "$bold" = "0" ] && boldattr="" || boldattr="+bold"
# $cmd can be empty if not run from Zle
local buf="${BUFFER%% #}"
buf="${buf## #}"
list1=( "$buf" "[F1-Accept] [F2-Reject] [F3-Undo] [F4-Semicolon]" )
undolist=( "$list1[1]" )
integer term_height="$LINES"
integer term_width="$COLUMNS"
if [[ "$term_height" -lt 1 || "$term_width" -lt 1 ]]; then
local stty_out=$( stty size )
term_height="${stty_out% *}"
term_width="${stty_out#* }"
fi
_zca_init_windows
zcurses bg "cmd" "$boldattr" white/black
zcurses bg "main" "$boldattr" white/black
zcurses bg "status" "$boldattr" white/black
# First draw two vanilla (no remembering of state) h-lists, saving their default state
HLIST_DRAW_ONLY=1
HLIST_REMEMBER_STATE=0
typeset -a HLIST_ENABLED_EVENTS
HLIST_START_IN_UNIQ_MODE=1
local HLIST_TRACK_SEGMENTS=0
h-list "main" $(( term_height-7 )) $term_width "status" "3" "$term_width" " History: " "0"
# Save default state of list 2
_zca_switch_lists_states 0
unset HLIST_START_IN_UNIQ_MODE
HLIST_ENABLED_EVENTS=( "BR_MOVE_LEFT" "BR_MOVE_RIGHT" )
HLIST_TRACK_SEGMENTS=1
h-list "cmd" "4" $term_width "" "0" "0" " Command: " "1" "${list1[@]}"
# Save default state of list 1
_zca_switch_lists_states 1
HLIST_DRAW_ONLY=0
HLIST_REMEMBER_STATE=1 # From now on lists remember their state
# Now go into loop of input handling of either of the two lists
while (( 1 )); do
if [ "$active_window" = "0" ]; then
_zca_switch_lists_states "1"
HLIST_DRAW_ONLY=1
h-list "main" $(( term_height-7 )) $term_width "status" "3" "$term_width" " History: " "0" "${history[@]}"
HLIST_DRAW_ONLY=0
_zca_switch_lists_states "0"
HLIST_DISABLE_SEARCH=1
h-list "cmd" "4" $term_width "" "0" "0" " Command: " "1" "${list1[@]}"
else
_zca_switch_lists_states "0"
HLIST_DRAW_ONLY=1
h-list "cmd" "4" $term_width "" "0" "0" " Command: " "0" "${list1[@]}"
HLIST_DRAW_ONLY=0
_zca_switch_lists_states "1"
HLIST_DISABLE_SEARCH=0
h-list "main" $(( term_height-7 )) $term_width "status" "3" "$term_width" " History: " "1" "${history[@]}"
fi
# Init before possible simulation
cur_bkp=-1
if [ "$REPLY" = "LEAVE" ]; then
(( active_window = 1 - active_window ))
_zca_switch_lists_states "$active_window"
elif [[ ("$REPLY" = "MOVE_LEFT" || "$REPLY" = "MOVE_RIGHT" ||
"$REPLY" = "BR_MOVE_LEFT" || "$REPLY" = "BR_MOVE_RIGHT") && "$active_window" = 0 ]]; then
#
# Shift + cursor key - move existing element
#
local cmd="$reply[1]"
typeset -a tmp
tmp=( "${(z)cmd}" )
integer nseg="$#tmp"
[[ "$HLIST_CURRENT_SEGMENT" -gt "$nseg" ]] && HLIST_CURRENT_SEGMENT="$nseg"
if [[ "$REPLY" = "MOVE_LEFT" || "$REPLY" = "BR_MOVE_LEFT" ]]; then
if [ "$HLIST_CURRENT_SEGMENT" -gt "1" ]; then
local dest="$tmp[HLIST_CURRENT_SEGMENT-1]"
tmp[HLIST_CURRENT_SEGMENT-1]="$tmp[HLIST_CURRENT_SEGMENT]";
tmp[HLIST_CURRENT_SEGMENT]="$dest"
list1[1]="${(j: :)tmp}"
(( HLIST_CURRENT_SEGMENT -- ))
# Remember for undo
undolist=( "$list1[1]" "$undolist[@]" )
fi
elif [[ "$REPLY" = "MOVE_RIGHT" || "$REPLY" = "BR_MOVE_RIGHT" ]]; then
if [ "$HLIST_CURRENT_SEGMENT" -lt "$nseg" ]; then
local dest="$tmp[HLIST_CURRENT_SEGMENT+1]"
tmp[HLIST_CURRENT_SEGMENT+1]="$tmp[HLIST_CURRENT_SEGMENT]";
tmp[HLIST_CURRENT_SEGMENT]="$dest"
list1[1]="${(j: :)tmp}"
(( HLIST_CURRENT_SEGMENT ++ ))
# Remember for undo
undolist=( "$list1[1]" "$undolist[@]" )
fi
fi
elif [[ ("$REPLY" = -(#c0,1)[0-9]## && "$REPLY" -gt 0) || "$REPLY" = F[1-4] ]]; then
if [[ "$REPLY" = F[1-4] ]]; then
# Simulate
reply=( "" "[F1-Accept] [F2-Reject] [F3-Undo] [F4-Semicolon]" )
local key="$REPLY"
REPLY="2"
cur_bkp="$HLIST_CURRENT_SEGMENT"
# Simulate F1-Accept selection
[ "$key" = "F1" ] && HLIST_CURRENT_SEGMENT="1"
# Simulate F2-Reject selection
[ "$key" = "F2" ] && HLIST_CURRENT_SEGMENT="2"
# Simulate F3-Reject selection
[ "$key" = "F3" ] && HLIST_CURRENT_SEGMENT="3"
# Simulate F4-Semicolon selection
[ "$key" = "F4" ] && HLIST_CURRENT_SEGMENT="4"
fi
#
# Selection - add or remove element (or Accept, Reject, Undo, Semicolon)
#
answer="$reply[REPLY]"
typeset -a tmp
tmp=( "${(z)answer}" )
integer nseg="$#tmp"
integer cur_seg="$HLIST_CURRENT_SEGMENT"
[[ "$cur_seg" -gt "$nseg" ]] && cur_seg="$nseg"
# Get the interesting part - the selected segment
answer="$tmp[$cur_seg]"
if [ "$answer" = "[F1-Accept]" ]; then
# ZLE?
if [ "${(t)CURSOR}" = "integer-local-special" ]; then
zle redisplay
zle kill-buffer
zle -U "$list1[1]"
break
else
print -zr "$list1[1]"
break
fi
elif [ "$answer" = "[F2-Reject]" ]; then
# QUIT (1/2)
[ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
break
elif [ "$answer" = "[F3-Undo]" ]; then
if [ "$#undolist" -gt 1 ]; then
# Move previous to position of the current, deleting current
list1[1]="$undolist[2]"
shift undolist
fi
elif [ "$answer" = "[F4-Semicolon]" ]; then
# Addition of semicolon
[ -z "$list1[1]" ] && list1[1]=";" || list1[1]="$list1[1] ;"
# Remember for undo
undolist=( "$list1[1]" "$undolist[@]" )
else
#
# Here is where add or remove logic operates
#
if [ "$active_window" = "0" ]; then
# Delete of segment
tmp[cur_seg]=()
list1[1]="${(j: :)tmp}"
# Remember for undo
undolist=( "$list1[1]" "$undolist[@]" )
elif [ "$active_window" = "1" ]; then
# Addition of segment
[ -z "$list1[1]" ] && list1[1]="$answer" || list1[1]="$list1[1] $answer"
# Remember for undo
undolist=( "$list1[1]" "$undolist[@]" )
fi
fi
elif [[ "$REPLY" = -(#c0,1)[0-9]## && "$REPLY" -lt 0 ]]; then
# QUIT (2/2)
[ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
break
fi
# After simulating, restore current segment
[ "$cur_bkp" -ne "-1" ] && HLIST_CURRENT_SEGMENT="$cur_bkp"
done
# vim: set filetype=zsh: