Add shared command path primitives

This commit is contained in:
2026-10-19 15:08:00 +00:00
parent d7cc12a347
commit b3fb795224
5 changed files with 207 additions and 30 deletions

View File

@@ -11,6 +11,7 @@ import (
"strings"
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
spfcobra "github.com/spf13/cobra"
"github.com/spf13/pflag"
@@ -63,16 +64,17 @@ func (session *Session) Parse(argv []string) commandmeta.Result {
}
result.Key = selectedNode.Key
var pathOK bool
result.Path, pathOK = pathFor(selected, session.declarations)
selectedPath, pathOK := pathFor(selected, session.declarations)
if !pathOK {
return failure(result, "selected command is not part of the declared tree")
}
result.Path = []string(selectedPath)
consumed := len(leading) - len(unconsumed)
if consumed != len(result.Path) || !equalPath(leading[:consumed], result.Path) {
if consumed != len(selectedPath) || !commandpath.FromTokens(leading[:consumed]).Equal(selectedPath) {
return failure(result, "command path must match a registered command exactly")
}
remaining := append(append([]string(nil), unconsumed...), tail...)
remaining := append(commandpath.CloneTokens(unconsumed), tail...)
if err := selected.ParseFlags(remaining); err != nil {
return failure(result, err.Error())
}
@@ -105,12 +107,12 @@ func (session *Session) RenderHelp(path []string) (string, *commandmeta.Failure)
}
selected, remaining, err := session.root.Find(path)
if err != nil {
return "", &commandmeta.Failure{Message: fmt.Sprintf("unknown help path %q", strings.Join(path, " ")), Usage: true}
return "", &commandmeta.Failure{Message: fmt.Sprintf("unknown help path %q", commandpath.FromTokens(path).String()), Usage: true}
}
declaration := session.declarations[selected]
selectedPath, pathOK := pathFor(selected, session.declarations)
if declaration == nil || !pathOK || len(remaining) != 0 || !equalPath(path, selectedPath) {
return "", &commandmeta.Failure{Message: fmt.Sprintf("unknown help path %q", strings.Join(path, " ")), Usage: true}
if declaration == nil || !pathOK || len(remaining) != 0 || !commandpath.FromTokens(path).Equal(selectedPath) {
return "", &commandmeta.Failure{Message: fmt.Sprintf("unknown help path %q", commandpath.FromTokens(path).String()), Usage: true}
}
buffer := new(bytes.Buffer)
previousOut, previousErr := selected.OutOrStdout(), selected.ErrOrStderr()
@@ -134,7 +136,7 @@ func (session *Session) UsageLine(path []string) (string, *commandmeta.Failure)
selected, remaining, err := session.root.Find(path)
declaration := session.declarations[selected]
selectedPath, pathOK := pathFor(selected, session.declarations)
if err != nil || declaration == nil || !pathOK || len(remaining) != 0 || !equalPath(path, selectedPath) {
if err != nil || declaration == nil || !pathOK || len(remaining) != 0 || !commandpath.FromTokens(path).Equal(selectedPath) {
return "", &commandmeta.Failure{Message: "usage path is not registered"}
}
line := selected.UseLine()
@@ -303,28 +305,16 @@ func flagUsage(flag commandmeta.Flag) string {
return usage
}
func equalPath(left, right []string) bool {
if len(left) != len(right) {
return false
}
for index := range left {
if left[index] != right[index] {
return false
}
}
return true
}
func splitRoutingPrefix(argv []string) ([]string, []string) {
for index, argument := range argv {
if argument == "--" || (strings.HasPrefix(argument, "-") && argument != "-") {
return append([]string(nil), argv[:index]...), append([]string(nil), argv[index:]...)
return commandpath.CloneTokens(argv[:index]), commandpath.CloneTokens(argv[index:])
}
}
return append([]string(nil), argv...), nil
return commandpath.CloneTokens(argv), nil
}
func pathFor(selected *spfcobra.Command, declarations map[*spfcobra.Command]*commandmeta.Command) ([]string, bool) {
func pathFor(selected *spfcobra.Command, declarations map[*spfcobra.Command]*commandmeta.Command) (commandpath.Path, bool) {
var reverse []string
for current := selected; current != nil; current = current.Parent() {
declaration := declarations[current]
@@ -338,7 +328,7 @@ func pathFor(selected *spfcobra.Command, declarations map[*spfcobra.Command]*com
for left, right := 0, len(reverse)-1; left < right; left, right = left+1, right-1 {
reverse[left], reverse[right] = reverse[right], reverse[left]
}
return reverse, true
return commandpath.FromTokens(reverse), true
}
func failure(result commandmeta.Result, message string) commandmeta.Result {