mirror of
https://github.com/syncthing/syncthing.git
synced 2024-11-16 02:18:44 -07:00
162 lines
3.1 KiB
Go
162 lines
3.1 KiB
Go
package flags
|
|
|
|
import (
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
"unsafe"
|
|
)
|
|
|
|
type lookup struct {
|
|
shortNames map[string]*Option
|
|
longNames map[string]*Option
|
|
|
|
required map[*Option]bool
|
|
commands map[string]*Command
|
|
}
|
|
|
|
func newCommand(name string, shortDescription string, longDescription string, data interface{}) *Command {
|
|
return &Command{
|
|
Group: newGroup(shortDescription, longDescription, data),
|
|
Name: name,
|
|
}
|
|
}
|
|
|
|
func (c *Command) scanSubCommandHandler(parentg *Group) scanHandler {
|
|
f := func(realval reflect.Value, sfield *reflect.StructField) (bool, error) {
|
|
mtag := newMultiTag(string(sfield.Tag))
|
|
|
|
if err := mtag.Parse(); err != nil {
|
|
return true, err
|
|
}
|
|
|
|
subcommand := mtag.Get("command")
|
|
|
|
if len(subcommand) != 0 {
|
|
ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr()))
|
|
|
|
shortDescription := mtag.Get("description")
|
|
longDescription := mtag.Get("long-description")
|
|
|
|
if _, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface()); err != nil {
|
|
return true, err
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
return parentg.scanSubGroupHandler(realval, sfield)
|
|
}
|
|
|
|
return f
|
|
}
|
|
|
|
func (c *Command) scan() error {
|
|
return c.scanType(c.scanSubCommandHandler(c.Group))
|
|
}
|
|
|
|
func (c *Command) eachCommand(f func(*Command), recurse bool) {
|
|
f(c)
|
|
|
|
for _, cc := range c.commands {
|
|
if recurse {
|
|
cc.eachCommand(f, true)
|
|
} else {
|
|
f(cc)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Command) eachActiveGroup(f func(g *Group)) {
|
|
c.eachGroup(f)
|
|
|
|
if c.Active != nil {
|
|
c.Active.eachActiveGroup(f)
|
|
}
|
|
}
|
|
|
|
func (c *Command) addHelpGroups(showHelp func() error) {
|
|
if !c.hasBuiltinHelpGroup {
|
|
c.addHelpGroup(showHelp)
|
|
c.hasBuiltinHelpGroup = true
|
|
}
|
|
|
|
for _, cc := range c.commands {
|
|
cc.addHelpGroups(showHelp)
|
|
}
|
|
}
|
|
|
|
func (c *Command) makeLookup() lookup {
|
|
ret := lookup{
|
|
shortNames: make(map[string]*Option),
|
|
longNames: make(map[string]*Option),
|
|
|
|
required: make(map[*Option]bool),
|
|
commands: make(map[string]*Command),
|
|
}
|
|
|
|
c.eachGroup(func(g *Group) {
|
|
for _, option := range g.options {
|
|
if option.Required && option.canCli() {
|
|
ret.required[option] = true
|
|
}
|
|
|
|
if option.ShortName != 0 {
|
|
ret.shortNames[string(option.ShortName)] = option
|
|
}
|
|
|
|
if len(option.LongName) > 0 {
|
|
ret.longNames[option.LongName] = option
|
|
}
|
|
}
|
|
})
|
|
|
|
for _, subcommand := range c.commands {
|
|
ret.commands[subcommand.Name] = subcommand
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (c *Command) groupByName(name string) *Group {
|
|
if grp := c.Group.groupByName(name); grp != nil {
|
|
return grp
|
|
}
|
|
|
|
for _, subc := range c.commands {
|
|
prefix := subc.Name + "."
|
|
|
|
if strings.HasPrefix(name, prefix) {
|
|
if grp := subc.groupByName(name[len(prefix):]); grp != nil {
|
|
return grp
|
|
}
|
|
} else if name == subc.Name {
|
|
return subc.Group
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type commandList []*Command
|
|
|
|
func (c commandList) Less(i, j int) bool {
|
|
return c[i].Name < c[j].Name
|
|
}
|
|
|
|
func (c commandList) Len() int {
|
|
return len(c)
|
|
}
|
|
|
|
func (c commandList) Swap(i, j int) {
|
|
c[i], c[j] = c[j], c[i]
|
|
}
|
|
|
|
func (c *Command) sortedCommands() []*Command {
|
|
ret := make(commandList, len(c.commands))
|
|
copy(ret, c.commands)
|
|
|
|
sort.Sort(ret)
|
|
return []*Command(ret)
|
|
}
|