Add InfluencedByPermissions field to Command struct

This commit is contained in:
Xueming Feng 2024-04-17 16:48:53 +08:00
parent 5a1acea321
commit 7edfda55d3
3 changed files with 44 additions and 6 deletions

View file

@ -254,6 +254,12 @@ type Command struct {
// SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions.
// Must be > 0. // Must be > 0.
SuggestionsMinimumDistance int SuggestionsMinimumDistance int
// InfluencedByPermissions indicates that the output is influenced by the
// permission it is run with. Thus, when a command such as sudo appears on the
// command-line, it will use commands like sudo or doas to gain extra privileges
// when retrieving information for completion. Available only to Zsh.
InfluencedByPermissions bool
} }
// Context returns underlying command context. If command was executed // Context returns underlying command context. If command was executed

View file

@ -21,6 +21,15 @@ import (
"os" "os"
) )
const (
// ZstyleGainPrivileges enables the use of commands like sudo or doas to
// gain extra privileges when retrieving information for completion.
ZstyleGainPrivileges = `zstyle ':completion:*:%s\*' gain-privileges yes`
// ZshCompRunCmdPermFlag indicates the command output is influenced by the
// permissions it is run with.
ZshCompRunCmdPermFlag = ` -p`
)
// GenZshCompletionFile generates zsh completion file including descriptions. // GenZshCompletionFile generates zsh completion file including descriptions.
func (c *Command) GenZshCompletionFile(filename string) error { func (c *Command) GenZshCompletionFile(filename string) error {
return c.genZshCompletionFile(filename, true) return c.genZshCompletionFile(filename, true)
@ -79,16 +88,23 @@ func (c *Command) genZshCompletionFile(filename string, includeDesc bool) error
func (c *Command) genZshCompletion(w io.Writer, includeDesc bool) error { func (c *Command) genZshCompletion(w io.Writer, includeDesc bool) error {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
genZshComp(buf, c.Name(), includeDesc) genZshComp(buf, c.Name(), includeDesc, c.InfluencedByPermissions)
_, err := buf.WriteTo(w) _, err := buf.WriteTo(w)
return err return err
} }
func genZshComp(buf io.StringWriter, name string, includeDesc bool) { func genZshComp(buf io.StringWriter, name string, includeDesc bool, permission bool) {
compCmd := ShellCompRequestCmd compCmd := ShellCompRequestCmd
if !includeDesc { if !includeDesc {
compCmd = ShellCompNoDescRequestCmd compCmd = ShellCompNoDescRequestCmd
} }
zstyleGain := ""
permFlag := ""
if permission {
zstyleGain = fmt.Sprintf(ZstyleGainPrivileges, name)
permFlag = ZshCompRunCmdPermFlag
}
WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s WriteStringAndCheck(buf, fmt.Sprintf(`#compdef %[1]s
compdef _%[1]s %[1]s compdef _%[1]s %[1]s
@ -145,10 +161,14 @@ _%[1]s()
requestComp="${requestComp} \"\"" requestComp="${requestComp} \"\""
fi fi
__%[1]s_debug "About to call: eval ${requestComp}" # Set zstyle if gain-privileges is requested
__%[1]s_debug "Setting zstyle: %[10]s"
%[10]s
# Use eval to handle any environment variables and such __%[1]s_debug "About to call: _call_program%[11]s %[1]s-tag ${requestComp}"
out=$(eval ${requestComp} 2>/dev/null)
# Use _call_program to call the completion code
out=$(_call_program%[11]s %[1]s-tag ${requestComp})
__%[1]s_debug "completion output: ${out}" __%[1]s_debug "completion output: ${out}"
# Extract the directive integer following a : from the last line # Extract the directive integer following a : from the last line
@ -304,5 +324,5 @@ fi
`, name, compCmd, `, name, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder,
activeHelpMarker)) activeHelpMarker, zstyleGain, permFlag))
} }

View file

@ -31,3 +31,15 @@ func TestZshCompletionWithActiveHelp(t *testing.T) {
activeHelpVar := activeHelpEnvVar(c.Name()) activeHelpVar := activeHelpEnvVar(c.Name())
checkOmit(t, output, fmt.Sprintf("%s=0", activeHelpVar)) checkOmit(t, output, fmt.Sprintf("%s=0", activeHelpVar))
} }
func TestZshCompletionWithInfluencedPermission(t *testing.T) {
c := &Command{Use: "c", Run: emptyRun, InfluencedByPermissions: true}
buf := new(bytes.Buffer)
assertNoErr(t, c.GenZshCompletion(buf))
output := buf.String()
// check that related commands are being generated
check(t, output, fmt.Sprintf(ZstyleGainPrivileges, c.Name()))
check(t, output, fmt.Sprintf("_call_program -p %s-tag", c.Name()))
}