From aa597eea6da08e050b42442f316cc24aec9cf614 Mon Sep 17 00:00:00 2001 From: Kordan Ou Date: Sat, 20 Feb 2016 21:52:21 +0800 Subject: [PATCH 1/3] Add an autosuggest widget: autosuggest-execute. --- README.md | 6 ++++-- src/bind.zsh | 2 ++ src/config.zsh | 4 ++++ src/widgets.zsh | 14 +++++++++++++- zsh-autosuggestions.zsh | 20 +++++++++++++++++++- 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index abf4790..a72ea01 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ This plugin works by triggering custom behavior when certain [zle widgets](http: - `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: Widgets in this array will clear the suggestion when invoked. - `ZSH_AUTOSUGGEST_ACCEPT_WIDGETS`: Widgets in this array will accept the suggestion when invoked. +- `ZSH_AUTOSUGGEST_EXECUTE_WIDGETS`: Widgets in this array will execute the suggestion when invoked. - `ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS`: Widgets in this array will partially accept the suggestion when invoked. Widgets not in any of these lists will update the suggestion when invoked. @@ -79,10 +80,11 @@ Widgets not in any of these lists will update the suggestion when invoked. ### Key Bindings -This plugin provides two widgets that you can use with `bindkey`: +This plugin provides three widgets that you can use with `bindkey`: 1. `autosuggest-accept`: Accepts the current suggestion. -2. `autosuggest-clear`: Clears the current suggestion. +2. `autosuggest-execute`: Accepts and executes the current suggestion. +3. `autosuggest-clear`: Clears the current suggestion. For example, this would bind ctrl + space to accept the current suggestion. diff --git a/src/bind.zsh b/src/bind.zsh index cc020de..030c6cf 100644 --- a/src/bind.zsh +++ b/src/bind.zsh @@ -55,6 +55,8 @@ _zsh_autosuggest_bind_widgets() { _zsh_autosuggest_bind_widget $widget clear elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then _zsh_autosuggest_bind_widget $widget accept + elif [ ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]; then + _zsh_autosuggest_bind_widget $widget execute elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then _zsh_autosuggest_bind_widget $widget partial_accept else diff --git a/src/config.zsh b/src/config.zsh index b5a0f02..ae34f82 100644 --- a/src/config.zsh +++ b/src/config.zsh @@ -32,6 +32,10 @@ ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=( vi-end-of-line ) +# Widgets that accept the entire suggestion and execute it +ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=( +) + # Widgets that accept the suggestion as far as the cursor moves ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=( forward-word diff --git a/src/widgets.zsh b/src/widgets.zsh index 1537b8a..3c75cd3 100644 --- a/src/widgets.zsh +++ b/src/widgets.zsh @@ -47,6 +47,17 @@ _zsh_autosuggest_accept() { _zsh_autosuggest_invoke_original_widget $@ } +# Accept the entire suggestion and execute it +_zsh_autosuggest_execute() { + # Add the suggestion to the buffer + BUFFER="$BUFFER$POSTDISPLAY" + + # Remove the suggestion + unset POSTDISPLAY + + zle .accept-line +} + # Partially accept the suggestion _zsh_autosuggest_partial_accept() { # Save the contents of the buffer so we can restore later if needed @@ -71,7 +82,7 @@ _zsh_autosuggest_partial_accept() { fi } -for action in clear modify accept partial_accept; do +for action in clear modify accept partial_accept execute; do eval "_zsh_autosuggest_widget_$action() { _zsh_autosuggest_highlight_reset _zsh_autosuggest_$action \$@ @@ -81,3 +92,4 @@ 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 diff --git a/zsh-autosuggestions.zsh b/zsh-autosuggestions.zsh index 552bbdf..6124953 100644 --- a/zsh-autosuggestions.zsh +++ b/zsh-autosuggestions.zsh @@ -58,6 +58,10 @@ ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=( vi-end-of-line ) +# Widgets that accept the entire suggestion and execute it +ZSH_AUTOSUGGEST_EXECUTE_WIDGETS=( +) + # Widgets that accept the suggestion as far as the cursor moves ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=( forward-word @@ -159,6 +163,8 @@ _zsh_autosuggest_bind_widgets() { _zsh_autosuggest_bind_widget $widget clear elif [ ${ZSH_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]; then _zsh_autosuggest_bind_widget $widget accept + elif [ ${ZSH_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]; then + _zsh_autosuggest_bind_widget $widget execute elif [ ${ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]; then _zsh_autosuggest_bind_widget $widget partial_accept else @@ -252,6 +258,17 @@ _zsh_autosuggest_accept() { _zsh_autosuggest_invoke_original_widget $@ } +# Accept the entire suggestion and execute it +_zsh_autosuggest_execute() { + # Add the suggestion to the buffer + BUFFER="$BUFFER$POSTDISPLAY" + + # Remove the suggestion + unset POSTDISPLAY + + zle .accept-line +} + # Partially accept the suggestion _zsh_autosuggest_partial_accept() { # Save the contents of the buffer so we can restore later if needed @@ -276,7 +293,7 @@ _zsh_autosuggest_partial_accept() { fi } -for action in clear modify accept partial_accept; do +for action in clear modify accept partial_accept execute; do eval "_zsh_autosuggest_widget_$action() { _zsh_autosuggest_highlight_reset _zsh_autosuggest_$action \$@ @@ -286,6 +303,7 @@ 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 #--------------------------------------------------------------------# # Suggestion # From 8c3fdea75ddcb83558b2d41c39a6fbec424f7ce1 Mon Sep 17 00:00:00 2001 From: Eric Freese Date: Tue, 23 Feb 2016 10:20:13 -0700 Subject: [PATCH 2/3] Call original accept-line widget when executing suggestion --- src/widgets.zsh | 4 +++- zsh-autosuggestions.zsh | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets.zsh b/src/widgets.zsh index 3c75cd3..925a5e2 100644 --- a/src/widgets.zsh +++ b/src/widgets.zsh @@ -55,7 +55,9 @@ _zsh_autosuggest_execute() { # Remove the suggestion unset POSTDISPLAY - zle .accept-line + # Call the original `accept-line` to handle syntax highlighting or + # other potential custom behavior + _zsh_autosuggest_invoke_original_widget "accept-line" } # Partially accept the suggestion diff --git a/zsh-autosuggestions.zsh b/zsh-autosuggestions.zsh index 6124953..cd8ad5a 100644 --- a/zsh-autosuggestions.zsh +++ b/zsh-autosuggestions.zsh @@ -266,7 +266,9 @@ _zsh_autosuggest_execute() { # Remove the suggestion unset POSTDISPLAY - zle .accept-line + # Call the original `accept-line` to handle syntax highlighting or + # other potential custom behavior + _zsh_autosuggest_invoke_original_widget "accept-line" } # Partially accept the suggestion From 125f48c7f2b2860f3294a2209d9c56b58fabe003 Mon Sep 17 00:00:00 2001 From: Eric Freese Date: Tue, 23 Feb 2016 10:33:40 -0700 Subject: [PATCH 3/3] Add test for execute widget --- script/test.zsh | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/script/test.zsh b/script/test.zsh index 45f3dbc..ba563a6 100755 --- a/script/test.zsh +++ b/script/test.zsh @@ -177,6 +177,29 @@ testWidgetFunctionAcceptCursorNotAtEnd() { "$POSTDISPLAY" } +testWidgetFunctionExecute() { + BUFFER="ec" + POSTDISPLAY="ho hello" + + stub _zsh_autosuggest_invoke_original_widget + + _zsh_autosuggest_execute + + assertTrue \ + "accept-line not invoked" \ + "stub_called_with _zsh_autosuggest_invoke_original_widget 'accept-line'" + + assertEquals \ + "BUFFER was not modified" \ + "echo hello" \ + "$BUFFER" + + assertEquals \ + "POSTDISPLAY was not cleared" \ + "" \ + "$POSTDISPLAY" +} + testWidgetFunctionPartialAcceptCursorMovesOutOfBuffer() { BUFFER="ec" POSTDISPLAY="ho hello" @@ -281,6 +304,32 @@ testWidgetClear() { "stub_called _zsh_autosuggest_highlight_apply" } +testWidgetExecute() { + stub _zsh_autosuggest_highlight_reset + stub _zsh_autosuggest_execute + stub _zsh_autosuggest_highlight_apply + + # Call the function pointed to by the widget since we can't call + # the widget itself when zle is not active + ${widgets[autosuggest-execute]#*:} "original-widget" + + assertTrue \ + "autosuggest-execute widget does not exist" \ + "zle -l autosuggest-execute" + + assertTrue \ + "highlight_reset was not called" \ + "stub_called _zsh_autosuggest_highlight_reset" + + assertTrue \ + "widget function was not called" \ + "stub_called _zsh_autosuggest_execute" + + assertTrue \ + "highlight_apply was not called" \ + "stub_called _zsh_autosuggest_highlight_apply" +} + testEscapeCommandPrefix() { assertEquals \ "Did not escape single backslash" \