Repository: rsteube/carapace
Pull request #993 (2024-02-17 07:45:06)

bash: handle COMP_TYPE
fix rsteube/carapace-bin#2247


Patch:
diff --git a/internal/shell/bash/action.go b/internal/shell/bash/action.go
index 0e3529a..ad2adc4 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 c7511e2..ea75992 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 1663ddf..bd55e7f 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}}"
 


Test patch:
diff --git a/example/cmd/_test/bash-ble.sh b/example/cmd/_test/bash-ble.sh
index ea4fa69..94c1ad7 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 f4ed518..e1e08fb 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}}"