Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes/bpm async fix #223

Merged
merged 3 commits into from
Mar 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,15 @@ As of `v0.4.0`, suggestions are fetched asynchronously using the `zsh/zpty` modu

### 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.
2. `autosuggest-execute`: Accepts and executes 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.

Expand Down
36 changes: 36 additions & 0 deletions spec/integrations/bracketed_paste_magic_spec.rb
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions spec/integrations/zle_input_stack_spec.rb
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions spec/terminal_session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ def send_keys(*keys)
self
end

def paste_string(str)
tmux_command("set-buffer -- '#{str}'")
tmux_command("paste-buffer -dpr -t 0")

self
end

def content(esc_seqs: false)
cmd = 'capture-pane -p -t 0'
cmd += ' -e' if esc_seqs
Expand Down
19 changes: 19 additions & 0 deletions spec/widgets/disable_spec.rb
Original file line number Diff line number Diff line change
@@ -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
42 changes: 42 additions & 0 deletions spec/widgets/enable_spec.rb
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions spec/widgets/fetch_spec.rb
Original file line number Diff line number Diff line change
@@ -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
26 changes: 26 additions & 0 deletions spec/widgets/toggle_spec.rb
Original file line number Diff line number Diff line change
@@ -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
42 changes: 41 additions & 1 deletion src/widgets.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,30 @@
# 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
_zsh_autosuggest_clear() {
# Remove the suggestion
Expand All @@ -15,6 +39,9 @@ _zsh_autosuggest_clear() {
_zsh_autosuggest_modify() {
local -i retval

# Only added to zsh very recently
local -i KEYS_QUEUED_COUNT

# Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY"
Expand All @@ -26,6 +53,11 @@ _zsh_autosuggest_modify() {
_zsh_autosuggest_invoke_original_widget $@
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
if [ $#BUFFER -gt $#orig_buffer ]; then
local added=${BUFFER#$orig_buffer}
Expand All @@ -43,6 +75,11 @@ _zsh_autosuggest_modify() {
return $retval
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
if [ $#BUFFER -gt 0 ]; then
if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -le "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then
Expand Down Expand Up @@ -142,7 +179,7 @@ _zsh_autosuggest_partial_accept() {
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() {
local -i retval

Expand All @@ -164,3 +201,6 @@ zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
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
42 changes: 41 additions & 1 deletion zsh-autosuggestions.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,30 @@ _zsh_autosuggest_highlight_apply() {
# 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
_zsh_autosuggest_clear() {
# Remove the suggestion
Expand All @@ -293,6 +317,9 @@ _zsh_autosuggest_clear() {
_zsh_autosuggest_modify() {
local -i retval

# Only added to zsh very recently
local -i KEYS_QUEUED_COUNT

# Save the contents of the buffer/postdisplay
local orig_buffer="$BUFFER"
local orig_postdisplay="$POSTDISPLAY"
Expand All @@ -304,6 +331,11 @@ _zsh_autosuggest_modify() {
_zsh_autosuggest_invoke_original_widget $@
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
if [ $#BUFFER -gt $#orig_buffer ]; then
local added=${BUFFER#$orig_buffer}
Expand All @@ -321,6 +353,11 @@ _zsh_autosuggest_modify() {
return $retval
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
if [ $#BUFFER -gt 0 ]; then
if [ -z "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" -o $#BUFFER -le "$ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" ]; then
Expand Down Expand Up @@ -420,7 +457,7 @@ _zsh_autosuggest_partial_accept() {
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() {
local -i retval

Expand All @@ -442,6 +479,9 @@ zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
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

#--------------------------------------------------------------------#
# Default Suggestion Strategy #
Expand Down