package commandkit import ( "sort" internalcobra "gitea.maximumdirect.net/eric/CommandKit/internal/cobra" commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta" "gitea.maximumdirect.net/eric/CommandKit/internal/commandpath" ) func (a *App) parse(args []string, options commandmeta.ParseOptions) commandmeta.Result { if a == nil { return commandmeta.Result{Failure: &commandmeta.Failure{Message: "cannot parse commands on a nil app"}} } return internalcobra.Parse(a.routeSnapshot().metadata, args, options) } func (a *App) routeSnapshot() *routingSnapshot { if a == nil { return nil } if a.snapshot == nil { a.snapshot = a.buildRoutingSnapshot() } return a.snapshot } func (a *App) buildRoutingSnapshot() *routingSnapshot { root := &commandmeta.Command{Name: a.identity.Name, CoreFlags: commandmeta.ReportingFlags()} snapshot := &routingSnapshot{ metadata: root, runners: make(map[commandmeta.Key]commandPayload), aliases: a.aliases, canonical: buildCanonicalTree(a.commands), flagAliases: a.flagAliases, discoveryFlags: a.discoveryFlags, } for _, rule := range a.routingRules { if rule.record.kind != commandAliasRule { continue } snapshot.commandAliases = append(snapshot.commandAliases, commandmeta.CommandAlias{ Source: []string(rule.record.sourcePath.Clone()), Target: []string(snapshot.aliases.Resolve(rule.record.targetPath)), }) } sort.Slice(snapshot.commandAliases, func(i, j int) bool { return commandpath.FromTokens(snapshot.commandAliases[i].Source).Key() < commandpath.FromTokens(snapshot.commandAliases[j].Source).Key() }) names := make([]string, 0, len(a.commands)) for name := range a.commands { names = append(names, name) } sort.Strings(names) var key commandmeta.Key for _, name := range names { root.Children = append(root.Children, bridgeCommand(a.commands[name].command, snapshot, &key)) } return snapshot } func bridgeCommand(command Command, snapshot *routingSnapshot, next *commandmeta.Key) *commandmeta.Command { record := command.record *next = *next + 1 declaration := &commandmeta.Command{ Key: *next, Name: record.name, Summary: record.summary, Description: record.description, CoreFlags: commandmeta.ReportingFlags(), } if record.payload != nil { snapshot.runners[declaration.Key] = record.payload declaration.Runnable = record.payload.hasRun() declaration.Flags = record.payload.bridgeFlags() declaration.Arguments = record.payload.bridgeArguments() } children := append([]Command(nil), record.children...) sort.Slice(children, func(i, j int) bool { return children[i].record.name < children[j].record.name }) for _, child := range children { if child.record == nil || child.record.absent { continue } declaration.Children = append(declaration.Children, bridgeCommand(child, snapshot, next)) } return declaration }