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:
378