Merge pull request #142 from zsh-users/v0.3.x

v0.3.2
This commit is contained in:
Eric Freese 2016-05-28 08:28:18 -06:00
commit 62cdba4e0f
24 changed files with 374 additions and 204 deletions

View file

@ -1,5 +1,13 @@
# 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 ## v0.3.1
- Fixes issue with `vi-next-char` not accepting suggestion (#137). - Fixes issue with `vi-next-char` not accepting suggestion (#137).

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.1 v0.3.2

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

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

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,6 +34,8 @@ _zsh_autosuggest_modify() {
else else
unset POSTDISPLAY unset POSTDISPLAY
fi fi
return $retval
} }
# Accept the entire suggestion # Accept the entire suggestion
@ -70,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"
@ -78,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
@ -90,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

@ -6,6 +6,17 @@ oneTimeSetUp() {
source_autosuggestions source_autosuggestions
} }
setUp() {
BUFFER=''
POSTDISPLAY=''
CURSOR=0
KEYMAP='main'
}
tearDown() {
restore _zsh_autosuggest_invoke_original_widget
}
testCursorAtEnd() { testCursorAtEnd() {
BUFFER='echo' BUFFER='echo'
POSTDISPLAY=' hello' POSTDISPLAY=' hello'
@ -104,6 +115,19 @@ testViCursorNotAtEnd() {
"$POSTDISPLAY" "$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() { testWidget() {
stub _zsh_autosuggest_highlight_reset stub _zsh_autosuggest_highlight_reset
stub _zsh_autosuggest_accept stub _zsh_autosuggest_accept
@ -128,6 +152,10 @@ testWidget() {
assertTrue \ assertTrue \
'highlight_apply was not called' \ 'highlight_apply was not called' \
'stub_called _zsh_autosuggest_highlight_apply' 'stub_called _zsh_autosuggest_highlight_apply'
restore _zsh_autosuggest_highlight_reset
restore _zsh_autosuggest_accept
restore _zsh_autosuggest_highlight_apply
} }
run_tests "$0" run_tests "$0"

View file

@ -6,6 +6,15 @@ oneTimeSetUp() {
source_autosuggestions source_autosuggestions
} }
setUp() {
BUFFER=''
POSTDISPLAY=''
}
tearDown() {
restore _zsh_autosuggest_invoke_original_widget
}
testClear() { testClear() {
BUFFER='ec' BUFFER='ec'
POSTDISPLAY='ho hello' POSTDISPLAY='ho hello'
@ -22,6 +31,19 @@ testClear() {
"$POSTDISPLAY" "$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() { testWidget() {
stub _zsh_autosuggest_highlight_reset stub _zsh_autosuggest_highlight_reset
stub _zsh_autosuggest_clear stub _zsh_autosuggest_clear
@ -46,6 +68,10 @@ testWidget() {
assertTrue \ assertTrue \
'highlight_apply was not called' \ 'highlight_apply was not called' \
'stub_called _zsh_autosuggest_highlight_apply' 'stub_called _zsh_autosuggest_highlight_apply'
restore _zsh_autosuggest_highlight_reset
restore _zsh_autosuggest_clear
restore _zsh_autosuggest_highlight_apply
} }
run_tests "$0" 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

@ -6,10 +6,17 @@ oneTimeSetUp() {
source_autosuggestions source_autosuggestions
} }
testModify() { setUp() {
BUFFER='' BUFFER=''
POSTDISPLAY='' POSTDISPLAY=''
}
tearDown() {
restore _zsh_autosuggest_invoke_original_widget
restore _zsh_autosuggest_suggestion
}
testModify() {
stub_and_eval \ stub_and_eval \
_zsh_autosuggest_invoke_original_widget \ _zsh_autosuggest_invoke_original_widget \
'BUFFER+="e"' 'BUFFER+="e"'
@ -33,9 +40,19 @@ testModify() {
'POSTDISPLAY does not contain suggestion' \ 'POSTDISPLAY does not contain suggestion' \
'cho hello' \ 'cho hello' \
"$POSTDISPLAY" "$POSTDISPLAY"
}
restore _zsh_autosuggest_invoke_original_widget testRetval() {
restore _zsh_autosuggest_suggestion 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" run_tests "$0"

View file

@ -6,6 +6,16 @@ oneTimeSetUp() {
source_autosuggestions source_autosuggestions
} }
setUp() {
BUFFER=''
POSTDISPLAY=''
CURSOR=0
}
tearDown() {
restore _zsh_autosuggest_invoke_original_widget
}
testCursorMovesOutOfBuffer() { testCursorMovesOutOfBuffer() {
BUFFER='ec' BUFFER='ec'
POSTDISPLAY='ho hello' POSTDISPLAY='ho hello'
@ -58,4 +68,17 @@ testCursorStaysInBuffer() {
"$POSTDISPLAY" "$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" 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.1 # 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
@ -230,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
@ -245,6 +252,8 @@ _zsh_autosuggest_modify() {
else else
unset POSTDISPLAY unset POSTDISPLAY
fi fi
return $retval
} }
# Accept the entire suggestion # Accept the entire suggestion
@ -287,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"
@ -295,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
@ -307,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
@ -327,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
} }
@ -342,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 #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@ -355,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
@ -384,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*
@ -395,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