Merge pull request #223 from zsh-users/fixes/bpm_async_fix

Fixes/bpm async fix
This commit is contained in:
Eric Freese 2017-03-05 12:59:19 -05:00 committed by GitHub
commit 40b96f6cfd
10 changed files with 265 additions and 3 deletions

View file

@ -101,11 +101,15 @@ As of `v0.4.0`, suggestions are fetched asynchronously using the `zsh/zpty` modu
### Key Bindings ### Key Bindings
This plugin provides three widgets that you can use with `bindkey`: This plugin provides a few widgets that you can use with `bindkey`:
1. `autosuggest-accept`: Accepts the current suggestion. 1. `autosuggest-accept`: Accepts the current suggestion.
2. `autosuggest-execute`: Accepts and executes the current suggestion. 2. `autosuggest-execute`: Accepts and executes the current suggestion.
3. `autosuggest-clear`: Clears the current suggestion. 3. `autosuggest-clear`: Clears the current suggestion.
4. `autosuggest-fetch`: Fetches a suggestion (works even when suggestions are disabled).
5. `autosuggest-disable`: Disables suggestions.
6. `autosuggest-enable`: Re-enables suggestions.
7. `autosuggest-toggle`: Toggles between enabled/disabled suggestions.
For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion. For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion.

View file

@ -0,0 +1,36 @@
describe 'pasting using bracketed-paste-magic' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -Uz bracketed-paste-magic').
run_command('zle -N bracketed-paste bracketed-paste-magic')
end
end
context 'with suggestions disabled while pasting' do
before do
session.
run_command('bpm_init() { zle autosuggest-disable }').
run_command('bpm_finish() { zle autosuggest-enable }').
run_command('zstyle :bracketed-paste-magic paste-init bpm_init').
run_command('zstyle :bracketed-paste-magic paste-finish bpm_finish')
end
it 'does not show an incorrect suggestion' do
with_history('echo hello') do
session.paste_string("echo #{'a' * 60}")
sleep 1
expect(session.content).to eq("echo #{'a' * 60}")
end
end
it 'shows a suggestion after a non-modifying keystroke' do
with_history('echo hello') do
session.paste_string('echo')
sleep 1
session.send_keys('left')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View file

@ -0,0 +1,24 @@
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('foo() { zle -U - "echo hello" }; zle -N foo; bindkey ^B foo')
end
end
let(:options) { ['unset ZSH_AUTOSUGGEST_USE_ASYNC', 'ZSH_AUTOSUGGEST_STRATEGY=test'] }
# TODO: This is only possible with the $KEYS_QUEUED_COUNT widget parameter, coming soon...
xit 'does not fetch a suggestion for every inserted character' do
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
end
it 'shows a suggestion when the widget completes' do
with_history('echo hello world') do
session.send_keys('C-b')
wait_for { session.content(esc_seqs: true) }.to match(/\Aecho hello\e\[[0-9]+m world/)
end
end
end

View file

@ -41,6 +41,13 @@ class TerminalSession
self self
end end
def paste_string(str)
tmux_command("set-buffer -- '#{str}'")
tmux_command("paste-buffer -dpr -t 0")
self
end
def content(esc_seqs: false) def content(esc_seqs: false)
cmd = 'capture-pane -p -t 0' cmd = 'capture-pane -p -t 0'
cmd += ' -e' if esc_seqs cmd += ' -e' if esc_seqs

View file

@ -0,0 +1,19 @@
describe 'the `autosuggest-disable` widget' do
before do
session.run_command('bindkey ^B autosuggest-disable')
end
it 'disables suggestions and clears the suggestion' do
with_history('echo hello') do
session.send_string('echo')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo')
session.send_string(' h')
sleep 1
expect(session.content).to eq('echo h')
end
end
end

View file

@ -0,0 +1,42 @@
describe 'the `autosuggest-enable` widget' do
before do
session.
run_command('typeset -g _ZSH_AUTOSUGGEST_DISABLED').
run_command('bindkey ^B autosuggest-enable')
end
it 'enables suggestions and fetches a suggestion' do
with_history('echo hello') do
session.send_string('e')
sleep 1
expect(session.content).to eq('e')
session.send_keys('C-b')
session.send_string('c')
wait_for { session.content }.to eq('echo hello')
end
end
context 'invoked on an empty buffer' do
it 'does not fetch a suggestion' do
with_history('echo hello') do
session.send_keys('C-b')
sleep 1
expect(session.content).to eq('')
end
end
end
context 'invoked on a non-empty buffer' do
it 'fetches a suggestion' do
with_history('echo hello') do
session.send_string('e')
sleep 1
expect(session.content).to eq('e')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View file

@ -0,0 +1,24 @@
describe 'the `autosuggest-fetch` widget' do
context 'when suggestions are disabled' do
before do
session.
run_command('bindkey ^B autosuggest-disable').
run_command('bindkey ^F autosuggest-fetch').
send_keys('C-b')
end
it 'will fetch and display a suggestion' do
with_history('echo hello') do
session.send_string('echo h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-f')
wait_for { session.content }.to eq('echo hello')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View file

@ -0,0 +1,26 @@
describe 'the `autosuggest-toggle` widget' do
before do
session.run_command('bindkey ^B autosuggest-toggle')
end
it 'toggles suggestions' do
with_history('echo world', 'echo hello') do
session.send_string('echo')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo')
session.send_string(' h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-b')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-h')
session.send_string('w')
wait_for { session.content }.to eq('echo world')
end
end
end

View file

@ -3,6 +3,30 @@
# Autosuggest Widget Implementations # # Autosuggest Widget Implementations #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Disable suggestions
_zsh_autosuggest_disable() {
typeset -g _ZSH_AUTOSUGGEST_DISABLED
_zsh_autosuggest_clear
}
# Enable suggestions
_zsh_autosuggest_enable() {
unset _ZSH_AUTOSUGGEST_DISABLED
if [ $#BUFFER -gt 0 ]; then
_zsh_autosuggest_fetch
fi
}
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if [ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]; then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
fi
}
# Clear the suggestion # Clear the suggestion
_zsh_autosuggest_clear() { _zsh_autosuggest_clear() {
# Remove the suggestion # Remove the suggestion
@ -15,6 +39,9 @@ _zsh_autosuggest_clear() {
_zsh_autosuggest_modify() { _zsh_autosuggest_modify() {
local -i retval local -i retval
# Only added to zsh very recently
local -i KEYS_QUEUED_COUNT
# Save the contents of the buffer/postdisplay # Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER" local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY" local orig_postdisplay="$POSTDISPLAY"
@ -26,6 +53,11 @@ _zsh_autosuggest_modify() {
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$? retval=$?
# Don't fetch a new suggestion if there's more input to be read immediately
if [[ $PENDING > 0 ]] || [[ $KEYS_QUEUED_COUNT > 0 ]]; then
return $retval
fi
# Optimize if manually typing in the suggestion # Optimize if manually typing in the suggestion
if [ $#BUFFER -gt $#orig_buffer ]; then if [ $#BUFFER -gt $#orig_buffer ]; then
local added=${BUFFER#$orig_buffer} local added=${BUFFER#$orig_buffer}
@ -43,6 +75,11 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Bail out if suggestions are disabled
if [ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]; then
return $?
fi
# Get a new suggestion if the buffer is not empty after modification # Get a new suggestion if the buffer is not empty after modification
if [ $#BUFFER -gt 0 ]; then if [ $#BUFFER -gt 0 ]; then
if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -le "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -le "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then
@ -142,7 +179,7 @@ _zsh_autosuggest_partial_accept() {
return $retval return $retval
} }
for action in clear modify fetch suggest accept partial_accept execute; 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
@ -164,3 +201,6 @@ zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
zle -N autosuggest-accept _zsh_autosuggest_widget_accept zle -N autosuggest-accept _zsh_autosuggest_widget_accept
zle -N autosuggest-clear _zsh_autosuggest_widget_clear zle -N autosuggest-clear _zsh_autosuggest_widget_clear
zle -N autosuggest-execute _zsh_autosuggest_widget_execute 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

@ -281,6 +281,30 @@ _zsh_autosuggest_highlight_apply() {
# Autosuggest Widget Implementations # # Autosuggest Widget Implementations #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Disable suggestions
_zsh_autosuggest_disable() {
typeset -g _ZSH_AUTOSUGGEST_DISABLED
_zsh_autosuggest_clear
}
# Enable suggestions
_zsh_autosuggest_enable() {
unset _ZSH_AUTOSUGGEST_DISABLED
if [ $#BUFFER -gt 0 ]; then
_zsh_autosuggest_fetch
fi
}
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if [ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]; then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
fi
}
# Clear the suggestion # Clear the suggestion
_zsh_autosuggest_clear() { _zsh_autosuggest_clear() {
# Remove the suggestion # Remove the suggestion
@ -293,6 +317,9 @@ _zsh_autosuggest_clear() {
_zsh_autosuggest_modify() { _zsh_autosuggest_modify() {
local -i retval local -i retval
# Only added to zsh very recently
local -i KEYS_QUEUED_COUNT
# Save the contents of the buffer/postdisplay # Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER" local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY" local orig_postdisplay="$POSTDISPLAY"
@ -304,6 +331,11 @@ _zsh_autosuggest_modify() {
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$? retval=$?
# Don't fetch a new suggestion if there's more input to be read immediately
if [[ $PENDING > 0 ]] || [[ $KEYS_QUEUED_COUNT > 0 ]]; then
return $retval
fi
# Optimize if manually typing in the suggestion # Optimize if manually typing in the suggestion
if [ $#BUFFER -gt $#orig_buffer ]; then if [ $#BUFFER -gt $#orig_buffer ]; then
local added=${BUFFER#$orig_buffer} local added=${BUFFER#$orig_buffer}
@ -321,6 +353,11 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Bail out if suggestions are disabled
if [ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]; then
return $?
fi
# Get a new suggestion if the buffer is not empty after modification # Get a new suggestion if the buffer is not empty after modification
if [ $#BUFFER -gt 0 ]; then if [ $#BUFFER -gt 0 ]; then
if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -le "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -le "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then
@ -420,7 +457,7 @@ _zsh_autosuggest_partial_accept() {
return $retval return $retval
} }
for action in clear modify fetch suggest accept partial_accept execute; 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
@ -442,6 +479,9 @@ zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
zle -N autosuggest-accept _zsh_autosuggest_widget_accept zle -N autosuggest-accept _zsh_autosuggest_widget_accept
zle -N autosuggest-clear _zsh_autosuggest_widget_clear zle -N autosuggest-clear _zsh_autosuggest_widget_clear
zle -N autosuggest-execute _zsh_autosuggest_widget_execute 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
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Default Suggestion Strategy # # Default Suggestion Strategy #