Add zsh-autosuggestion
authorJoerg Jaspert <joerg@debian.org>
Thu, 3 Nov 2016 16:31:28 +0000 (17:31 +0100)
committerJoerg Jaspert <joerg@debian.org>
Thu, 3 Nov 2016 16:31:45 +0000 (17:31 +0100)
36 files changed:
.zsh/70_Plugins.zsh
.zsh/external/zsh-autosuggestions/.editorconfig [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/.gitmodules [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/CHANGELOG.md [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/DESCRIPTION [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/LICENSE [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/Makefile [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/README.md [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/URL [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/VERSION [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/script/test_runner.zsh [new file with mode: 0755]
.zsh/external/zsh-autosuggestions/src/bind.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/config.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/deprecated.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/highlight.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/start.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/strategies/default.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/strategies/match_prev_cmd.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/suggestion.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/src/widgets.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/bind_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/highlight_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/strategies/default_test.zsh [new file with mode: 0755]
.zsh/external/zsh-autosuggestions/test/strategies/match_prev_cmd_test.zsh [new file with mode: 0755]
.zsh/external/zsh-autosuggestions/test/strategies_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/suggestion_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/test_helper.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/widgets/accept_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/widgets/clear_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/widgets/execute_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/widgets/modify_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/test/widgets/partial_accept_test.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh [new file with mode: 0644]
.zsh/external/zsh-autosuggestions/zsh-autosuggestions.zsh [new file with mode: 0644]
.zsh/plugins/zsh-autosuggestions.zsh [new symlink]
.zsh/zshenv.local.sample

index 72a03f6..8586c19 100644 (file)
@@ -29,6 +29,7 @@ __ () {
             history-substring-search.zsh
             per-directory-history.plugin.zsh
             zaw.zsh
+            zsh-autosuggestions.zsh
         )
         for file in $plugins; do
             debug "PLUGIN: Trying to load ${file}"...
diff --git a/.zsh/external/zsh-autosuggestions/.editorconfig b/.zsh/external/zsh-autosuggestions/.editorconfig
new file mode 100644 (file)
index 0000000..51c4765
--- /dev/null
@@ -0,0 +1,10 @@
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = tab
+indent_size = 4
+
+[*.md]
+indent_style = space
diff --git a/.zsh/external/zsh-autosuggestions/.gitmodules b/.zsh/external/zsh-autosuggestions/.gitmodules
new file mode 100644 (file)
index 0000000..b45eb46
--- /dev/null
@@ -0,0 +1,6 @@
+[submodule "vendor/shunit2"]
+       path = vendor/shunit2
+       url = https://github.com/kward/shunit2
+[submodule "vendor/stub.sh"]
+       path = vendor/stub.sh
+       url = https://github.com/ericfreese/stub.sh
diff --git a/.zsh/external/zsh-autosuggestions/CHANGELOG.md b/.zsh/external/zsh-autosuggestions/CHANGELOG.md
new file mode 100644 (file)
index 0000000..50a1e0a
--- /dev/null
@@ -0,0 +1,36 @@
+# Changelog
+
+## v0.3.3
+- Switch from $history array to fc builtin for better performance with large HISTFILEs (#164)
+- Fix tilde handling when extended_glob is set (#168)
+- Add config option for maximum buffer length to fetch suggestions for (#178)
+- Add config option for list of widgets to ignore (#184)
+- Don't fetch a new suggestion unless a modification widget actually modifies the buffer (#183)
+
+## v0.3.2
+- Test runner now supports running specific tests and choosing zsh binary
+- Return code from original widget is now correctly passed through (#135)
+- Add `vi-add-eol` to list of accept widgets (#143)
+- Escapes widget names within evals to fix problems with irregular widget names (#152)
+- Plugin now clears suggestion while within a completion menu (#149)
+- .plugin file no longer relies on symbolic link support, fixing issues on Windows (#156)
+
+## v0.3.1
+
+- Fixes issue with `vi-next-char` not accepting suggestion (#137).
+- Fixes global variable warning when WARN_CREATE_GLOBAL option enabled (#133).
+- Split out a separate test file for each widget.
+
+## v0.3.0
+
+- Adds `autosuggest-execute` widget (PR #124).
+- Adds concept of suggestion "strategies" for different ways of fetching suggestions.
+- Adds "match_prev_cmd" strategy (PR #131).
+- Uses git submodules for testing dependencies.
+- Lots of test cleanup.
+- Various bug fixes for zsh 5.0.x and `sh_word_split` option.
+
+
+## v0.2.17
+
+Start of changelog.
diff --git a/.zsh/external/zsh-autosuggestions/DESCRIPTION b/.zsh/external/zsh-autosuggestions/DESCRIPTION
new file mode 100644 (file)
index 0000000..b69200f
--- /dev/null
@@ -0,0 +1 @@
+Fish-like fast/unobtrusive autosuggestions for zsh.
diff --git a/.zsh/external/zsh-autosuggestions/LICENSE b/.zsh/external/zsh-autosuggestions/LICENSE
new file mode 100644 (file)
index 0000000..ee52ee2
--- /dev/null
@@ -0,0 +1,23 @@
+Copyright (c) 2013 Thiago de Arruda
+Copyright (c) 2016 Eric Freese
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/.zsh/external/zsh-autosuggestions/Makefile b/.zsh/external/zsh-autosuggestions/Makefile
new file mode 100644 (file)
index 0000000..fde3691
--- /dev/null
@@ -0,0 +1,47 @@
+SRC_DIR    := ./src
+VENDOR_DIR := ./vendor
+
+SRC_FILES := \
+       $(SRC_DIR)/config.zsh \
+       $(SRC_DIR)/deprecated.zsh \
+       $(SRC_DIR)/bind.zsh \
+       $(SRC_DIR)/highlight.zsh \
+       $(SRC_DIR)/widgets.zsh \
+       $(SRC_DIR)/suggestion.zsh \
+       $(SRC_DIR)/strategies/*.zsh \
+       $(SRC_DIR)/start.zsh
+
+HEADER_FILES := \
+       DESCRIPTION \
+       URL \
+       VERSION \
+       LICENSE
+
+PLUGIN_TARGET := zsh-autosuggestions.zsh
+
+SHUNIT2 := $(VENDOR_DIR)/shunit2/2.1.6
+STUB_SH := $(VENDOR_DIR)/stub.sh/stub.sh
+
+TEST_PREREQS := \
+       $(SHUNIT2) \
+       $(STUB_SH)
+
+all: $(PLUGIN_TARGET)
+
+$(PLUGIN_TARGET): $(HEADER_FILES) $(SRC_FILES)
+       cat $(HEADER_FILES) | sed -e 's/^/# /g' > $@
+       cat $(SRC_FILES) >> $@
+
+$(SHUNIT2):
+       git submodule update --init vendor/shunit2
+
+$(STUB_SH):
+       git submodule update --init vendor/stub.sh
+
+.PHONY: clean
+clean:
+       rm $(PLUGIN_TARGET)
+
+.PHONY: test
+test: all $(TEST_PREREQS)
+       script/test_runner.zsh $(TESTS)
diff --git a/.zsh/external/zsh-autosuggestions/README.md b/.zsh/external/zsh-autosuggestions/README.md
new file mode 100644 (file)
index 0000000..3a5c3f3
--- /dev/null
@@ -0,0 +1,165 @@
+# zsh-autosuggestions
+
+_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
+
+It suggests commands as you type, based on command history.
+
+<a href="https://asciinema.org/a/37390" target="_blank"><img src="https://asciinema.org/a/37390.png" width="400" /></a>
+
+
+## Installation
+
+### Manual
+
+1. Clone this repository somewhere on your machine. This guide will assume `~/.zsh/zsh-autosuggestions`.
+
+    ```sh
+    git clone git://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
+    ```
+
+2. Add the following to your `.zshrc`:
+
+    ```sh
+    source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
+    ```
+
+3. Start a new terminal session.
+
+
+### Oh My Zsh
+
+1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`)
+
+    ```sh
+    git clone git://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
+    ```
+
+2. Add the plugin to the list of plugins for Oh My Zsh to load:
+
+    ```sh
+    plugins=(zsh-autosuggestions)
+    ```
+
+3. Start a new terminal session.
+
+
+## Usage
+
+As you type commands, you will see a completion offered after the cursor in a muted gray color. This color can be changed by setting the `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` variable. See [configuration](#configuration).
+
+If you press the <kbd>→</kbd> key (`forward-char` widget) or <kbd>End</kbd> (`end-of-line` widget) with the cursor at the end of the buffer, it will accept the suggestion, replacing the contents of the command line buffer with the suggestion.
+
+If you invoke the `forward-word` widget, it will partially accept the suggestion up to the point that the cursor moves to.
+
+
+## Configuration
+
+You may want to override the default global config variables after sourcing the plugin. Default values of these variables can be found [here](src/config.zsh).
+
+**Note:** If you are using Oh My Zsh, you can put this configuration in a file in the `$ZSH_CUSTOM` directory. See their comments on [overriding internals](https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals).
+
+
+### Suggestion Highlight Style
+
+Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion is shown with. The default is `fg=8`.
+
+
+### Suggestion Strategy
+
+Set `ZSH_AUTOSUGGEST_STRATEGY` to choose the strategy for generating suggestions. There are currently two to choose from:
+
+- `default`: Chooses the most recent match.
+- `match_prev_cmd`: Chooses the most recent match whose preceding history item matches the most recently executed command ([more info](src/strategies/match_prev_cmd.zsh)). Note that this strategy won't work as expected with ZSH options that don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`.
+
+
+### Widget Mapping
+
+This plugin works by triggering custom behavior when certain [zle widgets](http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets) are invoked. You can add and remove widgets from these arrays to change the behavior of this plugin:
+
+- `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: Widgets in this array will clear the suggestion when invoked.
+- `ZSH_AUTOSUGGEST_ACCEPT_WIDGETS`: Widgets in this array will accept the suggestion when invoked.
+- `ZSH_AUTOSUGGEST_EXECUTE_WIDGETS`: Widgets in this array will execute the suggestion when invoked.
+- `ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS`: Widgets in this array will partially accept the suggestion when invoked.
+- `ZSH_AUTOSUGGEST_IGNORE_WIDGETS`: Widgets in this array will not trigger any custom behavior.
+
+Widgets that modify the buffer and are not found in any of these arrays will fetch a new suggestion after they are invoked.
+
+**Note:** A widget shouldn't belong to more than one of the above arrays.
+
+
+### Disabling suggestion for large buffers
+
+Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20.
+This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for too long strings.
+
+
+### Key Bindings
+
+This plugin provides three widgets that you can use with `bindkey`:
+
+1. `autosuggest-accept`: Accepts the current suggestion.
+2. `autosuggest-execute`: Accepts and executes the current suggestion.
+3. `autosuggest-clear`: Clears the current suggestion.
+
+For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion.
+
+```sh
+bindkey '^ ' autosuggest-accept
+```
+
+
+## Troubleshooting
+
+If you have a problem, please search through [the list of issues on GitHub](https://github.com/zsh-users/zsh-autosuggestions/issues) to see if someone else has already reported it.
+
+
+### Reporting an Issue
+
+Before reporting an issue, please try temporarily disabling sections of your configuration and other plugins that may be conflicting with this plugin to isolate the problem.
+
+When reporting an issue, please include:
+
+- The smallest, simplest `.zshrc` configuration that will reproduce the problem. See [this comment](https://github.com/zsh-users/zsh-autosuggestions/issues/102#issuecomment-180944764) for a good example of what this means.
+- The version of zsh you're using (`zsh --version`)
+- Which operating system you're running
+
+
+## Uninstallation
+
+1. Remove the code referencing this plugin from `~/.zshrc`.
+
+2. Remove the git repository from your hard drive
+
+    ```sh
+    rm -rf ~/.zsh/zsh-autosuggestions # Or wherever you installed
+    ```
+
+
+## Development
+
+### Build Process
+
+Edit the source files in `src/`. Run `make` to build `zsh-autosuggestions.zsh` from those source files.
+
+
+### Pull Requests
+
+Pull requests are welcome! If you send a pull request, please:
+
+- Request to merge into the `develop` branch (*NOT* `master`)
+- Match the existing coding conventions.
+- Include helpful comments to keep the barrier-to-entry low for people new to the project.
+- Write tests that cover your code as much as possible.
+
+
+### Testing
+
+Testing is performed with [`shunit2`](https://github.com/kward/shunit2) (v2.1.6). Documentation can be found [here](http://shunit2.googlecode.com/svn/trunk/source/2.1/doc/shunit2.html).
+
+The test script lives at `script/test_runner.zsh`. To run the tests, run `make test`.
+
+
+## License
+
+This project is licensed under [MIT license](http://opensource.org/licenses/MIT).
+For the full text of the license, see the [LICENSE](LICENSE) file.
diff --git a/.zsh/external/zsh-autosuggestions/URL b/.zsh/external/zsh-autosuggestions/URL
new file mode 100644 (file)
index 0000000..4e2bd94
--- /dev/null
@@ -0,0 +1 @@
+https://github.com/zsh-users/zsh-autosuggestions
diff --git a/.zsh/external/zsh-autosuggestions/VERSION b/.zsh/external/zsh-autosuggestions/VERSION
new file mode 100644 (file)
index 0000000..600e6fd
--- /dev/null
@@ -0,0 +1 @@
+v0.3.3
diff --git a/.zsh/external/zsh-autosuggestions/script/test_runner.zsh b/.zsh/external/zsh-autosuggestions/script/test_runner.zsh
new file mode 100755 (executable)
index 0000000..0ff4173
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/env zsh
+
+DIR="${0:a:h}"
+ROOT_DIR="$DIR/.."
+TEST_DIR="$ROOT_DIR/test"
+
+header() {
+       local message="$1"
+
+       cat <<-EOF
+
+#====================================================================#
+# $message
+#====================================================================#
+       EOF
+}
+
+# ZSH binary to use
+local zsh_bin="zsh"
+
+while getopts ":z:" opt; do
+       case $opt in
+               z)
+                       zsh_bin="$OPTARG"
+                       ;;
+               \?)
+                       echo "Invalid option: -$OPTARG" >&2
+                       exit 1
+                       ;;
+               :)
+                       echo "Option -$OPTARG requires an argument" >&2
+                       exit 1
+                       ;;
+       esac
+done
+
+shift $((OPTIND -1))
+
+# Test suites to run
+local -a tests
+if [ $#@ -gt 0 ]; then
+       tests=($@)
+else
+       tests=($TEST_DIR/**/*_test.zsh)
+fi
+
+local -i retval=0
+
+for suite in $tests; do
+       header "${suite#"$ROOT_DIR/"}"
+       "$zsh_bin" -f "$suite" || retval=$?
+done
+
+exit $retval
diff --git a/.zsh/external/zsh-autosuggestions/src/bind.zsh b/.zsh/external/zsh-autosuggestions/src/bind.zsh
new file mode 100644 (file)
index 0000000..49763e8
--- /dev/null
@@ -0,0 +1,91 @@
+
+#--------------------------------------------------------------------#
+# Widget Helpers                                                     #
+#--------------------------------------------------------------------#
+
+# Bind a single widget to an autosuggest widget, saving a reference to the original widget
+_zsh_autosuggest_bind_widget() {
+       local widget=$1
+       local autosuggest_action=$2
+       local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
+
+       # Save a reference to the original widget
+       case $widgets[$widget] in
+               # Already bound
+               user:_zsh_autosuggest_(bound|orig)_*);;
+
+               # User-defined widget
+               user:*)
+                       zle -N $prefix$widget ${widgets[$widget]#*:}
+                       ;;
+
+               # Built-in widget
+               builtin)
+                       eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
+                       zle -N $prefix$widget _zsh_autosuggest_orig_$widget
+                       ;;
+
+               # Completion widget
+               completion:*)
+                       eval "zle -C $prefix${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
+                       ;;
+       esac
+
+       # Pass the original widget's name explicitly into the autosuggest
+       # function. Use this passed in widget name to call the original
+       # widget instead of relying on the $WIDGET variable being set
+       # correctly. $WIDGET cannot be trusted because other plugins call
+       # zle without the `-w` flag (e.g. `zle self-insert` instead of
+       # `zle self-insert -w`).
+       eval "_zsh_autosuggest_bound_${(q)widget}() {
+               _zsh_autosuggest_widget_$autosuggest_action $prefix${(q)widget} \$@
+       }"
+
+       # Create the bound widget
+       zle -N $widget _zsh_autosuggest_bound_$widget
+}
+
+# Map all configured widgets to the right autosuggest widgets
+_zsh_autosuggest_bind_widgets() {
+       local widget
+       local ignore_widgets
+
+       ignore_widgets=(
+               .\*
+               _\*
+               zle-line-\*
+               autosuggest-\*
+               $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
+               $ZSH_AUTOSUGGEST_IGNORE_WIDGETS
+       )
+
+       # Find every widget we might want to bind and bind it appropriately
+       for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
+               if [ ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget clear
+               elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget accept
+               elif [ ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget execute
+               elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget partial_accept
+               else
+                       # Assume any unspecified widget might modify the buffer
+                       _zsh_autosuggest_bind_widget $widget modify
+               fi
+       done
+}
+
+# Given the name of an original widget and args, invoke it, if it exists
+_zsh_autosuggest_invoke_original_widget() {
+       # Do nothing unless called with at least one arg
+       [ $# -gt 0 ] || return
+
+       local original_widget_name="$1"
+
+       shift
+
+       if [ $widgets[$original_widget_name] ]; then
+               zle $original_widget_name -- $@
+       fi
+}
diff --git a/.zsh/external/zsh-autosuggestions/src/config.zsh b/.zsh/external/zsh-autosuggestions/src/config.zsh
new file mode 100644 (file)
index 0000000..f519f6f
--- /dev/null
@@ -0,0 +1,62 @@
+
+#--------------------------------------------------------------------#
+# Global Configuration Variables                                     #
+#--------------------------------------------------------------------#
+
+# Color to use when highlighting suggestion
+# Uses format of `region_highlight`
+# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
+
+# Prefix to use when saving original versions of bound widgets
+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
+
+ZSH_AUTOSUGGEST_STRATEGY=default
+
+# Widgets that clear the suggestion
+ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
+       history-search-forward
+       history-search-backward
+       history-beginning-search-forward
+       history-beginning-search-backward
+       history-substring-search-up
+       history-substring-search-down
+       up-line-or-history
+       down-line-or-history
+       accept-line
+)
+
+# Widgets that accept the entire suggestion
+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
+       forward-char
+       end-of-line
+       vi-forward-char
+       vi-end-of-line
+       vi-add-eol
+)
+
+# Widgets that accept the entire suggestion and execute it
+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
+)
+
+# Widgets that accept the suggestion as far as the cursor moves
+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
+       forward-word
+       vi-forward-word
+       vi-forward-word-end
+       vi-forward-blank-word
+       vi-forward-blank-word-end
+)
+
+# Widgets that should be ignored (globbing supported but must be escaped)
+ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
+       orig-\*
+       beep
+       run-help
+       set-local-history
+       which-command
+       yank
+)
+
+# Max size of buffer to trigger autosuggestion. Leave undefined for no upper bound.
+ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=
diff --git a/.zsh/external/zsh-autosuggestions/src/deprecated.zsh b/.zsh/external/zsh-autosuggestions/src/deprecated.zsh
new file mode 100644 (file)
index 0000000..bcf0d74
--- /dev/null
@@ -0,0 +1,36 @@
+
+#--------------------------------------------------------------------#
+# Handle Deprecated Variables/Widgets                                #
+#--------------------------------------------------------------------#
+
+_zsh_autosuggest_deprecated_warning() {
+       >&2 echo "zsh-autosuggestions: $@"
+}
+
+_zsh_autosuggest_check_deprecated_config() {
+       if [ -n "$AUTOSUGGESTION_HIGHLIGHT_COLOR" ]; then
+               _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_COLOR is deprecated. Use ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE instead."
+               [ -z "$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" ] && ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=$AUTOSUGGESTION_HIGHLIGHT_STYLE
+               unset AUTOSUGGESTION_HIGHLIGHT_STYLE
+       fi
+
+       if [ -n "$AUTOSUGGESTION_HIGHLIGHT_CURSOR" ]; then
+               _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_CURSOR is deprecated."
+               unset AUTOSUGGESTION_HIGHLIGHT_CURSOR
+       fi
+
+       if [ -n "$AUTOSUGGESTION_ACCEPT_RIGHT_ARROW" ]; then
+               _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_ACCEPT_RIGHT_ARROW is deprecated. The right arrow now accepts the suggestion by default."
+               unset AUTOSUGGESTION_ACCEPT_RIGHT_ARROW
+       fi
+}
+
+_zsh_autosuggest_deprecated_start_widget() {
+       _zsh_autosuggest_deprecated_warning "The autosuggest-start widget is deprecated. For more info, see the README at https://github.com/zsh-users/zsh-autosuggestions."
+       zle -D autosuggest-start
+       eval "zle-line-init() {
+               $(echo $functions[${widgets[zle-line-init]#*:}] | sed -e 's/zle autosuggest-start//g')
+       }"
+}
+
+zle -N autosuggest-start _zsh_autosuggest_deprecated_start_widget
diff --git a/.zsh/external/zsh-autosuggestions/src/highlight.zsh b/.zsh/external/zsh-autosuggestions/src/highlight.zsh
new file mode 100644 (file)
index 0000000..a8ff08a
--- /dev/null
@@ -0,0 +1,26 @@
+
+#--------------------------------------------------------------------#
+# Highlighting                                                       #
+#--------------------------------------------------------------------#
+
+# If there was a highlight, remove it
+_zsh_autosuggest_highlight_reset() {
+       typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+
+       if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
+               region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
+               unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+       fi
+}
+
+# If there's a suggestion, highlight it
+_zsh_autosuggest_highlight_apply() {
+       typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+
+       if [ $#POSTDISPLAY -gt 0 ]; then
+               _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
+               region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
+       else
+               unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+       fi
+}
diff --git a/.zsh/external/zsh-autosuggestions/src/start.zsh b/.zsh/external/zsh-autosuggestions/src/start.zsh
new file mode 100644 (file)
index 0000000..54f5bb8
--- /dev/null
@@ -0,0 +1,13 @@
+
+#--------------------------------------------------------------------#
+# Start                                                              #
+#--------------------------------------------------------------------#
+
+# Start the autosuggestion widgets
+_zsh_autosuggest_start() {
+       _zsh_autosuggest_check_deprecated_config
+       _zsh_autosuggest_bind_widgets
+}
+
+autoload -Uz add-zsh-hook
+add-zsh-hook precmd _zsh_autosuggest_start
diff --git a/.zsh/external/zsh-autosuggestions/src/strategies/default.zsh b/.zsh/external/zsh-autosuggestions/src/strategies/default.zsh
new file mode 100644 (file)
index 0000000..29333f5
--- /dev/null
@@ -0,0 +1,11 @@
+
+#--------------------------------------------------------------------#
+# Default Suggestion Strategy                                        #
+#--------------------------------------------------------------------#
+# Suggests the most recent history item that matches the given
+# prefix.
+#
+
+_zsh_autosuggest_strategy_default() {
+       fc -lnrm "$1*" 1 2>/dev/null | head -n 1
+}
diff --git a/.zsh/external/zsh-autosuggestions/src/strategies/match_prev_cmd.zsh b/.zsh/external/zsh-autosuggestions/src/strategies/match_prev_cmd.zsh
new file mode 100644 (file)
index 0000000..bf8bdd9
--- /dev/null
@@ -0,0 +1,52 @@
+
+#--------------------------------------------------------------------#
+# Match Previous Command Suggestion Strategy                         #
+#--------------------------------------------------------------------#
+# Suggests the most recent history item that matches the given
+# prefix and whose preceding history item also matches the most
+# recently executed command.
+#
+# For example, suppose your history has the following entries:
+#   - pwd
+#   - ls foo
+#   - ls bar
+#   - pwd
+#
+# Given the history list above, when you type 'ls', the suggestion
+# will be 'ls foo' rather than 'ls bar' because your most recently
+# executed command (pwd) was previously followed by 'ls foo'.
+#
+# Note that this strategy won't work as expected with ZSH options that don't
+# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
+# `HIST_EXPIRE_DUPS_FIRST`.
+
+_zsh_autosuggest_strategy_match_prev_cmd() {
+       local prefix="$1"
+
+       # Get all history event numbers that correspond to history
+       # entries that match pattern $prefix*
+       local history_match_keys
+       history_match_keys=(${(k)history[(R)$prefix*]})
+
+       # By default we use the first history number (most recent history entry)
+       local histkey="${history_match_keys[1]}"
+
+       # Get the previously executed command
+       local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
+
+       # Iterate up to the first 200 history event numbers that match $prefix
+       for key in "${(@)history_match_keys[1,200]}"; do
+               # Stop if we ran out of history
+               [[ $key -gt 1 ]] || break
+
+               # See if the history entry preceding the suggestion matches the
+               # previous command, and use it if it does
+               if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
+                       histkey="$key"
+                       break
+               fi
+       done
+
+       # Echo the matched history entry
+       echo -E "$history[$histkey]"
+}
diff --git a/.zsh/external/zsh-autosuggestions/src/suggestion.zsh b/.zsh/external/zsh-autosuggestions/src/suggestion.zsh
new file mode 100644 (file)
index 0000000..31a9f76
--- /dev/null
@@ -0,0 +1,21 @@
+
+#--------------------------------------------------------------------#
+# Suggestion                                                         #
+#--------------------------------------------------------------------#
+
+# Delegate to the selected strategy to determine a suggestion
+_zsh_autosuggest_suggestion() {
+       local escaped_prefix="$(_zsh_autosuggest_escape_command "$1")"
+       local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY"
+
+       if [ -n "$functions[$strategy_function]" ]; then
+               echo -E "$($strategy_function "$escaped_prefix")"
+       fi
+}
+
+_zsh_autosuggest_escape_command() {
+       setopt localoptions EXTENDED_GLOB
+
+       # Escape special chars in the string (requires EXTENDED_GLOB)
+       echo -E "${1//(#m)[\\()\[\]|*?~]/\\$MATCH}"
+}
diff --git a/.zsh/external/zsh-autosuggestions/src/widgets.zsh b/.zsh/external/zsh-autosuggestions/src/widgets.zsh
new file mode 100644 (file)
index 0000000..57f378e
--- /dev/null
@@ -0,0 +1,135 @@
+
+#--------------------------------------------------------------------#
+# Autosuggest Widget Implementations                                 #
+#--------------------------------------------------------------------#
+
+# Clear the suggestion
+_zsh_autosuggest_clear() {
+       # Remove the suggestion
+       unset POSTDISPLAY
+
+       _zsh_autosuggest_invoke_original_widget $@
+}
+
+# Modify the buffer and get a new suggestion
+_zsh_autosuggest_modify() {
+       local -i retval
+
+       # Save the contents of the buffer/postdisplay
+       local orig_buffer="$BUFFER"
+       local orig_postdisplay="$POSTDISPLAY"
+
+       # Clear suggestion while original widget runs
+       unset POSTDISPLAY
+
+       # Original widget may modify the buffer
+       _zsh_autosuggest_invoke_original_widget $@
+       retval=$?
+
+       # Don't fetch a new suggestion if the buffer hasn't changed
+       if [ "$BUFFER" = "$orig_buffer" ]; then
+               POSTDISPLAY="$orig_postdisplay"
+               return $retval
+       fi
+
+       # Get a new suggestion if the buffer is not empty after modification
+       local suggestion
+       if [ $#BUFFER -gt 0 ]; then
+               if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -lt "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then
+                       suggestion="$(_zsh_autosuggest_suggestion "$BUFFER")"
+               fi
+       fi
+
+       # Add the suggestion to the POSTDISPLAY
+       if [ -n "$suggestion" ]; then
+               POSTDISPLAY="${suggestion#$BUFFER}"
+       fi
+
+       return $retval
+}
+
+# Accept the entire suggestion
+_zsh_autosuggest_accept() {
+       local -i max_cursor_pos=$#BUFFER
+
+       # When vicmd keymap is active, the cursor can't move all the way
+       # to the end of the buffer
+       if [ "$KEYMAP" = "vicmd" ]; then
+               max_cursor_pos=$((max_cursor_pos - 1))
+       fi
+
+       # Only accept if the cursor is at the end of the buffer
+       if [ $CURSOR -eq $max_cursor_pos ]; then
+               # Add the suggestion to the buffer
+               BUFFER="$BUFFER$POSTDISPLAY"
+
+               # Remove the suggestion
+               unset POSTDISPLAY
+
+               # Move the cursor to the end of the buffer
+               CURSOR=${#BUFFER}
+       fi
+
+       _zsh_autosuggest_invoke_original_widget $@
+}
+
+# Accept the entire suggestion and execute it
+_zsh_autosuggest_execute() {
+       # Add the suggestion to the buffer
+       BUFFER="$BUFFER$POSTDISPLAY"
+
+       # Remove the suggestion
+       unset POSTDISPLAY
+
+       # Call the original `accept-line` to handle syntax highlighting or
+       # other potential custom behavior
+       _zsh_autosuggest_invoke_original_widget "accept-line"
+}
+
+# Partially accept the suggestion
+_zsh_autosuggest_partial_accept() {
+       local -i retval
+
+       # Save the contents of the buffer so we can restore later if needed
+       local original_buffer="$BUFFER"
+
+       # Temporarily accept the suggestion.
+       BUFFER="$BUFFER$POSTDISPLAY"
+
+       # Original widget moves the cursor
+       _zsh_autosuggest_invoke_original_widget $@
+       retval=$?
+
+       # If we've moved past the end of the original buffer
+       if [ $CURSOR -gt $#original_buffer ]; then
+               # Set POSTDISPLAY to text right of the cursor
+               POSTDISPLAY="$RBUFFER"
+
+               # Clip the buffer at the cursor
+               BUFFER="$LBUFFER"
+       else
+               # Restore the original buffer
+               BUFFER="$original_buffer"
+       fi
+
+       return $retval
+}
+
+for action in clear modify accept partial_accept execute; do
+       eval "_zsh_autosuggest_widget_$action() {
+               local -i retval
+
+               _zsh_autosuggest_highlight_reset
+
+               _zsh_autosuggest_$action \$@
+               retval=\$?
+
+               _zsh_autosuggest_highlight_apply
+
+               return \$retval
+       }"
+done
+
+zle -N autosuggest-accept _zsh_autosuggest_widget_accept
+zle -N autosuggest-clear _zsh_autosuggest_widget_clear
+zle -N autosuggest-execute _zsh_autosuggest_widget_execute
diff --git a/.zsh/external/zsh-autosuggestions/test/bind_test.zsh b/.zsh/external/zsh-autosuggestions/test/bind_test.zsh
new file mode 100644 (file)
index 0000000..f73ea7f
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+testInvokeOriginalWidgetDefined() {
+       stub_and_eval \
+               zle \
+               'return 1'
+
+       _zsh_autosuggest_invoke_original_widget 'self-insert'
+
+       assertEquals \
+               '1' \
+               "$?"
+
+       assertTrue \
+               'zle was not invoked' \
+               'stub_called zle'
+
+       restore zle
+}
+
+testInvokeOriginalWidgetUndefined() {
+       stub_and_eval \
+               zle \
+               'return 1'
+
+       _zsh_autosuggest_invoke_original_widget 'some-undefined-widget'
+
+       assertEquals \
+               '0' \
+               "$?"
+
+       assertFalse \
+               'zle was invoked' \
+               'stub_called zle'
+
+       restore zle
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/highlight_test.zsh b/.zsh/external/zsh-autosuggestions/test/highlight_test.zsh
new file mode 100644 (file)
index 0000000..7268af8
--- /dev/null
@@ -0,0 +1,73 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+testHighlightDefaultStyle() {
+       assertEquals \
+               'fg=8' \
+               "$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
+}
+
+testHighlightApplyWithSuggestion() {
+       local orig_style=ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE
+       ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=4'
+
+       BUFFER='ec'
+       POSTDISPLAY='ho hello'
+       region_highlight=('0 2 fg=1')
+
+       _zsh_autosuggest_highlight_apply
+
+       assertEquals \
+               'highlight did not use correct style' \
+               "0 2 fg=1 2 10 $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" \
+               "$region_highlight"
+
+       assertEquals \
+               'higlight was not saved to be removed later' \
+               "2 10 $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" \
+               "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT"
+
+       ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=orig_style
+}
+
+testHighlightApplyWithoutSuggestion() {
+       BUFFER='echo hello'
+       POSTDISPLAY=''
+       region_highlight=('0 4 fg=1')
+
+       _zsh_autosuggest_highlight_apply
+
+       assertEquals \
+               'region_highlight was modified' \
+               '0 4 fg=1' \
+               "$region_highlight"
+
+       assertNull \
+               'last highlight region was not cleared' \
+               "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT"
+}
+
+testHighlightReset() {
+       BUFFER='ec'
+       POSTDISPLAY='ho hello'
+       region_highlight=('0 1 fg=1' '2 10 fg=8' '1 2 fg=1')
+       _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT='2 10 fg=8'
+
+       _zsh_autosuggest_highlight_reset
+
+       assertEquals \
+               'last highlight region was not removed' \
+               '0 1 fg=1 1 2 fg=1' \
+               "$region_highlight"
+
+       assertNull \
+               'last highlight variable was not cleared' \
+               "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT"
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/strategies/default_test.zsh b/.zsh/external/zsh-autosuggestions/test/strategies/default_test.zsh
new file mode 100755 (executable)
index 0000000..f5200e6
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+testNoMatch() {
+       set_history <<-'EOF'
+               ls foo
+               ls bar
+       EOF
+
+       assertSuggestion \
+               'foo' \
+               ''
+
+       assertSuggestion \
+               'ls q' \
+               ''
+}
+
+testBasicMatches() {
+       set_history <<-'EOF'
+               ls foo
+               ls bar
+       EOF
+
+       assertSuggestion \
+               'ls f' \
+               'ls foo'
+
+       assertSuggestion \
+               'ls b' \
+               'ls bar'
+}
+
+testMostRecentMatch() {
+       set_history <<-'EOF'
+               ls foo
+               cd bar
+               ls baz
+               cd quux
+       EOF
+
+       assertSuggestion \
+               'ls' \
+               'ls baz'
+
+       assertSuggestion \
+               'cd' \
+               'cd quux'
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/strategies/match_prev_cmd_test.zsh b/.zsh/external/zsh-autosuggestions/test/strategies/match_prev_cmd_test.zsh
new file mode 100755 (executable)
index 0000000..bf3fc64
--- /dev/null
@@ -0,0 +1,74 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+
+       ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd
+}
+
+testNoMatch() {
+       set_history <<-'EOF'
+               ls foo
+               ls bar
+       EOF
+
+       assertSuggestion \
+               'foo' \
+               ''
+
+       assertSuggestion \
+               'ls q' \
+               ''
+}
+
+testBasicMatches() {
+       set_history <<-'EOF'
+               ls foo
+               ls bar
+       EOF
+
+       assertSuggestion \
+               'ls f' \
+               'ls foo'
+
+       assertSuggestion \
+               'ls b' \
+               'ls bar'
+}
+
+testMostRecentMatch() {
+       set_history <<-'EOF'
+               ls foo
+               cd bar
+               ls baz
+               cd quux
+       EOF
+
+       assertSuggestion \
+               'ls' \
+               'ls baz'
+
+       assertSuggestion \
+               'cd' \
+               'cd quux'
+}
+
+testMatchMostRecentAfterPreviousCmd() {
+       set_history <<-'EOF'
+               echo what
+               ls foo
+               ls bar
+               echo what
+               ls baz
+               ls quux
+               echo what
+       EOF
+
+       assertSuggestion \
+               'ls' \
+               'ls baz'
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/strategies_test.zsh b/.zsh/external/zsh-autosuggestions/test/strategies_test.zsh
new file mode 100644 (file)
index 0000000..0a937f4
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+assertBackslashSuggestion() {
+       set_history <<-'EOF'
+               echo "hello\nworld"
+       EOF
+
+       assertSuggestion \
+               'echo "hello\' \
+               'echo "hello\nworld"'
+}
+
+assertDoubleBackslashSuggestion() {
+       set_history <<-'EOF'
+               echo "\\"
+       EOF
+
+       assertSuggestion \
+               'echo "\\' \
+               'echo "\\"'
+}
+
+assertTildeSuggestion() {
+       set_history <<-'EOF'
+               cd ~/something
+       EOF
+
+       assertSuggestion \
+               'cd' \
+               'cd ~/something'
+
+       assertSuggestion \
+               'cd ~' \
+               'cd ~/something'
+
+       assertSuggestion \
+               'cd ~/s' \
+               'cd ~/something'
+}
+
+assertTildeSuggestionWithExtendedGlob() {
+       setopt local_options extended_glob
+
+       assertTildeSuggestion
+}
+
+assertParenthesesSuggestion() {
+       set_history <<-'EOF'
+               echo "$(ls foo)"
+       EOF
+
+       assertSuggestion \
+               'echo "$(' \
+               'echo "$(ls foo)"'
+}
+
+assertSquareBracketsSuggestion() {
+       set_history <<-'EOF'
+               echo "$history[123]"
+       EOF
+
+       assertSuggestion \
+               'echo "$history[' \
+               'echo "$history[123]"'
+}
+
+assertHashSuggestion() {
+       set_history <<-'EOF'
+               echo "#yolo"
+       EOF
+
+       assertSuggestion \
+               'echo "#' \
+               'echo "#yolo"'
+}
+
+testSpecialCharsForAllStrategies() {
+       local strategies
+       strategies=(
+               "default"
+               "match_prev_cmd"
+       )
+
+       for s in $strategies; do
+               ZSH_AUTOSUGGEST_STRATEGY="$s"
+
+               assertBackslashSuggestion
+               assertDoubleBackslashSuggestion
+               assertTildeSuggestion
+               assertTildeSuggestionWithExtendedGlob
+               assertParenthesesSuggestion
+               assertSquareBracketsSuggestion
+       done
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/suggestion_test.zsh b/.zsh/external/zsh-autosuggestions/test/suggestion_test.zsh
new file mode 100644 (file)
index 0000000..fc6330d
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+testEscapeCommand() {
+       assertEquals \
+               'Did not escape single backslash' \
+               '\\' \
+               "$(_zsh_autosuggest_escape_command '\')"
+
+       assertEquals \
+               'Did not escape two backslashes' \
+               '\\\\' \
+               "$(_zsh_autosuggest_escape_command '\\')"
+
+       assertEquals \
+               'Did not escape parentheses' \
+               '\(\)' \
+               "$(_zsh_autosuggest_escape_command '()')"
+
+       assertEquals \
+               'Did not escape square brackets' \
+               '\[\]' \
+               "$(_zsh_autosuggest_escape_command '[]')"
+
+       assertEquals \
+               'Did not escape pipe' \
+               '\|' \
+               "$(_zsh_autosuggest_escape_command '|')"
+
+       assertEquals \
+               'Did not escape star' \
+               '\*' \
+               "$(_zsh_autosuggest_escape_command '*')"
+
+       assertEquals \
+               'Did not escape question mark' \
+               '\?' \
+               "$(_zsh_autosuggest_escape_command '?')"
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/test_helper.zsh b/.zsh/external/zsh-autosuggestions/test/test_helper.zsh
new file mode 100644 (file)
index 0000000..7e7dbc0
--- /dev/null
@@ -0,0 +1,60 @@
+DIR="${0:a:h}"
+ROOT_DIR="$DIR/.."
+VENDOR_DIR="$ROOT_DIR/vendor"
+
+# Use stub.sh for stubbing/mocking
+source "$VENDOR_DIR/stub.sh/stub.sh"
+
+#--------------------------------------------------------------------#
+# Helper Functions                                                   #
+#--------------------------------------------------------------------#
+
+# Source the autosuggestions plugin file
+source_autosuggestions() {
+       source "$ROOT_DIR/zsh-autosuggestions.zsh"
+}
+
+# Set history list from stdin
+set_history() {
+       # Make a tmp file in shunit's tmp dir
+       local tmp=$(mktemp "$SHUNIT_TMPDIR/hist.XXX")
+
+       # Write from stdin to the tmp file
+       > "$tmp"
+
+       # Write an extra line to simulate history active mode
+       # See https://github.com/zsh-users/zsh/blob/ca3bc0d95d7deab4f5381f12b15047de748c0814/Src/hist.c#L69-L82
+       echo >> "$tmp"
+
+       # Clear history and re-read from the tmp file
+       fc -P; fc -p; fc -R "$tmp"
+
+       rm "$tmp"
+}
+
+# Should be called at the bottom of every test suite file
+# Pass in the name of the test script ($0) for shunit
+run_tests() {
+       local test_script="$1"
+       shift
+
+       # Required for shunit to work with zsh
+       setopt localoptions shwordsplit
+       SHUNIT_PARENT="$test_script"
+
+       source "$VENDOR_DIR/shunit2/2.1.6/src/shunit2"
+}
+
+#--------------------------------------------------------------------#
+# Custom Assertions                                                  #
+#--------------------------------------------------------------------#
+
+assertSuggestion() {
+       local prefix="$1"
+       local expected_suggestion="$2"
+
+       assertEquals \
+               "Did not get correct suggestion for prefix:<$prefix> using strategy <$ZSH_AUTOSUGGEST_STRATEGY>" \
+               "$expected_suggestion" \
+               "$(_zsh_autosuggest_suggestion "$prefix")"
+}
diff --git a/.zsh/external/zsh-autosuggestions/test/widgets/accept_test.zsh b/.zsh/external/zsh-autosuggestions/test/widgets/accept_test.zsh
new file mode 100644 (file)
index 0000000..f126091
--- /dev/null
@@ -0,0 +1,161 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+setUp() {
+       BUFFER=''
+       POSTDISPLAY=''
+       CURSOR=0
+       KEYMAP='main'
+}
+
+tearDown() {
+       restore _zsh_autosuggest_invoke_original_widget
+}
+
+testCursorAtEnd() {
+       BUFFER='echo'
+       POSTDISPLAY=' hello'
+       CURSOR=4
+
+       stub _zsh_autosuggest_invoke_original_widget
+
+       _zsh_autosuggest_accept 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was not modified' \
+               'echo hello' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY was not cleared' \
+               '' \
+               "$POSTDISPLAY"
+}
+
+testCursorNotAtEnd() {
+       BUFFER='echo'
+       POSTDISPLAY=' hello'
+       CURSOR=2
+
+       stub _zsh_autosuggest_invoke_original_widget
+
+       _zsh_autosuggest_accept 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was modified' \
+               'echo' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY was modified' \
+               ' hello' \
+               "$POSTDISPLAY"
+}
+
+testViCursorAtEnd() {
+       BUFFER='echo'
+       POSTDISPLAY=' hello'
+       CURSOR=3
+       KEYMAP='vicmd'
+
+       stub _zsh_autosuggest_invoke_original_widget
+
+       _zsh_autosuggest_accept 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was not modified' \
+               'echo hello' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY was not cleared' \
+               '' \
+               "$POSTDISPLAY"
+}
+
+testViCursorNotAtEnd() {
+       BUFFER='echo'
+       POSTDISPLAY=' hello'
+       CURSOR=2
+       KEYMAP='vicmd'
+
+       stub _zsh_autosuggest_invoke_original_widget
+
+       _zsh_autosuggest_accept 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was modified' \
+               'echo' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY was modified' \
+               ' hello' \
+               "$POSTDISPLAY"
+}
+
+testRetval() {
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'return 1'
+
+       _zsh_autosuggest_widget_accept 'original-widget'
+
+       assertEquals \
+               'Did not return correct value from original widget' \
+               '1' \
+               "$?"
+}
+
+testWidget() {
+       stub _zsh_autosuggest_highlight_reset
+       stub _zsh_autosuggest_accept
+       stub _zsh_autosuggest_highlight_apply
+
+       # Call the function pointed to by the widget since we can't call
+       # the widget itself when zle is not active
+       ${widgets[autosuggest-accept]#*:} 'original-widget'
+
+       assertTrue \
+               'autosuggest-accept widget does not exist' \
+               'zle -l autosuggest-accept'
+
+       assertTrue \
+               'highlight_reset was not called' \
+               'stub_called _zsh_autosuggest_highlight_reset'
+
+       assertTrue \
+               'widget function was not called' \
+               'stub_called _zsh_autosuggest_accept'
+
+       assertTrue \
+               'highlight_apply was not called' \
+               'stub_called _zsh_autosuggest_highlight_apply'
+
+       restore _zsh_autosuggest_highlight_reset
+       restore _zsh_autosuggest_accept
+       restore _zsh_autosuggest_highlight_apply
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/widgets/clear_test.zsh b/.zsh/external/zsh-autosuggestions/test/widgets/clear_test.zsh
new file mode 100644 (file)
index 0000000..f0500c5
--- /dev/null
@@ -0,0 +1,77 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+setUp() {
+       BUFFER=''
+       POSTDISPLAY=''
+}
+
+tearDown() {
+       restore _zsh_autosuggest_invoke_original_widget
+}
+
+testClear() {
+       BUFFER='ec'
+       POSTDISPLAY='ho hello'
+
+       _zsh_autosuggest_clear 'original-widget'
+
+       assertEquals \
+               'BUFFER was modified' \
+               'ec' \
+               "$BUFFER"
+
+       assertNull \
+               'POSTDISPLAY was not cleared' \
+               "$POSTDISPLAY"
+}
+
+testRetval() {
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'return 1'
+
+       _zsh_autosuggest_widget_clear 'original-widget'
+
+       assertEquals \
+               'Did not return correct value from original widget' \
+               '1' \
+               "$?"
+}
+
+testWidget() {
+       stub _zsh_autosuggest_highlight_reset
+       stub _zsh_autosuggest_clear
+       stub _zsh_autosuggest_highlight_apply
+
+       # Call the function pointed to by the widget since we can't call
+       # the widget itself when zle is not active
+       ${widgets[autosuggest-clear]#*:} 'original-widget'
+
+       assertTrue \
+               'autosuggest-clear widget does not exist' \
+               'zle -l autosuggest-clear'
+
+       assertTrue \
+               'highlight_reset was not called' \
+               'stub_called _zsh_autosuggest_highlight_reset'
+
+       assertTrue \
+               'widget function was not called' \
+               'stub_called _zsh_autosuggest_clear'
+
+       assertTrue \
+               'highlight_apply was not called' \
+               'stub_called _zsh_autosuggest_highlight_apply'
+
+       restore _zsh_autosuggest_highlight_reset
+       restore _zsh_autosuggest_clear
+       restore _zsh_autosuggest_highlight_apply
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/widgets/execute_test.zsh b/.zsh/external/zsh-autosuggestions/test/widgets/execute_test.zsh
new file mode 100644 (file)
index 0000000..cb346db
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+tearDown() {
+       restore _zsh_autosuggest_invoke_original_widget
+}
+
+testRetval() {
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'return 1'
+
+       _zsh_autosuggest_widget_execute 'original-widget'
+
+       assertEquals \
+               'Did not return correct value from original widget' \
+               '1' \
+               "$?"
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/widgets/modify_test.zsh b/.zsh/external/zsh-autosuggestions/test/widgets/modify_test.zsh
new file mode 100644 (file)
index 0000000..7ed6346
--- /dev/null
@@ -0,0 +1,88 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+setUp() {
+       BUFFER=''
+       POSTDISPLAY=''
+       ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=''
+}
+
+tearDown() {
+       restore _zsh_autosuggest_invoke_original_widget
+       restore _zsh_autosuggest_suggestion
+}
+
+testModify() {
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'BUFFER+="e"'
+
+       stub_and_echo \
+               _zsh_autosuggest_suggestion \
+               'echo hello'
+
+       _zsh_autosuggest_modify 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was not modified' \
+               'e' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY does not contain suggestion' \
+               'cho hello' \
+               "$POSTDISPLAY"
+}
+
+testModifyBufferTooLarge() {
+
+       ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE='20'
+
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'BUFFER+="012345678901234567890"'
+
+       stub_and_echo \
+               _zsh_autosuggest_suggestion \
+               '012345678901234567890123456789'
+
+       _zsh_autosuggest_modify 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was not modified' \
+               '012345678901234567890' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY does not contain suggestion' \
+               '' \
+               "$POSTDISPLAY"
+}
+
+testRetval() {
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'return 1'
+
+       _zsh_autosuggest_widget_modify 'original-widget'
+
+       assertEquals \
+               'Did not return correct value from original widget' \
+               '1' \
+               "$?"
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/test/widgets/partial_accept_test.zsh b/.zsh/external/zsh-autosuggestions/test/widgets/partial_accept_test.zsh
new file mode 100644 (file)
index 0000000..60c78a6
--- /dev/null
@@ -0,0 +1,84 @@
+#!/usr/bin/env zsh
+
+source "${0:a:h}/../test_helper.zsh"
+
+oneTimeSetUp() {
+       source_autosuggestions
+}
+
+setUp() {
+       BUFFER=''
+       POSTDISPLAY=''
+       CURSOR=0
+}
+
+tearDown() {
+       restore _zsh_autosuggest_invoke_original_widget
+}
+
+testCursorMovesOutOfBuffer() {
+       BUFFER='ec'
+       POSTDISPLAY='ho hello'
+       CURSOR=1
+
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'CURSOR=5; LBUFFER="echo "; RBUFFER="hello"'
+
+       _zsh_autosuggest_partial_accept 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was not modified correctly' \
+               'echo ' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY was not modified correctly' \
+               'hello' \
+               "$POSTDISPLAY"
+}
+
+testCursorStaysInBuffer() {
+       BUFFER='echo hello'
+       POSTDISPLAY=' world'
+       CURSOR=1
+
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'CURSOR=5; LBUFFER="echo "; RBUFFER="hello"'
+
+       _zsh_autosuggest_partial_accept 'original-widget'
+
+       assertTrue \
+               'original widget not invoked' \
+               'stub_called _zsh_autosuggest_invoke_original_widget'
+
+       assertEquals \
+               'BUFFER was modified' \
+               'echo hello' \
+               "$BUFFER"
+
+       assertEquals \
+               'POSTDISPLAY was modified' \
+               ' world' \
+               "$POSTDISPLAY"
+}
+
+testRetval() {
+       stub_and_eval \
+               _zsh_autosuggest_invoke_original_widget \
+               'return 1'
+
+       _zsh_autosuggest_widget_partial_accept 'original-widget'
+
+       assertEquals \
+               'Did not return correct value from original widget' \
+               '1' \
+               "$?"
+}
+
+run_tests "$0"
diff --git a/.zsh/external/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh b/.zsh/external/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh
new file mode 100644 (file)
index 0000000..16c2256
--- /dev/null
@@ -0,0 +1 @@
+source ${0:A:h}/zsh-autosuggestions.zsh
diff --git a/.zsh/external/zsh-autosuggestions/zsh-autosuggestions.zsh b/.zsh/external/zsh-autosuggestions/zsh-autosuggestions.zsh
new file mode 100644 (file)
index 0000000..4905776
--- /dev/null
@@ -0,0 +1,474 @@
+# Fish-like fast/unobtrusive autosuggestions for zsh.
+# https://github.com/zsh-users/zsh-autosuggestions
+# v0.3.3
+# Copyright (c) 2013 Thiago de Arruda
+# Copyright (c) 2016 Eric Freese
+# 
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+# 
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+#--------------------------------------------------------------------#
+# Global Configuration Variables                                     #
+#--------------------------------------------------------------------#
+
+# Color to use when highlighting suggestion
+# Uses format of `region_highlight`
+# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
+ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
+
+# Prefix to use when saving original versions of bound widgets
+ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
+
+ZSH_AUTOSUGGEST_STRATEGY=default
+
+# Widgets that clear the suggestion
+ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
+       history-search-forward
+       history-search-backward
+       history-beginning-search-forward
+       history-beginning-search-backward
+       history-substring-search-up
+       history-substring-search-down
+       up-line-or-history
+       down-line-or-history
+       accept-line
+)
+
+# Widgets that accept the entire suggestion
+ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
+       forward-char
+       end-of-line
+       vi-forward-char
+       vi-end-of-line
+       vi-add-eol
+)
+
+# Widgets that accept the entire suggestion and execute it
+ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=(
+)
+
+# Widgets that accept the suggestion as far as the cursor moves
+ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
+       forward-word
+       emacs-forward-word
+       vi-forward-word
+       vi-forward-word-end
+       vi-forward-blank-word
+       vi-forward-blank-word-end
+)
+
+# Widgets that should be ignored (globbing supported but must be escaped)
+ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
+       orig-\*
+       beep
+       run-help
+       set-local-history
+       which-command
+       yank
+)
+
+# Max size of buffer to trigger autosuggestion. Leave undefined for no upper bound.
+ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=
+
+#--------------------------------------------------------------------#
+# Handle Deprecated Variables/Widgets                                #
+#--------------------------------------------------------------------#
+
+_zsh_autosuggest_deprecated_warning() {
+       >&2 echo "zsh-autosuggestions: $@"
+}
+
+_zsh_autosuggest_check_deprecated_config() {
+       if [ -n "$AUTOSUGGESTION_HIGHLIGHT_COLOR" ]; then
+               _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_COLOR is deprecated. Use ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE instead."
+               [ -z "$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" ] && ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=$AUTOSUGGESTION_HIGHLIGHT_STYLE
+               unset AUTOSUGGESTION_HIGHLIGHT_STYLE
+       fi
+
+       if [ -n "$AUTOSUGGESTION_HIGHLIGHT_CURSOR" ]; then
+               _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_HIGHLIGHT_CURSOR is deprecated."
+               unset AUTOSUGGESTION_HIGHLIGHT_CURSOR
+       fi
+
+       if [ -n "$AUTOSUGGESTION_ACCEPT_RIGHT_ARROW" ]; then
+               _zsh_autosuggest_deprecated_warning "AUTOSUGGESTION_ACCEPT_RIGHT_ARROW is deprecated. The right arrow now accepts the suggestion by default."
+               unset AUTOSUGGESTION_ACCEPT_RIGHT_ARROW
+       fi
+}
+
+_zsh_autosuggest_deprecated_start_widget() {
+       _zsh_autosuggest_deprecated_warning "The autosuggest-start widget is deprecated. For more info, see the README at https://github.com/zsh-users/zsh-autosuggestions."
+       zle -D autosuggest-start
+       eval "zle-line-init() {
+               $(echo $functions[${widgets[zle-line-init]#*:}] | sed -e 's/zle autosuggest-start//g')
+       }"
+}
+
+zle -N autosuggest-start _zsh_autosuggest_deprecated_start_widget
+
+#--------------------------------------------------------------------#
+# Widget Helpers                                                     #
+#--------------------------------------------------------------------#
+
+# Bind a single widget to an autosuggest widget, saving a reference to the original widget
+_zsh_autosuggest_bind_widget() {
+       local widget=$1
+       local autosuggest_action=$2
+       local prefix=$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
+
+       # Save a reference to the original widget
+       case $widgets[$widget] in
+               # Already bound
+               user:_zsh_autosuggest_(bound|orig)_*);;
+
+               # User-defined widget
+               user:*)
+                       zle -N $prefix$widget ${widgets[$widget]#*:}
+                       ;;
+
+               # Built-in widget
+               builtin)
+                       eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
+                       zle -N $prefix$widget _zsh_autosuggest_orig_$widget
+                       ;;
+
+               # Completion widget
+               completion:*)
+                       eval "zle -C $prefix${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
+                       ;;
+       esac
+
+       # Pass the original widget's name explicitly into the autosuggest
+       # function. Use this passed in widget name to call the original
+       # widget instead of relying on the $WIDGET variable being set
+       # correctly. $WIDGET cannot be trusted because other plugins call
+       # zle without the `-w` flag (e.g. `zle self-insert` instead of
+       # `zle self-insert -w`).
+       eval "_zsh_autosuggest_bound_${(q)widget}() {
+               _zsh_autosuggest_widget_$autosuggest_action $prefix${(q)widget} \$@
+       }"
+
+       # Create the bound widget
+       zle -N $widget _zsh_autosuggest_bound_$widget
+}
+
+# Map all configured widgets to the right autosuggest widgets
+_zsh_autosuggest_bind_widgets() {
+       local widget
+       local ignore_widgets
+
+       ignore_widgets=(
+               .\*
+               _\*
+               zle-line-\*
+               autosuggest-\*
+               $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
+               $ZSH_AUTOSUGGEST_IGNORE_WIDGETS
+       )
+
+       # Find every widget we might want to bind and bind it appropriately
+       for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
+               if [ ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget clear
+               elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget accept
+               elif [ ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget execute
+               elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then
+                       _zsh_autosuggest_bind_widget $widget partial_accept
+               else
+                       # Assume any unspecified widget might modify the buffer
+                       _zsh_autosuggest_bind_widget $widget modify
+               fi
+       done
+}
+
+# Given the name of an original widget and args, invoke it, if it exists
+_zsh_autosuggest_invoke_original_widget() {
+       # Do nothing unless called with at least one arg
+       [ $# -gt 0 ] || return
+
+       local original_widget_name="$1"
+
+       shift
+
+       if [ $widgets[$original_widget_name] ]; then
+               zle $original_widget_name -- $@
+       fi
+}
+
+#--------------------------------------------------------------------#
+# Highlighting                                                       #
+#--------------------------------------------------------------------#
+
+# If there was a highlight, remove it
+_zsh_autosuggest_highlight_reset() {
+       typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+
+       if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
+               region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
+               unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+       fi
+}
+
+# If there's a suggestion, highlight it
+_zsh_autosuggest_highlight_apply() {
+       typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+
+       if [ $#POSTDISPLAY -gt 0 ]; then
+               _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
+               region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
+       else
+               unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
+       fi
+}
+
+#--------------------------------------------------------------------#
+# Autosuggest Widget Implementations                                 #
+#--------------------------------------------------------------------#
+
+# Clear the suggestion
+_zsh_autosuggest_clear() {
+       # Remove the suggestion
+       unset POSTDISPLAY
+
+       _zsh_autosuggest_invoke_original_widget $@
+}
+
+# Modify the buffer and get a new suggestion
+_zsh_autosuggest_modify() {
+       local -i retval
+
+       # Save the contents of the buffer/postdisplay
+       local orig_buffer="$BUFFER"
+       local orig_postdisplay="$POSTDISPLAY"
+
+       # Clear suggestion while original widget runs
+       unset POSTDISPLAY
+
+       # Original widget may modify the buffer
+       _zsh_autosuggest_invoke_original_widget $@
+       retval=$?
+
+       # Don't fetch a new suggestion if the buffer hasn't changed
+       if [ "$BUFFER" = "$orig_buffer" ]; then
+               POSTDISPLAY="$orig_postdisplay"
+               return $retval
+       fi
+
+       # Get a new suggestion if the buffer is not empty after modification
+       local suggestion
+       if [ $#BUFFER -gt 0 ]; then
+               if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -lt "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then
+                       suggestion="$(_zsh_autosuggest_suggestion "$BUFFER")"
+               fi
+       fi
+
+       # Add the suggestion to the POSTDISPLAY
+       if [ -n "$suggestion" ]; then
+               POSTDISPLAY="${suggestion#$BUFFER}"
+       fi
+
+       return $retval
+}
+
+# Accept the entire suggestion
+_zsh_autosuggest_accept() {
+       local -i max_cursor_pos=$#BUFFER
+
+       # When vicmd keymap is active, the cursor can't move all the way
+       # to the end of the buffer
+       if [ "$KEYMAP" = "vicmd" ]; then
+               max_cursor_pos=$((max_cursor_pos - 1))
+       fi
+
+       # Only accept if the cursor is at the end of the buffer
+       if [ $CURSOR -eq $max_cursor_pos ]; then
+               # Add the suggestion to the buffer
+               BUFFER="$BUFFER$POSTDISPLAY"
+
+               # Remove the suggestion
+               unset POSTDISPLAY
+
+               # Move the cursor to the end of the buffer
+               CURSOR=${#BUFFER}
+       fi
+
+       _zsh_autosuggest_invoke_original_widget $@
+}
+
+# Accept the entire suggestion and execute it
+_zsh_autosuggest_execute() {
+       # Add the suggestion to the buffer
+       BUFFER="$BUFFER$POSTDISPLAY"
+
+       # Remove the suggestion
+       unset POSTDISPLAY
+
+       # Call the original `accept-line` to handle syntax highlighting or
+       # other potential custom behavior
+       _zsh_autosuggest_invoke_original_widget "accept-line"
+}
+
+# Partially accept the suggestion
+_zsh_autosuggest_partial_accept() {
+       local -i retval
+
+       # Save the contents of the buffer so we can restore later if needed
+       local original_buffer="$BUFFER"
+
+       # Temporarily accept the suggestion.
+       BUFFER="$BUFFER$POSTDISPLAY"
+
+       # Original widget moves the cursor
+       _zsh_autosuggest_invoke_original_widget $@
+       retval=$?
+
+       # If we've moved past the end of the original buffer
+       if [ $CURSOR -gt $#original_buffer ]; then
+               # Set POSTDISPLAY to text right of the cursor
+               POSTDISPLAY="$RBUFFER"
+
+               # Clip the buffer at the cursor
+               BUFFER="$LBUFFER"
+       else
+               # Restore the original buffer
+               BUFFER="$original_buffer"
+       fi
+
+       return $retval
+}
+
+for action in clear modify accept partial_accept execute; do
+       eval "_zsh_autosuggest_widget_$action() {
+               local -i retval
+
+               _zsh_autosuggest_highlight_reset
+
+               _zsh_autosuggest_$action \$@
+               retval=\$?
+
+               _zsh_autosuggest_highlight_apply
+
+               return \$retval
+       }"
+done
+
+zle -N autosuggest-accept _zsh_autosuggest_widget_accept
+zle -N autosuggest-clear _zsh_autosuggest_widget_clear
+zle -N autosuggest-execute _zsh_autosuggest_widget_execute
+
+#--------------------------------------------------------------------#
+# Suggestion                                                         #
+#--------------------------------------------------------------------#
+
+# Delegate to the selected strategy to determine a suggestion
+_zsh_autosuggest_suggestion() {
+       local escaped_prefix="$(_zsh_autosuggest_escape_command "$1")"
+       local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY"
+
+       if [ -n "$functions[$strategy_function]" ]; then
+               echo -E "$($strategy_function "$escaped_prefix")"
+       fi
+}
+
+_zsh_autosuggest_escape_command() {
+       setopt localoptions EXTENDED_GLOB
+
+       # Escape special chars in the string (requires EXTENDED_GLOB)
+       echo -E "${1//(#m)[\\()\[\]|*?~]/\\$MATCH}"
+}
+
+#--------------------------------------------------------------------#
+# Default Suggestion Strategy                                        #
+#--------------------------------------------------------------------#
+# Suggests the most recent history item that matches the given
+# prefix.
+#
+
+_zsh_autosuggest_strategy_default() {
+       fc -lnrm "$1*" 1 2>/dev/null | head -n 1
+}
+
+#--------------------------------------------------------------------#
+# Match Previous Command Suggestion Strategy                         #
+#--------------------------------------------------------------------#
+# Suggests the most recent history item that matches the given
+# prefix and whose preceding history item also matches the most
+# recently executed command.
+#
+# For example, suppose your history has the following entries:
+#   - pwd
+#   - ls foo
+#   - ls bar
+#   - pwd
+#
+# Given the history list above, when you type 'ls', the suggestion
+# will be 'ls foo' rather than 'ls bar' because your most recently
+# executed command (pwd) was previously followed by 'ls foo'.
+#
+# Note that this strategy won't work as expected with ZSH options that don't
+# preserve the history order such as `HIST_IGNORE_ALL_DUPS` or
+# `HIST_EXPIRE_DUPS_FIRST`.
+
+_zsh_autosuggest_strategy_match_prev_cmd() {
+       local prefix="$1"
+
+       # Get all history event numbers that correspond to history
+       # entries that match pattern $prefix*
+       local history_match_keys
+       history_match_keys=(${(k)history[(R)$prefix*]})
+
+       # By default we use the first history number (most recent history entry)
+       local histkey="${history_match_keys[1]}"
+
+       # Get the previously executed command
+       local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
+
+       # Iterate up to the first 200 history event numbers that match $prefix
+       for key in "${(@)history_match_keys[1,200]}"; do
+               # Stop if we ran out of history
+               [[ $key -gt 1 ]] || break
+
+               # See if the history entry preceding the suggestion matches the
+               # previous command, and use it if it does
+               if [[ "${history[$((key - 1))]}" == "$prev_cmd" ]]; then
+                       histkey="$key"
+                       break
+               fi
+       done
+
+       # Echo the matched history entry
+       echo -E "$history[$histkey]"
+}
+
+#--------------------------------------------------------------------#
+# Start                                                              #
+#--------------------------------------------------------------------#
+
+# Start the autosuggestion widgets
+_zsh_autosuggest_start() {
+       _zsh_autosuggest_check_deprecated_config
+       _zsh_autosuggest_bind_widgets
+}
+
+autoload -Uz add-zsh-hook
+add-zsh-hook precmd _zsh_autosuggest_start
diff --git a/.zsh/plugins/zsh-autosuggestions.zsh b/.zsh/plugins/zsh-autosuggestions.zsh
new file mode 120000 (symlink)
index 0000000..c2659f7
--- /dev/null
@@ -0,0 +1 @@
+../external/zsh-autosuggestions/zsh-autosuggestions.zsh
\ No newline at end of file
index 0f81d5f..648b67c 100644 (file)
@@ -183,7 +183,8 @@ lmanpath=(
 # zstyle ':ganneff:config' plugins git-extras.plugin.zsh \
 #    history-substring-search.zsh \
 #    per-directory-history.plugin.zsh \
-#    zaw.zsh
+#    zaw.zsh \
+#    zsh-autosuggestion.zsh
 
 ## oh-my-zsh plugins can also be loaded, in case you like one of it.
 ## Simply list their names here, and put their directories into