| 
									
										
										
										
											2011-07-14 21:41:26 -07:00
										 |  |  | #!/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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 14:06:58 +01:00
										 |  |  | zmodload zsh/terminfo | 
					
						
							| 
									
										
										
										
											2014-03-24 22:32:56 +01:00
										 |  |  | if [[ -n "$terminfo[kcuu1]" ]]; then | 
					
						
							|  |  |  |   bindkey "$terminfo[kcuu1]" history-substring-search-up | 
					
						
							|  |  |  | fi | 
					
						
							|  |  |  | if [[ -n "$terminfo[kcud1]" ]]; then | 
					
						
							|  |  |  |   bindkey "$terminfo[kcud1]" history-substring-search-down | 
					
						
							|  |  |  | fi | 
					
						
							| 
									
										
										
										
											2011-07-14 21:41:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #----------------------------------------------------------------------------- | 
					
						
							|  |  |  | # 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 |