104 lines
2.8 KiB
Go
104 lines
2.8 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 len(path) == 0:
|
|
result.kind = routeCanonical
|
|
default:
|
|
discovery, ok := findDiscoveryPath(snapshot.discoveryFlags, resolved, path)
|
|
if !ok && len(snapshot.discoveryFlags) > 0 {
|
|
discovery, ok = findDiscoveryPath(snapshot.discoveryFlags, snapshot.aliases.ResolutionPaths(path)...)
|
|
}
|
|
if ok {
|
|
result.kind = routeDiscovery
|
|
result.discoveryPath = discovery
|
|
result.enteredPath = path.Clone()
|
|
result.args = commandpath.CloneTokens(trailing)
|
|
} else if trace.operandOwner != nil {
|
|
result.kind = routeCanonical
|
|
result.canonicalPath = trace.operandOwner.path.Clone()
|
|
} else {
|
|
result.enteredPath = path.Clone()
|
|
}
|
|
}
|
|
if result.kind == routeCanonical {
|
|
result.enteredPath = enteredEndpoint(path, origins, len(result.canonicalPath))
|
|
}
|
|
|
|
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, paths ...commandpath.Path) (commandpath.Path, bool) {
|
|
for _, path := range paths {
|
|
if _, exists := contexts[path.Key()]; len(path) > 0 && exists {
|
|
return path.Clone(), true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|