From de6200e45d30e82864434a1d58b4df0081634e14 Mon Sep 17 00:00:00 2001 From: Daniel Mar Date: Fri, 11 Apr 2025 06:22:58 -0700 Subject: [PATCH] feat(shell): support completion in the middle of a prompt (#450) I think it's better to insert our output at the cursor so this can be invoked in the middle of a prompt. Previously we would assume the cursor is at the end of the prompt and invocation in the middle of one would discard everything after the cursor. --------- Co-authored-by: Alexandre Pasmantier <47638216+alexpasmantier@users.noreply.github.com> --- television/utils/shell/completion.bash | 10 +++++++--- television/utils/shell/completion.fish | 5 +++-- television/utils/shell/completion.zsh | 20 +++++++++++--------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/television/utils/shell/completion.bash b/television/utils/shell/completion.bash index e352efe..8a2bae7 100644 --- a/television/utils/shell/completion.bash +++ b/television/utils/shell/completion.bash @@ -1,14 +1,18 @@ function tv_smart_autocomplete() { + # prefix (lhs of cursor) local current_prompt="${READLINE_LINE:0:$READLINE_POINT}" - local output=$(tv --autocomplete-prompt "$current_prompt") + local output=$(tv --autocomplete-prompt "$current_prompt" | tr '\n' ' ') if [[ -n $output ]]; then + # suffix (rhs of cursor) + local rhs="${READLINE_LINE:$READLINE_POINT}" # add a space if the prompt does not end with one [[ "${current_prompt}" != *" " ]] && current_prompt="${current_prompt} " - READLINE_LINE=$current_prompt$output - READLINE_POINT=${#READLINE_LINE} + local lhs=$current_prompt$output + READLINE_LINE=$lhs$rhs + READLINE_POINT=${#lhs} fi } diff --git a/television/utils/shell/completion.fish b/television/utils/shell/completion.fish index c02cb00..97fd9a2 100644 --- a/television/utils/shell/completion.fish +++ b/television/utils/shell/completion.fish @@ -1,12 +1,13 @@ function tv_smart_autocomplete + # prefix (lhs of cursor) set -l current_prompt (commandline -cp) set -l output (tv --autocomplete-prompt "$current_prompt") if test -n "$output" # add a space if the prompt does not end with one (unless the prompt is an implicit cd, e.g. '\.') - string match -q -r '.*( |./)$' -- "$current_prompt" || set current_prompt "$current_prompt " - commandline -r "$current_prompt$output" + string match -q -r '.*( |./)$' -- "$current_prompt" || set output " $output" + commandline -i "$output" commandline -f repaint end end diff --git a/television/utils/shell/completion.zsh b/television/utils/shell/completion.zsh index ab0255b..ad6c7ae 100644 --- a/television/utils/shell/completion.zsh +++ b/television/utils/shell/completion.zsh @@ -2,22 +2,25 @@ _tv_smart_autocomplete() { emulate -L zsh zle -I + # prefix (lhs of cursor) local current_prompt current_prompt=$LBUFFER local output - - output=$(tv --autocomplete-prompt "$current_prompt" $*) - + output=$(tv --autocomplete-prompt "$current_prompt" $* | tr '\n' ' ') if [[ -n $output ]]; then - zle reset-prompt - RBUFFER="" + # suffix (rhs of cursor) + local rhs=$RBUFFER # add a space if the prompt does not end with one [[ "${current_prompt}" != *" " ]] && current_prompt="${current_prompt} " - LBUFFER=$current_prompt$output - # uncomment this to automatically accept the line + LBUFFER=$current_prompt$output + CURSOR=${#LBUFFER} + RBUFFER=$rhs + + zle reset-prompt + # uncomment this to automatically accept the line # (i.e. run the command without having to press enter twice) # zle accept-line fi @@ -39,7 +42,7 @@ _tv_shell_history() { RBUFFER="" LBUFFER=$output - # uncomment this to automatically accept the line + # uncomment this to automatically accept the line # (i.e. run the command without having to press enter twice) # zle accept-line fi @@ -52,4 +55,3 @@ zle -N tv-shell-history _tv_shell_history bindkey '{tv_smart_autocomplete_keybinding}' tv-smart-autocomplete bindkey '{tv_shell_history_keybinding}' tv-shell-history -