Repository: rsteube/carapace
Pull request #418 (2022-02-13 19:19:45)

removed legacy uid placeholder


Patch:
diff --git a/carapace.go b/carapace.go
index 3a6c4d7..12f3e44 100644
--- a/carapace.go
+++ b/carapace.go
@@ -170,7 +170,6 @@ func complete(cmd *cobra.Command, args []string) (string, error) {
 			return s, nil
 		} else {
 			shell := args[0]
-			id := args[1]
 			current := args[len(args)-1]
 			previous := args[len(args)-2]
 
@@ -183,50 +182,44 @@ func complete(cmd *cobra.Command, args []string) (string, error) {
 				return ActionMessage(err.Error()).Invoke(context).value(shell, current), nil
 			}
 
-			switch id {
-			case "_":
-				// TODO needs more cleanup and tests
-				var targetAction Action
-				if flag := lookupFlag(targetCmd, previous); !targetCmd.DisableFlagParsing && flag != nil && flag.NoOptDefVal == "" && !common.IsDash(targetCmd) { // previous arg is a flag and needs a value
-					targetAction = storage.getFlag(targetCmd, flag.Name)
-				} else if !targetCmd.DisableFlagParsing && strings.HasPrefix(current, "-") && !common.IsDash(targetCmd) { // assume flag
-					if strings.Contains(current, "=") { // complete value for optarg flag
-						if flag := lookupFlag(targetCmd, current); flag != nil && flag.NoOptDefVal != "" {
-							a := storage.getFlag(targetCmd, flag.Name)
-							splitted := strings.SplitN(current, "=", 2)
-							context.CallbackValue = splitted[1]
-							if opts.LongShorthand {
-								splitted[0] = splitted[0][1:] // revert the added `-` so that the resulting prefix is correct
-							}
-							current = strings.Replace(current, "=", opts.OptArgDelimiter, 1)                  // revert (potentially) overridden optarg divider for `.value()` invocation below
-							targetAction = a.Invoke(context).Prefix(splitted[0] + opts.OptArgDelimiter).ToA() // prefix with (potentially) overridden optarg delimiter
+			// TODO needs more cleanup and tests
+			var targetAction Action
+			if flag := lookupFlag(targetCmd, previous); !targetCmd.DisableFlagParsing && flag != nil && flag.NoOptDefVal == "" && !common.IsDash(targetCmd) { // previous arg is a flag and needs a value
+				targetAction = storage.getFlag(targetCmd, flag.Name)
+			} else if !targetCmd.DisableFlagParsing && strings.HasPrefix(current, "-") && !common.IsDash(targetCmd) { // assume flag
+				if strings.Contains(current, "=") { // complete value for optarg flag
+					if flag := lookupFlag(targetCmd, current); flag != nil && flag.NoOptDefVal != "" {
+						a := storage.getFlag(targetCmd, flag.Name)
+						splitted := strings.SplitN(current, "=", 2)
+						context.CallbackValue = splitted[1]
+						if opts.LongShorthand {
+							splitted[0] = splitted[0][1:] // revert the added `-` so that the resulting prefix is correct
 						}
-					} else { // complete flagnames
-						targetAction = actionFlags(targetCmd)
-					}
-				} else {
-					if len(context.Args) > 0 {
-						context.Args = context.Args[:len(context.Args)-1] // current word being completed is a positional so remove it from context.Args
+						current = strings.Replace(current, "=", opts.OptArgDelimiter, 1)                  // revert (potentially) overridden optarg divider for `.value()` invocation below
+						targetAction = a.Invoke(context).Prefix(splitted[0] + opts.OptArgDelimiter).ToA() // prefix with (potentially) overridden optarg delimiter
 					}
+				} else { // complete flagnames
+					targetAction = actionFlags(targetCmd)
+				}
+			} else {
+				if len(context.Args) > 0 {
+					context.Args = context.Args[:len(context.Args)-1] // current word being completed is a positional so remove it from context.Args
+				}
 
-					if common.IsDash(targetCmd) {
-						targetAction = findAction(targetCmd, targetArgs[targetCmd.ArgsLenAtDash():])
-					} else {
-						targetAction = findAction(targetCmd, targetArgs)
-						if targetCmd.HasAvailableSubCommands() && len(targetArgs) <= 1 {
-							subcommandA := actionSubcommands(targetCmd).Invoke(context)
-							targetAction = targetAction.Invoke(context).Merge(subcommandA).ToA()
-						}
+				if common.IsDash(targetCmd) {
+					targetAction = findAction(targetCmd, targetArgs[targetCmd.ArgsLenAtDash():])
+				} else {
+					targetAction = findAction(targetCmd, targetArgs)
+					if targetCmd.HasAvailableSubCommands() && len(targetArgs) <= 1 {
+						subcommandA := actionSubcommands(targetCmd).Invoke(context)
+						targetAction = targetAction.Invoke(context).Merge(subcommandA).ToA()
 					}
 				}
-				if opts.LongShorthand {
-					current = strings.TrimPrefix(current, "-")
-				}
-				return targetAction.Invoke(context).value(shell, current), nil
-			default:
-				// TODO disable support for direct uid invocation
-				//fmt.Fprintln(io.MultiWriter(os.Stdout, logger.Writer()), actionMap.invokeCallback(id, context).Invoke(context).value(shell, context.CallbackValue))
 			}
+			if opts.LongShorthand {
+				current = strings.TrimPrefix(current, "-")
+			}
+			return targetAction.Invoke(context).value(shell, current), nil
 		}
 	}
 	return "", nil // TODO
@@ -247,8 +240,8 @@ func findAction(targetCmd *cobra.Command, targetArgs []string) Action {
 
 func findTarget(cmd *cobra.Command, args []string) (*cobra.Command, []string, error) {
 	origArg := []string{}
-	if len(args) > 3 {
-		origArg = args[3:]
+	if len(args) > 2 {
+		origArg = args[2:]
 	}
 	return common.TraverseLenient(cmd, origArg)
 }
diff --git a/internal/assert/assert.go b/internal/assert/assert.go
index 9ce52b2..ae1a7ba 100644
--- a/internal/assert/assert.go
+++ b/internal/assert/assert.go
@@ -2,10 +2,13 @@
 package assert
 
 import (
-	exec "golang.org/x/sys/execabs"
 	"io/ioutil"
 	"os"
+	"path/filepath"
+	"runtime"
 	"testing"
+
+	exec "golang.org/x/sys/execabs"
 )
 
 // Equal calls t.Error if given strings are not equal
@@ -18,6 +21,7 @@ func Equal(t *testing.T, expected string, actual string) {
 		_ = ioutil.WriteFile(expectedFile.Name(), []byte(expected), os.ModePerm)
 		_ = ioutil.WriteFile(actualFile.Name(), []byte(actual), os.ModePerm)
 		output, _ := exec.Command("diff", "--color=always", expectedFile.Name(), actualFile.Name()).Output()
-		t.Error("\n" + string(output))
+		_, file, line, _ := runtime.Caller(1)
+		t.Errorf("%v:%v:\n%v", filepath.Base(file), line, string(output))
 	}
 }
diff --git a/internal/bash/snippet.go b/internal/bash/snippet.go
index b0c8b5b..d8feeda 100644
--- a/internal/bash/snippet.go
+++ b/internal/bash/snippet.go
@@ -16,7 +16,7 @@ _%v_completion() {
 
   local compline="${COMP_LINE:0:${COMP_POINT}}"
   local IFS=$'\n'
-  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs %v _carapace bash "_")
+  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs %v _carapace bash)
   [[ "${COMPREPLY[*]}" == "" ]] && COMPREPLY=() # fix for mapfile creating a non-empty array from empty command output
 
   [[ ${COMPREPLY[0]} == *[/=@:.,$'\001'] ]] && compopt -o nospace
diff --git a/internal/elvish/snippet.go b/internal/elvish/snippet.go
index 0bbc453..56c93df 100644
--- a/internal/elvish/snippet.go
+++ b/internal/elvish/snippet.go
@@ -10,7 +10,7 @@ import (
 // Snippet creates the elvish completion script
 func Snippet(cmd *cobra.Command) string {
 	return fmt.Sprintf(`set edit:completion:arg-completer[%v] = {|@arg|
-    %v _carapace elvish _ (all $arg) | from-json | all (one) | each {|c| edit:complex-candidate $c[Value] &display=$c[Display] &code-suffix=$c[CodeSuffix] }
+    %v _carapace elvish (all $arg) | from-json | all (one) | each {|c| edit:complex-candidate $c[Value] &display=$c[Display] &code-suffix=$c[CodeSuffix] }
 }
 `, cmd.Name(), uid.Executable())
 }
diff --git a/internal/fish/snippet.go b/internal/fish/snippet.go
index 2ea5f66..c74db4c 100644
--- a/internal/fish/snippet.go
+++ b/internal/fish/snippet.go
@@ -23,7 +23,7 @@ func Snippet(cmd *cobra.Command) string {
 end
 
 function _%v_callback
-  commandline -cp | sed "s/\$/"(_%v_quote_suffix)"/" | sed "s/ \$/ ''/" | xargs %v _carapace fish _
+  commandline -cp | sed "s/\$/"(_%v_quote_suffix)"/" | sed "s/ \$/ ''/" | xargs %v _carapace fish
 end
 
 complete -c %v -f
diff --git a/internal/nushell/snippet.go b/internal/nushell/snippet.go
index fe371f7..37daeec 100644
--- a/internal/nushell/snippet.go
+++ b/internal/nushell/snippet.go
@@ -10,5 +10,5 @@ import (
 
 // Snippet creates the nushell completion script
 func Snippet(cmd *cobra.Command) string {
-	return fmt.Sprintf("config set completion.%v [%v _carapace nushell _]", cmd.Name(), uid.Executable())
+	return fmt.Sprintf("config set completion.%v [%v _carapace nushell]", cmd.Name(), uid.Executable())
 }
diff --git a/internal/oil/snippet.go b/internal/oil/snippet.go
index 8cbddce..e86bcad 100644
--- a/internal/oil/snippet.go
+++ b/internal/oil/snippet.go
@@ -14,7 +14,7 @@ func Snippet(cmd *cobra.Command) string {
 _%v_completion() {
   local compline="${COMP_LINE:0:${COMP_POINT}}"
   local IFS=$'\n'
-  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs %v _carapace oil "_")
+  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs %v _carapace oil)
   [[ "${COMPREPLY[@]}" == "" ]] && COMPREPLY=() # fix for mapfile creating a non-empty array from empty command output
   [[ ${COMPREPLY[0]} == *[/=@:.,$'\001'] ]] && compopt -o nospace
   # TODO use mapfile
diff --git a/internal/powershell/snippet.go b/internal/powershell/snippet.go
index b56c929..e57fbf6 100644
--- a/internal/powershell/snippet.go
+++ b/internal/powershell/snippet.go
@@ -42,9 +42,9 @@ Function _%v_completer {
 
     $completions = @(
       if (!$wordToComplete) {
-        %v _carapace powershell _ $($elems| ForEach-Object {$_}) '""' | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
+        %v _carapace powershell $($elems| ForEach-Object {$_}) '""' | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
       } else {
-        %v _carapace powershell _ $($elems| ForEach-Object {$_}) | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
+        %v _carapace powershell $($elems| ForEach-Object {$_}) | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
       }
     )
 
diff --git a/internal/tcsh/snippet.go b/internal/tcsh/snippet.go
index 6fc2216..14206cb 100644
--- a/internal/tcsh/snippet.go
+++ b/internal/tcsh/snippet.go
@@ -11,5 +11,5 @@ import (
 // Snippet creates the tcsh completion script
 func Snippet(cmd *cobra.Command) string {
 	// TODO initial version - needs to handle open quotes
-	return fmt.Sprintf("complete \"%v\" 'p@*@`echo \"$COMMAND_LINE'\"''\"'\" | xargs %v _carapace tcsh _ `@@' ;", cmd.Name(), uid.Executable())
+	return fmt.Sprintf("complete \"%v\" 'p@*@`echo \"$COMMAND_LINE'\"''\"'\" | xargs %v _carapace tcsh `@@' ;", cmd.Name(), uid.Executable())
 }
diff --git a/internal/xonsh/snippet.go b/internal/xonsh/snippet.go
index e65dd38..0cdbf1e 100644
--- a/internal/xonsh/snippet.go
+++ b/internal/xonsh/snippet.go
@@ -26,7 +26,7 @@ def _%v_completer(context):
             """quick fix for partially quoted prefix completion ('prefix',<TAB>)"""
             return s.translate(str.maketrans('', '', '\'"'))
 
-        output, _ = Popen(['%v', '_carapace', 'xonsh', '_', *[a.value for a in context.args], fix_prefix(context.prefix)], stdout=PIPE, stderr=PIPE).communicate()
+        output, _ = Popen(['%v', '_carapace', 'xonsh', *[a.value for a in context.args], fix_prefix(context.prefix)], stdout=PIPE, stderr=PIPE).communicate()
         try:
             result = {RichCompletion(c["Value"], display=c["Display"], description=c["Description"], prefix_len=len(context.raw_prefix), append_closing_quote=False) for c in loads(output)}
         except:
diff --git a/internal/zsh/snippet.go b/internal/zsh/snippet.go
index 608886c..d810543 100644
--- a/internal/zsh/snippet.go
+++ b/internal/zsh/snippet.go
@@ -17,13 +17,13 @@ function _%v_completion {
   # shellcheck disable=SC2207,SC2086,SC2154
   if echo ${words}"''" | xargs echo 2>/dev/null > /dev/null; then
     # shellcheck disable=SC2207,SC2086
-    local c=($(echo ${words}"''" | xargs %v _carapace zsh _ ))
+    local c=($(echo ${words}"''" | xargs %v _carapace zsh ))
   elif echo ${words} | sed "s/\$/'/" | xargs echo 2>/dev/null > /dev/null; then
     # shellcheck disable=SC2207,SC2086
-    local c=($(echo ${words} | sed "s/\$/'/" | xargs %v _carapace zsh _ ))
+    local c=($(echo ${words} | sed "s/\$/'/" | xargs %v _carapace zsh))
   else
     # shellcheck disable=SC2207,SC2086
-    local c=($(echo ${words} | sed 's/$/"/'  | xargs %v _carapace zsh _ ))
+    local c=($(echo ${words} | sed 's/$/"/'  | xargs %v _carapace zsh))
   fi
 
   # shellcheck disable=SC2034,2206


Test patch:
diff --git a/carapace_test.go b/carapace_test.go
index b9cd09a..c101062 100644
--- a/carapace_test.go
+++ b/carapace_test.go
@@ -47,7 +47,7 @@ func execCompletion(args ...string) (context Context) {
 
 	rootCmd.AddCommand(subCmd)
 
-	os.Args = append([]string{"root", "_carapace", "elvish", "_", "root"}, args...)
+	os.Args = append([]string{"root", "_carapace", "elvish", "root"}, args...)
 	rootCmd.Execute()
 	return
 }
diff --git a/example/_test/invoke_oil b/example/_test/invoke_oil
index dd4d6b5..77688ab 100755
--- a/example/_test/invoke_oil
+++ b/example/_test/invoke_oil
@@ -4,7 +4,7 @@
 _example_completion() {
   local compline="${COMP_LINE:0:${COMP_POINT}}"
   local IFS=$'\n'
-  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs example _carapace oil "_")
+  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs example _carapace oil)
   [[ "${COMPREPLY[@]}" == "" ]] && COMPREPLY=() # fix for mapfile creating a non-empty array from empty command output
   [[ ${COMPREPLY[0]} == *[/=@:.,] ]] && compopt -o nospace
 }
diff --git a/example/cmd/_test/bash.sh b/example/cmd/_test/bash.sh
index 4bd4340..03f64af 100644
--- a/example/cmd/_test/bash.sh
+++ b/example/cmd/_test/bash.sh
@@ -4,7 +4,7 @@ _example_completion() {
 
   local compline="${COMP_LINE:0:${COMP_POINT}}"
   local IFS=$'\n'
-  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs example _carapace bash "_")
+  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs example _carapace bash)
   [[ "${COMPREPLY[*]}" == "" ]] && COMPREPLY=() # fix for mapfile creating a non-empty array from empty command output
 
   [[ ${COMPREPLY[0]} == *[/=@:.,$'\001'] ]] && compopt -o nospace
diff --git a/example/cmd/_test/elvish.elv b/example/cmd/_test/elvish.elv
index 4d527f0..b0d52ab 100644
--- a/example/cmd/_test/elvish.elv
+++ b/example/cmd/_test/elvish.elv
@@ -1,4 +1,4 @@
 set edit:completion:arg-completer[example] = {|@arg|
-    example _carapace elvish _ (all $arg) | from-json | all (one) | each {|c| edit:complex-candidate $c[Value] &display=$c[Display] &code-suffix=$c[CodeSuffix] }
+    example _carapace elvish (all $arg) | from-json | all (one) | each {|c| edit:complex-candidate $c[Value] &display=$c[Display] &code-suffix=$c[CodeSuffix] }
 }
 
diff --git a/example/cmd/_test/fish.fish b/example/cmd/_test/fish.fish
index 33ab6fd..1a520d1 100644
--- a/example/cmd/_test/fish.fish
+++ b/example/cmd/_test/fish.fish
@@ -11,7 +11,7 @@ function _example_quote_suffix
 end
 
 function _example_callback
-  commandline -cp | sed "s/\$/"(_example_quote_suffix)"/" | sed "s/ \$/ ''/" | xargs example _carapace fish _
+  commandline -cp | sed "s/\$/"(_example_quote_suffix)"/" | sed "s/ \$/ ''/" | xargs example _carapace fish
 end
 
 complete -c example -f
diff --git a/example/cmd/_test/oil.sh b/example/cmd/_test/oil.sh
index 978acaa..0bb4c04 100644
--- a/example/cmd/_test/oil.sh
+++ b/example/cmd/_test/oil.sh
@@ -2,7 +2,7 @@
 _example_completion() {
   local compline="${COMP_LINE:0:${COMP_POINT}}"
   local IFS=$'\n'
-  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs example _carapace oil "_")
+  mapfile -t COMPREPLY < <(echo "$compline" | sed -e "s/ \$/ ''/" -e 's/"/\"/g' | xargs example _carapace oil)
   [[ "${COMPREPLY[@]}" == "" ]] && COMPREPLY=() # fix for mapfile creating a non-empty array from empty command output
   [[ ${COMPREPLY[0]} == *[/=@:.,$'\001'] ]] && compopt -o nospace
   # TODO use mapfile
diff --git a/example/cmd/_test/powershell.ps1 b/example/cmd/_test/powershell.ps1
index e7668c0..d606a2f 100644
--- a/example/cmd/_test/powershell.ps1
+++ b/example/cmd/_test/powershell.ps1
@@ -30,9 +30,9 @@ Function _example_completer {
 
     $completions = @(
       if (!$wordToComplete) {
-        example _carapace powershell _ $($elems| ForEach-Object {$_}) '""' | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
+        example _carapace powershell $($elems| ForEach-Object {$_}) '""' | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
       } else {
-        example _carapace powershell _ $($elems| ForEach-Object {$_}) | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
+        example _carapace powershell $($elems| ForEach-Object {$_}) | ConvertFrom-Json | ForEach-Object { [CompletionResult]::new($_.CompletionText, $_.ListItemText, [CompletionResultType]::ParameterValue, $_.ToolTip) }
       }
     )
 
diff --git a/example/cmd/_test/xonsh.py b/example/cmd/_test/xonsh.py
index 01d03be..60d9e1c 100644
--- a/example/cmd/_test/xonsh.py
+++ b/example/cmd/_test/xonsh.py
@@ -12,7 +12,7 @@ def _example_completer(context):
             """quick fix for partially quoted prefix completion ('prefix',<TAB>)"""
             return s.translate(str.maketrans('', '', '\'"'))
 
-        output, _ = Popen(['example', '_carapace', 'xonsh', '_', *[a.value for a in context.args], fix_prefix(context.prefix)], stdout=PIPE, stderr=PIPE).communicate()
+        output, _ = Popen(['example', '_carapace', 'xonsh', *[a.value for a in context.args], fix_prefix(context.prefix)], stdout=PIPE, stderr=PIPE).communicate()
         try:
             result = {RichCompletion(c["Value"], display=c["Display"], description=c["Description"], prefix_len=len(context.raw_prefix), append_closing_quote=False) for c in loads(output)}
         except:
diff --git a/example/cmd/_test/zsh.sh b/example/cmd/_test/zsh.sh
index f5e495c..439e265 100644
--- a/example/cmd/_test/zsh.sh
+++ b/example/cmd/_test/zsh.sh
@@ -5,13 +5,13 @@ function _example_completion {
   # shellcheck disable=SC2207,SC2086,SC2154
   if echo ${words}"''" | xargs echo 2>/dev/null > /dev/null; then
     # shellcheck disable=SC2207,SC2086
-    local c=($(echo ${words}"''" | xargs example _carapace zsh _ ))
+    local c=($(echo ${words}"''" | xargs example _carapace zsh ))
   elif echo ${words} | sed "s/\$/'/" | xargs echo 2>/dev/null > /dev/null; then
     # shellcheck disable=SC2207,SC2086
-    local c=($(echo ${words} | sed "s/\$/'/" | xargs example _carapace zsh _ ))
+    local c=($(echo ${words} | sed "s/\$/'/" | xargs example _carapace zsh))
   else
     # shellcheck disable=SC2207,SC2086
-    local c=($(echo ${words} | sed 's/$/"/'  | xargs example _carapace zsh _ ))
+    local c=($(echo ${words} | sed 's/$/"/'  | xargs example _carapace zsh))
   fi
 
   # shellcheck disable=SC2034,2206