mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-07-30 04:52:46 +00:00
294 lines
5.9 KiB
Go
294 lines
5.9 KiB
Go
// nolint: golint
|
|
package kingpin
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Data model for Kingpin command-line structure.
|
|
|
|
type FlagGroupModel struct {
|
|
Flags []*ClauseModel
|
|
}
|
|
|
|
func (f *FlagGroupModel) FlagByName(name string) *ClauseModel {
|
|
for _, flag := range f.Flags {
|
|
if flag.Name == name {
|
|
return flag
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (f *FlagGroupModel) FlagSummary() string {
|
|
out := []string{}
|
|
count := 0
|
|
for _, flag := range f.Flags {
|
|
if flag.Name != "help" {
|
|
count++
|
|
}
|
|
if flag.Required {
|
|
if flag.IsBoolFlag() {
|
|
out = append(out, fmt.Sprintf("--[no-]%s", flag.Name))
|
|
} else {
|
|
out = append(out, fmt.Sprintf("--%s=%s", flag.Name, flag.FormatPlaceHolder()))
|
|
}
|
|
}
|
|
}
|
|
if count != len(out) {
|
|
out = append(out, T("[<flags>]"))
|
|
}
|
|
return strings.Join(out, " ")
|
|
}
|
|
|
|
type ClauseModel struct {
|
|
Name string
|
|
Help string
|
|
Short rune
|
|
Default []string
|
|
Envar string
|
|
PlaceHolder string
|
|
Required bool
|
|
Hidden bool
|
|
Value Value
|
|
Cumulative bool
|
|
}
|
|
|
|
func (c *ClauseModel) String() string {
|
|
return c.Value.String()
|
|
}
|
|
|
|
func (c *ClauseModel) IsBoolFlag() bool {
|
|
if fl, ok := c.Value.(boolFlag); ok {
|
|
return fl.IsBoolFlag()
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (c *ClauseModel) FormatPlaceHolder() string {
|
|
if c.PlaceHolder != "" {
|
|
return c.PlaceHolder
|
|
}
|
|
if len(c.Default) > 0 {
|
|
ellipsis := ""
|
|
if len(c.Default) > 1 {
|
|
ellipsis = "..."
|
|
}
|
|
if _, ok := c.Value.(*stringValue); ok {
|
|
return strconv.Quote(c.Default[0]) + ellipsis
|
|
}
|
|
return c.Default[0] + ellipsis
|
|
}
|
|
return strings.ToUpper(c.Name)
|
|
}
|
|
|
|
type ArgGroupModel struct {
|
|
Args []*ClauseModel
|
|
}
|
|
|
|
func (a *ArgGroupModel) ArgSummary() string {
|
|
depth := 0
|
|
out := []string{}
|
|
for _, arg := range a.Args {
|
|
h := "<" + arg.Name + ">"
|
|
if arg.Cumulative {
|
|
h += " ..."
|
|
}
|
|
if !arg.Required {
|
|
h = "[" + h
|
|
depth++
|
|
}
|
|
out = append(out, h)
|
|
}
|
|
if len(out) == 0 {
|
|
return ""
|
|
}
|
|
out[len(out)-1] = out[len(out)-1] + strings.Repeat("]", depth)
|
|
return strings.Join(out, " ")
|
|
}
|
|
|
|
type CmdGroupModel struct {
|
|
Commands []*CmdModel
|
|
}
|
|
|
|
func (c *CmdGroupModel) FlattenedCommands() (out []*CmdModel) {
|
|
for _, cmd := range c.Commands {
|
|
if cmd.OptionalSubcommands {
|
|
out = append(out, cmd)
|
|
}
|
|
if len(cmd.Commands) == 0 {
|
|
out = append(out, cmd)
|
|
}
|
|
out = append(out, cmd.FlattenedCommands()...)
|
|
}
|
|
return
|
|
}
|
|
|
|
type CmdModel struct {
|
|
Name string
|
|
Aliases []string
|
|
Help string
|
|
Depth int
|
|
Hidden bool
|
|
Default bool
|
|
OptionalSubcommands bool
|
|
Parent *CmdModel
|
|
*FlagGroupModel
|
|
*ArgGroupModel
|
|
*CmdGroupModel
|
|
}
|
|
|
|
func (c *CmdModel) String() string {
|
|
return c.CmdSummary()
|
|
}
|
|
|
|
func (c *CmdModel) CmdSummary() string {
|
|
out := []string{}
|
|
for cursor := c; cursor != nil; cursor = cursor.Parent {
|
|
text := cursor.Name
|
|
if cursor.Default {
|
|
text = "*" + text
|
|
}
|
|
if flags := cursor.FlagSummary(); flags != "" {
|
|
text += " " + flags
|
|
}
|
|
if args := cursor.ArgSummary(); args != "" {
|
|
text += " " + args
|
|
}
|
|
out = append([]string{text}, out...)
|
|
}
|
|
return strings.Join(out, " ")
|
|
}
|
|
|
|
// FullCommand is the command path to this node, excluding positional arguments and flags.
|
|
func (c *CmdModel) FullCommand() string {
|
|
out := []string{}
|
|
for i := c; i != nil; i = i.Parent {
|
|
out = append([]string{i.Name}, out...)
|
|
}
|
|
return strings.Join(out, " ")
|
|
}
|
|
|
|
type ApplicationModel struct {
|
|
Name string
|
|
Help string
|
|
Version string
|
|
Author string
|
|
*ArgGroupModel
|
|
*CmdGroupModel
|
|
*FlagGroupModel
|
|
}
|
|
|
|
func (a *ApplicationModel) AppSummary() string {
|
|
summary := a.Name
|
|
if flags := a.FlagSummary(); flags != "" {
|
|
summary += " " + flags
|
|
}
|
|
if args := a.ArgSummary(); args != "" {
|
|
summary += " " + args
|
|
}
|
|
if len(a.Commands) > 0 {
|
|
summary += " <command>"
|
|
}
|
|
return summary
|
|
}
|
|
|
|
func (a *ApplicationModel) FindModelForCommand(cmd *CmdClause) *CmdModel {
|
|
if cmd == nil {
|
|
return nil
|
|
}
|
|
path := []string{}
|
|
for c := cmd; c != nil; c = c.parent {
|
|
path = append([]string{c.name}, path...)
|
|
}
|
|
var selected *CmdModel
|
|
cursor := a.CmdGroupModel
|
|
for _, component := range path {
|
|
for _, cmd := range cursor.Commands {
|
|
if cmd.Name == component {
|
|
selected = cmd
|
|
cursor = cmd.CmdGroupModel
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if selected == nil {
|
|
panic("this shouldn't happen")
|
|
}
|
|
return selected
|
|
}
|
|
|
|
func (a *Application) Model() *ApplicationModel {
|
|
return &ApplicationModel{
|
|
Name: a.Name,
|
|
Help: a.Help,
|
|
Version: a.version,
|
|
Author: a.author,
|
|
FlagGroupModel: a.flagGroup.Model(),
|
|
ArgGroupModel: a.argGroup.Model(),
|
|
CmdGroupModel: a.cmdGroup.Model(nil),
|
|
}
|
|
}
|
|
|
|
func (a *argGroup) Model() *ArgGroupModel {
|
|
m := &ArgGroupModel{}
|
|
for _, arg := range a.args {
|
|
m.Args = append(m.Args, arg.Model())
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (f *flagGroup) Model() *FlagGroupModel {
|
|
m := &FlagGroupModel{}
|
|
for _, fl := range f.flagOrder {
|
|
m.Flags = append(m.Flags, fl.Model())
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (f *Clause) Model() *ClauseModel {
|
|
_, cumulative := f.value.(cumulativeValue)
|
|
return &ClauseModel{
|
|
Name: f.name,
|
|
Help: f.help,
|
|
Short: f.shorthand,
|
|
Default: f.defaultValues,
|
|
Envar: f.envar,
|
|
PlaceHolder: f.placeholder,
|
|
Required: f.required,
|
|
Hidden: f.hidden,
|
|
Value: f.value,
|
|
Cumulative: cumulative,
|
|
}
|
|
}
|
|
|
|
func (c *cmdGroup) Model(parent *CmdModel) *CmdGroupModel {
|
|
m := &CmdGroupModel{}
|
|
for _, cm := range c.commandOrder {
|
|
m.Commands = append(m.Commands, cm.Model(parent))
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (c *CmdClause) Model(parent *CmdModel) *CmdModel {
|
|
depth := 0
|
|
for i := c; i != nil; i = i.parent {
|
|
depth++
|
|
}
|
|
cmd := &CmdModel{
|
|
Name: c.name,
|
|
Parent: parent,
|
|
Aliases: c.aliases,
|
|
Help: c.help,
|
|
Depth: depth,
|
|
Hidden: c.hidden,
|
|
Default: c.isDefault,
|
|
OptionalSubcommands: c.optionalSubcommands,
|
|
FlagGroupModel: c.flagGroup.Model(),
|
|
ArgGroupModel: c.argGroup.Model(),
|
|
}
|
|
cmd.CmdGroupModel = c.cmdGroup.Model(cmd)
|
|
return cmd
|
|
}
|