|
| 1 | +emulate -LR zsh |
| 2 | +setopt typesetsilent extendedglob noshortloops |
| 3 | + |
| 4 | +# When an error, then no cursor keys bindings |
| 5 | +zmodload zsh/terminfo 2>/dev/null |
| 6 | +zmodload zsh/termcap 2>/dev/null |
| 7 | + |
| 8 | +# Prepare output variables for zew-process-buffer |
| 9 | +local ZEW_PB_WORDS ZEW_PB_WORDS_BEGINNINGS ZEW_PB_SPACES |
| 10 | +local ZEW_PB_SELECTED_WORD ZEW_PB_LEFT ZEW_PB_RIGHT |
| 11 | + |
| 12 | +typeset -g __zew_hcw_index __zew_hcw_left __zew_hcw_right |
| 13 | +typeset -g __zew_hcw_widget_name __zew_hcw_restart __zew_hcw_call_count |
| 14 | +typeset -gaU __zew_hcw_found |
| 15 | + |
| 16 | +(( __zew_hcw_call_count ++ )) |
| 17 | + |
| 18 | +_zhcw_main() { |
| 19 | + |
| 20 | +autoload zew-process-buffer |
| 21 | +zew-process-buffer "$BUFFER" "$CURSOR" |
| 22 | + |
| 23 | +# First call or restart? |
| 24 | +if [[ "$__zew_hcw_call_count" -le 1 || "$__zew_hcw_restart" = "1" ]]; then |
| 25 | + # '0' will get changed into $to_display limit |
| 26 | + [[ "$WIDGET" != *-backwards ]] && __zew_hcw_index="1" || __zew_hcw_index="0" |
| 27 | + __zew_hcw_widget_name="${WIDGET%-backwards}" |
| 28 | + __zew_hcw_left="$ZEW_PB_LEFT" |
| 29 | + __zew_hcw_right="$ZEW_PB_RIGHT" |
| 30 | + __zew_hcw_found=( ) |
| 31 | + __zew_hcw_finished="0" |
| 32 | + __zew_hcw_restart="0" |
| 33 | +else |
| 34 | + # Consecutive call |
| 35 | + [[ "$WIDGET" != *-backwards ]] && (( __zew_hcw_index ++ )) || (( __zew_hcw_index -- )) |
| 36 | +fi |
| 37 | + |
| 38 | +# Find history words matching $left ... $right |
| 39 | +if [ "$#__zew_hcw_found" -eq "0" ]; then |
| 40 | + repeat 1; do |
| 41 | + __zew_hcw_found=( "${(@M)historywords:#(#i)$__zew_hcw_left*$__zew_hcw_right}" ) |
| 42 | + done |
| 43 | + |
| 44 | + # The first result should be always $__zew_hcw_left$__zew_hcw_right |
| 45 | + if [ "$__zew_hcw_found[1]" != "$__zew_hcw_left$__zew_hcw_right" ]; then |
| 46 | + __zew_hcw_found=( "$__zew_hcw_left$__zew_hcw_right" "$__zew_hcw_found[@]" ) |
| 47 | + fi |
| 48 | +fi |
| 49 | + |
| 50 | +if [ "$#__zew_hcw_found" -le "0" ]; then |
| 51 | + zle -M "No matches found" |
| 52 | + return 0 |
| 53 | +fi |
| 54 | + |
| 55 | +# Pagination, index value guards |
| 56 | +integer page_size=$(( LINES / 2 )) |
| 57 | +integer max_index="$#__zew_hcw_found" |
| 58 | +[ "$page_size" -gt "$max_index" ] && page_size="$max_index" |
| 59 | +[ "$__zew_hcw_index" -le 0 ] && __zew_hcw_index="$max_index" |
| 60 | +[ "$__zew_hcw_index" -gt "$max_index" ] && __zew_hcw_index=1 |
| 61 | +integer page_start_idx=$(( ((__zew_hcw_index-1)/page_size)*page_size+1 )) |
| 62 | +integer on_page_idx=$(( (__zew_hcw_index-1) % page_size + 1 )) |
| 63 | + |
| 64 | +# Display matches |
| 65 | +typeset -a disp_list |
| 66 | +disp_list=( "${(@)__zew_hcw_found[page_start_idx,page_start_idx+page_size-1]}" ) |
| 67 | + |
| 68 | +# Add two spaces before every element |
| 69 | +disp_list=( "${(@)disp_list/(#m)*/ ${MATCH}}" ) |
| 70 | + |
| 71 | +# Add > before active element |
| 72 | +local entry="${disp_list[on_page_idx]}" |
| 73 | +entry[1]='>' |
| 74 | +disp_list[on_page_idx]="$entry" |
| 75 | + |
| 76 | +zle -M -- \ |
| 77 | +"Searching for '${__zew_hcw_left}_${__zew_hcw_right}'. "\ |
| 78 | +"Element #$__zew_hcw_index of $max_index"$'\n'"${(F)disp_list}" |
| 79 | + |
| 80 | +# Regenerate command line |
| 81 | +local buf="" |
| 82 | +integer nwords="${#ZEW_PB_WORDS}" |
| 83 | +for (( i=1; i<=nwords; i++ )); do |
| 84 | + if [ "$i" = "$ZEW_PB_SELECTED_WORD" ]; then |
| 85 | + buf+="${ZEW_PB_SPACES[i]}${__zew_hcw_found[__zew_hcw_index]}" |
| 86 | + else |
| 87 | + buf+="${ZEW_PB_SPACES[i]}${ZEW_PB_WORDS[i]}" |
| 88 | + fi |
| 89 | +done |
| 90 | + |
| 91 | +if [[ "$nwords" = "0" && "$ZEW_PB_SELECTED_WORD" = "0" ]]; then |
| 92 | + buf+="${__zew_hcw_found[__zew_hcw_index]}" |
| 93 | +fi |
| 94 | + |
| 95 | +# Add trailing spaces |
| 96 | +buf+="$ZEW_PB_SPACES[i]" |
| 97 | + |
| 98 | +# Set command line |
| 99 | +BUFFER="$buf" |
| 100 | + |
| 101 | +} |
| 102 | + |
| 103 | +_zhcw_self_insert() { |
| 104 | + LBUFFER+="${KEYS[-1]}" |
| 105 | + __zew_hcw_restart="1" |
| 106 | + _zhcw_main |
| 107 | +} |
| 108 | + |
| 109 | +_zhcw_backward_delete_char() { |
| 110 | + LBUFFER="${LBUFFER%?}" |
| 111 | + __zew_hcw_restart="1" |
| 112 | + _zhcw_main |
| 113 | +} |
| 114 | + |
| 115 | +_zhcw_delete_char() { |
| 116 | + RBUFFER="${RBUFFER#?}" |
| 117 | + __zew_hcw_restart="1" |
| 118 | + _zhcw_main |
| 119 | +} |
| 120 | + |
| 121 | +_zhcw_main |
| 122 | + |
| 123 | +if [ "$__zew_hcw_call_count" -eq "1" ]; then |
| 124 | + # Make the zhcw keymap a copy of the current main |
| 125 | + bindkey -N zhcw emacs |
| 126 | + |
| 127 | + local down_widget="${WIDGET%-backwards}" |
| 128 | + local up_widget="${down_widget}-backwards" |
| 129 | + |
| 130 | + # Manual, termcap, terminfo |
| 131 | + bindkey -M zhcw '^[OA' "$up_widget" |
| 132 | + bindkey -M zhcw '^[OB' "$down_widget" |
| 133 | + bindkey -M zhcw '^[[A' "$up_widget" |
| 134 | + bindkey -M zhcw '^[[B' "$down_widget" |
| 135 | + [ -n "$termcap[ku]" ] && bindkey -M zhcw "$termcap[ku]" "$up_widget" |
| 136 | + [ -n "$termcap[kd]" ] && bindkey -M zhcw "$termcap[kd]" "$down_widget" |
| 137 | + [ -n "$termcap[kD]" ] && bindkey -M zhcw "$termcap[kD]" delete-char |
| 138 | + [ -n "$terminfo[kcuu1]" ] && bindkey -M zhcw "$terminfo[kcuu1]" "$up_widget" |
| 139 | + [ -n "$terminfo[kcud1]" ] && bindkey -M zhcw "$terminfo[kcud1]" "$down_widget" |
| 140 | + [ -n "$terminfo[kdch1]" ] && bindkey -M zhcw "$terminfo[kdch1]" delete-char |
| 141 | + |
| 142 | + # Needed for Fedora 23, zsh-5.1.1 |
| 143 | + bindkey -M zhcw ' ' self-insert |
| 144 | + |
| 145 | + # Substitute self-insert, backward-delete-char, delete-char |
| 146 | + zle -A self-insert saved-self-insert |
| 147 | + zle -A backward-delete-char saved-backward-delete-char |
| 148 | + zle -A delete-char saved-delete-char |
| 149 | + |
| 150 | + zle -N self-insert _zhcw_self_insert |
| 151 | + zle -N backward-delete-char _zhcw_backward_delete_char |
| 152 | + zle -N delete-char _zhcw_delete_char |
| 153 | + |
| 154 | + zle recursive-edit -K zhcw |
| 155 | + zle -M "" |
| 156 | + |
| 157 | + zle -A saved-self-insert self-insert |
| 158 | + zle -A saved-backward-delete-char backward-delete-char |
| 159 | + zle -A saved-delete-char delete-char |
| 160 | + zle -D saved-self-insert saved-backward-delete-char saved-delete-char |
| 161 | + |
| 162 | + # Full reinitialisation at next call |
| 163 | + __zew_hcw_call_count="0" |
| 164 | +fi |
| 165 | + |
| 166 | +# vim:ft=zsh |
0 commit comments