Files
commandkit/internal/commandmeta/metadata.go

217 lines
6.0 KiB
Go

// Package commandmeta owns the neutral metadata exchanged by CommandKit and
// its command-line backend.
package commandmeta
import "strings"
// Key identifies one command inside one routing snapshot.
type Key uint64
// Command describes one node in a neutral command tree.
type Command struct {
Key Key
Name string
Summary string
Description string
Runnable bool
Flags []Flag
// CoreFlags are parsed by CommandKit but do not occupy consumer binding indexes.
CoreFlags []Flag
Arguments []Argument
Children []*Command
}
// Argument describes one positional input for usage rendering.
type Argument struct {
Name string
Usage string
Min int
Max int
Completion CompletionHint
}
// Flag describes one local option without exposing a backend value.
type Flag struct {
Name string
Short string
Usage string
Default string
Boolean bool
Repeated bool
Required bool
Completion CompletionHint
}
// CompletionKind selects the neutral value suggestion strategy.
type CompletionKind uint8
const (
CompletionNone CompletionKind = iota
CompletionChoices
CompletionFiles
CompletionDirectories
)
// CompletionChoice carries a literal value and optional description.
type CompletionChoice struct {
Value string
Description string
}
// CompletionHint describes value suggestions without backend types.
type CompletionHint struct {
Kind CompletionKind
Choices []CompletionChoice
}
// CompletionResult contains neutral suggestions and the entered value prefix.
type CompletionResult struct {
Kind CompletionKind
Choices []CompletionChoice
Prefix string
}
var reportingFlags = [...]Flag{
{Name: "quiet", Usage: "hide command output and optional messages; keep failures visible", Default: "false", Boolean: true},
{Name: "verbose", Usage: "show warning and informational messages", Default: "false", Boolean: true},
{Name: "debug", Usage: "show debugging messages", Default: "false", Boolean: true},
{Name: "progress", Usage: "show progress messages", Default: "false", Boolean: true},
{Name: "format", Usage: "report format: text, yaml, or json", Completion: CompletionHint{Kind: CompletionChoices, Choices: []CompletionChoice{{Value: "text"}, {Value: "yaml"}, {Value: "json"}}}},
}
// BooleanCompletion returns the ordinary explicit boolean suggestions.
func BooleanCompletion() CompletionHint {
return CompletionHint{Kind: CompletionChoices, Choices: []CompletionChoice{{Value: "true"}, {Value: "false"}}}
}
// HelpFlag describes the built-in help option for parser contexts.
func HelpFlag() Flag {
return Flag{Name: "help", Short: "h", Boolean: true, Completion: BooleanCompletion()}
}
// ReportingFlags returns the flags shared by CommandKit's invocation reporter.
func ReportingFlags() []Flag {
flags := append([]Flag(nil), reportingFlags[:]...)
for index := range flags {
if flags[index].Boolean {
flags[index].Completion = BooleanCompletion()
} else {
flags[index].Completion.Choices = append([]CompletionChoice(nil), flags[index].Completion.Choices...)
}
}
return flags
}
// EffectiveFlags combines the shared debug option while preserving consumer order.
func EffectiveFlags(flags, core []Flag) []Flag {
result := append([]Flag(nil), flags...)
shared := -1
for i, flag := range result {
if flag.Name == "debug" && flag.Boolean {
shared = i
break
}
}
for _, flag := range core {
if flag.Name == "debug" && shared >= 0 {
app := result[shared]
usage := flag.Usage
if app.Usage != "" {
usage += "; " + app.Usage
}
if strings.EqualFold(app.Default, "true") {
usage += "; application input defaults to true (reporting defaults to ordinary)"
}
flag.Usage, flag.Short, flag.Required, flag.Completion = usage, app.Short, app.Required, app.Completion
result[shared] = flag
continue
}
result = append(result, flag)
}
return result
}
// IsReportingFlag reports whether name is reserved for a shared reporting flag.
func IsReportingFlag(name string) bool {
for _, flag := range reportingFlags {
if flag.Name == name {
return true
}
}
return false
}
// FlagAlias maps one option spelling to a canonical flag spelling.
type FlagAlias struct {
Source string
Target string
}
// CommandAlias describes one explicitly declared command route for help.
type CommandAlias struct {
Source []string
Target []string
}
// HelpView selects a canonical or alias-only command help presentation.
type HelpView struct {
EnteredPath []string
CanonicalPath []string
Discovery bool
CoreFlags []Flag
CommandAliases []CommandAlias
FlagAliases []FlagAlias
}
// Failure is a neutral parsing or presentation failure.
type Failure struct {
Message string
Usage bool
}
// FlagOccurrence records one parsed spelling and its unconverted value.
type FlagOccurrence struct {
Name string // canonical flag name
Spelling string // entered long spelling or individual short spelling
RawValue string // unconverted value collected by the parser
}
// ReportingMode selects visibility for shared reporting messages.
type ReportingMode uint8
const (
ReportingModeNormal ReportingMode = iota
ReportingModeQuiet
ReportingModeVerbose
ReportingModeDebug
)
// ReportingSelection contains the resolved reporting options for one parse.
type ReportingSelection struct {
Mode ReportingMode
Progress bool
ProgressSet bool
Format string
}
// Result contains the selected command and raw input collected by the adapter.
type Result struct {
Key Key
Path []string
HelpRequested bool
FlagValues [][]string
FlagSpellings [][]string
FlagOccurrences []FlagOccurrence
Reporting ReportingSelection
Operands []string
Failure *Failure
}
// ParseOptions selects flag aliases for parser contexts.
type ParseOptions struct {
// FlagAliasesForPath selects aliases for the actual parser context when
// routing has not already selected one. It overrides FlagAliases when set.
FlagAliasesForPath func([]string) []FlagAlias
FlagAliases []FlagAlias
}