command_private.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package flags
  2. import (
  3. "reflect"
  4. "sort"
  5. "strings"
  6. "unsafe"
  7. )
  8. type lookup struct {
  9. shortNames map[string]*Option
  10. longNames map[string]*Option
  11. required map[*Option]bool
  12. commands map[string]*Command
  13. }
  14. func newCommand(name string, shortDescription string, longDescription string, data interface{}) *Command {
  15. return &Command{
  16. Group: newGroup(shortDescription, longDescription, data),
  17. Name: name,
  18. }
  19. }
  20. func (c *Command) scanSubCommandHandler(parentg *Group) scanHandler {
  21. f := func(realval reflect.Value, sfield *reflect.StructField) (bool, error) {
  22. mtag := newMultiTag(string(sfield.Tag))
  23. if err := mtag.Parse(); err != nil {
  24. return true, err
  25. }
  26. subcommand := mtag.Get("command")
  27. if len(subcommand) != 0 {
  28. ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr()))
  29. shortDescription := mtag.Get("description")
  30. longDescription := mtag.Get("long-description")
  31. if _, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface()); err != nil {
  32. return true, err
  33. }
  34. return true, nil
  35. }
  36. return parentg.scanSubGroupHandler(realval, sfield)
  37. }
  38. return f
  39. }
  40. func (c *Command) scan() error {
  41. return c.scanType(c.scanSubCommandHandler(c.Group))
  42. }
  43. func (c *Command) eachCommand(f func(*Command), recurse bool) {
  44. f(c)
  45. for _, cc := range c.commands {
  46. if recurse {
  47. cc.eachCommand(f, true)
  48. } else {
  49. f(cc)
  50. }
  51. }
  52. }
  53. func (c *Command) eachActiveGroup(f func(g *Group)) {
  54. c.eachGroup(f)
  55. if c.Active != nil {
  56. c.Active.eachActiveGroup(f)
  57. }
  58. }
  59. func (c *Command) addHelpGroups(showHelp func() error) {
  60. if !c.hasBuiltinHelpGroup {
  61. c.addHelpGroup(showHelp)
  62. c.hasBuiltinHelpGroup = true
  63. }
  64. for _, cc := range c.commands {
  65. cc.addHelpGroups(showHelp)
  66. }
  67. }
  68. func (c *Command) makeLookup() lookup {
  69. ret := lookup{
  70. shortNames: make(map[string]*Option),
  71. longNames: make(map[string]*Option),
  72. required: make(map[*Option]bool),
  73. commands: make(map[string]*Command),
  74. }
  75. c.eachGroup(func(g *Group) {
  76. for _, option := range g.options {
  77. if option.Required && option.canCli() {
  78. ret.required[option] = true
  79. }
  80. if option.ShortName != 0 {
  81. ret.shortNames[string(option.ShortName)] = option
  82. }
  83. if len(option.LongName) > 0 {
  84. ret.longNames[option.LongName] = option
  85. }
  86. }
  87. })
  88. for _, subcommand := range c.commands {
  89. ret.commands[subcommand.Name] = subcommand
  90. }
  91. return ret
  92. }
  93. func (c *Command) groupByName(name string) *Group {
  94. if grp := c.Group.groupByName(name); grp != nil {
  95. return grp
  96. }
  97. for _, subc := range c.commands {
  98. prefix := subc.Name + "."
  99. if strings.HasPrefix(name, prefix) {
  100. if grp := subc.groupByName(name[len(prefix):]); grp != nil {
  101. return grp
  102. }
  103. } else if name == subc.Name {
  104. return subc.Group
  105. }
  106. }
  107. return nil
  108. }
  109. type commandList []*Command
  110. func (c commandList) Less(i, j int) bool {
  111. return c[i].Name < c[j].Name
  112. }
  113. func (c commandList) Len() int {
  114. return len(c)
  115. }
  116. func (c commandList) Swap(i, j int) {
  117. c[i], c[j] = c[j], c[i]
  118. }
  119. func (c *Command) sortedCommands() []*Command {
  120. ret := make(commandList, len(c.commands))
  121. copy(ret, c.commands)
  122. sort.Sort(ret)
  123. return []*Command(ret)
  124. }