Support fallback strategies by setting array in config

This commit is contained in:
Eric Freese 2018-06-06 21:49:03 -06:00
parent 949c374195
commit bcbdad83e9
10 changed files with 100 additions and 55 deletions

View file

@ -9,6 +9,7 @@ SRC_FILES := \
$(SRC_DIR)/highlight.zsh \
$(SRC_DIR)/widgets.zsh \
$(SRC_DIR)/strategies/*.zsh \
$(SRC_DIR)/fetch.zsh \
$(SRC_DIR)/async.zsh \
$(SRC_DIR)/start.zsh

View file

@ -2,7 +2,7 @@
_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
It suggests commands as you type, based on command history.
It suggests commands as you type.
Requirements: Zsh v4.3.11 or later
@ -39,10 +39,13 @@ Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion
### Suggestion Strategy
Set `ZSH_AUTOSUGGEST_STRATEGY` to choose the strategy for generating suggestions. There are currently two to choose from:
`ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. The strategies in the array are tried successively until a suggestion is found. There are currently three built-in strategies 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`.
- `history`: Chooses the most recent match from history.
- `match_prev_cmd`: Like `history`, but 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`.
- `completion`: (experimental) Chooses a suggestion based on what tab-completion would suggest.
For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine.
### Widget Mapping

View file

@ -2,7 +2,7 @@ describe 'using `zle -U`' do
let(:before_sourcing) do
-> do
session.
run_command('_zsh_autosuggest_strategy_test() { sleep 1; _zsh_autosuggest_strategy_default "$1" }').
run_command('_zsh_autosuggest_strategy_test() { sleep 1; _zsh_autosuggest_strategy_history "$1" }').
run_command('foo() { zle -U - "echo hello" }; zle -N foo; bindkey ^B foo')
end
end

View file

@ -1,20 +1,45 @@
describe 'a suggestion for a given prefix' do
let(:options) { ['_zsh_autosuggest_strategy_default() { suggestion="echo foo" }'] }
let(:history_strategy) { '_zsh_autosuggest_strategy_history() { suggestion="history" }' }
let(:foobar_strategy) { '_zsh_autosuggest_strategy_foobar() { [[ "foobar baz" = $1* ]] && suggestion="foobar baz" }' }
let(:foobaz_strategy) { '_zsh_autosuggest_strategy_foobaz() { [[ "foobaz bar" = $1* ]] && suggestion="foobaz bar" }' }
it 'is determined by calling the default strategy function' do
session.send_string('e')
wait_for { session.content }.to eq('echo foo')
let(:options) { [ history_strategy ] }
it 'by default is determined by calling the `history` strategy function' do
session.send_string('h')
wait_for { session.content }.to eq('history')
end
context 'when ZSH_AUTOSUGGEST_STRATEGY is set' do
context 'when ZSH_AUTOSUGGEST_STRATEGY is set to an array' do
let(:options) { [
'_zsh_autosuggest_strategy_custom() { suggestion="echo foo" }',
'ZSH_AUTOSUGGEST_STRATEGY=custom'
foobar_strategy,
foobaz_strategy,
'ZSH_AUTOSUGGEST_STRATEGY=(foobar foobaz)'
] }
it 'is determined by calling the specified strategy function' do
session.send_string('e')
wait_for { session.content }.to eq('echo foo')
it 'is determined by the first strategy function to return a suggestion' do
session.send_string('foo')
wait_for { session.content }.to eq('foobar baz')
session.send_string('baz')
wait_for { session.content }.to eq('foobaz bar')
end
end
context 'when ZSH_AUTOSUGGEST_STRATEGY is set to a string' do
let(:options) { [
foobar_strategy,
foobaz_strategy,
'ZSH_AUTOSUGGEST_STRATEGY="foobar foobaz"'
] }
it 'is determined by the first strategy function to return a suggestion' do
session.send_string('foo')
wait_for { session.content }.to eq('foobar baz')
session.send_string('baz')
wait_for { session.content }.to eq('foobaz bar')
end
end
end

View file

@ -35,7 +35,7 @@ _zsh_autosuggest_async_server() {
# Run suggestion search in the background
(
local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$query"
_zsh_autosuggest_fetch_suggestion "$query"
echo -n -E "$suggestion"$'\0'
) &

View file

@ -11,7 +11,9 @@ 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
# Strategies to use to fetch a suggestion
# Will try each strategy in order until a suggestion is returned
ZSH_AUTOSUGGEST_STRATEGY=(history)
# Widgets that clear the suggestion
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(

23
src/fetch.zsh Normal file
View file

@ -0,0 +1,23 @@
#--------------------------------------------------------------------#
# Fetch Suggestion #
#--------------------------------------------------------------------#
# Loops through all specified strategies and returns a suggestion
# from the first strategy to provide one.
#
_zsh_autosuggest_fetch_suggestion() {
typeset -g suggestion
local -a strategies
# Ensure we are working with an array
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
for strategy in $strategies; do
# Try to get a suggestion from this strategy
_zsh_autosuggest_strategy_$strategy "$1"
# Break once we've found a suggestion
[[ -n "$suggestion" ]] && break
done
}

View file

@ -1,17 +0,0 @@
#--------------------------------------------------------------------#
# Default Suggestion Strategy #
#--------------------------------------------------------------------#
# Will provide suggestions from your history. If no matches are found
# in history, will provide a suggestion from the completion engine.
#
_zsh_autosuggest_strategy_default() {
typeset -g suggestion
_zsh_autosuggest_strategy_history "$1"
if [[ -z "$suggestion" ]]; then
_zsh_autosuggest_strategy_completion "$1"
fi
}

View file

@ -97,7 +97,7 @@ _zsh_autosuggest_fetch() {
_zsh_autosuggest_async_request "$BUFFER"
else
local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$BUFFER"
_zsh_autosuggest_fetch_suggestion "$BUFFER"
_zsh_autosuggest_suggest "$suggestion"
fi
}

View file

@ -47,7 +47,9 @@ 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
# Strategies to use to fetch a suggestion
# Will try each strategy in order until a suggestion is returned
ZSH_AUTOSUGGEST_STRATEGY=(history)
# Widgets that clear the suggestion
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
@ -381,7 +383,7 @@ _zsh_autosuggest_fetch() {
_zsh_autosuggest_async_request "$BUFFER"
else
local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$BUFFER"
_zsh_autosuggest_fetch_suggestion "$BUFFER"
_zsh_autosuggest_suggest "$suggestion"
fi
}
@ -619,23 +621,6 @@ _zsh_autosuggest_strategy_completion() {
suggestion="${1[1,$i-1]}$completion"
}
#--------------------------------------------------------------------#
# Default Suggestion Strategy #
#--------------------------------------------------------------------#
# Will provide suggestions from your history. If no matches are found
# in history, will provide a suggestion from the completion engine.
#
_zsh_autosuggest_strategy_default() {
typeset -g suggestion
_zsh_autosuggest_strategy_history "$1"
if [[ -z "$suggestion" ]]; then
_zsh_autosuggest_strategy_completion "$1"
fi
}
#--------------------------------------------------------------------#
# History Suggestion Strategy #
#--------------------------------------------------------------------#
@ -720,6 +705,29 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
typeset -g suggestion="$history[$histkey]"
}
#--------------------------------------------------------------------#
# Fetch Suggestion #
#--------------------------------------------------------------------#
# Loops through all specified strategies and returns a suggestion
# from the first strategy to provide one.
#
_zsh_autosuggest_fetch_suggestion() {
typeset -g suggestion
local -a strategies
# Ensure we are working with an array
strategies=(${=ZSH_AUTOSUGGEST_STRATEGY})
for strategy in $strategies; do
# Try to get a suggestion from this strategy
_zsh_autosuggest_strategy_$strategy "$1"
# Break once we've found a suggestion
[[ -n "$suggestion" ]] && break
done
}
#--------------------------------------------------------------------#
# Async #
#--------------------------------------------------------------------#
@ -756,7 +764,7 @@ _zsh_autosuggest_async_server() {
# Run suggestion search in the background
(
local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$query"
_zsh_autosuggest_fetch_suggestion "$query"
echo -n -E "$suggestion"$'\0'
) &