n-list-input
9537 bytes
1# Copy this file into /usr/share/zsh/site-functions/
2# and add 'autoload n-list-input` to .zshrc
3#
4# This is an internal function not for direct use
5
6emulate -L zsh
7
8zmodload zsh/curses
9
10setopt typesetsilent
11
12# Compute first to show index
13_nlist_compute_first_to_show_idx() {
14 from_what_idx_list_is_shown=0+((current_idx-1)/page_height)*page_height+1
15}
16
17_nlist_update_from_keywords() {
18 keywordisfresh="1"
19 if [ "$nkeywords" -gt 0 ]; then
20 curkeyword=$(( (curkeyword+1) % (nkeywords+1) ))
21 if [ "$curkeyword" -eq "0" ]; then
22 buffer=""
23 else
24 buffer="${keywords[curkeyword]}"
25 fi
26 fi
27}
28
29_nlist_iterate_theme() {
30 themeisfresh="1"
31 if [ "$1" = "1" ]; then
32 curtheme=$(( (curtheme+1) % (nthemes+1) ))
33 else
34 curtheme=curtheme-1
35 [ "$curtheme" -lt 0 ] && curtheme=nthemes
36 fi
37
38 if [ "$nthemes" -gt 0 ]; then
39 local theme=${themes[curtheme]}
40 [ "$curtheme" -eq "0" ] && theme="$backuptheme"
41
42 colorpair="${theme%/*}"
43 bold="${theme##*/}"
44 background="${colorpair#*/}"
45 zcurses bg main "$colorpair"
46 zcurses bg inner "$colorpair"
47 fi
48}
49
50_nlist_rotate_buffer() {
51 setopt localoptions noglob
52
53 local -a words
54 words=( ${(s: :)buffer} )
55 words=( ${words[-1]} ${words[1,-2]} )
56
57 local space=""
58 [ "${buffer[-1]}" = " " ] && space=" "
59
60 buffer="${(j: :)words}$space"
61}
62
63typeset -ga reply
64reply=( -1 '' )
65integer current_idx="$1"
66integer from_what_idx_list_is_shown="$2"
67integer page_height="$3"
68integer page_width="$4"
69integer last_element="$5"
70integer hscroll="$6"
71local key="$7"
72integer search="$8"
73local buffer="$9"
74integer uniq_mode="$10"
75integer f_mode="$11"
76
77#
78# Listening for input
79#
80
81if [ "$search" = "0" ]; then
82
83case "$key" in
84 (UP|k|$'\C-P')
85 # Are there any elements before the current one?
86 [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
87 _nlist_compute_first_to_show_idx
88 ;;
89 (DOWN|j|$'\C-N')
90 # Are there any elements after the current one?
91 [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
92 _nlist_compute_first_to_show_idx
93 ;;
94 (PPAGE|$'\b'|$'\C-?'|BACKSPACE)
95 current_idx=current_idx-page_height
96 [ "$current_idx" -lt 1 ] && current_idx=1;
97 _nlist_compute_first_to_show_idx
98 ;;
99 (NPAGE|" ")
100 current_idx=current_idx+page_height
101 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
102 _nlist_compute_first_to_show_idx
103 ;;
104 ($'\C-U')
105 current_idx=current_idx-page_height/2
106 [ "$current_idx" -lt 1 ] && current_idx=1;
107 _nlist_compute_first_to_show_idx
108 ;;
109 ($'\C-D')
110 current_idx=current_idx+page_height/2
111 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
112 _nlist_compute_first_to_show_idx
113 ;;
114 (HOME|g)
115 current_idx=1
116 _nlist_compute_first_to_show_idx
117 ;;
118 (END|G)
119 current_idx=last_element
120 _nlist_compute_first_to_show_idx
121 ;;
122 ($'\n'|ENTER)
123 # Is that element selectable?
124 # Check for this only when there is no search
125 if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
126 ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
127 then
128 # Save current element in the result variable
129 reply=( $current_idx "SELECT" )
130 fi
131 ;;
132 (H|'?')
133 # This event needs to be enabled
134 if [[ "${NLIST_ENABLED_EVENTS[(r)HELP]}" = "HELP" ]]; then
135 reply=( -1 "HELP" )
136 fi
137 ;;
138 (F1)
139 # This event needs to be enabled
140 if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then
141 reply=( -1 "$key" )
142 fi
143 ;;
144 (F4|F5|F6|F7|F8|F9|F10|DC)
145 # ignore; F2, F3 are used below
146 ;;
147 (q)
148 reply=( -1 "QUIT" )
149 ;;
150 (/)
151 search=1
152 _nlist_cursor_visibility 1
153 ;;
154 ($'\t')
155 reply=( $current_idx "LEAVE" )
156 ;;
157 ($'\C-L')
158 reply=( -1 "REDRAW" )
159 ;;
160 (\])
161 [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
162 [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] &&
163 for idx in "${(n)NLIST_HOP_INDEXES[@]}"; do
164 if [ "$idx" -gt "$current_idx" ]; then
165 current_idx=$idx
166 _nlist_compute_first_to_show_idx
167 break
168 fi
169 done
170 ;;
171 (\[)
172 [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
173 [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] &&
174 for idx in "${(nO)NLIST_HOP_INDEXES[@]}"; do
175 if [ "$idx" -lt "$current_idx" ]; then
176 current_idx=$idx
177 _nlist_compute_first_to_show_idx
178 break
179 fi
180 done
181 ;;
182 ('<'|'{'|LEFT|'h')
183 hscroll=hscroll-7
184 [ "$hscroll" -lt 0 ] && hscroll=0
185 ;;
186 ('>'|'}'|RIGHT|'l')
187 hscroll+=7
188 ;;
189 ($'\E')
190 buffer=""
191 ;;
192 (F3)
193 if [ "$search" = "1" ]; then
194 search=0
195 _nlist_cursor_visibility 0
196 else
197 search=1
198 _nlist_cursor_visibility 1
199 fi
200 ;;
201 (o|$'\C-O')
202 uniq_mode=1-uniq_mode
203 ;;
204 (f|$'\C-F')
205 (( f_mode=(f_mode+1) % 3 ))
206 ;;
207 ($'\x1F'|F2|$'\C-X')
208 search=1
209 _nlist_cursor_visibility 1
210 _nlist_update_from_keywords
211 ;;
212 ($'\C-T')
213 _nlist_iterate_theme 1
214 ;;
215 ($'\C-G')
216 _nlist_iterate_theme 0
217 ;;
218 ($'\C-E'|e)
219 # This event needs to be enabled
220 if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then
221 reply=( -1 "EDIT" )
222 fi
223 ;;
224 ($'\C-A')
225 _nlist_rotate_buffer
226 ;;
227 (*)
228 ;;
229esac
230
231else
232
233case "$key" in
234 ($'\n'|ENTER)
235 if [ "$NLIST_INSTANT_SELECT" = "1" ]; then
236 if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
237 ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
238 then
239 reply=( $current_idx "SELECT" )
240 fi
241 else
242 search=0
243 _nlist_cursor_visibility 0
244 fi
245 ;;
246 ($'\C-L')
247 reply=( -1 "REDRAW" )
248 ;;
249
250 #
251 # Slightly limited navigation
252 #
253
254 (UP|$'\C-P')
255 [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
256 _nlist_compute_first_to_show_idx
257 ;;
258 (DOWN|$'\C-N')
259 [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
260 _nlist_compute_first_to_show_idx
261 ;;
262 (PPAGE)
263 current_idx=current_idx-page_height
264 [ "$current_idx" -lt 1 ] && current_idx=1;
265 _nlist_compute_first_to_show_idx
266 ;;
267 (NPAGE)
268 current_idx=current_idx+page_height
269 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
270 _nlist_compute_first_to_show_idx
271 ;;
272 ($'\C-U')
273 current_idx=current_idx-page_height/2
274 [ "$current_idx" -lt 1 ] && current_idx=1;
275 _nlist_compute_first_to_show_idx
276 ;;
277 ($'\C-D')
278 current_idx=current_idx+page_height/2
279 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
280 _nlist_compute_first_to_show_idx
281 ;;
282 (HOME)
283 current_idx=1
284 _nlist_compute_first_to_show_idx
285 ;;
286 (END)
287 current_idx=last_element
288 _nlist_compute_first_to_show_idx
289 ;;
290 (LEFT)
291 hscroll=hscroll-7
292 [ "$hscroll" -lt 0 ] && hscroll=0
293 ;;
294 (RIGHT)
295 hscroll+=7
296 ;;
297 (F1)
298 # This event needs to be enabled
299 if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then
300 reply=( -1 "$key" )
301 fi
302 ;;
303 (F4|F5|F6|F7|F8|F9|F10|DC)
304 # ignore; F2, F3 are used below
305 ;;
306
307 #
308 # The input
309 #
310
311 ($'\b'|$'\C-?'|BACKSPACE)
312 buffer="${buffer%?}"
313 ;;
314 ($'\C-W')
315 [ "$buffer" = "${buffer% *}" ] && buffer="" || buffer="${buffer% *}"
316 ;;
317 ($'\C-K')
318 buffer=""
319 ;;
320 ($'\E')
321 buffer=""
322 search=0
323 _nlist_cursor_visibility 0
324 ;;
325 (F3)
326 if [ "$search" = "1" ]; then
327 search=0
328 _nlist_cursor_visibility 0
329 else
330 search=1
331 _nlist_cursor_visibility 1
332 fi
333 ;;
334 ($'\C-O')
335 uniq_mode=1-uniq_mode
336 ;;
337 ($'\C-F')
338 (( f_mode=(f_mode+1) % 3 ))
339 ;;
340 ($'\x1F'|F2|$'\C-X')
341 _nlist_update_from_keywords
342 ;;
343 ($'\C-T')
344 _nlist_iterate_theme 1
345 ;;
346 ($'\C-G')
347 _nlist_iterate_theme 0
348 ;;
349 ($'\C-E')
350 # This event needs to be enabled
351 if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then
352 reply=( -1 "EDIT" )
353 fi
354 ;;
355 ($'\C-A')
356 _nlist_rotate_buffer
357 ;;
358 (*)
359 if [[ $#key == 1 && $((#key)) -lt 31 ]]; then
360 # ignore all other control keys
361 else
362 buffer+="$key"
363 fi
364 ;;
365esac
366
367fi
368
369reply[3]="$current_idx"
370reply[4]="$from_what_idx_list_is_shown"
371reply[5]="$hscroll"
372reply[6]="$search"
373reply[7]="$buffer"
374reply[8]="$uniq_mode"
375reply[9]="$f_mode"
376
377# vim: set filetype=zsh: