From 010d8136fcf5807349e8ad6543eeba217ab6c912 Mon Sep 17 00:00:00 2001 From: rsteube Date: Sat, 17 Feb 2024 08:44:26 +0100 Subject: [PATCH] bash: handle COMP_TYPE --- example/cmd/_test/bash-ble.sh | 3 ++- example/cmd/_test/bash.sh | 3 ++- internal/shell/bash/action.go | 9 ++++----- internal/shell/bash/patch.go | 10 ++++++++++ internal/shell/bash/snippet.go | 3 ++- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/example/cmd/_test/bash-ble.sh b/example/cmd/_test/bash-ble.sh index ea4fa694a..94c1ad7ed 100644 --- a/example/cmd/_test/bash-ble.sh +++ b/example/cmd/_test/bash-ble.sh @@ -1,8 +1,9 @@ #!/bin/bash _example_completion() { - export COMP_WORDBREAKS export COMP_LINE export COMP_POINT + export COMP_TYPE + export COMP_WORDBREAKS local nospace data compline="${COMP_LINE:0:${COMP_POINT}}" diff --git a/example/cmd/_test/bash.sh b/example/cmd/_test/bash.sh index f4ed5186d..e1e08fb23 100644 --- a/example/cmd/_test/bash.sh +++ b/example/cmd/_test/bash.sh @@ -1,8 +1,9 @@ #!/bin/bash _example_completion() { - export COMP_WORDBREAKS export COMP_LINE export COMP_POINT + export COMP_TYPE + export COMP_WORDBREAKS local nospace data compline="${COMP_LINE:0:${COMP_POINT}}" diff --git a/internal/shell/bash/action.go b/internal/shell/bash/action.go index 0e3529a4c..ad2adc4f8 100644 --- a/internal/shell/bash/action.go +++ b/internal/shell/bash/action.go @@ -74,13 +74,11 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu meta.Nospace.Add('*') } - nospace := true + nospace := false vals := make([]string, len(values)) for index, val := range values { - if len(values) == 1 { - if !meta.Nospace.Matches(val.Value) { - nospace = false - } + if len(values) == 1 || compType != COMP_TYPE_LIST_SUCCESSIVE_TABS { + nospace = nospace || meta.Nospace.Matches(val.Value) vals[index] = sanitizer.Replace(val.Value) if requiresQuoting(vals[index]) { @@ -98,6 +96,7 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu } } } else { + nospace = true val.Display = displayReplacer.Replace(val.Display) val.Description = displayReplacer.Replace(val.Description) if val.Description != "" { diff --git a/internal/shell/bash/patch.go b/internal/shell/bash/patch.go index c7511e20b..ea75992f4 100644 --- a/internal/shell/bash/patch.go +++ b/internal/shell/bash/patch.go @@ -17,6 +17,15 @@ func (r RedirectError) Error() string { // TODO yuck! - set by Patch which also unsets bash comp environment variables so that they don't affect further completion // introduces state and hides what is happening but works for now var wordbreakPrefix string = "" +var compType = "" + +const ( + COMP_TYPE_NORMAL = "9" // TAB, for normal completion + COMP_TYPE_LIST_PARTIAL_WORD = "33" // ‘!’, for listing alternatives on partial word completion, + COMP_TYPE_MENU_COMPLETION = "37" // ‘%’, for menu completion + COMP_TYPE_LIST_SUCCESSIVE_TABS = "63" // ‘?’, for listing completions after successive tabs, + COMP_TYPE_LIST_NOT_UNMODIFIED = "64" // ‘@’, to list completions if the word is not unmodified +) func CompLine() (string, bool) { line, ok := os.LookupEnv("COMP_LINE") @@ -68,6 +77,7 @@ func Patch(args []string) ([]string, error) { // TODO document and fix wordbreak // TODO find a better solution to pass the wordbreakprefix to bash/action.go wordbreakPrefix = tokens.CurrentPipeline().WordbreakPrefix() + compType = os.Getenv("COMP_TYPE") unsetBashCompEnv() return args, nil diff --git a/internal/shell/bash/snippet.go b/internal/shell/bash/snippet.go index 1663ddfef..bd55e7f27 100644 --- a/internal/shell/bash/snippet.go +++ b/internal/shell/bash/snippet.go @@ -12,9 +12,10 @@ import ( func Snippet(cmd *cobra.Command) string { result := fmt.Sprintf(`#!/bin/bash _%v_completion() { - export COMP_WORDBREAKS export COMP_LINE export COMP_POINT + export COMP_TYPE + export COMP_WORDBREAKS local nospace data compline="${COMP_LINE:0:${COMP_POINT}}"