commit
						ae315ded4d
					
				|  | @ -1,5 +1,10 @@ | |||
| # Changelog | ||||
| 
 | ||||
| ## v0.6.4 | ||||
| - Fix `vi-forward-char` triggering a bell when using it to accept a suggestion (#488) | ||||
| - New configuration option to skip completion suggestions when buffer matches a pattern (#487) | ||||
| - New configuration option to ignore history entries matching a pattern (#456) | ||||
| 
 | ||||
| ## v0.6.3 | ||||
| - Fixed bug moving cursor to end of buffer after accepting suggestion (#453) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										14
									
								
								README.md
								
								
								
								
							
							
						
						
									
										14
									
								
								README.md
								
								
								
								
							|  | @ -53,8 +53,8 @@ For more info, read the Character Highlighting section of the zsh manual: `man z | |||
| `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: | ||||
| 
 | ||||
| - `history`: Chooses the most recent match from history. | ||||
| - `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module) | ||||
| - `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. (requires `zpty` module) | ||||
| 
 | ||||
| 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. | ||||
| 
 | ||||
|  | @ -87,6 +87,18 @@ As of `v0.4.0`, suggestions can be fetched asynchronously. To enable this behavi | |||
| 
 | ||||
| Set `ZSH_AUTOSUGGEST_MANUAL_REBIND` (it can be set to anything) to disable automatic widget re-binding on each precmd. This can be a big boost to performance, but you'll need to handle re-binding yourself if any of the widget lists change or if you or another plugin wrap any of the autosuggest widgets. To re-bind widgets, run `_zsh_autosuggest_bind_widgets`. | ||||
| 
 | ||||
| ### Ignoring history suggestions that match a pattern | ||||
| 
 | ||||
| Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a glob pattern to prevent offering suggestions for history entries that match the pattern. For example, set it to `"cd *"` to never suggest any `cd` commands from history. Or set to `"?(#c50,)"` to never suggest anything 50 characters or longer. | ||||
| 
 | ||||
| **Note:** This only affects the `history` and `match_prev_cmd` suggestion strategies. | ||||
| 
 | ||||
| ### Skipping completion suggestions for certain cases | ||||
| 
 | ||||
| Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a glob pattern to prevent offering completion suggestions when the buffer matches that pattern. For example, set it to `"git *"` to disable completion suggestions for git subcommands. | ||||
| 
 | ||||
| **Note:** This only affects the `completion` suggestion strategy. | ||||
| 
 | ||||
| 
 | ||||
| ### Key Bindings | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,9 @@ describe 'the `completion` suggestion strategy' do | |||
|       session. | ||||
|         run_command('autoload compinit && compinit'). | ||||
|         run_command('_foo() { compadd bar; compadd bat }'). | ||||
|         run_command('compdef _foo baz') | ||||
|         run_command('_num() { compadd two; compadd three }'). | ||||
|         run_command('compdef _foo baz'). | ||||
|         run_command('compdef _num one') | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | @ -37,6 +39,21 @@ describe 'the `completion` suggestion strategy' do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   context 'when ZSH_AUTOSUGGEST_COMPLETION_IGNORE is set to a pattern' do | ||||
|     let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=completion', 'ZSH_AUTOSUGGEST_COMPLETION_IGNORE="one *"'] } | ||||
| 
 | ||||
|     it 'makes suggestions when the buffer does not match the pattern' do | ||||
|       session.send_string('baz ') | ||||
|       wait_for { session.content }.to eq('baz bar') | ||||
|     end | ||||
| 
 | ||||
|     it 'does not make suggestions when the buffer matches the pattern' do | ||||
|       session.send_string('one t') | ||||
|       sleep 1 | ||||
|       expect(session.content).to eq('one t') | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   context 'when async mode is enabled' do | ||||
|     let(:options) { ['ZSH_AUTOSUGGEST_USE_ASYNC=true', 'ZSH_AUTOSUGGEST_STRATEGY=completion'] } | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,5 +8,16 @@ describe 'the `history` suggestion strategy' do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   context 'when ZSH_AUTOSUGGEST_HISTORY_IGNORE is set to a pattern' do | ||||
|     let(:options) { ['ZSH_AUTOSUGGEST_HISTORY_IGNORE="* bar"'] } | ||||
| 
 | ||||
|     it 'does not make suggestions that match the pattern' do | ||||
|       with_history('ls foo', 'ls bar', 'echo baz') do | ||||
|         session.send_string('ls') | ||||
|         wait_for { session.content }.to eq('ls foo') | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   include_examples 'special characters' | ||||
| end | ||||
|  |  | |||
|  | @ -3,19 +3,32 @@ require 'strategies/special_characters_helper' | |||
| describe 'the `match_prev_cmd` strategy' do | ||||
|   let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd'] } | ||||
| 
 | ||||
|   it 'suggests the last matching history entry after the previous command' do | ||||
|     with_history( | ||||
|   let(:history) { [ | ||||
|     'echo what', | ||||
|     'ls foo', | ||||
|     'echo what', | ||||
|     'ls bar', | ||||
|     'ls baz', | ||||
|     'echo what' | ||||
|     ) do | ||||
|   ] } | ||||
| 
 | ||||
|   it 'suggests the last matching history entry after the previous command' do | ||||
|     with_history(*history) do | ||||
|       session.send_string('ls') | ||||
|       wait_for { session.content }.to eq('ls bar') | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   context 'when ZSH_AUTOSUGGEST_HISTORY_IGNORE is set to a pattern' do | ||||
|     let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=match_prev_cmd', 'ZSH_AUTOSUGGEST_HISTORY_IGNORE="* bar"'] } | ||||
| 
 | ||||
|     it 'does not make suggestions that match the pattern' do | ||||
|       with_history(*history) do | ||||
|         session.send_string('ls') | ||||
|         wait_for { session.content }.to eq('ls foo') | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   include_examples 'special characters' | ||||
| end | ||||
|  |  | |||
|  | @ -96,6 +96,12 @@ _zsh_autosuggest_capture_completion_async() { | |||
| } | ||||
| 
 | ||||
| _zsh_autosuggest_strategy_completion() { | ||||
| 	# Reset options to defaults and enable LOCAL_OPTIONS | ||||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Enable extended glob for completion ignore pattern | ||||
| 	setopt EXTENDED_GLOB | ||||
| 
 | ||||
| 	typeset -g suggestion | ||||
| 	local line REPLY | ||||
| 
 | ||||
|  | @ -105,6 +111,9 @@ _zsh_autosuggest_strategy_completion() { | |||
| 	# Exit if we don't have zpty | ||||
| 	zmodload zsh/zpty 2>/dev/null || return | ||||
| 
 | ||||
| 	# Exit if our search string matches the ignore pattern | ||||
| 	[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return | ||||
| 
 | ||||
| 	# Zle will be inactive if we are in async mode | ||||
| 	if zle; then | ||||
| 		zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync | ||||
|  | @ -122,7 +131,7 @@ _zsh_autosuggest_strategy_completion() { | |||
| 		# versions of zsh (older than 5.3), we sometimes get extra bytes after | ||||
| 		# the second null byte, so trim those off the end. | ||||
| 		# See http://www.zsh.org/mla/workers/2015/msg03290.html | ||||
| 		suggestion="${${line#*$'\0'}%$'\0'*}" | ||||
| 		suggestion="${${(@0)line}[2]}" | ||||
| 	} always { | ||||
| 		# Destroy the pty | ||||
| 		zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ _zsh_autosuggest_strategy_history() { | |||
| 	# Reset options to defaults and enable LOCAL_OPTIONS | ||||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Enable globbing flags so that we can use (#m) | ||||
| 	# Enable globbing flags so that we can use (#m) and (x~y) glob operator | ||||
| 	setopt EXTENDED_GLOB | ||||
| 
 | ||||
| 	# Escape backslashes and all of the glob operators so we can use | ||||
|  | @ -19,7 +19,14 @@ _zsh_autosuggest_strategy_history() { | |||
| 	# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 | ||||
| 	local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" | ||||
| 
 | ||||
| 	# Get the history items that match | ||||
| 	# Get the history items that match the prefix, excluding those that match | ||||
| 	# the ignore pattern | ||||
| 	local pattern="$prefix*" | ||||
| 	if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then | ||||
| 		pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" | ||||
| 	fi | ||||
| 
 | ||||
| 	# Give the first history item matching the pattern as the suggestion | ||||
| 	# - (r) subscript flag makes the pattern match on values | ||||
| 	typeset -g suggestion="${history[(r)${prefix}*]}" | ||||
| 	typeset -g suggestion="${history[(r)$pattern]}" | ||||
| } | ||||
|  |  | |||
|  | @ -24,16 +24,23 @@ _zsh_autosuggest_strategy_match_prev_cmd() { | |||
| 	# Reset options to defaults and enable LOCAL_OPTIONS | ||||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Enable globbing flags so that we can use (#m) | ||||
| 	# Enable globbing flags so that we can use (#m) and (x~y) glob operator | ||||
| 	setopt EXTENDED_GLOB | ||||
| 
 | ||||
| 	# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 | ||||
| 	local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" | ||||
| 
 | ||||
| 	# Get the history items that match the prefix, excluding those that match | ||||
| 	# the ignore pattern | ||||
| 	local pattern="$prefix*" | ||||
| 	if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then | ||||
| 		pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" | ||||
| 	fi | ||||
| 
 | ||||
| 	# Get all history event numbers that correspond to history | ||||
| 	# entries that match pattern $prefix* | ||||
| 	# entries that match the pattern | ||||
| 	local history_match_keys | ||||
| 	history_match_keys=(${(k)history[(R)$prefix*]}) | ||||
| 	history_match_keys=(${(k)history[(R)$~pattern]}) | ||||
| 
 | ||||
| 	# By default we use the first history number (most recent history entry) | ||||
| 	local histkey="${history_match_keys[1]}" | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ _zsh_autosuggest_modify() { | |||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Don't fetch a new suggestion if there's more input to be read immediately | ||||
| 	if (( $PENDING > 0 )) || (( $KEYS_QUEUED_COUNT > 0 )); then | ||||
| 	if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then | ||||
| 		POSTDISPLAY="$orig_postdisplay" | ||||
| 		return $retval | ||||
| 	fi | ||||
|  | @ -119,7 +119,7 @@ _zsh_autosuggest_suggest() { | |||
| 
 | ||||
| # Accept the entire suggestion | ||||
| _zsh_autosuggest_accept() { | ||||
| 	local -i max_cursor_pos=$#BUFFER | ||||
| 	local -i retval max_cursor_pos=$#BUFFER | ||||
| 
 | ||||
| 	# When vicmd keymap is active, the cursor can't move all the way | ||||
| 	# to the end of the buffer | ||||
|  | @ -127,23 +127,33 @@ _zsh_autosuggest_accept() { | |||
| 		max_cursor_pos=$((max_cursor_pos - 1)) | ||||
| 	fi | ||||
| 
 | ||||
| 	# If we're not in a valid state to accept a suggestion, just run the | ||||
| 	# original widget and bail out | ||||
| 	if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then | ||||
| 		_zsh_autosuggest_invoke_original_widget $@ | ||||
| 		return | ||||
| 	fi | ||||
| 
 | ||||
| 	# Only accept if the cursor is at the end of the buffer | ||||
| 	if [[ $CURSOR = $max_cursor_pos ]]; then | ||||
| 	# Add the suggestion to the buffer | ||||
| 	BUFFER="$BUFFER$POSTDISPLAY" | ||||
| 
 | ||||
| 	# Remove the suggestion | ||||
| 	unset POSTDISPLAY | ||||
| 
 | ||||
| 	# Run the original widget before manually moving the cursor so that the | ||||
| 	# cursor movement doesn't make the widget do something unexpected | ||||
| 	_zsh_autosuggest_invoke_original_widget $@ | ||||
| 	retval=$? | ||||
| 
 | ||||
| 	# Move the cursor to the end of the buffer | ||||
| 	if [[ "$KEYMAP" = "vicmd" ]]; then | ||||
| 		CURSOR=$(($#BUFFER - 1)) | ||||
| 	else | ||||
| 		CURSOR=$#BUFFER | ||||
| 	fi | ||||
| 	fi | ||||
| 
 | ||||
| 	_zsh_autosuggest_invoke_original_widget $@ | ||||
| 	return $retval | ||||
| } | ||||
| 
 | ||||
| # Accept the entire suggestion and execute it | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # Fish-like fast/unobtrusive autosuggestions for zsh. | ||||
| # https://github.com/zsh-users/zsh-autosuggestions | ||||
| # v0.6.3 | ||||
| # v0.6.4 | ||||
| # Copyright (c) 2013 Thiago de Arruda | ||||
| # Copyright (c) 2016-2019 Eric Freese | ||||
| #  | ||||
|  | @ -318,7 +318,7 @@ _zsh_autosuggest_modify() { | |||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Don't fetch a new suggestion if there's more input to be read immediately | ||||
| 	if (( $PENDING > 0 )) || (( $KEYS_QUEUED_COUNT > 0 )); then | ||||
| 	if (( $PENDING > 0 || $KEYS_QUEUED_COUNT > 0 )); then | ||||
| 		POSTDISPLAY="$orig_postdisplay" | ||||
| 		return $retval | ||||
| 	fi | ||||
|  | @ -381,7 +381,7 @@ _zsh_autosuggest_suggest() { | |||
| 
 | ||||
| # Accept the entire suggestion | ||||
| _zsh_autosuggest_accept() { | ||||
| 	local -i max_cursor_pos=$#BUFFER | ||||
| 	local -i retval max_cursor_pos=$#BUFFER | ||||
| 
 | ||||
| 	# When vicmd keymap is active, the cursor can't move all the way | ||||
| 	# to the end of the buffer | ||||
|  | @ -389,23 +389,33 @@ _zsh_autosuggest_accept() { | |||
| 		max_cursor_pos=$((max_cursor_pos - 1)) | ||||
| 	fi | ||||
| 
 | ||||
| 	# If we're not in a valid state to accept a suggestion, just run the | ||||
| 	# original widget and bail out | ||||
| 	if (( $CURSOR != $max_cursor_pos || !$#POSTDISPLAY )); then | ||||
| 		_zsh_autosuggest_invoke_original_widget $@ | ||||
| 		return | ||||
| 	fi | ||||
| 
 | ||||
| 	# Only accept if the cursor is at the end of the buffer | ||||
| 	if [[ $CURSOR = $max_cursor_pos ]]; then | ||||
| 	# Add the suggestion to the buffer | ||||
| 	BUFFER="$BUFFER$POSTDISPLAY" | ||||
| 
 | ||||
| 	# Remove the suggestion | ||||
| 	unset POSTDISPLAY | ||||
| 
 | ||||
| 	# Run the original widget before manually moving the cursor so that the | ||||
| 	# cursor movement doesn't make the widget do something unexpected | ||||
| 	_zsh_autosuggest_invoke_original_widget $@ | ||||
| 	retval=$? | ||||
| 
 | ||||
| 	# Move the cursor to the end of the buffer | ||||
| 	if [[ "$KEYMAP" = "vicmd" ]]; then | ||||
| 		CURSOR=$(($#BUFFER - 1)) | ||||
| 	else | ||||
| 		CURSOR=$#BUFFER | ||||
| 	fi | ||||
| 	fi | ||||
| 
 | ||||
| 	_zsh_autosuggest_invoke_original_widget $@ | ||||
| 	return $retval | ||||
| } | ||||
| 
 | ||||
| # Accept the entire suggestion and execute it | ||||
|  | @ -582,6 +592,12 @@ _zsh_autosuggest_capture_completion_async() { | |||
| } | ||||
| 
 | ||||
| _zsh_autosuggest_strategy_completion() { | ||||
| 	# Reset options to defaults and enable LOCAL_OPTIONS | ||||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Enable extended glob for completion ignore pattern | ||||
| 	setopt EXTENDED_GLOB | ||||
| 
 | ||||
| 	typeset -g suggestion | ||||
| 	local line REPLY | ||||
| 
 | ||||
|  | @ -591,6 +607,9 @@ _zsh_autosuggest_strategy_completion() { | |||
| 	# Exit if we don't have zpty | ||||
| 	zmodload zsh/zpty 2>/dev/null || return | ||||
| 
 | ||||
| 	# Exit if our search string matches the ignore pattern | ||||
| 	[[ -n "$ZSH_AUTOSUGGEST_COMPLETION_IGNORE" ]] && [[ "$1" == $~ZSH_AUTOSUGGEST_COMPLETION_IGNORE ]] && return | ||||
| 
 | ||||
| 	# Zle will be inactive if we are in async mode | ||||
| 	if zle; then | ||||
| 		zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync | ||||
|  | @ -608,7 +627,7 @@ _zsh_autosuggest_strategy_completion() { | |||
| 		# versions of zsh (older than 5.3), we sometimes get extra bytes after | ||||
| 		# the second null byte, so trim those off the end. | ||||
| 		# See http://www.zsh.org/mla/workers/2015/msg03290.html | ||||
| 		suggestion="${${line#*$'\0'}%$'\0'*}" | ||||
| 		suggestion="${${(@0)line}[2]}" | ||||
| 	} always { | ||||
| 		# Destroy the pty | ||||
| 		zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME | ||||
|  | @ -626,7 +645,7 @@ _zsh_autosuggest_strategy_history() { | |||
| 	# Reset options to defaults and enable LOCAL_OPTIONS | ||||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Enable globbing flags so that we can use (#m) | ||||
| 	# Enable globbing flags so that we can use (#m) and (x~y) glob operator | ||||
| 	setopt EXTENDED_GLOB | ||||
| 
 | ||||
| 	# Escape backslashes and all of the glob operators so we can use | ||||
|  | @ -635,9 +654,16 @@ _zsh_autosuggest_strategy_history() { | |||
| 	# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 | ||||
| 	local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" | ||||
| 
 | ||||
| 	# Get the history items that match | ||||
| 	# Get the history items that match the prefix, excluding those that match | ||||
| 	# the ignore pattern | ||||
| 	local pattern="$prefix*" | ||||
| 	if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then | ||||
| 		pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" | ||||
| 	fi | ||||
| 
 | ||||
| 	# Give the first history item matching the pattern as the suggestion | ||||
| 	# - (r) subscript flag makes the pattern match on values | ||||
| 	typeset -g suggestion="${history[(r)${prefix}*]}" | ||||
| 	typeset -g suggestion="${history[(r)$pattern]}" | ||||
| } | ||||
| 
 | ||||
| #--------------------------------------------------------------------# | ||||
|  | @ -665,16 +691,23 @@ _zsh_autosuggest_strategy_match_prev_cmd() { | |||
| 	# Reset options to defaults and enable LOCAL_OPTIONS | ||||
| 	emulate -L zsh | ||||
| 
 | ||||
| 	# Enable globbing flags so that we can use (#m) | ||||
| 	# Enable globbing flags so that we can use (#m) and (x~y) glob operator | ||||
| 	setopt EXTENDED_GLOB | ||||
| 
 | ||||
| 	# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 | ||||
| 	local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" | ||||
| 
 | ||||
| 	# Get the history items that match the prefix, excluding those that match | ||||
| 	# the ignore pattern | ||||
| 	local pattern="$prefix*" | ||||
| 	if [[ -n $ZSH_AUTOSUGGEST_HISTORY_IGNORE ]]; then | ||||
| 		pattern="($pattern)~($ZSH_AUTOSUGGEST_HISTORY_IGNORE)" | ||||
| 	fi | ||||
| 
 | ||||
| 	# Get all history event numbers that correspond to history | ||||
| 	# entries that match pattern $prefix* | ||||
| 	# entries that match the pattern | ||||
| 	local history_match_keys | ||||
| 	history_match_keys=(${(k)history[(R)$prefix*]}) | ||||
| 	history_match_keys=(${(k)history[(R)$~pattern]}) | ||||
| 
 | ||||
| 	# By default we use the first history number (most recent history entry) | ||||
| 	local histkey="${history_match_keys[1]}" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue