diff options
Diffstat (limited to 'plugins/history-substring-search')
3 files changed, 661 insertions, 0 deletions
| diff --git a/plugins/history-substring-search/README b/plugins/history-substring-search/README new file mode 100644 index 000000000..be11adf76 --- /dev/null +++ b/plugins/history-substring-search/README @@ -0,0 +1,7 @@ +To activate this script, load it into an interactive ZSH session: + +  % source history-substring-search.zsh + +See the "history-substring-search.zsh" file for more information: + +  % sed -n '2,/^$/s/^#//p' history-substring-search.zsh | more diff --git a/plugins/history-substring-search/history-substring-search.plugin.zsh b/plugins/history-substring-search/history-substring-search.plugin.zsh new file mode 100644 index 000000000..99a5922c5 --- /dev/null +++ b/plugins/history-substring-search/history-substring-search.plugin.zsh @@ -0,0 +1,12 @@ +# This file integrates the history-substring-search script into oh-my-zsh. + +source "$ZSH/plugins/history-substring-search/history-substring-search.zsh" + +if test "$CASE_SENSITIVE" = true; then +  unset HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS +fi + +if test "$DISABLE_COLOR" = true; then +  unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +  unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND +fi diff --git a/plugins/history-substring-search/history-substring-search.zsh b/plugins/history-substring-search/history-substring-search.zsh new file mode 100644 index 000000000..53f707c79 --- /dev/null +++ b/plugins/history-substring-search/history-substring-search.zsh @@ -0,0 +1,642 @@ +#!/usr/bin/env zsh +# +# This is a clean-room implementation of the Fish[1] shell's history search +# feature, where you can type in any part of any previously entered command +# and press the UP and DOWN arrow keys to cycle through the matching commands. +# +#----------------------------------------------------------------------------- +# Usage +#----------------------------------------------------------------------------- +# +# 1. Load this script into your interactive ZSH session: +# +#       % source history-substring-search.zsh +# +#    If you want to use the zsh-syntax-highlighting[6] script along with this +#    script, then make sure that you load it *before* you load this script: +# +#       % source zsh-syntax-highlighting.zsh +#       % source history-substring-search.zsh +# +# 2. Type any part of any previous command and then: +# +#     * Press the UP arrow key to select the nearest command that (1) contains +#       your query and (2) is older than the current command in the command +#       history. +# +#     * Press the DOWN arrow key to select the nearest command that (1) +#       contains your query and (2) is newer than the current command in the +#       command history. +# +#     * Press ^U (the Control and U keys simultaneously) to abort the search. +# +# 3. If a matching command spans more than one line of text, press the LEFT +#    arrow key to move the cursor away from the end of the command, and then: +# +#     * Press the UP arrow key to move the cursor to the line above.  When the +#       cursor reaches the first line of the command, pressing the UP arrow +#       key again will cause this script to perform another search. +# +#     * Press the DOWN arrow key to move the cursor to the line below.  When +#       the cursor reaches the last line of the command, pressing the DOWN +#       arrow key again will cause this script to perform another search. +# +#----------------------------------------------------------------------------- +# Configuration +#----------------------------------------------------------------------------- +# +# This script defines the following global variables. You may override their +# default values only after having loaded this script into your ZSH session. +# +# * HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND is a global variable that defines +#   how the query should be highlighted inside a matching command. Its default +#   value causes this script to highlight using bold, white text on a magenta +#   background. See the "Character Highlighting" section in the zshzle(1) man +#   page to learn about the kinds of values you may assign to this variable. +# +# * HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND is a global variable that +#   defines how the query should be highlighted when no commands in the +#   history match it. Its default value causes this script to highlight using +#   bold, white text on a red background. See the "Character Highlighting" +#   section in the zshzle(1) man page to learn about the kinds of values you +#   may assign to this variable. +# +# * HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS is a global variable that defines +#   how the command history will be searched for your query. Its default value +#   causes this script to perform a case-insensitive search. See the "Globbing +#   Flags" section in the zshexpn(1) man page to learn about the kinds of +#   values you may assign to this variable. +# +#----------------------------------------------------------------------------- +# History +#----------------------------------------------------------------------------- +# +# This script was originally written by Peter Stephenson[2], who published it +# to the ZSH users mailing list (thereby making it public domain) in September +# 2009. It was later revised by Guido van Steen and released under the BSD +# license (see below) as part of the fizsh[3] project in January 2011. +# +# It was later extracted from fizsh[3] release 1.0.1, refactored heavily, and +# repackaged as both an oh-my-zsh plugin[4] and as an independently loadable +# ZSH script[5] by Suraj N. Kurapati in 2011. +# +# It was further developed[4] by Guido van Steen, Suraj N. Kurapati, Sorin +# Ionescu, and Vincent Guerci in 2011. +# +# [1]: http://fishshell.com +# [2]: http://www.zsh.org/mla/users/2009/msg00818.html +# [3]: http://sourceforge.net/projects/fizsh/ +# [4]: https://github.com/robbyrussell/oh-my-zsh/pull/215 +# [5]: https://github.com/sunaku/zsh-history-substring-search +# [6]: https://github.com/nicoulaj/zsh-syntax-highlighting +# +############################################################################## +# +# Copyright (c) 2009 Peter Stephenson +# Copyright (c) 2011 Guido van Steen +# Copyright (c) 2011 Suraj N. Kurapati +# Copyright (c) 2011 Sorin Ionescu +# Copyright (c) 2011 Vincent Guerci +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +#  * Redistributions of source code must retain the above copyright +#    notice, this list of conditions and the following disclaimer. +# +#  * Redistributions in binary form must reproduce the above +#    copyright notice, this list of conditions and the following +#    disclaimer in the documentation and/or other materials provided +#    with the distribution. +# +#  * Neither the name of the FIZSH nor the names of its contributors +#    may be used to endorse or promote products derived from this +#    software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################## + +#----------------------------------------------------------------------------- +# configuration variables +#----------------------------------------------------------------------------- + +HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND='bg=magenta,fg=white,bold' +HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold' +HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i' + +#----------------------------------------------------------------------------- +# the main ZLE widgets +#----------------------------------------------------------------------------- + +function history-substring-search-up() { +  _history-substring-search-begin + +  _history-substring-search-up-history || +  _history-substring-search-up-buffer || +  _history-substring-search-up-search + +  _history-substring-search-end +} + +function history-substring-search-down() { +  _history-substring-search-begin + +  _history-substring-search-down-history || +  _history-substring-search-down-buffer || +  _history-substring-search-down-search + +  _history-substring-search-end +} + +zle -N history-substring-search-up +zle -N history-substring-search-down + +bindkey '\e[A' history-substring-search-up +bindkey '\e[B' history-substring-search-down + +#----------------------------------------------------------------------------- +# implementation details +#----------------------------------------------------------------------------- + +setopt extendedglob +zmodload -F zsh/parameter + +# +# We have to "override" some keys and widgets if the +# zsh-syntax-highlighting plugin has not been loaded: +# +# https://github.com/nicoulaj/zsh-syntax-highlighting +# +if [[ $+functions[_zsh_highlight] -eq 0 ]]; then +  # +  # Dummy implementation of _zsh_highlight() +  # that simply removes existing highlights +  # +  function _zsh_highlight() { +    region_highlight=() +  } + +  # +  # Remove existing highlights when the user +  # inserts printable characters into $BUFFER +  # +  function ordinary-key-press() { +    if [[ $KEYS == [[:print:]] ]]; then +      region_highlight=() +    fi +    zle .self-insert +  } +  zle -N self-insert ordinary-key-press + +  # +  # Override ZLE widgets to invoke _zsh_highlight() +  # +  # https://github.com/nicoulaj/zsh-syntax-highlighting/blob/ +  # bb7fcb79fad797a40077bebaf6f4e4a93c9d8163/zsh-syntax-highlighting.zsh#L121 +  # +  #--------------8<-------------------8<-------------------8<----------------- +  # +  # Copyright (c) 2010-2011 zsh-syntax-highlighting contributors +  # All rights reserved. +  # +  # Redistribution and use in source and binary forms, with or without +  # modification, are permitted provided that the following conditions are +  # met: +  # +  #  * Redistributions of source code must retain the above copyright +  #    notice, this list of conditions and the following disclaimer. +  # +  #  * Redistributions in binary form must reproduce the above copyright +  #    notice, this list of conditions and the following disclaimer in the +  #    documentation and/or other materials provided with the distribution. +  # +  #  * Neither the name of the zsh-syntax-highlighting contributors nor the +  #    names of its contributors may be used to endorse or promote products +  #    derived from this software without specific prior written permission. +  # +  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +  # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +  # Load ZSH module zsh/zleparameter, needed to override user defined widgets. +  zmodload zsh/zleparameter 2>/dev/null || { +    echo 'zsh-syntax-highlighting: failed loading zsh/zleparameter, exiting.' >&2 +    return -1 +  } + +  # Override ZLE widgets to make them invoke _zsh_highlight. +  for event in ${${(f)"$(zle -la)"}:#(_*|orig-*|.run-help|.which-command)}; do +    if [[ "$widgets[$event]" == completion:* ]]; then +      eval "zle -C orig-$event ${${${widgets[$event]}#*:}/:/ } ; $event() { builtin zle orig-$event && _zsh_highlight } ; zle -N $event" +    else +      case $event in +        accept-and-menu-complete) +          eval "$event() { builtin zle .$event && _zsh_highlight } ; zle -N $event" +          ;; + +        # The following widgets should NOT remove any previously +        # applied highlighting. Therefore we do not remap them. +        .forward-char|.backward-char|.up-line-or-history|.down-line-or-history) +          ;; + +        .*) +          clean_event=$event[2,${#event}] # Remove the leading dot in the event name +          case ${widgets[$clean_event]-} in +            (completion|user):*) +              ;; +            *) +              eval "$clean_event() { builtin zle $event && _zsh_highlight } ; zle -N $clean_event" +              ;; +          esac +          ;; +        *) +          ;; +      esac +    fi +  done +  unset event clean_event +  #-------------->8------------------->8------------------->8----------------- +fi + +function _history-substring-search-begin() { +  _history_substring_search_move_cursor_eol=false +  _history_substring_search_query_highlight= + +  # +  # Continue using the previous $_history_substring_search_result by default, +  # unless the current query was cleared or a new/different query was entered. +  # +  if [[ -z $BUFFER || $BUFFER != $_history_substring_search_result ]]; then +    # +    # For the purpose of highlighting we will also keep +    # a version without doubly-escaped meta characters. +    # +    _history_substring_search_query=$BUFFER + +    # +    # $BUFFER contains the text that is in the command-line currently. +    # we put an extra "\\" before meta characters such as "\(" and "\)", +    # so that they become "\\\(" and "\\\)". +    # +    _history_substring_search_query_escaped=${BUFFER//(#m)[\][()|\\*?#<>~^]/\\$MATCH} + +    # +    # Find all occurrences of the search query in the history file. +    # +    # (k) turns it an array of line numbers. +    # +    # (on) seems to remove duplicates, which are default +    #      options. They can be turned off by (ON). +    # +    _history_substring_search_matches=(${(kon)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)*${_history_substring_search_query_escaped}*]}) + +    # +    # Define the range of values that $_history_substring_search_match_index +    # can take: [0, $_history_substring_search_matches_count_plus]. +    # +    _history_substring_search_matches_count=$#_history_substring_search_matches +    _history_substring_search_matches_count_plus=$(( _history_substring_search_matches_count + 1 )) +    _history_substring_search_matches_count_sans=$(( _history_substring_search_matches_count - 1 )) + +    # +    # If $_history_substring_search_match_index is equal to +    # $_history_substring_search_matches_count_plus, this indicates that we +    # are beyond the beginning of $_history_substring_search_matches. +    # +    # If $_history_substring_search_match_index is equal to 0, this indicates +    # that we are beyond the end of $_history_substring_search_matches. +    # +    # If we have initially pressed "up" we have to initialize +    # $_history_substring_search_match_index to +    # $_history_substring_search_matches_count_plus so that it will be +    # decreased to $_history_substring_search_matches_count. +    # +    # If we have initially pressed "down" we have to initialize +    # $_history_substring_search_match_index to +    # $_history_substring_search_matches_count so that it will be increased to +    # $_history_substring_search_matches_count_plus. +    # +    if [[ $WIDGET == history-substring-search-down ]]; then +       _history_substring_search_match_index=$_history_substring_search_matches_count +    else +      _history_substring_search_match_index=$_history_substring_search_matches_count_plus +    fi +  fi +} + +function _history-substring-search-end() { +  _history_substring_search_result=$BUFFER + +  # move the cursor to the end of the command line +  if [[ $_history_substring_search_move_cursor_eol == true ]]; then +    CURSOR=${#BUFFER} +  fi + +  # highlight command line using zsh-syntax-highlighting +  _zsh_highlight + +  # highlight the search query inside the command line +  if [[ -n $_history_substring_search_query_highlight && -n $_history_substring_search_query ]]; then +    # +    # The following expression yields a variable $MBEGIN, which +    # indicates the begin position + 1 of the first occurrence +    # of _history_substring_search_query_escaped in $BUFFER. +    # +    : ${(S)BUFFER##(#m$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)($_history_substring_search_query##)} +    local begin=$(( MBEGIN - 1 )) +    local end=$(( begin + $#_history_substring_search_query )) +    region_highlight+=("$begin $end $_history_substring_search_query_highlight") +  fi + +  # For debugging purposes: +  # zle -R "mn: "$_history_substring_search_match_index" m#: "${#_history_substring_search_matches} +  # read -k -t 200 && zle -U $REPLY + +  # Exit successfully from the history-substring-search-* widgets. +  true +} + +function _history-substring-search-up-buffer() { +  # +  # Check if the UP arrow was pressed to move the cursor within a multi-line +  # buffer. This amounts to three tests: +  # +  # 1. $#buflines -gt 1. +  # +  # 2. $CURSOR -ne $#BUFFER. +  # +  # 3. Check if we are on the first line of the current multi-line buffer. +  #    If so, pressing UP would amount to leaving the multi-line buffer. +  # +  #    We check this by adding an extra "x" to $LBUFFER, which makes +  #    sure that xlbuflines is always equal to the number of lines +  #    until $CURSOR (including the line with the cursor on it). +  # +  local buflines XLBUFFER xlbuflines +  buflines=(${(f)BUFFER}) +  XLBUFFER=$LBUFFER"x" +  xlbuflines=(${(f)XLBUFFER}) + +  if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xlbuflines -ne 1 ]]; then +    zle up-line-or-history +    return true +  fi + +  false +} + +function _history-substring-search-down-buffer() { +  # +  # Check if the DOWN arrow was pressed to move the cursor within a multi-line +  # buffer. This amounts to three tests: +  # +  # 1. $#buflines -gt 1. +  # +  # 2. $CURSOR -ne $#BUFFER. +  # +  # 3. Check if we are on the last line of the current multi-line buffer. +  #    If so, pressing DOWN would amount to leaving the multi-line buffer. +  # +  #    We check this by adding an extra "x" to $RBUFFER, which makes +  #    sure that xrbuflines is always equal to the number of lines +  #    from $CURSOR (including the line with the cursor on it). +  # +  local buflines XRBUFFER xrbuflines +  buflines=(${(f)BUFFER}) +  XRBUFFER="x"$RBUFFER +  xrbuflines=(${(f)XRBUFFER}) + +  if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xrbuflines -ne 1 ]]; then +    zle down-line-or-history +    return true +  fi + +  false +} + +function _history-substring-search-up-history() { +  # +  # Behave like up in ZSH, except clear the $BUFFER +  # when beginning of history is reached like in Fish. +  # +  if [[ -z $_history_substring_search_query ]]; then + +    # we have reached the absolute top of history +    if [[ $HISTNO -eq 1 ]]; then +      BUFFER= + +    # going up from somewhere below the top of history +    else +      zle up-history +    fi + +    return true +  fi + +  false +} + +function _history-substring-search-down-history() { +  # +  # Behave like down-history in ZSH, except clear the +  # $BUFFER when end of history is reached like in Fish. +  # +  if [[ -z $_history_substring_search_query ]]; then + +    # going down from the absolute top of history +    if [[ $HISTNO -eq 1 && -z $BUFFER ]]; then +      BUFFER=${history[1]} +      _history_substring_search_move_cursor_eol=true + +    # going down from somewhere above the bottom of history +    else +      zle down-history +    fi + +    return true +  fi + +  false +} + +function _history-substring-search-up-search() { +  _history_substring_search_move_cursor_eol=true + +  # +  # Highlight matches during history-substring-up-search: +  # +  # The following constants have been initialized in +  # _history-substring-search-up/down-search(): +  # +  # $_history_substring_search_matches is the current list of matches +  # $_history_substring_search_matches_count is the current number of matches +  # $_history_substring_search_matches_count_plus is the current number of matches + 1 +  # $_history_substring_search_matches_count_sans is the current number of matches - 1 +  # $_history_substring_search_match_index is the index of the current match +  # +  # The range of values that $_history_substring_search_match_index can take +  # is: [0, $_history_substring_search_matches_count_plus].  A value of 0 +  # indicates that we are beyond the end of +  # $_history_substring_search_matches. A value of +  # $_history_substring_search_matches_count_plus indicates that we are beyond +  # the beginning of $_history_substring_search_matches. +  # +  # In _history-substring-search-up-search() the initial value of +  # $_history_substring_search_match_index is +  # $_history_substring_search_matches_count_plus.  This value is set in +  # _history-substring-search-begin().  _history-substring-search-up-search() +  # will initially decrease it to $_history_substring_search_matches_count. +  # +  if [[ $_history_substring_search_match_index -ge 2 ]]; then +    # +    # Highlight the next match: +    # +    # 1. Decrease the value of $_history_substring_search_match_index. +    # +    # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +    #    to highlight the current buffer. +    # +    (( _history_substring_search_match_index-- )) +    BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]] +    _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND + +  elif [[ $_history_substring_search_match_index -eq 1 ]]; then +    # +    # We will move beyond the end of $_history_substring_search_matches: +    # +    # 1. Decrease the value of $_history_substring_search_match_index. +    # +    # 2. Save the current buffer in $_history_substring_search_old_buffer, +    #    so that it can be retrieved by +    #    _history-substring-search-down-search() later. +    # +    # 3. Make $BUFFER equal to $_history_substring_search_query. +    # +    # 4. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND +    #    to highlight the current buffer. +    # +    (( _history_substring_search_match_index-- )) +    _history_substring_search_old_buffer=$BUFFER +    BUFFER=$_history_substring_search_query +    _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND + +  elif [[ $_history_substring_search_match_index -eq $_history_substring_search_matches_count_plus ]]; then +    # +    # We were beyond the beginning of $_history_substring_search_matches but +    # UP makes us move back to $_history_substring_search_matches: +    # +    # 1. Decrease the value of $_history_substring_search_match_index. +    # +    # 2. Restore $BUFFER from $_history_substring_search_old_buffer. +    # +    # 3. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +    #    to highlight the current buffer. +    # +    (( _history_substring_search_match_index-- )) +    BUFFER=$_history_substring_search_old_buffer +    _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +  fi +} + +function _history-substring-search-down-search() { +  _history_substring_search_move_cursor_eol=true + +  # +  # Highlight matches during history-substring-up-search: +  # +  # The following constants have been initialized in +  # _history-substring-search-up/down-search(): +  # +  # $_history_substring_search_matches is the current list of matches +  # $_history_substring_search_matches_count is the current number of matches +  # $_history_substring_search_matches_count_plus is the current number of matches + 1 +  # $_history_substring_search_matches_count_sans is the current number of matches - 1 +  # $_history_substring_search_match_index is the index of the current match +  # +  # The range of values that $_history_substring_search_match_index can take +  # is: [0, $_history_substring_search_matches_count_plus].  A value of 0 +  # indicates that we are beyond the end of +  # $_history_substring_search_matches. A value of +  # $_history_substring_search_matches_count_plus indicates that we are beyond +  # the beginning of $_history_substring_search_matches. +  # +  # In _history-substring-search-down-search() the initial value of +  # $_history_substring_search_match_index is +  # $_history_substring_search_matches_count.  This value is set in +  # _history-substring-search-begin(). +  # _history-substring-search-down-search() will initially increase it to +  # $_history_substring_search_matches_count_plus. +  # +  if [[ $_history_substring_search_match_index -le $_history_substring_search_matches_count_sans ]]; then +    # +    # Highlight the next match: +    # +    # 1. Increase $_history_substring_search_match_index by 1. +    # +    # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +    #    to highlight the current buffer. +    # +    (( _history_substring_search_match_index++ )) +    BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]] +    _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND + +  elif [[ $_history_substring_search_match_index -eq $_history_substring_search_matches_count ]]; then +    # +    # We will move beyond the beginning of $_history_substring_search_matches: +    # +    # 1. Increase $_history_substring_search_match_index by 1. +    # +    # 2. Save the current buffer in $_history_substring_search_old_buffer, so +    #    that it can be retrieved by _history-substring-search-up-search() +    #    later. +    # +    # 3. Make $BUFFER equal to $_history_substring_search_query. +    # +    # 4. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND +    #    to highlight the current buffer. +    # +    (( _history_substring_search_match_index++ )) +    _history_substring_search_old_buffer=$BUFFER +    BUFFER=$_history_substring_search_query +    _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND + +  elif [[ $_history_substring_search_match_index -eq 0 ]]; then +    # +    # We were beyond the end of $_history_substring_search_matches but DOWN +    # makes us move back to the $_history_substring_search_matches: +    # +    # 1. Increase $_history_substring_search_match_index by 1. +    # +    # 2. Restore $BUFFER from $_history_substring_search_old_buffer. +    # +    # 3. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +    #    to highlight the current buffer. +    # +    (( _history_substring_search_match_index++ )) +    BUFFER=$_history_substring_search_old_buffer +    _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND +  fi +} + +# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- +# vim: ft=zsh sw=2 ts=2 et | 
