# Copy this file into /usr/share/zsh/site-functions/ # and add 'autoload n-list-input` to .zshrc # # This is an internal function not for direct use emulate -L zsh zmodload zsh/curses setopt typesetsilent # Compute first to show index _nlist_compute_first_to_show_idx() { from_what_idx_list_is_shown=0+((current_idx-1)/page_height)*page_height+1 } _nlist_update_from_keywords() { keywordisfresh="1" if [ "$nkeywords" -gt 0 ]; then curkeyword=$(( (curkeyword+1) % (nkeywords+1) )) if [ "$curkeyword" -eq "0" ]; then buffer="" else buffer="${keywords[curkeyword]}" fi fi } _nlist_iterate_theme() { themeisfresh="1" if [ "$1" = "1" ]; then curtheme=$(( (curtheme+1) % (nthemes+1) )) else curtheme=curtheme-1 [ "$curtheme" -lt 0 ] && curtheme=nthemes fi if [ "$nthemes" -gt 0 ]; then local theme=${themes[curtheme]} [ "$curtheme" -eq "0" ] && theme="$backuptheme" colorpair="${theme%/*}" bold="${theme##*/}" background="${colorpair#*/}" zcurses bg main "$colorpair" zcurses bg inner "$colorpair" fi } _nlist_rotate_buffer() { setopt localoptions noglob local -a words words=( ${(s: :)buffer} ) words=( ${words[-1]} ${words[1,-2]} ) local space="" [ "${buffer[-1]}" = " " ] && space=" " buffer="${(j: :)words}$space" } typeset -ga reply reply=( -1 '' ) integer current_idx="$1" integer from_what_idx_list_is_shown="$2" integer page_height="$3" integer page_width="$4" integer last_element="$5" integer hscroll="$6" local key="$7" integer search="$8" local buffer="$9" integer uniq_mode="$10" integer f_mode="$11" # # Listening for input # if [ "$search" = "0" ]; then case "$key" in (UP|k|$'\C-P') # Are there any elements before the current one? [ "$current_idx" -gt 1 ] && current_idx=current_idx-1; _nlist_compute_first_to_show_idx ;; (DOWN|j|$'\C-N') # Are there any elements after the current one? [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1; _nlist_compute_first_to_show_idx ;; (PPAGE|$'\b'|$'\C-?'|BACKSPACE) current_idx=current_idx-page_height [ "$current_idx" -lt 1 ] && current_idx=1; _nlist_compute_first_to_show_idx ;; (NPAGE|" ") current_idx=current_idx+page_height [ "$current_idx" -gt "$last_element" ] && current_idx=last_element; _nlist_compute_first_to_show_idx ;; ($'\C-U') current_idx=current_idx-page_height/2 [ "$current_idx" -lt 1 ] && current_idx=1; _nlist_compute_first_to_show_idx ;; ($'\C-D') current_idx=current_idx+page_height/2 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element; _nlist_compute_first_to_show_idx ;; (HOME|g) current_idx=1 _nlist_compute_first_to_show_idx ;; (END|G) current_idx=last_element _nlist_compute_first_to_show_idx ;; ($'\n'|ENTER) # Is that element selectable? # Check for this only when there is no search if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 || ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]] then # Save current element in the result variable reply=( $current_idx "SELECT" ) fi ;; (H|'?') # This event needs to be enabled if [[ "${NLIST_ENABLED_EVENTS[(r)HELP]}" = "HELP" ]]; then reply=( -1 "HELP" ) fi ;; (F1) # This event needs to be enabled if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then reply=( -1 "$key" ) fi ;; (F4|F5|F6|F7|F8|F9|F10|DC) # ignore; F2, F3 are used below ;; (q) reply=( -1 "QUIT" ) ;; (/) search=1 _nlist_cursor_visibility 1 ;; ($'\t') reply=( $current_idx "LEAVE" ) ;; ($'\C-L') reply=( -1 "REDRAW" ) ;; (\]) [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] && [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] && for idx in "${(n)NLIST_HOP_INDEXES[@]}"; do if [ "$idx" -gt "$current_idx" ]; then current_idx=$idx _nlist_compute_first_to_show_idx break fi done ;; (\[) [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] && [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] && for idx in "${(nO)NLIST_HOP_INDEXES[@]}"; do if [ "$idx" -lt "$current_idx" ]; then current_idx=$idx _nlist_compute_first_to_show_idx break fi done ;; ('<'|'{'|LEFT|'h') hscroll=hscroll-7 [ "$hscroll" -lt 0 ] && hscroll=0 ;; ('>'|'}'|RIGHT|'l') hscroll+=7 ;; ($'\E') buffer="" ;; (F3) if [ "$search" = "1" ]; then search=0 _nlist_cursor_visibility 0 else search=1 _nlist_cursor_visibility 1 fi ;; (o|$'\C-O') uniq_mode=1-uniq_mode ;; (f|$'\C-F') (( f_mode=(f_mode+1) % 3 )) ;; ($'\x1F'|F2|$'\C-X') search=1 _nlist_cursor_visibility 1 _nlist_update_from_keywords ;; ($'\C-T') _nlist_iterate_theme 1 ;; ($'\C-G') _nlist_iterate_theme 0 ;; ($'\C-E'|e) # This event needs to be enabled if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then reply=( -1 "EDIT" ) fi ;; ($'\C-A') _nlist_rotate_buffer ;; (*) ;; esac else case "$key" in ($'\n'|ENTER) if [ "$NLIST_INSTANT_SELECT" = "1" ]; then if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 || ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]] then reply=( $current_idx "SELECT" ) fi else search=0 _nlist_cursor_visibility 0 fi ;; ($'\C-L') reply=( -1 "REDRAW" ) ;; # # Slightly limited navigation # (UP|$'\C-P') [ "$current_idx" -gt 1 ] && current_idx=current_idx-1; _nlist_compute_first_to_show_idx ;; (DOWN|$'\C-N') [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1; _nlist_compute_first_to_show_idx ;; (PPAGE) current_idx=current_idx-page_height [ "$current_idx" -lt 1 ] && current_idx=1; _nlist_compute_first_to_show_idx ;; (NPAGE) current_idx=current_idx+page_height [ "$current_idx" -gt "$last_element" ] && current_idx=last_element; _nlist_compute_first_to_show_idx ;; ($'\C-U') current_idx=current_idx-page_height/2 [ "$current_idx" -lt 1 ] && current_idx=1; _nlist_compute_first_to_show_idx ;; ($'\C-D') current_idx=current_idx+page_height/2 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element; _nlist_compute_first_to_show_idx ;; (HOME) current_idx=1 _nlist_compute_first_to_show_idx ;; (END) current_idx=last_element _nlist_compute_first_to_show_idx ;; (LEFT) hscroll=hscroll-7 [ "$hscroll" -lt 0 ] && hscroll=0 ;; (RIGHT) hscroll+=7 ;; (F1) # This event needs to be enabled if [[ "${NLIST_ENABLED_EVENTS[(r)F1]}" = "F1" ]]; then reply=( -1 "$key" ) fi ;; (F4|F5|F6|F7|F8|F9|F10|DC) # ignore; F2, F3 are used below ;; # # The input # ($'\b'|$'\C-?'|BACKSPACE) buffer="${buffer%?}" ;; ($'\C-W') [ "$buffer" = "${buffer% *}" ] && buffer="" || buffer="${buffer% *}" ;; ($'\C-K') buffer="" ;; ($'\E') buffer="" search=0 _nlist_cursor_visibility 0 ;; (F3) if [ "$search" = "1" ]; then search=0 _nlist_cursor_visibility 0 else search=1 _nlist_cursor_visibility 1 fi ;; ($'\C-O') uniq_mode=1-uniq_mode ;; ($'\C-F') (( f_mode=(f_mode+1) % 3 )) ;; ($'\x1F'|F2|$'\C-X') _nlist_update_from_keywords ;; ($'\C-T') _nlist_iterate_theme 1 ;; ($'\C-G') _nlist_iterate_theme 0 ;; ($'\C-E') # This event needs to be enabled if [[ "${NLIST_ENABLED_EVENTS[(r)EDIT]}" = "EDIT" ]]; then reply=( -1 "EDIT" ) fi ;; ($'\C-A') _nlist_rotate_buffer ;; (*) if [[ $#key == 1 && $((#key)) -lt 31 ]]; then # ignore all other control keys else buffer+="$key" fi ;; esac fi reply[3]="$current_idx" reply[4]="$from_what_idx_list_is_shown" reply[5]="$hscroll" reply[6]="$search" reply[7]="$buffer" reply[8]="$uniq_mode" reply[9]="$f_mode" # vim: set filetype=zsh: