diff --git a/ziactioncomplete b/zi-action-complete similarity index 55% rename from ziactioncomplete rename to zi-action-complete index 21971de18..7b369cbcf 100644 --- a/ziactioncomplete +++ b/zi-action-complete @@ -1,25 +1,74 @@ # -*- mode: sh; sh-indentation: 4; indent-tabs-mode: nil; sh-basic-offset: 4; -*- # Copyright (c) 2016-2020 Sebastian Gniazdowski and contributors. -ziactioncomplete() +zi-action-complete() { # Emulate zsh and useful options emulate -L zsh -o extended_glob -o warn_create_global -o typeset_silent \ -o no_short_loops -o rc_quotes -o no_auto_pushd + # The index of the match that's inserted in cmd line + integer -g ziac_midx + typeset -ga ziac_matches ziac_wids + typeset -g ziac_prevw ziac_mt + local -a match mbegin mend + typeset -gA Times + + # # Invoke the helper/worker function that does all needed $BUFFER processing - ziprocessbuffer + # + + zi-process-buffer || return 1 integer i j pos=$CURSOR size=${#ZINIT_PB_WORDS} newcursor - local w=$ZINIT_PB_WORDS[ZINIT_PB_SELECTED_WORD] buf - local -a matches=( $ZINIT[PLUGINS_DIR]/*${w//\//---}*(-onND[1,8]) ) - REPLY=${${matches[1]:t}//---//} + local w=$ZINIT_PB_WORDS[ZINIT_PB_SELECTED_WORD] LWIDGET buf + (( Times[$WIDGET] = Times[$WIDGET] <= 0 ? + EPOCHREALTIME-3 : Times[$WIDGET] )) + + # Detect series. + if (( EPOCHREALTIME - Times[$WIDGET] < 1 )); then + LWIDGET=$WIDGET + else + LWIDGET= ziac_prevw= + fi + Times[$WIDGET]=$EPOCHREALTIME + + if [[ $WIDGET == zi-action-complete-ice && $WIDGET != $LWIDGET && $ziac_prevw != $w ]] + then + local -a ice_order=( + ${(Aons:|:)ZINIT[ice-list]} + ${(@)${(A@kons:|:)${ZINIT_EXTS[ice-mods]//\'\'/}}/(#s)<->-/} + ) + ziac_prevw=$w + match=() + w=${w//(#b)(([=:]|)[\'\"]?#([\'\"]|(#e)))/} + ziac_mt=$match[1] + + ziac_matches=( ${(onM)ice_order:#*$w*} ) + elif (( ziac_midx )) && [[ $WIDGET == *-ice && $WIDGET == $LWIDGET ]]; then + ziac_midx+=1 + fi + if [[ $WIDGET == zi-action-complete && $WIDGET != $LWIDGET && $ziac_prevw != $w ]]; then + ziac_matches=( $ZINIT[PLUGINS_DIR]/*${w//\//---}*(-onND[1,18]) ) + ziac_prevw=$w + ziac_mt= + elif (( ziac_midx )) && [[ $WIDGET == *-complete && $WIDGET == $LWIDGET ]]; then + ziac_midx+=1 + fi + if (( !ziac_midx || ziac_midx > $#ziac_matches )); then + ziac_midx=1 + fi + + if [[ -z $ziac_matches ]]; then + zle -M "No matches for $w found" + return 1 + fi + REPLY=${${ziac_matches[$ziac_midx]:t}//---//}$ziac_mt for (( i=1; i<=size; i++ )); do # Check if we're at (i.e. directly at or after, # when after are just spaces) current word if [[ $i = $ZINIT_PB_SELECTED_WORD ]]; then - # Check if we're at the word itself, - # or at some distance after it - if [[ $WIDGET == ziactioncompleteinsert ]] && (( pos > (ZINIT_PB_WORDS_BEGINNINGS[i] + ${#ZINIT_PB_WORDS[i]} - 1) )); then + # INSERT MODE? I.e.: addition of a new token at the pointed free space? + if [[ $WIDGET == zi-action-completeinsert ]] && (( pos > (ZINIT_PB_WORDS_BEGINNINGS[i] + ${#ZINIT_PB_WORDS[i]} - 1) )); then # We need to introduce new word # First move all words and spaces forward for (( j=size; j>=i+1; j-- )); do @@ -45,6 +94,7 @@ ziactioncomplete() # Cursor will be at end of newly added word newcursor=$(( ZINIT_PB_WORDS_BEGINNINGS[i+1] + ${#ZINIT_PB_WORDS[i+1]} - 1 )) + # OR REPLACE MODE – substitute the match for the input/needle token else ZINIT_PB_WORDS[i]=$REPLY diff --git a/ziprocessbuffer b/zi-process-buffer similarity index 82% rename from ziprocessbuffer rename to zi-process-buffer index a03362728..b63e65c05 100644 --- a/ziprocessbuffer +++ b/zi-process-buffer @@ -3,7 +3,7 @@ # $2 - optional parameter containing cursor (default is $CURSOR) # # Output: -# ZINIT_PB_WORDS - split of "$1" into shell words; array +# ZINIT_PB_WORDS - split of $1 into shell words; array # ZINIT_PB_WORDS_BEGINNINGS - indexes of first letters of corresponding words in ZINIT_PB_WORDS # ZINIT_PB_SPACES - white spaces before corresponding words in ZINIT_PB_WORDS # ZINIT_PB_SELECTED_WORD - index in ZINIT_PB_WORDS pointing to word activated by cursor position @@ -22,10 +22,10 @@ local cursor="${2:-$CURSOR}" ZINIT_PB_WORDS=( "${(Z+n+)buf}" ) ZINIT_PB_SPACES=( ) ZINIT_PB_WORDS_BEGINNINGS=( ) -ZINIT_PB_SELECTED_WORD="-1" +ZINIT_PB_SELECTED_WORD=-1 # (Z+n+) will return 1 element for buf that is empty or only whitespace -if [[ "$buf" = ( |$'\t')# ]]; then +if [[ $buf = ( |$'\t')# ]]; then ZINIT_PB_WORDS=( ) integer nwords=0 else @@ -63,29 +63,29 @@ for (( i=1; i<=nwords; i++ )); do # This is the beginning of current word ZINIT_PB_WORDS_BEGINNINGS[i]=$(( char_count + 1 )) # Remember the spaces - ZINIT_PB_SPACES[i]="$MATCH" + ZINIT_PB_SPACES[i]=$MATCH # Remove the word wordlen="${#word}" - [[ "${buf[1,wordlen]}" != "$word" ]] && return 1 # should not happen unless bug in (z) + [[ "${buf[1,wordlen]}" != $word ]] && return 1 # should not happen unless bug in (z) buf="${buf[wordlen+1,-1]}" # Spaces point to previous shell word # Visual cursor right after spaces (-ge) -> not enough to select previous word (-gt required) - [[ "$ZINIT_PB_SELECTED_WORD" -eq "-1" && "$char_count" -gt "$cursor" ]] && ZINIT_PB_SELECTED_WORD=$(( i-1 )) + [[ $ZINIT_PB_SELECTED_WORD -eq -1 && $char_count -gt $cursor ]] && ZINIT_PB_SELECTED_WORD=$(( i-1 )) # Actual characters point to current shell word # Visual cursor right after letters (-ge) -> enough to select current word char_count=char_count+"$#word" - [[ "$ZINIT_PB_SELECTED_WORD" -eq "-1" && "$char_count" -ge "$cursor" ]] && ZINIT_PB_SELECTED_WORD="$i" + [[ $ZINIT_PB_SELECTED_WORD -eq -1 && $char_count -ge $cursor ]] && ZINIT_PB_SELECTED_WORD=$i done # What's left in $buf can be only white spaces char_count=char_count+"$#buf" -ZINIT_PB_SPACES[i]="$buf" +ZINIT_PB_SPACES[i]=$buf # Visual cursor right after spaces (-ge) -> enough to select last word -[[ "$ZINIT_PB_SELECTED_WORD" -eq "-1" && "$char_count" -ge "$cursor" ]] && ZINIT_PB_SELECTED_WORD=$(( i-1 )) +[[ $ZINIT_PB_SELECTED_WORD -eq -1 && $char_count -ge $cursor ]] && ZINIT_PB_SELECTED_WORD=$(( i-1 )) # Divide active word into two halves integer diff=$(( cursor - ZINIT_PB_WORDS_BEGINNINGS[ZINIT_PB_SELECTED_WORD] + 1 )) @@ -93,4 +93,6 @@ word="${ZINIT_PB_WORDS[ZINIT_PB_SELECTED_WORD]}" ZINIT_PB_LEFT="${word[1,diff]}" ZINIT_PB_RIGHT="${word[diff+1,-1]}" +[[ $ZINIT_PB_SELECTED_WORD -gt 0 ]] + # vim:ft=zsh diff --git a/zinit.zsh b/zinit.zsh index a1bab9265..862f593eb 100644 --- a/zinit.zsh +++ b/zinit.zsh @@ -3282,10 +3282,13 @@ zle -N zi-browse-symbol-pforwards zi-browse-symbol bindkey "^K" zi-browse-symbol # A custom completion of plugin ids (alt-a) and of ice names (alt-c) -zinit null light-mode autoload'ziactioncomplete;ziprocessbuffer' for %$ZINIT[BIN_DIR] -zle -N ziactioncomplete -zle -N ziactioncompleteinsert ziactioncomplete -bindkey '\ea' ziactioncomplete -bindkey '\eA' ziactioncompleteinsert +zinit null light-mode autoload'zi-action-complete;zi-process-buffer' for %$ZINIT[BIN_DIR] +zle -N zi-action-complete +zle -N zi-action-complete-ice zi-action-complete +# Alt-A and Alt-C are default. +zstyle -s ":zinit:action-complete:plugin-id" key ZINIT_TMP || ZINIT_TMP='\eA' +[[ -n $ZINIT_TMP ]] && bindkey $ZINIT_TMP zi-action-complete +zstyle -s ":zinit:action-complete:ice" key ZINIT_TMP || ZINIT_TMP='\eC' +[[ -n $ZINIT_TMP ]] && bindkey $ZINIT_TMP zi-action-complete-ice # vim:ft=zsh:sw=4:sts=4:et:foldmarker=[[[,]]]:foldmethod=marker