Compare commits

...

25 Commits

Author SHA1 Message Date
Eric Freese
cce68de46d v0.3.2 2016-05-28 08:27:08 -06:00
Eric Freese
4a2d9f9049 Fix Makefile to not create symbolic link after PR #156 was merged 2016-05-28 08:26:24 -06:00
Eric Freese
7c688ec20c Add note to readme about PRs going to develop branch 2016-05-28 08:23:53 -06:00
Eric Freese
96eb0fae77 Changelog updates for v0.3.2 2016-05-28 08:18:52 -06:00
Eric Freese
5e5bfdb659 Merge pull request #156 from adamkruszewski/v0.3.x
Adjust plugin.zsh file to run on zsh 5.1 in mSYS2.
2016-05-12 08:53:20 -06:00
adamkruszewski
0a6c34947c Adjust plugin.zsh file to run on zsh 5.1 in mSYS2. 2016-05-11 17:02:41 +02:00
Eric Freese
e87bc74654 Fix 118: Clear suggestion before original widget to fix completions
See PR #149
2016-04-25 14:42:09 -06:00
Eric Freese
964773aa75 Use array indices for forward compatibility
See issue #152
2016-04-25 14:26:37 -06:00
Eric Freese
945c660856 Fix #152 by escaping widget names inside evals
Solves problems when dealing with widget names with irregular
characters such as those that come from `opp.zsh`.
2016-04-25 14:26:35 -06:00
Eric Freese
011d8bdfd1 Refactor to remove prev cmd function and simplify escaping 2016-04-25 14:19:26 -06:00
Eric Freese
c5f57da2b8 Pull duplicated test logic from strategies into single test file 2016-04-22 14:14:29 -06:00
Eric Freese
c477db2696 Remove unused test variables from Makefile 2016-04-15 13:41:41 -06:00
Eric Freese
d7001f2c34 Fix readme test script reference. 2016-04-15 13:40:18 -06:00
Eric Freese
6d6e7820f3 Fix #143: Add vi-add-eol to list of accept widgets. 2016-04-15 13:37:50 -06:00
Eric Freese
9bef50fac1 Merge pull request #140 from zsh-users/fixes/bound_widget_return_code
Keep track of return value from original widget (#135)
2016-04-14 11:18:01 -06:00
Eric Freese
1d4f7e157e Keep track of return value from original widget (#135) 2016-04-06 17:13:04 -06:00
Eric Freese
2acf25e065 Formatting 2016-03-15 09:24:13 -06:00
Eric Freese
ba7109169d Clean up tests with setUp and tearDown functions 2016-03-15 09:05:55 -06:00
Eric Freese
a28e72e84a Test Runner now supports running specific tests and choosing zsh bin 2016-03-15 09:04:17 -06:00
Eric Freese
87facd9b85 bump version v0.3.1 2016-03-14 22:33:26 -06:00
Eric Freese
dc822c54f8 Fix #133 2016-03-14 21:50:04 -06:00
Eric Freese
15c5db898f Fix #137 2016-03-14 21:41:14 -06:00
Eric Freese
46d5fe174d Remove extra newline 2016-03-14 18:02:16 -06:00
Eric Freese
6c31a02892 Remove old test script 2016-03-14 17:44:24 -06:00
Eric Freese
9ec62a1a23 Split out a separate test file for each widget 2016-03-14 17:38:37 -06:00
26 changed files with 575 additions and 674 deletions

View File

@@ -1,5 +1,19 @@
# Changelog # Changelog
## 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 ## v0.3.0
- Adds `autosuggest-execute` widget (PR #124). - Adds `autosuggest-execute` widget (PR #124).

View File

@@ -1,5 +1,4 @@
SRC_DIR := ./src SRC_DIR := ./src
TEST_DIR := ./script
VENDOR_DIR := ./vendor VENDOR_DIR := ./vendor
SRC_FILES := \ SRC_FILES := \
@@ -19,11 +18,6 @@ HEADER_FILES := \
LICENSE LICENSE
PLUGIN_TARGET := zsh-autosuggestions.zsh PLUGIN_TARGET := zsh-autosuggestions.zsh
OH_MY_ZSH_LINK_TARGET := zsh-autosuggestions.plugin.zsh
ALL_TARGETS := \
$(PLUGIN_TARGET) \
$(OH_MY_ZSH_LINK_TARGET)
SHUNIT2 := $(VENDOR_DIR)/shunit2/2.1.6 SHUNIT2 := $(VENDOR_DIR)/shunit2/2.1.6
STUB_SH := $(VENDOR_DIR)/stub.sh/stub.sh STUB_SH := $(VENDOR_DIR)/stub.sh/stub.sh
@@ -32,18 +26,12 @@ TEST_PREREQS := \
$(SHUNIT2) \ $(SHUNIT2) \
$(STUB_SH) $(STUB_SH)
TEST_FILES := \ all: $(PLUGIN_TARGET)
$(TEST_DIR)/**/*.zsh
all: $(ALL_TARGETS)
$(PLUGIN_TARGET): $(HEADER_FILES) $(SRC_FILES) $(PLUGIN_TARGET): $(HEADER_FILES) $(SRC_FILES)
cat $(HEADER_FILES) | sed -e 's/^/# /g' > $@ cat $(HEADER_FILES) | sed -e 's/^/# /g' > $@
cat $(SRC_FILES) >> $@ cat $(SRC_FILES) >> $@
$(OH_MY_ZSH_LINK_TARGET): $(PLUGIN_TARGET)
ln -s $(PLUGIN_TARGET) $@
$(SHUNIT2): $(SHUNIT2):
git submodule update --init vendor/shunit2 git submodule update --init vendor/shunit2
@@ -52,8 +40,8 @@ $(STUB_SH):
.PHONY: clean .PHONY: clean
clean: clean:
rm $(ALL_TARGETS) rm $(PLUGIN_TARGET)
.PHONY: test .PHONY: test
test: all $(TEST_PREREQS) test: all $(TEST_PREREQS)
script/test_runner.zsh script/test_runner.zsh $(TESTS)

View File

@@ -139,6 +139,7 @@ Edit the source files in `src/`. Run `make` to build `zsh-autosuggestions.zsh` f
Pull requests are welcome! If you send a pull request, please: 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. - Match the existing coding conventions.
- Include helpful comments to keep the barrier-to-entry low for people new to the project. - 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. - Write tests that cover your code as much as possible.
@@ -148,7 +149,7 @@ Pull requests are welcome! If you send a pull request, please:
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). 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.zsh`. To run the tests, run `make test`. The test script lives at `script/test_runner.zsh`. To run the tests, run `make test`.
## License ## License

View File

@@ -1 +1 @@
v0.3.0 v0.3.2

View File

@@ -1,374 +0,0 @@
#!/usr/bin/env zsh
SCRIPT_DIR=$(dirname "$0")
TEST_DIR=$SCRIPT_DIR/../test
DIST_DIR=$SCRIPT_DIR/../
# Use stub.sh for stubbing/mocking
source $TEST_DIR/stub-1.0.2.sh
source $DIST_DIR/zsh-autosuggestions.zsh
#--------------------------------------------------------------------#
# Highlighting #
#--------------------------------------------------------------------#
testHighlightDefaultStyle() {
assertEquals \
"fg=8" \
"$ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
}
testHighlightApplyWithSuggestion() {
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"
}
#--------------------------------------------------------------------#
# Widgets #
#--------------------------------------------------------------------#
testWidgetFunctionClear() {
BUFFER="ec"
POSTDISPLAY="ho hello"
_zsh_autosuggest_clear "original-widget"
assertEquals \
"BUFFER was modified" \
"ec" \
"$BUFFER"
assertNull \
"POSTDISPLAY was not cleared" \
"$POSTDISPLAY"
}
testWidgetFunctionModify() {
BUFFER=""
POSTDISPLAY=""
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"
restore _zsh_autosuggest_invoke_original_widget
restore _zsh_autosuggest_suggestion
}
testWidgetFunctionAcceptCursorAtEnd() {
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"
}
testWidgetFunctionAcceptCursorNotAtEnd() {
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"
}
testWidgetFunctionExecute() {
BUFFER="ec"
POSTDISPLAY="ho hello"
stub _zsh_autosuggest_invoke_original_widget
_zsh_autosuggest_execute
assertTrue \
"accept-line not invoked" \
"stub_called_with _zsh_autosuggest_invoke_original_widget 'accept-line'"
assertEquals \
"BUFFER was not modified" \
"echo hello" \
"$BUFFER"
assertEquals \
"POSTDISPLAY was not cleared" \
"" \
"$POSTDISPLAY"
}
testWidgetFunctionPartialAcceptCursorMovesOutOfBuffer() {
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"
}
testWidgetFunctionPartialAcceptCursorStaysInBuffer() {
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"
}
testWidgetAccept() {
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"
}
testWidgetClear() {
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"
}
testWidgetExecute() {
stub _zsh_autosuggest_highlight_reset
stub _zsh_autosuggest_execute
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-execute]#*:} "original-widget"
assertTrue \
"autosuggest-execute widget does not exist" \
"zle -l autosuggest-execute"
assertTrue \
"highlight_reset was not called" \
"stub_called _zsh_autosuggest_highlight_reset"
assertTrue \
"widget function was not called" \
"stub_called _zsh_autosuggest_execute"
assertTrue \
"highlight_apply was not called" \
"stub_called _zsh_autosuggest_highlight_apply"
}
testEscapeCommandPrefix() {
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 "?")"
}
# For zsh compatibility
setopt shwordsplit
SHUNIT_PARENT=$0
source $TEST_DIR/shunit2-2.1.6/src/shunit2

View File

@@ -15,15 +15,40 @@ header() {
EOF EOF
} }
local -a tests # ZSH binary to use
local zsh_bin="zsh"
# Test suites to run while getopts ":z:" opt; do
tests=($TEST_DIR/**/*_test.zsh) case $opt in
z)
local retval=0 zsh_bin="$OPTARG"
for suite in $tests; do ;;
header "${suite#"$TEST_DIR"}" \?)
zsh -f "$suite" || retval=$? echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument" >&2
exit 1
;;
esac
done done
exit retval 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

View File

@@ -21,13 +21,13 @@ _zsh_autosuggest_bind_widget() {
# Built-in widget # Built-in widget
builtin) builtin)
eval "_zsh_autosuggest_orig_$widget() { zle .$widget }" eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$widget _zsh_autosuggest_orig_$widget zle -N $prefix$widget _zsh_autosuggest_orig_$widget
;; ;;
# Completion widget # Completion widget
completion:*) completion:*)
eval "zle -C $prefix$widget ${${widgets[$widget]#*:}/:/ }" eval "zle -C $prefix${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
;; ;;
esac esac
@@ -37,8 +37,8 @@ _zsh_autosuggest_bind_widget() {
# correctly. $WIDGET cannot be trusted because other plugins call # correctly. $WIDGET cannot be trusted because other plugins call
# zle without the `-w` flag (e.g. `zle self-insert` instead of # zle without the `-w` flag (e.g. `zle self-insert` instead of
# `zle self-insert -w`). # `zle self-insert -w`).
eval "_zsh_autosuggest_bound_$widget() { eval "_zsh_autosuggest_bound_${(q)widget}() {
_zsh_autosuggest_widget_$autosuggest_action $prefix$widget \$@ _zsh_autosuggest_widget_$autosuggest_action $prefix${(q)widget} \$@
}" }"
# Create the bound widget # Create the bound widget

View File

@@ -32,6 +32,7 @@ ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
end-of-line end-of-line
vi-forward-char vi-forward-char
vi-end-of-line vi-end-of-line
vi-add-eol
) )
# Widgets that accept the entire suggestion and execute it # Widgets that accept the entire suggestion and execute it

View File

@@ -5,6 +5,8 @@
# If there was a highlight, remove it # If there was a highlight, remove it
_zsh_autosuggest_highlight_reset() { _zsh_autosuggest_highlight_reset() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}") region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
@@ -13,6 +15,8 @@ _zsh_autosuggest_highlight_reset() {
# If there's a suggestion, highlight it # If there's a suggestion, highlight it
_zsh_autosuggest_highlight_apply() { _zsh_autosuggest_highlight_apply() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [ $#POSTDISPLAY -gt 0 ]; then if [ $#POSTDISPLAY -gt 0 ]; then
_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT") region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")

View File

@@ -7,7 +7,7 @@
# #
_zsh_autosuggest_strategy_default() { _zsh_autosuggest_strategy_default() {
local prefix="$(_zsh_autosuggest_escape_command "$1")" local prefix="$1"
# Get the keys of the history items that match # Get the keys of the history items that match
local -a histkeys local -a histkeys

View File

@@ -18,7 +18,7 @@
# #
_zsh_autosuggest_strategy_match_prev_cmd() { _zsh_autosuggest_strategy_match_prev_cmd() {
local prefix="$(_zsh_autosuggest_escape_command "$1")" local prefix="$1"
# Get all history event numbers that correspond to history # Get all history event numbers that correspond to history
# entries that match pattern $prefix* # entries that match pattern $prefix*
@@ -29,8 +29,7 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
local histkey="${history_match_keys[1]}" local histkey="${history_match_keys[1]}"
# Get the previously executed command # Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_prev_command)" local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
prev_cmd="$(_zsh_autosuggest_escape_command "$prev_cmd")"
# Iterate up to the first 200 history event numbers that match $prefix # Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do for key in "${(@)history_match_keys[1,200]}"; do
@@ -48,4 +47,3 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
# Echo the matched history entry # Echo the matched history entry
echo -E "$history[$histkey]" echo -E "$history[$histkey]"
} }

View File

@@ -5,11 +5,11 @@
# Delegate to the selected strategy to determine a suggestion # Delegate to the selected strategy to determine a suggestion
_zsh_autosuggest_suggestion() { _zsh_autosuggest_suggestion() {
local prefix="$1" local escaped_prefix="$(_zsh_autosuggest_escape_command "$1")"
local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY" local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY"
if [ -n "$functions[$strategy_function]" ]; then if [ -n "$functions[$strategy_function]" ]; then
echo -E "$($strategy_function "$prefix")" echo -E "$($strategy_function "$escaped_prefix")"
fi fi
} }
@@ -19,8 +19,3 @@ _zsh_autosuggest_escape_command() {
# Escape special chars in the string (requires EXTENDED_GLOB) # Escape special chars in the string (requires EXTENDED_GLOB)
echo -E "${1//(#m)[\\()\[\]|*?]/\\$MATCH}" echo -E "${1//(#m)[\\()\[\]|*?]/\\$MATCH}"
} }
# Get the previously executed command
_zsh_autosuggest_prev_command() {
echo -E "${history[$((HISTCMD-1))]}"
}

View File

@@ -13,8 +13,14 @@ _zsh_autosuggest_clear() {
# Modify the buffer and get a new suggestion # Modify the buffer and get a new suggestion
_zsh_autosuggest_modify() { _zsh_autosuggest_modify() {
local -i retval
# Clear suggestion while original widget runs
unset POSTDISPLAY
# Original widget modifies the buffer # Original widget modifies the buffer
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$?
# Get a new suggestion if the buffer is not empty after modification # Get a new suggestion if the buffer is not empty after modification
local suggestion local suggestion
@@ -28,12 +34,22 @@ _zsh_autosuggest_modify() {
else else
unset POSTDISPLAY unset POSTDISPLAY
fi fi
return $retval
} }
# Accept the entire suggestion # Accept the entire suggestion
_zsh_autosuggest_accept() { _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 # Only accept if the cursor is at the end of the buffer
if [ $CURSOR -eq $#BUFFER ]; then if [ $CURSOR -eq $max_cursor_pos ]; then
# Add the suggestion to the buffer # Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
@@ -62,6 +78,8 @@ _zsh_autosuggest_execute() {
# Partially accept the suggestion # Partially accept the suggestion
_zsh_autosuggest_partial_accept() { _zsh_autosuggest_partial_accept() {
local -i retval
# Save the contents of the buffer so we can restore later if needed # Save the contents of the buffer so we can restore later if needed
local original_buffer="$BUFFER" local original_buffer="$BUFFER"
@@ -70,6 +88,7 @@ _zsh_autosuggest_partial_accept() {
# Original widget moves the cursor # Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$?
# If we've moved past the end of the original buffer # If we've moved past the end of the original buffer
if [ $CURSOR -gt $#original_buffer ]; then if [ $CURSOR -gt $#original_buffer ]; then
@@ -82,13 +101,22 @@ _zsh_autosuggest_partial_accept() {
# Restore the original buffer # Restore the original buffer
BUFFER="$original_buffer" BUFFER="$original_buffer"
fi fi
return $retval
} }
for action in clear modify accept partial_accept execute; do for action in clear modify accept partial_accept execute; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval
_zsh_autosuggest_highlight_reset _zsh_autosuggest_highlight_reset
_zsh_autosuggest_$action \$@ _zsh_autosuggest_$action \$@
retval=\$?
_zsh_autosuggest_highlight_apply _zsh_autosuggest_highlight_apply
return \$retval
}" }"
done done

45
test/bind_test.zsh Normal file
View File

@@ -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"

View File

@@ -53,62 +53,4 @@ testMostRecentMatch() {
'cd quux' 'cd quux'
} }
testBackslash() {
set_history <<-'EOF'
echo "hello\nworld"
EOF
assertSuggestion \
'echo "hello\' \
'echo "hello\nworld"'
}
testDoubleBackslash() {
set_history <<-'EOF'
echo "\\"
EOF
assertSuggestion \
'echo "\\' \
'echo "\\"'
}
testTilde() {
set_history <<-'EOF'
cd ~/something
EOF
assertSuggestion \
'cd' \
'cd ~/something'
assertSuggestion \
'cd ~' \
'cd ~/something'
assertSuggestion \
'cd ~/s' \
'cd ~/something'
}
testParentheses() {
set_history <<-'EOF'
echo "$(ls foo)"
EOF
assertSuggestion \
'echo "$(' \
'echo "$(ls foo)"'
}
testSquareBrackets() {
set_history <<-'EOF'
echo "$history[123]"
EOF
assertSuggestion \
'echo "$history[' \
'echo "$history[123]"'
}
run_tests "$0" run_tests "$0"

View File

@@ -55,64 +55,6 @@ testMostRecentMatch() {
'cd quux' 'cd quux'
} }
testBackslash() {
set_history <<-'EOF'
echo "hello\nworld"
EOF
assertSuggestion \
'echo "hello\' \
'echo "hello\nworld"'
}
testDoubleBackslash() {
set_history <<-'EOF'
echo "\\"
EOF
assertSuggestion \
'echo "\\' \
'echo "\\"'
}
testTilde() {
set_history <<-'EOF'
cd ~/something
EOF
assertSuggestion \
'cd' \
'cd ~/something'
assertSuggestion \
'cd ~' \
'cd ~/something'
assertSuggestion \
'cd ~/s' \
'cd ~/something'
}
testParentheses() {
set_history <<-'EOF'
echo "$(ls foo)"
EOF
assertSuggestion \
'echo "$(' \
'echo "$(ls foo)"'
}
testSquareBrackets() {
set_history <<-'EOF'
echo "$history[123]"
EOF
assertSuggestion \
'echo "$history[' \
'echo "$history[123]"'
}
testMatchMostRecentAfterPreviousCmd() { testMatchMostRecentAfterPreviousCmd() {
set_history <<-'EOF' set_history <<-'EOF'
echo what echo what

95
test/strategies_test.zsh Normal file
View File

@@ -0,0 +1,95 @@
#!/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'
}
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
assertParenthesesSuggestion
assertSquareBracketsSuggestion
done
}
run_tests "$0"

View File

@@ -43,30 +43,4 @@ testEscapeCommand() {
"$(_zsh_autosuggest_escape_command '?')" "$(_zsh_autosuggest_escape_command '?')"
} }
testPrevCommand() {
set_history <<-'EOF'
ls foo
ls bar
ls baz
EOF
assertEquals \
'Did not output the last command' \
'ls baz' \
"$(_zsh_autosuggest_prev_command)"
set_history <<-'EOF'
ls foo
ls bar
ls baz
ls quux
ls foobar
EOF
assertEquals \
'Did not output the last command' \
'ls foobar' \
"$(_zsh_autosuggest_prev_command)"
}
run_tests "$0" run_tests "$0"

View File

@@ -54,7 +54,7 @@ assertSuggestion() {
local expected_suggestion="$2" local expected_suggestion="$2"
assertEquals \ assertEquals \
"Did not get correct suggestion for prefix:<$prefix>" \ "Did not get correct suggestion for prefix:<$prefix> using strategy <$ZSH_AUTOSUGGEST_STRATEGY>" \
"$expected_suggestion" \ "$expected_suggestion" \
"$(_zsh_autosuggest_suggestion "$prefix")" "$(_zsh_autosuggest_suggestion "$prefix")"
} }

View File

@@ -1,60 +1,23 @@
#!/usr/bin/env zsh #!/usr/bin/env zsh
source "${0:a:h}/test_helper.zsh" source "${0:a:h}/../test_helper.zsh"
oneTimeSetUp() { oneTimeSetUp() {
source_autosuggestions source_autosuggestions
} }
testWidgetFunctionClear() { setUp() {
BUFFER='ec'
POSTDISPLAY='ho hello'
_zsh_autosuggest_clear 'original-widget'
assertEquals \
'BUFFER was modified' \
'ec' \
"$BUFFER"
assertNull \
'POSTDISPLAY was not cleared' \
"$POSTDISPLAY"
}
testWidgetFunctionModify() {
BUFFER='' BUFFER=''
POSTDISPLAY='' POSTDISPLAY=''
CURSOR=0
stub_and_eval \ KEYMAP='main'
_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"
restore _zsh_autosuggest_invoke_original_widget
restore _zsh_autosuggest_suggestion
} }
testWidgetFunctionAcceptCursorAtEnd() { tearDown() {
restore _zsh_autosuggest_invoke_original_widget
}
testCursorAtEnd() {
BUFFER='echo' BUFFER='echo'
POSTDISPLAY=' hello' POSTDISPLAY=' hello'
CURSOR=4 CURSOR=4
@@ -78,7 +41,7 @@ testWidgetFunctionAcceptCursorAtEnd() {
"$POSTDISPLAY" "$POSTDISPLAY"
} }
testWidgetFunctionAcceptCursorNotAtEnd() { testCursorNotAtEnd() {
BUFFER='echo' BUFFER='echo'
POSTDISPLAY=' hello' POSTDISPLAY=' hello'
CURSOR=2 CURSOR=2
@@ -102,42 +65,40 @@ testWidgetFunctionAcceptCursorNotAtEnd() {
"$POSTDISPLAY" "$POSTDISPLAY"
} }
testWidgetFunctionPartialAcceptCursorMovesOutOfBuffer() { testViCursorAtEnd() {
BUFFER='ec' BUFFER='echo'
POSTDISPLAY='ho hello' POSTDISPLAY=' hello'
CURSOR=1 CURSOR=3
KEYMAP='vicmd'
stub_and_eval \ stub _zsh_autosuggest_invoke_original_widget
_zsh_autosuggest_invoke_original_widget \
'CURSOR=5; LBUFFER="echo "; RBUFFER="hello"'
_zsh_autosuggest_partial_accept 'original-widget' _zsh_autosuggest_accept 'original-widget'
assertTrue \ assertTrue \
'original widget not invoked' \ 'original widget not invoked' \
'stub_called _zsh_autosuggest_invoke_original_widget' 'stub_called _zsh_autosuggest_invoke_original_widget'
assertEquals \ assertEquals \
'BUFFER was not modified correctly' \ 'BUFFER was not modified' \
'echo ' \ 'echo hello' \
"$BUFFER" "$BUFFER"
assertEquals \ assertEquals \
'POSTDISPLAY was not modified correctly' \ 'POSTDISPLAY was not cleared' \
'hello' \ '' \
"$POSTDISPLAY" "$POSTDISPLAY"
} }
testWidgetFunctionPartialAcceptCursorStaysInBuffer() { testViCursorNotAtEnd() {
BUFFER='echo hello' BUFFER='echo'
POSTDISPLAY=' world' POSTDISPLAY=' hello'
CURSOR=1 CURSOR=2
KEYMAP='vicmd'
stub_and_eval \ stub _zsh_autosuggest_invoke_original_widget
_zsh_autosuggest_invoke_original_widget \
'CURSOR=5; LBUFFER="echo "; RBUFFER="hello"'
_zsh_autosuggest_partial_accept 'original-widget' _zsh_autosuggest_accept 'original-widget'
assertTrue \ assertTrue \
'original widget not invoked' \ 'original widget not invoked' \
@@ -145,16 +106,29 @@ testWidgetFunctionPartialAcceptCursorStaysInBuffer() {
assertEquals \ assertEquals \
'BUFFER was modified' \ 'BUFFER was modified' \
'echo hello' \ 'echo' \
"$BUFFER" "$BUFFER"
assertEquals \ assertEquals \
'POSTDISPLAY was modified' \ 'POSTDISPLAY was modified' \
' world' \ ' hello' \
"$POSTDISPLAY" "$POSTDISPLAY"
} }
testWidgetAccept() { 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_highlight_reset
stub _zsh_autosuggest_accept stub _zsh_autosuggest_accept
stub _zsh_autosuggest_highlight_apply stub _zsh_autosuggest_highlight_apply
@@ -178,32 +152,10 @@ testWidgetAccept() {
assertTrue \ assertTrue \
'highlight_apply was not called' \ 'highlight_apply was not called' \
'stub_called _zsh_autosuggest_highlight_apply' 'stub_called _zsh_autosuggest_highlight_apply'
}
testWidgetClear() { restore _zsh_autosuggest_highlight_reset
stub _zsh_autosuggest_highlight_reset restore _zsh_autosuggest_accept
stub _zsh_autosuggest_clear restore _zsh_autosuggest_highlight_apply
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'
} }
run_tests "$0" run_tests "$0"

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env zsh
source "${0:a:h}/../test_helper.zsh"
oneTimeSetUp() {
source_autosuggestions
}
setUp() {
BUFFER=''
POSTDISPLAY=''
}
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"
}
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"

View File

@@ -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"

View File

@@ -1 +0,0 @@
zsh-autosuggestions.zsh

View File

@@ -0,0 +1 @@
source ${0:A:h}/zsh-autosuggestions.zsh

View File

@@ -1,6 +1,6 @@
# Fish-like fast/unobtrusive autosuggestions for zsh. # Fish-like fast/unobtrusive autosuggestions for zsh.
# https://github.com/zsh-users/zsh-autosuggestions # https://github.com/zsh-users/zsh-autosuggestions
# v0.3.0 # v0.3.2
# Copyright (c) 2013 Thiago de Arruda # Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016 Eric Freese # Copyright (c) 2016 Eric Freese
# #
@@ -58,6 +58,7 @@ ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
end-of-line end-of-line
vi-forward-char vi-forward-char
vi-end-of-line vi-end-of-line
vi-add-eol
) )
# Widgets that accept the entire suggestion and execute it # Widgets that accept the entire suggestion and execute it
@@ -131,13 +132,13 @@ _zsh_autosuggest_bind_widget() {
# Built-in widget # Built-in widget
builtin) builtin)
eval "_zsh_autosuggest_orig_$widget() { zle .$widget }" eval "_zsh_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$widget _zsh_autosuggest_orig_$widget zle -N $prefix$widget _zsh_autosuggest_orig_$widget
;; ;;
# Completion widget # Completion widget
completion:*) completion:*)
eval "zle -C $prefix$widget ${${widgets[$widget]#*:}/:/ }" eval "zle -C $prefix${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
;; ;;
esac esac
@@ -147,8 +148,8 @@ _zsh_autosuggest_bind_widget() {
# correctly. $WIDGET cannot be trusted because other plugins call # correctly. $WIDGET cannot be trusted because other plugins call
# zle without the `-w` flag (e.g. `zle self-insert` instead of # zle without the `-w` flag (e.g. `zle self-insert` instead of
# `zle self-insert -w`). # `zle self-insert -w`).
eval "_zsh_autosuggest_bound_$widget() { eval "_zsh_autosuggest_bound_${(q)widget}() {
_zsh_autosuggest_widget_$autosuggest_action $prefix$widget \$@ _zsh_autosuggest_widget_$autosuggest_action $prefix${(q)widget} \$@
}" }"
# Create the bound widget # Create the bound widget
@@ -196,6 +197,8 @@ _zsh_autosuggest_invoke_original_widget() {
# If there was a highlight, remove it # If there was a highlight, remove it
_zsh_autosuggest_highlight_reset() { _zsh_autosuggest_highlight_reset() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then if [ -n "$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT" ]; then
region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}") region_highlight=("${(@)region_highlight:#$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT unset _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
@@ -204,6 +207,8 @@ _zsh_autosuggest_highlight_reset() {
# If there's a suggestion, highlight it # If there's a suggestion, highlight it
_zsh_autosuggest_highlight_apply() { _zsh_autosuggest_highlight_apply() {
typeset -g _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT
if [ $#POSTDISPLAY -gt 0 ]; then if [ $#POSTDISPLAY -gt 0 ]; then
_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE" _ZSH_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT") region_highlight+=("$_ZSH_AUTOSUGGEST_LAST_HIGHLIGHT")
@@ -226,8 +231,14 @@ _zsh_autosuggest_clear() {
# Modify the buffer and get a new suggestion # Modify the buffer and get a new suggestion
_zsh_autosuggest_modify() { _zsh_autosuggest_modify() {
local -i retval
# Clear suggestion while original widget runs
unset POSTDISPLAY
# Original widget modifies the buffer # Original widget modifies the buffer
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$?
# Get a new suggestion if the buffer is not empty after modification # Get a new suggestion if the buffer is not empty after modification
local suggestion local suggestion
@@ -241,12 +252,22 @@ _zsh_autosuggest_modify() {
else else
unset POSTDISPLAY unset POSTDISPLAY
fi fi
return $retval
} }
# Accept the entire suggestion # Accept the entire suggestion
_zsh_autosuggest_accept() { _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 # Only accept if the cursor is at the end of the buffer
if [ $CURSOR -eq $#BUFFER ]; then if [ $CURSOR -eq $max_cursor_pos ]; then
# Add the suggestion to the buffer # Add the suggestion to the buffer
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
@@ -275,6 +296,8 @@ _zsh_autosuggest_execute() {
# Partially accept the suggestion # Partially accept the suggestion
_zsh_autosuggest_partial_accept() { _zsh_autosuggest_partial_accept() {
local -i retval
# Save the contents of the buffer so we can restore later if needed # Save the contents of the buffer so we can restore later if needed
local original_buffer="$BUFFER" local original_buffer="$BUFFER"
@@ -283,6 +306,7 @@ _zsh_autosuggest_partial_accept() {
# Original widget moves the cursor # Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$?
# If we've moved past the end of the original buffer # If we've moved past the end of the original buffer
if [ $CURSOR -gt $#original_buffer ]; then if [ $CURSOR -gt $#original_buffer ]; then
@@ -295,13 +319,22 @@ _zsh_autosuggest_partial_accept() {
# Restore the original buffer # Restore the original buffer
BUFFER="$original_buffer" BUFFER="$original_buffer"
fi fi
return $retval
} }
for action in clear modify accept partial_accept execute; do for action in clear modify accept partial_accept execute; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval
_zsh_autosuggest_highlight_reset _zsh_autosuggest_highlight_reset
_zsh_autosuggest_$action \$@ _zsh_autosuggest_$action \$@
retval=\$?
_zsh_autosuggest_highlight_apply _zsh_autosuggest_highlight_apply
return \$retval
}" }"
done done
@@ -315,11 +348,11 @@ zle -N autosuggest-execute _zsh_autosuggest_widget_execute
# Delegate to the selected strategy to determine a suggestion # Delegate to the selected strategy to determine a suggestion
_zsh_autosuggest_suggestion() { _zsh_autosuggest_suggestion() {
local prefix="$1" local escaped_prefix="$(_zsh_autosuggest_escape_command "$1")"
local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY" local strategy_function="_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY"
if [ -n "$functions[$strategy_function]" ]; then if [ -n "$functions[$strategy_function]" ]; then
echo -E "$($strategy_function "$prefix")" echo -E "$($strategy_function "$escaped_prefix")"
fi fi
} }
@@ -330,11 +363,6 @@ _zsh_autosuggest_escape_command() {
echo -E "${1//(#m)[\\()\[\]|*?]/\\$MATCH}" echo -E "${1//(#m)[\\()\[\]|*?]/\\$MATCH}"
} }
# Get the previously executed command
_zsh_autosuggest_prev_command() {
echo -E "${history[$((HISTCMD-1))]}"
}
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Default Suggestion Strategy # # Default Suggestion Strategy #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@@ -343,7 +371,7 @@ _zsh_autosuggest_prev_command() {
# #
_zsh_autosuggest_strategy_default() { _zsh_autosuggest_strategy_default() {
local prefix="$(_zsh_autosuggest_escape_command "$1")" local prefix="$1"
# Get the keys of the history items that match # Get the keys of the history items that match
local -a histkeys local -a histkeys
@@ -372,7 +400,7 @@ _zsh_autosuggest_strategy_default() {
# #
_zsh_autosuggest_strategy_match_prev_cmd() { _zsh_autosuggest_strategy_match_prev_cmd() {
local prefix="$(_zsh_autosuggest_escape_command "$1")" local prefix="$1"
# Get all history event numbers that correspond to history # Get all history event numbers that correspond to history
# entries that match pattern $prefix* # entries that match pattern $prefix*
@@ -383,8 +411,7 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
local histkey="${history_match_keys[1]}" local histkey="${history_match_keys[1]}"
# Get the previously executed command # Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_prev_command)" local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
prev_cmd="$(_zsh_autosuggest_escape_command "$prev_cmd")"
# Iterate up to the first 200 history event numbers that match $prefix # Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do for key in "${(@)history_match_keys[1,200]}"; do
@@ -403,7 +430,6 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
echo -E "$history[$histkey]" echo -E "$history[$histkey]"
} }
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Start # # Start #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#