Compare commits

..

1 Commits

Author SHA1 Message Date
Eric Freese
767d55eba0 Allow loading the plugin in the background
If zle is already active (plugin has been loaded in the background),
just start the widgets and set up the automatic re-binding (if manual
rebind has not been specified).

See GitHub issue #481
2020-01-26 21:49:59 -07:00
15 changed files with 107 additions and 123 deletions

View File

@@ -1,11 +1,5 @@
# 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,10 +39,7 @@
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=( plugins=(zsh-autosuggestions)
# 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-2021 Eric Freese Copyright (c) 2016-2019 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,11 +79,9 @@ 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.
### Asynchronous Mode ### Enable Asynchronous Mode
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. 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).
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
@@ -91,13 +89,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](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. 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. **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](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. 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. **Note:** This only affects the `completion` suggestion strategy.

View File

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

View File

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

View File

@@ -1,6 +1,11 @@
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("echo \"\n\"") do with_history(-> {
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

@@ -0,0 +1,7 @@
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,7 +1,6 @@
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) { {} }
@@ -22,12 +21,11 @@ RSpec.shared_context 'terminal session' do
end end
def with_history(*commands, &block) def with_history(*commands, &block)
Tempfile.create do |f|
f.write(commands.map{|c| c.gsub("\n", "\\\n")}.join("\n"))
f.flush
session.run_command('fc -p') session.run_command('fc -p')
session.run_command("fc -R #{f.path}")
commands.each do |c|
c.respond_to?(:call) ? c.call : session.run_command(c)
end
session.clear_screen session.clear_screen
@@ -37,7 +35,6 @@ 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,71 +1,58 @@
shared_examples 'special characters' do shared_examples 'special characters' do
describe 'a special character in the buffer should be treated like any other character' do describe 'a special character in the buffer' do
it 'asterisk' do it 'should be treated like any other character' 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,8 +44,7 @@ _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
autoload -Uz is-at-least command true
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=(
.\* .\*
_\* _\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-} autosuggest-\*
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\* $ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS $ZSH_AUTOSUGGEST_IGNORE_WIDGETS
) )

View File

@@ -21,13 +21,11 @@ _zsh_autosuggest_start() {
# Mark for auto-loading the functions that we use # Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for # If zle is already running, go ahead and start the autosuggestion widgets.
# older versions because there is a bug when using async mode where ^C does not # Otherwise, wait until the next precmd.
# work immediately after fetching a suggestion. if zle; then
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 _zsh_autosuggest_start
if is-at-least 5.0.8; then (( ! ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )) && add-zsh-hook precmd _zsh_autosuggest_start
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC= else
fi
# Start the autosuggestion widgets on the next precmd
add-zsh-hook precmd _zsh_autosuggest_start add-zsh-hook precmd _zsh_autosuggest_start
fi

View File

@@ -20,7 +20,7 @@ _zsh_autosuggest_enable() {
# Toggle suggestions (enable/disable) # Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() { _zsh_autosuggest_toggle() {
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
_zsh_autosuggest_enable _zsh_autosuggest_enable
else else
_zsh_autosuggest_disable _zsh_autosuggest_disable
@@ -61,14 +61,25 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed # Optimize if manually typing in the suggestion
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then if (( $#BUFFER > $#orig_buffer )); then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}" local added=${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 (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
return $? return $?
fi fi
@@ -194,21 +205,8 @@ _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 $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval local -i retval
@@ -225,7 +223,12 @@ _zsh_autosuggest_partial_accept() {
}" }"
done done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do zle -N autosuggest-fetch _zsh_autosuggest_widget_fetch
zle -N autosuggest-$action _zsh_autosuggest_widget_$action zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
done zle -N autosuggest-accept _zsh_autosuggest_widget_accept
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.7.0 # v0.6.4
# Copyright (c) 2013 Thiago de Arruda # Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016-2021 Eric Freese # Copyright (c) 2016-2019 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=(
.\* .\*
_\* _\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-} 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 (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
_zsh_autosuggest_enable _zsh_autosuggest_enable
else else
_zsh_autosuggest_disable _zsh_autosuggest_disable
@@ -323,14 +323,25 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed # Optimize if manually typing in the suggestion
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then if (( $#BUFFER > $#orig_buffer )); then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}" local added=${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 (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
return $? return $?
fi fi
@@ -456,21 +467,8 @@ _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 $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval local -i retval
@@ -487,9 +485,14 @@ _zsh_autosuggest_partial_accept() {
}" }"
done done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do zle -N autosuggest-fetch _zsh_autosuggest_widget_fetch
zle -N autosuggest-$action _zsh_autosuggest_widget_$action zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
done zle -N autosuggest-accept _zsh_autosuggest_widget_accept
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
} }
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@@ -799,8 +802,7 @@ _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
autoload -Uz is-at-least command true
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
@@ -852,13 +854,11 @@ _zsh_autosuggest_start() {
# Mark for auto-loading the functions that we use # Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for # If zle is already running, go ahead and start the autosuggestion widgets.
# older versions because there is a bug when using async mode where ^C does not # Otherwise, wait until the next precmd.
# work immediately after fetching a suggestion. if zle; then
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 _zsh_autosuggest_start
if is-at-least 5.0.8; then (( ! ${+ZSH_AUTOSUGGEST_MANUAL_REBIND} )) && add-zsh-hook precmd _zsh_autosuggest_start
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC= else
fi
# Start the autosuggestion widgets on the next precmd
add-zsh-hook precmd _zsh_autosuggest_start add-zsh-hook precmd _zsh_autosuggest_start
fi