Files
commandkit/route.go

100 lines
2.7 KiB
Go

package commandkit
import (
"strings"
"gitea.maximumdirect.net/eric/CommandKit/internal/commandpath"
)
type routeKind uint8
const (
routeUnknown routeKind = iota
routeCanonical
routeDiscovery
)
type routeResult struct {
kind routeKind
args []string
enteredPath commandpath.Path
canonicalPath commandpath.Path
discoveryPath commandpath.Path
}
func resolveEnteredRoute(args []string, snapshot *routingSnapshot) routeResult {
path, trailing := commandPathTokens(args)
result := routeResult{kind: routeUnknown}
if snapshot == nil {
result.args = append(append([]string(nil), path...), trailing...)
result.enteredPath = path.Clone()
return result
}
resolved, origins := snapshot.aliases.ResolveWithProvenance(path)
trace := traceCanonicalPath(snapshot.canonical, resolved)
switch {
case trace.exact != nil:
result.kind = routeCanonical
result.canonicalPath = trace.exact.path.Clone()
case trace.operandOwner != nil:
result.kind = routeCanonical
result.canonicalPath = trace.operandOwner.path.Clone()
}
if result.kind == routeCanonical {
result.enteredPath = enteredEndpoint(path, origins, len(result.canonicalPath))
} else if len(path) == 0 {
result.kind = routeCanonical
} else if discovery, ok := findDiscoveryPath(snapshot.discoveryFlags, path); ok && len(discovery) == len(path) {
result.kind = routeDiscovery
result.discoveryPath = discovery
result.enteredPath = discovery.Clone()
result.args = commandpath.CloneTokens(trailing)
} else {
result.enteredPath = path.Clone()
}
if result.kind != routeDiscovery {
result.args = make([]string, 0, len(resolved)+len(trailing))
result.args = append(result.args, resolved...)
result.args = append(result.args, trailing...)
}
return result
}
func commandPathTokens(args []string) (commandpath.Path, []string) {
end := len(args)
for index, token := range args {
if token == "--" || (token != "-" && strings.HasPrefix(token, "-")) {
end = index
break
}
}
path := make(commandpath.Path, end)
copy(path, args[:end])
return path, append([]string(nil), args[end:]...)
}
func enteredEndpoint(path commandpath.Path, origins [][]int, canonicalLength int) commandpath.Path {
inputLength := 0
for _, componentOrigins := range origins[:canonicalLength] {
for _, origin := range componentOrigins {
if origin+1 > inputLength {
inputLength = origin + 1
}
}
}
return path[:inputLength].Clone()
}
func findDiscoveryPath(contexts map[string]resolvedFlagAliases, path commandpath.Path) (commandpath.Path, bool) {
for length := len(path); length > 0; length-- {
prefix := path[:length]
if _, exists := contexts[prefix.Key()]; exists {
return prefix.Clone(), true
}
}
return nil, false
}