Merge pull request #613 from zsh-users/develop

v0.7.0
This commit is contained in:
Eric Freese 2021-06-04 16:05:04 -06:00 committed by GitHub
commit a411ef3e09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 127 additions and 99 deletions

View file

@ -1,5 +1,11 @@
# Changelog # Changelog
## v0.7.0
- Enable asynchronous mode by default (#498)
- No longer wrap user widgets starting with `autosuggest-` prefix (#496)
- Fix a bug wrapping widgets that modify the buffer (#541)
## v0.6.4 ## v0.6.4
- Fix `vi-forward-char` triggering a bell when using it to accept a suggestion (#488) - 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 skip completion suggestions when buffer matches a pattern (#487)

View file

@ -39,7 +39,10 @@
2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`): 2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`):
```sh ```sh
plugins=(zsh-autosuggestions) plugins=(
# other plugins...
zsh-autosuggestions
)
``` ```
3. Start a new terminal session. 3. Start a new terminal session.

View file

@ -1,5 +1,5 @@
Copyright (c) 2013 Thiago de Arruda Copyright (c) 2013 Thiago de Arruda
Copyright (c) 2016-2019 Eric Freese Copyright (c) 2016-2021 Eric Freese
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation

View file

@ -79,9 +79,11 @@ Widgets that modify the buffer and are not found in any of these arrays will fet
Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20. Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20.
This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for strings that are too long. This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for strings that are too long.
### Enable Asynchronous Mode ### Asynchronous Mode
As of `v0.4.0`, suggestions can be fetched asynchronously. To enable this behavior, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable (it can be set to anything). Suggestions are fetched asynchronously by default in zsh versions 5.0.8 and greater. To disable asynchronous suggestions and fetch them synchronously instead, `unset ZSH_AUTOSUGGEST_USE_ASYNC` after sourcing the plugin.
Alternatively, if you are using a version of zsh older than 5.0.8 and want to enable asynchronous mode, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable after sourcing the plugin (it can be set to anything). Note that there is [a bug](https://github.com/zsh-users/zsh-autosuggestions/issues/364#issuecomment-481423232) in versions of zsh older than 5.0.8 where <kbd>ctrl</kbd> + <kbd>c</kbd> will fail to reset the prompt immediately after fetching a suggestion asynchronously.
### Disabling automatic widget re-binding ### Disabling automatic widget re-binding
@ -89,13 +91,13 @@ Set `ZSH_AUTOSUGGEST_MANUAL_REBIND` (it can be set to anything) to disable autom
### Ignoring history suggestions that match a pattern ### 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. Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) 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. **Note:** This only affects the `history` and `match_prev_cmd` suggestion strategies.
### Skipping completion suggestions for certain cases ### 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. Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) 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. **Note:** This only affects the `completion` suggestion strategy.

View file

@ -1 +1 @@
v0.6.4 v0.7.0

View file

@ -14,3 +14,4 @@
5.5.1 5.5.1
5.6.2 5.6.2
5.7.1 5.7.1
5.8

View file

@ -1,11 +1,6 @@
describe 'a multi-line suggestion' do describe 'a multi-line suggestion' do
it 'should be displayed on multiple lines' do it 'should be displayed on multiple lines' do
with_history(-> { with_history("echo \"\n\"") do
session.send_string('echo "')
session.send_keys('enter')
session.send_string('"')
session.send_keys('enter')
}) do
session.send_keys('e') session.send_keys('e')
wait_for { session.content }.to eq("echo \"\n\"") wait_for { session.content }.to eq("echo \"\n\"")
end end

View file

@ -1,7 +0,0 @@
describe 'suggestion fetching' do
it 'is performed synchronously'
context 'when ZSH_AUTOSUGGEST_USE_ASYNC is set' do
it 'is performed asynchronously'
end
end

View file

@ -1,6 +1,7 @@
require 'pry' require 'pry'
require 'rspec/wait' require 'rspec/wait'
require 'terminal_session' require 'terminal_session'
require 'tempfile'
RSpec.shared_context 'terminal session' do RSpec.shared_context 'terminal session' do
let(:term_opts) { {} } let(:term_opts) { {} }
@ -21,11 +22,12 @@ RSpec.shared_context 'terminal session' do
end end
def with_history(*commands, &block) def with_history(*commands, &block)
session.run_command('fc -p') Tempfile.create do |f|
f.write(commands.map{|c| c.gsub("\n", "\\\n")}.join("\n"))
f.flush
commands.each do |c| session.run_command('fc -p')
c.respond_to?(:call) ? c.call : session.run_command(c) session.run_command("fc -R #{f.path}")
end
session.clear_screen session.clear_screen
@ -35,6 +37,7 @@ RSpec.shared_context 'terminal session' do
session.run_command('fc -P') session.run_command('fc -P')
end end
end end
end
RSpec.configure do |config| RSpec.configure do |config|
config.expect_with :rspec do |expectations| config.expect_with :rspec do |expectations|

View file

@ -1,58 +1,71 @@
shared_examples 'special characters' do shared_examples 'special characters' do
describe 'a special character in the buffer' do describe 'a special character in the buffer should be treated like any other character' do
it 'should be treated like any other character' do it 'asterisk' do
with_history('echo "hello*"', 'echo "hello."') do with_history('echo "hello*"', 'echo "hello."') do
session.send_string('echo "hello*') session.send_string('echo "hello*')
wait_for { session.content }.to eq('echo "hello*"') wait_for { session.content }.to eq('echo "hello*"')
end end
end
it 'question mark' do
with_history('echo "hello?"', 'echo "hello."') do with_history('echo "hello?"', 'echo "hello."') do
session.send_string('echo "hello?') session.send_string('echo "hello?')
wait_for { session.content }.to eq('echo "hello?"') wait_for { session.content }.to eq('echo "hello?"')
end end
end
it 'backslash' do
with_history('echo "hello\nworld"') do with_history('echo "hello\nworld"') do
session.send_string('echo "hello\\') session.send_string('echo "hello\\')
wait_for { session.content }.to eq('echo "hello\nworld"') wait_for { session.content }.to eq('echo "hello\nworld"')
end end
end
it 'double backslash' do
with_history('echo "\\\\"') do with_history('echo "\\\\"') do
session.send_string('echo "\\\\') session.send_string('echo "\\\\')
wait_for { session.content }.to eq('echo "\\\\"') wait_for { session.content }.to eq('echo "\\\\"')
end end
end
it 'tilde' do
with_history('echo ~/foo') do with_history('echo ~/foo') do
session.send_string('echo ~') session.send_string('echo ~')
wait_for { session.content }.to eq('echo ~/foo') wait_for { session.content }.to eq('echo ~/foo')
end end
end
it 'parentheses' do
with_history('echo "$(ls foo)"') do with_history('echo "$(ls foo)"') do
session.send_string('echo "$(') session.send_string('echo "$(')
wait_for { session.content }.to eq('echo "$(ls foo)"') wait_for { session.content }.to eq('echo "$(ls foo)"')
end end
end
it 'square bracket' do
with_history('echo "$history[123]"') do with_history('echo "$history[123]"') do
session.send_string('echo "$history[') session.send_string('echo "$history[')
wait_for { session.content }.to eq('echo "$history[123]"') wait_for { session.content }.to eq('echo "$history[123]"')
session.send_string('123]') session.send_string('123]')
wait_for { session.content }.to eq('echo "$history[123]"') wait_for { session.content }.to eq('echo "$history[123]"')
end end
end
it 'octothorpe' do
with_history('echo "#yolo"') do with_history('echo "#yolo"') do
session.send_string('echo "#') session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#yolo"') wait_for { session.content }.to eq('echo "#yolo"')
end end
with_history('echo "#foo"', 'echo $#abc') do
session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#foo"')
end end
it 'caret' do
with_history('echo "^A"', 'echo "^B"') do with_history('echo "^A"', 'echo "^B"') do
session.send_string('echo "^A') session.send_string('echo "^A')
wait_for { session.content }.to eq('echo "^A"') wait_for { session.content }.to eq('echo "^A"')
end end
end
it 'dash' do
with_history('-foo() {}') do with_history('-foo() {}') do
session.send_string('-') session.send_string('-')
wait_for { session.content }.to eq('-foo() {}') wait_for { session.content }.to eq('-foo() {}')

View file

@ -44,7 +44,8 @@ _zsh_autosuggest_async_request() {
# There's a weird bug here where ^C stops working unless we force a fork # There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
command true autoload -Uz is-at-least
is-at-least 5.8 || command true
# Read the pid from the child process # Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD

View file

@ -69,7 +69,7 @@ _zsh_autosuggest_bind_widgets() {
ignore_widgets=( ignore_widgets=(
.\* .\*
_\* _\*
autosuggest-\* ${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\* $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS $ZSH_AUTOSUGGEST_IGNORE_WIDGETS
) )

View file

@ -18,6 +18,16 @@ _zsh_autosuggest_start() {
_zsh_autosuggest_bind_widgets _zsh_autosuggest_bind_widgets
} }
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd # Start the autosuggestion widgets on the next precmd
autoload -Uz add-zsh-hook
add-zsh-hook precmd _zsh_autosuggest_start add-zsh-hook precmd _zsh_autosuggest_start

View file

@ -45,8 +45,6 @@ _zsh_autosuggest_capture_completion_widget() {
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() { _zsh_autosuggest_capture_setup() {
autoload -Uz is-at-least
# There is a bug in zpty module in older zsh versions by which a # There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked # zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty # before it. Here we set up a zsh exit hook to SIGKILL the zpty

View file

@ -20,7 +20,7 @@ _zsh_autosuggest_enable() {
# Toggle suggestions (enable/disable) # Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() { _zsh_autosuggest_toggle() {
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
_zsh_autosuggest_enable _zsh_autosuggest_enable
else else
_zsh_autosuggest_disable _zsh_autosuggest_disable
@ -61,25 +61,14 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Optimize if manually typing in the suggestion # Optimize if manually typing in the suggestion or if buffer hasn't changed
if (( $#BUFFER > $#orig_buffer )); then if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
local added=${BUFFER#$orig_buffer} POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
# If the string added matches the beginning of the postdisplay
if [[ "$added" = "${orig_postdisplay:0:$#added}" ]]; then
POSTDISPLAY="${orig_postdisplay:$#added}"
return $retval
fi
fi
# Don't fetch a new suggestion if the buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer" ]]; then
POSTDISPLAY="$orig_postdisplay"
return $retval return $retval
fi fi
# Bail out if suggestions are disabled # Bail out if suggestions are disabled
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
return $? return $?
fi fi
@ -205,8 +194,21 @@ _zsh_autosuggest_partial_accept() {
} }
() { () {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
local action local action
for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval local -i retval
@ -223,12 +225,7 @@ _zsh_autosuggest_partial_accept() {
}" }"
done done
zle -N autosuggest-fetch _zsh_autosuggest_widget_fetch for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest zle -N autosuggest-$action _zsh_autosuggest_widget_$action
zle -N autosuggest-accept _zsh_autosuggest_widget_accept done
zle -N autosuggest-clear _zsh_autosuggest_widget_clear
zle -N autosuggest-execute _zsh_autosuggest_widget_execute
zle -N autosuggest-enable _zsh_autosuggest_widget_enable
zle -N autosuggest-disable _zsh_autosuggest_widget_disable
zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
} }

View file

@ -1,8 +1,8 @@
# 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.6.4 # v0.7.0
# Copyright (c) 2013 Thiago de Arruda # Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016-2019 Eric Freese # Copyright (c) 2016-2021 Eric Freese
# #
# Permission is hereby granted, free of charge, to any person # Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation # obtaining a copy of this software and associated documentation
@ -199,7 +199,7 @@ _zsh_autosuggest_bind_widgets() {
ignore_widgets=( ignore_widgets=(
.\* .\*
_\* _\*
autosuggest-\* ${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\* $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS $ZSH_AUTOSUGGEST_IGNORE_WIDGETS
) )
@ -282,7 +282,7 @@ _zsh_autosuggest_enable() {
# Toggle suggestions (enable/disable) # Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() { _zsh_autosuggest_toggle() {
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
_zsh_autosuggest_enable _zsh_autosuggest_enable
else else
_zsh_autosuggest_disable _zsh_autosuggest_disable
@ -323,25 +323,14 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Optimize if manually typing in the suggestion # Optimize if manually typing in the suggestion or if buffer hasn't changed
if (( $#BUFFER > $#orig_buffer )); then if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
local added=${BUFFER#$orig_buffer} POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
# If the string added matches the beginning of the postdisplay
if [[ "$added" = "${orig_postdisplay:0:$#added}" ]]; then
POSTDISPLAY="${orig_postdisplay:$#added}"
return $retval
fi
fi
# Don't fetch a new suggestion if the buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer" ]]; then
POSTDISPLAY="$orig_postdisplay"
return $retval return $retval
fi fi
# Bail out if suggestions are disabled # Bail out if suggestions are disabled
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
return $? return $?
fi fi
@ -467,8 +456,21 @@ _zsh_autosuggest_partial_accept() {
} }
() { () {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
local action local action
for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval local -i retval
@ -485,14 +487,9 @@ _zsh_autosuggest_partial_accept() {
}" }"
done done
zle -N autosuggest-fetch _zsh_autosuggest_widget_fetch for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest zle -N autosuggest-$action _zsh_autosuggest_widget_$action
zle -N autosuggest-accept _zsh_autosuggest_widget_accept done
zle -N autosuggest-clear _zsh_autosuggest_widget_clear
zle -N autosuggest-execute _zsh_autosuggest_widget_execute
zle -N autosuggest-enable _zsh_autosuggest_widget_enable
zle -N autosuggest-disable _zsh_autosuggest_widget_disable
zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
} }
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@ -541,8 +538,6 @@ _zsh_autosuggest_capture_completion_widget() {
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() { _zsh_autosuggest_capture_setup() {
autoload -Uz is-at-least
# There is a bug in zpty module in older zsh versions by which a # There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked # zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty # before it. Here we set up a zsh exit hook to SIGKILL the zpty
@ -804,7 +799,8 @@ _zsh_autosuggest_async_request() {
# There's a weird bug here where ^C stops working unless we force a fork # There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
command true autoload -Uz is-at-least
is-at-least 5.8 || command true
# Read the pid from the child process # Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
@ -853,6 +849,16 @@ _zsh_autosuggest_start() {
_zsh_autosuggest_bind_widgets _zsh_autosuggest_bind_widgets
} }
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd # Start the autosuggestion widgets on the next precmd
autoload -Uz add-zsh-hook
add-zsh-hook precmd _zsh_autosuggest_start add-zsh-hook precmd _zsh_autosuggest_start