diff options
-rw-r--r-- | Doc/Zsh/contrib.yo | 5 | ||||
-rw-r--r-- | Functions/Zle/smart-insert-last-word | 71 |
2 files changed, 55 insertions, 21 deletions
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index f2592c85e..8686e9430 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1127,6 +1127,11 @@ different widgets to use different patterns: example(zle -N insert-last-assignment smart-insert-last-word zstyle :insert-last-assignment match '[[:alpha:]][][[:alnum:]]#=*' bindkey '\e=' insert-last-assignment) + +If no interesting word is found and the tt(auto-previous) style is set to +a true value, the search continues upward through the history. When +tt(auto-previous) is unset or false (the default), the widget must be +invoked repeatedly in order to search earlier history lines. ) tindex(which-command) item(tt(which-command))( diff --git a/Functions/Zle/smart-insert-last-word b/Functions/Zle/smart-insert-last-word index 380c19954..269bd2808 100644 --- a/Functions/Zle/smart-insert-last-word +++ b/Functions/Zle/smart-insert-last-word @@ -2,6 +2,7 @@ # Inspired by Christoph Lange <langec@gmx.de> from zsh-users/3265; # rewritten to correct multiple-call behavior after zsh-users/3270; # modified to work with copy-earlier-word after zsh-users/5832. +# Edited further per zsh-users/10881 and zsh-users/10884. # # This function as a ZLE widget can replace insert-last-word, like so: # @@ -10,7 +11,7 @@ # With a numeric prefix, behaves like insert-last-word, except that words # in comments are ignored when interactive_comments is set. # -# Otherwise, the rightmost "interesting" word from the previous command is +# Otherwise, the rightmost "interesting" word from any previous command is # found and inserted. The default definition of "interesting" is that the # word contains at least one alphabetic character, slash, or backslash. # This definition can be overridden by use of a style like so: @@ -33,9 +34,17 @@ # zle -N insert-last-assignment smart-insert-last-word # zstyle :insert-last-assignment match '[[:alpha:]][][[:alnum:]]#=*' # bindkey '\e=' insert-last-assignment +# +# The "auto-previous" style, if set to a true value, causes the search to +# proceed upward through the history until an interesting word is found. +# If auto-previous is unset or false and there is no interesting word, the +# last word is returned. emulate -L zsh -setopt extendedglob +setopt extendedglob nohistignoredups + +# Begin by preserving completion suffix if any +zle auto-suffix-retain # Not strictly necessary: # (($+_ilw_hist)) || integer -g _ilw_hist _ilw_count _ilw_cursor _ilw_lcursor @@ -64,27 +73,47 @@ fi _ilw_hist=$HISTNO _ilw_count=$NUMERIC -zle .up-history || return 1 # Retrieve previous command -lastcmd=( ${${(z)BUFFER}:#\;} ) # Split into shell words -zle .down-history # Return to current command -CURSOR=$cursor # Restore cursor position -NUMERIC=${numeric:-1} # In case of fall through - -(( NUMERIC > $#lastcmd )) && return 1 - if [[ -z "$numeric" ]] then - integer i=1 - zstyle -s :$WIDGET match pattern || - pattern='*[[:alpha:]/\\]*' - while ((i <= $#lastcmd)); do - if [[ $lastcmd[-i] == $~pattern ]]; then - NUMERIC=$i - break - else - ((++i)) - fi - done + zstyle -s :$WIDGET match pattern || pattern='*[[:alpha:]/\\]*' fi + +# Note that we must use .up-history for navigation here because of +# possible "holes" in the $history hash (the result of dup expiry). +# We need $history because $BUFFER retains edits in progress as the +# user moves around the history, but we search the unedited lines. + +{ + zmodload -i zsh/parameter + zle .end-of-history # Start from final command + zle .up-history || return 1 # Retrieve previous command + local buffer=$history[$HISTNO] # Get unedited history line + lastcmd=( ${${(z)buffer}:#\;} ) # Split into shell words + if [[ -n "$pattern" ]] + then + # This is the "smart" part -- search right-to-left and + # latest-to-earliest through the history for a word. + integer n=0 found=$lastcmd[(I)$pattern] + if zstyle -t :$WIDGET auto-previous + then + while (( found == 0 && ++n )) + do + zle .up-history || return 1 + buffer=$history[$HISTNO] + lastcmd=( ${${(z)buffer}:#\;} ) + found=$lastcmd[(I)$pattern] + done + fi + (( found-- > 0 && # Account for 1-based index + (numeric = $#lastcmd - found) )) + fi +} always { + HISTNO=$_ilw_hist # Return to current command + CURSOR=$cursor # Restore cursor position + NUMERIC=${numeric:-1} # In case of fall-through +} + +(( NUMERIC > $#lastcmd )) && return 1 + LBUFFER[lcursor+1,cursor+1]=$lastcmd[-NUMERIC] _ilw_cursor=$CURSOR |