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