command.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  1. // Copyright © 2013 Steve Francia <spf@spf13.com>.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. //Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces.
  14. //In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code.
  15. package cobra
  16. import (
  17. "bytes"
  18. "fmt"
  19. "io"
  20. "os"
  21. "path/filepath"
  22. "runtime"
  23. "strings"
  24. "time"
  25. "github.com/inconshreveable/mousetrap"
  26. flag "github.com/spf13/pflag"
  27. )
  28. // Command is just that, a command for your application.
  29. // eg. 'go run' ... 'run' is the command. Cobra requires
  30. // you to define the usage and description as part of your command
  31. // definition to ensure usability.
  32. type Command struct {
  33. // Name is the command name, usually the executable's name.
  34. name string
  35. // The one-line usage message.
  36. Use string
  37. // An array of aliases that can be used instead of the first word in Use.
  38. Aliases []string
  39. // An array of command names for which this command will be suggested - similar to aliases but only suggests.
  40. SuggestFor []string
  41. // The short description shown in the 'help' output.
  42. Short string
  43. // The long message shown in the 'help <this-command>' output.
  44. Long string
  45. // Examples of how to use the command
  46. Example string
  47. // List of all valid non-flag arguments, used for bash completions *TODO* actually validate these
  48. ValidArgs []string
  49. // Custom functions used by the bash autocompletion generator
  50. BashCompletionFunction string
  51. // Is this command deprecated and should print this string when used?
  52. Deprecated string
  53. // Is this command hidden and should NOT show up in the list of available commands?
  54. Hidden bool
  55. // Full set of flags
  56. flags *flag.FlagSet
  57. // Set of flags childrens of this command will inherit
  58. pflags *flag.FlagSet
  59. // Flags that are declared specifically by this command (not inherited).
  60. lflags *flag.FlagSet
  61. // SilenceErrors is an option to quiet errors down stream
  62. SilenceErrors bool
  63. // Silence Usage is an option to silence usage when an error occurs.
  64. SilenceUsage bool
  65. // The *Run functions are executed in the following order:
  66. // * PersistentPreRun()
  67. // * PreRun()
  68. // * Run()
  69. // * PostRun()
  70. // * PersistentPostRun()
  71. // All functions get the same args, the arguments after the command name
  72. // PersistentPreRun: children of this command will inherit and execute
  73. PersistentPreRun func(cmd *Command, args []string)
  74. // PersistentPreRunE: PersistentPreRun but returns an error
  75. PersistentPreRunE func(cmd *Command, args []string) error
  76. // PreRun: children of this command will not inherit.
  77. PreRun func(cmd *Command, args []string)
  78. // PreRunE: PreRun but returns an error
  79. PreRunE func(cmd *Command, args []string) error
  80. // Run: Typically the actual work function. Most commands will only implement this
  81. Run func(cmd *Command, args []string)
  82. // RunE: Run but returns an error
  83. RunE func(cmd *Command, args []string) error
  84. // PostRun: run after the Run command.
  85. PostRun func(cmd *Command, args []string)
  86. // PostRunE: PostRun but returns an error
  87. PostRunE func(cmd *Command, args []string) error
  88. // PersistentPostRun: children of this command will inherit and execute after PostRun
  89. PersistentPostRun func(cmd *Command, args []string)
  90. // PersistentPostRunE: PersistentPostRun but returns an error
  91. PersistentPostRunE func(cmd *Command, args []string) error
  92. // DisableAutoGenTag remove
  93. DisableAutoGenTag bool
  94. // Commands is the list of commands supported by this program.
  95. commands []*Command
  96. // Parent Command for this command
  97. parent *Command
  98. // max lengths of commands' string lengths for use in padding
  99. commandsMaxUseLen int
  100. commandsMaxCommandPathLen int
  101. commandsMaxNameLen int
  102. flagErrorBuf *bytes.Buffer
  103. args []string // actual args parsed from flags
  104. output *io.Writer // nil means stderr; use Out() method instead
  105. usageFunc func(*Command) error // Usage can be defined by application
  106. usageTemplate string // Can be defined by Application
  107. helpTemplate string // Can be defined by Application
  108. helpFunc func(*Command, []string) // Help can be defined by application
  109. helpCommand *Command // The help command
  110. // The global normalization function that we can use on every pFlag set and children commands
  111. globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName
  112. // Disable the suggestions based on Levenshtein distance that go along with 'unknown command' messages
  113. DisableSuggestions bool
  114. // If displaying suggestions, allows to set the minimum levenshtein distance to display, must be > 0
  115. SuggestionsMinimumDistance int
  116. }
  117. // os.Args[1:] by default, if desired, can be overridden
  118. // particularly useful when testing.
  119. func (c *Command) SetArgs(a []string) {
  120. c.args = a
  121. }
  122. func (c *Command) getOut(def io.Writer) io.Writer {
  123. if c.output != nil {
  124. return *c.output
  125. }
  126. if c.HasParent() {
  127. return c.parent.Out()
  128. } else {
  129. return def
  130. }
  131. }
  132. func (c *Command) Out() io.Writer {
  133. return c.getOut(os.Stderr)
  134. }
  135. func (c *Command) getOutOrStdout() io.Writer {
  136. return c.getOut(os.Stdout)
  137. }
  138. // SetOutput sets the destination for usage and error messages.
  139. // If output is nil, os.Stderr is used.
  140. func (c *Command) SetOutput(output io.Writer) {
  141. c.output = &output
  142. }
  143. // Usage can be defined by application
  144. func (c *Command) SetUsageFunc(f func(*Command) error) {
  145. c.usageFunc = f
  146. }
  147. // Can be defined by Application
  148. func (c *Command) SetUsageTemplate(s string) {
  149. c.usageTemplate = s
  150. }
  151. // Can be defined by Application
  152. func (c *Command) SetHelpFunc(f func(*Command, []string)) {
  153. c.helpFunc = f
  154. }
  155. func (c *Command) SetHelpCommand(cmd *Command) {
  156. c.helpCommand = cmd
  157. }
  158. // Can be defined by Application
  159. func (c *Command) SetHelpTemplate(s string) {
  160. c.helpTemplate = s
  161. }
  162. // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands.
  163. // The user should not have a cyclic dependency on commands.
  164. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) {
  165. c.Flags().SetNormalizeFunc(n)
  166. c.PersistentFlags().SetNormalizeFunc(n)
  167. c.globNormFunc = n
  168. for _, command := range c.commands {
  169. command.SetGlobalNormalizationFunc(n)
  170. }
  171. }
  172. func (c *Command) UsageFunc() (f func(*Command) error) {
  173. if c.usageFunc != nil {
  174. return c.usageFunc
  175. }
  176. if c.HasParent() {
  177. return c.parent.UsageFunc()
  178. } else {
  179. return func(c *Command) error {
  180. err := tmpl(c.Out(), c.UsageTemplate(), c)
  181. if err != nil {
  182. fmt.Print(err)
  183. }
  184. return err
  185. }
  186. }
  187. }
  188. // HelpFunc returns either the function set by SetHelpFunc for this command
  189. // or a parent, or it returns a function which calls c.Help()
  190. func (c *Command) HelpFunc() func(*Command, []string) {
  191. cmd := c
  192. for cmd != nil {
  193. if cmd.helpFunc != nil {
  194. return cmd.helpFunc
  195. }
  196. cmd = cmd.parent
  197. }
  198. return func(*Command, []string) {
  199. err := c.Help()
  200. if err != nil {
  201. c.Println(err)
  202. }
  203. }
  204. }
  205. var minUsagePadding int = 25
  206. func (c *Command) UsagePadding() int {
  207. if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen {
  208. return minUsagePadding
  209. } else {
  210. return c.parent.commandsMaxUseLen
  211. }
  212. }
  213. var minCommandPathPadding int = 11
  214. //
  215. func (c *Command) CommandPathPadding() int {
  216. if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen {
  217. return minCommandPathPadding
  218. } else {
  219. return c.parent.commandsMaxCommandPathLen
  220. }
  221. }
  222. var minNamePadding int = 11
  223. func (c *Command) NamePadding() int {
  224. if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
  225. return minNamePadding
  226. } else {
  227. return c.parent.commandsMaxNameLen
  228. }
  229. }
  230. func (c *Command) UsageTemplate() string {
  231. if c.usageTemplate != "" {
  232. return c.usageTemplate
  233. }
  234. if c.HasParent() {
  235. return c.parent.UsageTemplate()
  236. } else {
  237. return `Usage:{{if .Runnable}}
  238. {{.UseLine}}{{if .HasFlags}} [flags]{{end}}{{end}}{{if .HasSubCommands}}
  239. {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
  240. Aliases:
  241. {{.NameAndAliases}}
  242. {{end}}{{if .HasExample}}
  243. Examples:
  244. {{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
  245. Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  246. {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasLocalFlags}}
  247. Flags:
  248. {{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasInheritedFlags}}
  249. Global Flags:
  250. {{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
  251. Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  252. {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasSubCommands }}
  253. Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
  254. `
  255. }
  256. }
  257. func (c *Command) HelpTemplate() string {
  258. if c.helpTemplate != "" {
  259. return c.helpTemplate
  260. }
  261. if c.HasParent() {
  262. return c.parent.HelpTemplate()
  263. } else {
  264. return `{{with or .Long .Short }}{{. | trim}}
  265. {{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`
  266. }
  267. }
  268. // Really only used when casting a command to a commander
  269. func (c *Command) resetChildrensParents() {
  270. for _, x := range c.commands {
  271. x.parent = c
  272. }
  273. }
  274. // Test if the named flag is a boolean flag.
  275. func isBooleanFlag(name string, f *flag.FlagSet) bool {
  276. flag := f.Lookup(name)
  277. if flag == nil {
  278. return false
  279. }
  280. return flag.Value.Type() == "bool"
  281. }
  282. // Test if the named flag is a boolean flag.
  283. func isBooleanShortFlag(name string, f *flag.FlagSet) bool {
  284. result := false
  285. f.VisitAll(func(f *flag.Flag) {
  286. if f.Shorthand == name && f.Value.Type() == "bool" {
  287. result = true
  288. }
  289. })
  290. return result
  291. }
  292. func stripFlags(args []string, c *Command) []string {
  293. if len(args) < 1 {
  294. return args
  295. }
  296. c.mergePersistentFlags()
  297. commands := []string{}
  298. inQuote := false
  299. inFlag := false
  300. for _, y := range args {
  301. if !inQuote {
  302. switch {
  303. case strings.HasPrefix(y, "\""):
  304. inQuote = true
  305. case strings.Contains(y, "=\""):
  306. inQuote = true
  307. case strings.HasPrefix(y, "--") && !strings.Contains(y, "="):
  308. // TODO: this isn't quite right, we should really check ahead for 'true' or 'false'
  309. inFlag = !isBooleanFlag(y[2:], c.Flags())
  310. case strings.HasPrefix(y, "-") && !strings.Contains(y, "=") && len(y) == 2 && !isBooleanShortFlag(y[1:], c.Flags()):
  311. inFlag = true
  312. case inFlag:
  313. inFlag = false
  314. case y == "":
  315. // strip empty commands, as the go tests expect this to be ok....
  316. case !strings.HasPrefix(y, "-"):
  317. commands = append(commands, y)
  318. inFlag = false
  319. }
  320. }
  321. if strings.HasSuffix(y, "\"") && !strings.HasSuffix(y, "\\\"") {
  322. inQuote = false
  323. }
  324. }
  325. return commands
  326. }
  327. // argsMinusFirstX removes only the first x from args. Otherwise, commands that look like
  328. // openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]).
  329. func argsMinusFirstX(args []string, x string) []string {
  330. for i, y := range args {
  331. if x == y {
  332. ret := []string{}
  333. ret = append(ret, args[:i]...)
  334. ret = append(ret, args[i+1:]...)
  335. return ret
  336. }
  337. }
  338. return args
  339. }
  340. // find the target command given the args and command tree
  341. // Meant to be run on the highest node. Only searches down.
  342. func (c *Command) Find(args []string) (*Command, []string, error) {
  343. if c == nil {
  344. return nil, nil, fmt.Errorf("Called find() on a nil Command")
  345. }
  346. var innerfind func(*Command, []string) (*Command, []string)
  347. innerfind = func(c *Command, innerArgs []string) (*Command, []string) {
  348. argsWOflags := stripFlags(innerArgs, c)
  349. if len(argsWOflags) == 0 {
  350. return c, innerArgs
  351. }
  352. nextSubCmd := argsWOflags[0]
  353. matches := make([]*Command, 0)
  354. for _, cmd := range c.commands {
  355. if cmd.Name() == nextSubCmd || cmd.HasAlias(nextSubCmd) { // exact name or alias match
  356. return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd))
  357. }
  358. if EnablePrefixMatching {
  359. if strings.HasPrefix(cmd.Name(), nextSubCmd) { // prefix match
  360. matches = append(matches, cmd)
  361. }
  362. for _, x := range cmd.Aliases {
  363. if strings.HasPrefix(x, nextSubCmd) {
  364. matches = append(matches, cmd)
  365. }
  366. }
  367. }
  368. }
  369. // only accept a single prefix match - multiple matches would be ambiguous
  370. if len(matches) == 1 {
  371. return innerfind(matches[0], argsMinusFirstX(innerArgs, argsWOflags[0]))
  372. }
  373. return c, innerArgs
  374. }
  375. commandFound, a := innerfind(c, args)
  376. argsWOflags := stripFlags(a, commandFound)
  377. // no subcommand, always take args
  378. if !commandFound.HasSubCommands() {
  379. return commandFound, a, nil
  380. }
  381. // root command with subcommands, do subcommand checking
  382. if commandFound == c && len(argsWOflags) > 0 {
  383. suggestionsString := ""
  384. if !c.DisableSuggestions {
  385. if c.SuggestionsMinimumDistance <= 0 {
  386. c.SuggestionsMinimumDistance = 2
  387. }
  388. if suggestions := c.SuggestionsFor(argsWOflags[0]); len(suggestions) > 0 {
  389. suggestionsString += "\n\nDid you mean this?\n"
  390. for _, s := range suggestions {
  391. suggestionsString += fmt.Sprintf("\t%v\n", s)
  392. }
  393. }
  394. }
  395. return commandFound, a, fmt.Errorf("unknown command %q for %q%s", argsWOflags[0], commandFound.CommandPath(), suggestionsString)
  396. }
  397. return commandFound, a, nil
  398. }
  399. func (c *Command) SuggestionsFor(typedName string) []string {
  400. suggestions := []string{}
  401. for _, cmd := range c.commands {
  402. if cmd.IsAvailableCommand() {
  403. levenshteinDistance := ld(typedName, cmd.Name(), true)
  404. suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance
  405. suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName))
  406. if suggestByLevenshtein || suggestByPrefix {
  407. suggestions = append(suggestions, cmd.Name())
  408. }
  409. for _, explicitSuggestion := range cmd.SuggestFor {
  410. if strings.EqualFold(typedName, explicitSuggestion) {
  411. suggestions = append(suggestions, cmd.Name())
  412. }
  413. }
  414. }
  415. }
  416. return suggestions
  417. }
  418. func (c *Command) VisitParents(fn func(*Command)) {
  419. var traverse func(*Command) *Command
  420. traverse = func(x *Command) *Command {
  421. if x != c {
  422. fn(x)
  423. }
  424. if x.HasParent() {
  425. return traverse(x.parent)
  426. }
  427. return x
  428. }
  429. traverse(c)
  430. }
  431. func (c *Command) Root() *Command {
  432. var findRoot func(*Command) *Command
  433. findRoot = func(x *Command) *Command {
  434. if x.HasParent() {
  435. return findRoot(x.parent)
  436. }
  437. return x
  438. }
  439. return findRoot(c)
  440. }
  441. // ArgsLenAtDash will return the length of f.Args at the moment when a -- was
  442. // found during arg parsing. This allows your program to know which args were
  443. // before the -- and which came after. (Description from
  444. // https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash).
  445. func (c *Command) ArgsLenAtDash() int {
  446. return c.Flags().ArgsLenAtDash()
  447. }
  448. func (c *Command) execute(a []string) (err error) {
  449. if c == nil {
  450. return fmt.Errorf("Called Execute() on a nil Command")
  451. }
  452. if len(c.Deprecated) > 0 {
  453. c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated)
  454. }
  455. // initialize help flag as the last point possible to allow for user
  456. // overriding
  457. c.initHelpFlag()
  458. err = c.ParseFlags(a)
  459. if err != nil {
  460. return err
  461. }
  462. // If help is called, regardless of other flags, return we want help
  463. // Also say we need help if the command isn't runnable.
  464. helpVal, err := c.Flags().GetBool("help")
  465. if err != nil {
  466. // should be impossible to get here as we always declare a help
  467. // flag in initHelpFlag()
  468. c.Println("\"help\" flag declared as non-bool. Please correct your code")
  469. return err
  470. }
  471. if helpVal || !c.Runnable() {
  472. return flag.ErrHelp
  473. }
  474. c.preRun()
  475. argWoFlags := c.Flags().Args()
  476. for p := c; p != nil; p = p.Parent() {
  477. if p.PersistentPreRunE != nil {
  478. if err := p.PersistentPreRunE(c, argWoFlags); err != nil {
  479. return err
  480. }
  481. break
  482. } else if p.PersistentPreRun != nil {
  483. p.PersistentPreRun(c, argWoFlags)
  484. break
  485. }
  486. }
  487. if c.PreRunE != nil {
  488. if err := c.PreRunE(c, argWoFlags); err != nil {
  489. return err
  490. }
  491. } else if c.PreRun != nil {
  492. c.PreRun(c, argWoFlags)
  493. }
  494. if c.RunE != nil {
  495. if err := c.RunE(c, argWoFlags); err != nil {
  496. return err
  497. }
  498. } else {
  499. c.Run(c, argWoFlags)
  500. }
  501. if c.PostRunE != nil {
  502. if err := c.PostRunE(c, argWoFlags); err != nil {
  503. return err
  504. }
  505. } else if c.PostRun != nil {
  506. c.PostRun(c, argWoFlags)
  507. }
  508. for p := c; p != nil; p = p.Parent() {
  509. if p.PersistentPostRunE != nil {
  510. if err := p.PersistentPostRunE(c, argWoFlags); err != nil {
  511. return err
  512. }
  513. break
  514. } else if p.PersistentPostRun != nil {
  515. p.PersistentPostRun(c, argWoFlags)
  516. break
  517. }
  518. }
  519. return nil
  520. }
  521. func (c *Command) preRun() {
  522. for _, x := range initializers {
  523. x()
  524. }
  525. }
  526. func (c *Command) errorMsgFromParse() string {
  527. s := c.flagErrorBuf.String()
  528. x := strings.Split(s, "\n")
  529. if len(x) > 0 {
  530. return x[0]
  531. } else {
  532. return ""
  533. }
  534. }
  535. // Call execute to use the args (os.Args[1:] by default)
  536. // and run through the command tree finding appropriate matches
  537. // for commands and then corresponding flags.
  538. func (c *Command) Execute() error {
  539. _, err := c.ExecuteC()
  540. return err
  541. }
  542. func (c *Command) ExecuteC() (cmd *Command, err error) {
  543. // Regardless of what command execute is called on, run on Root only
  544. if c.HasParent() {
  545. return c.Root().ExecuteC()
  546. }
  547. if EnableWindowsMouseTrap && runtime.GOOS == "windows" {
  548. if mousetrap.StartedByExplorer() {
  549. c.Print(MousetrapHelpText)
  550. time.Sleep(5 * time.Second)
  551. os.Exit(1)
  552. }
  553. }
  554. // initialize help as the last point possible to allow for user
  555. // overriding
  556. c.initHelpCmd()
  557. var args []string
  558. // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155
  559. if len(c.args) == 0 && filepath.Base(os.Args[0]) != "cobra.test" {
  560. args = os.Args[1:]
  561. } else {
  562. args = c.args
  563. }
  564. cmd, flags, err := c.Find(args)
  565. if err != nil {
  566. // If found parse to a subcommand and then failed, talk about the subcommand
  567. if cmd != nil {
  568. c = cmd
  569. }
  570. if !c.SilenceErrors {
  571. c.Println("Error:", err.Error())
  572. c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
  573. }
  574. return c, err
  575. }
  576. err = cmd.execute(flags)
  577. if err != nil {
  578. // If root command has SilentErrors flagged,
  579. // all subcommands should respect it
  580. if !cmd.SilenceErrors && !c.SilenceErrors {
  581. if err == flag.ErrHelp {
  582. cmd.HelpFunc()(cmd, args)
  583. return cmd, nil
  584. }
  585. c.Println("Error:", err.Error())
  586. }
  587. // If root command has SilentUsage flagged,
  588. // all subcommands should respect it
  589. if !cmd.SilenceUsage && !c.SilenceUsage {
  590. c.Println(cmd.UsageString())
  591. }
  592. return cmd, err
  593. }
  594. return cmd, nil
  595. }
  596. func (c *Command) initHelpFlag() {
  597. if c.Flags().Lookup("help") == nil {
  598. c.Flags().BoolP("help", "h", false, "help for "+c.Name())
  599. }
  600. }
  601. func (c *Command) initHelpCmd() {
  602. if c.helpCommand == nil {
  603. if !c.HasSubCommands() {
  604. return
  605. }
  606. c.helpCommand = &Command{
  607. Use: "help [command]",
  608. Short: "Help about any command",
  609. Long: `Help provides help for any command in the application.
  610. Simply type ` + c.Name() + ` help [path to command] for full details.`,
  611. PersistentPreRun: func(cmd *Command, args []string) {},
  612. PersistentPostRun: func(cmd *Command, args []string) {},
  613. Run: func(c *Command, args []string) {
  614. cmd, _, e := c.Root().Find(args)
  615. if cmd == nil || e != nil {
  616. c.Printf("Unknown help topic %#q.", args)
  617. c.Root().Usage()
  618. } else {
  619. helpFunc := cmd.HelpFunc()
  620. helpFunc(cmd, args)
  621. }
  622. },
  623. }
  624. }
  625. c.AddCommand(c.helpCommand)
  626. }
  627. // Used for testing
  628. func (c *Command) ResetCommands() {
  629. c.commands = nil
  630. c.helpCommand = nil
  631. }
  632. //Commands returns a slice of child commands.
  633. func (c *Command) Commands() []*Command {
  634. return c.commands
  635. }
  636. // AddCommand adds one or more commands to this parent command.
  637. func (c *Command) AddCommand(cmds ...*Command) {
  638. for i, x := range cmds {
  639. if cmds[i] == c {
  640. panic("Command can't be a child of itself")
  641. }
  642. cmds[i].parent = c
  643. // update max lengths
  644. usageLen := len(x.Use)
  645. if usageLen > c.commandsMaxUseLen {
  646. c.commandsMaxUseLen = usageLen
  647. }
  648. commandPathLen := len(x.CommandPath())
  649. if commandPathLen > c.commandsMaxCommandPathLen {
  650. c.commandsMaxCommandPathLen = commandPathLen
  651. }
  652. nameLen := len(x.Name())
  653. if nameLen > c.commandsMaxNameLen {
  654. c.commandsMaxNameLen = nameLen
  655. }
  656. // If glabal normalization function exists, update all children
  657. if c.globNormFunc != nil {
  658. x.SetGlobalNormalizationFunc(c.globNormFunc)
  659. }
  660. c.commands = append(c.commands, x)
  661. }
  662. }
  663. // AddCommand removes one or more commands from a parent command.
  664. func (c *Command) RemoveCommand(cmds ...*Command) {
  665. commands := []*Command{}
  666. main:
  667. for _, command := range c.commands {
  668. for _, cmd := range cmds {
  669. if command == cmd {
  670. command.parent = nil
  671. continue main
  672. }
  673. }
  674. commands = append(commands, command)
  675. }
  676. c.commands = commands
  677. // recompute all lengths
  678. c.commandsMaxUseLen = 0
  679. c.commandsMaxCommandPathLen = 0
  680. c.commandsMaxNameLen = 0
  681. for _, command := range c.commands {
  682. usageLen := len(command.Use)
  683. if usageLen > c.commandsMaxUseLen {
  684. c.commandsMaxUseLen = usageLen
  685. }
  686. commandPathLen := len(command.CommandPath())
  687. if commandPathLen > c.commandsMaxCommandPathLen {
  688. c.commandsMaxCommandPathLen = commandPathLen
  689. }
  690. nameLen := len(command.Name())
  691. if nameLen > c.commandsMaxNameLen {
  692. c.commandsMaxNameLen = nameLen
  693. }
  694. }
  695. }
  696. // Convenience method to Print to the defined output
  697. func (c *Command) Print(i ...interface{}) {
  698. fmt.Fprint(c.Out(), i...)
  699. }
  700. // Convenience method to Println to the defined output
  701. func (c *Command) Println(i ...interface{}) {
  702. str := fmt.Sprintln(i...)
  703. c.Print(str)
  704. }
  705. // Convenience method to Printf to the defined output
  706. func (c *Command) Printf(format string, i ...interface{}) {
  707. str := fmt.Sprintf(format, i...)
  708. c.Print(str)
  709. }
  710. // Output the usage for the command
  711. // Used when a user provides invalid input
  712. // Can be defined by user by overriding UsageFunc
  713. func (c *Command) Usage() error {
  714. c.mergePersistentFlags()
  715. err := c.UsageFunc()(c)
  716. return err
  717. }
  718. // Output the help for the command
  719. // Used when a user calls help [command]
  720. // by the default HelpFunc in the commander
  721. func (c *Command) Help() error {
  722. c.mergePersistentFlags()
  723. err := tmpl(c.getOutOrStdout(), c.HelpTemplate(), c)
  724. return err
  725. }
  726. func (c *Command) UsageString() string {
  727. tmpOutput := c.output
  728. bb := new(bytes.Buffer)
  729. c.SetOutput(bb)
  730. c.Usage()
  731. c.output = tmpOutput
  732. return bb.String()
  733. }
  734. // CommandPath returns the full path to this command.
  735. func (c *Command) CommandPath() string {
  736. str := c.Name()
  737. x := c
  738. for x.HasParent() {
  739. str = x.parent.Name() + " " + str
  740. x = x.parent
  741. }
  742. return str
  743. }
  744. //The full usage for a given command (including parents)
  745. func (c *Command) UseLine() string {
  746. str := ""
  747. if c.HasParent() {
  748. str = c.parent.CommandPath() + " "
  749. }
  750. return str + c.Use
  751. }
  752. // For use in determining which flags have been assigned to which commands
  753. // and which persist
  754. func (c *Command) DebugFlags() {
  755. c.Println("DebugFlags called on", c.Name())
  756. var debugflags func(*Command)
  757. debugflags = func(x *Command) {
  758. if x.HasFlags() || x.HasPersistentFlags() {
  759. c.Println(x.Name())
  760. }
  761. if x.HasFlags() {
  762. x.flags.VisitAll(func(f *flag.Flag) {
  763. if x.HasPersistentFlags() {
  764. if x.persistentFlag(f.Name) == nil {
  765. c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
  766. } else {
  767. c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]")
  768. }
  769. } else {
  770. c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]")
  771. }
  772. })
  773. }
  774. if x.HasPersistentFlags() {
  775. x.pflags.VisitAll(func(f *flag.Flag) {
  776. if x.HasFlags() {
  777. if x.flags.Lookup(f.Name) == nil {
  778. c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
  779. }
  780. } else {
  781. c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]")
  782. }
  783. })
  784. }
  785. c.Println(x.flagErrorBuf)
  786. if x.HasSubCommands() {
  787. for _, y := range x.commands {
  788. debugflags(y)
  789. }
  790. }
  791. }
  792. debugflags(c)
  793. }
  794. // Name returns the command's name: the first word in the use line.
  795. func (c *Command) Name() string {
  796. if c.name != "" {
  797. return c.name
  798. }
  799. name := c.Use
  800. i := strings.Index(name, " ")
  801. if i >= 0 {
  802. name = name[:i]
  803. }
  804. return name
  805. }
  806. // Determine if a given string is an alias of the command.
  807. func (c *Command) HasAlias(s string) bool {
  808. for _, a := range c.Aliases {
  809. if a == s {
  810. return true
  811. }
  812. }
  813. return false
  814. }
  815. func (c *Command) NameAndAliases() string {
  816. return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ")
  817. }
  818. func (c *Command) HasExample() bool {
  819. return len(c.Example) > 0
  820. }
  821. // Determine if the command is itself runnable
  822. func (c *Command) Runnable() bool {
  823. return c.Run != nil || c.RunE != nil
  824. }
  825. // Determine if the command has children commands
  826. func (c *Command) HasSubCommands() bool {
  827. return len(c.commands) > 0
  828. }
  829. // IsAvailableCommand determines if a command is available as a non-help command
  830. // (this includes all non deprecated/hidden commands)
  831. func (c *Command) IsAvailableCommand() bool {
  832. if len(c.Deprecated) != 0 || c.Hidden {
  833. return false
  834. }
  835. if c.HasParent() && c.Parent().helpCommand == c {
  836. return false
  837. }
  838. if c.Runnable() || c.HasAvailableSubCommands() {
  839. return true
  840. }
  841. return false
  842. }
  843. // IsHelpCommand determines if a command is a 'help' command; a help command is
  844. // determined by the fact that it is NOT runnable/hidden/deprecated, and has no
  845. // sub commands that are runnable/hidden/deprecated
  846. func (c *Command) IsHelpCommand() bool {
  847. // if a command is runnable, deprecated, or hidden it is not a 'help' command
  848. if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden {
  849. return false
  850. }
  851. // if any non-help sub commands are found, the command is not a 'help' command
  852. for _, sub := range c.commands {
  853. if !sub.IsHelpCommand() {
  854. return false
  855. }
  856. }
  857. // the command either has no sub commands, or no non-help sub commands
  858. return true
  859. }
  860. // HasHelpSubCommands determines if a command has any avilable 'help' sub commands
  861. // that need to be shown in the usage/help default template under 'additional help
  862. // topics'
  863. func (c *Command) HasHelpSubCommands() bool {
  864. // return true on the first found available 'help' sub command
  865. for _, sub := range c.commands {
  866. if sub.IsHelpCommand() {
  867. return true
  868. }
  869. }
  870. // the command either has no sub commands, or no available 'help' sub commands
  871. return false
  872. }
  873. // HasAvailableSubCommands determines if a command has available sub commands that
  874. // need to be shown in the usage/help default template under 'available commands'
  875. func (c *Command) HasAvailableSubCommands() bool {
  876. // return true on the first found available (non deprecated/help/hidden)
  877. // sub command
  878. for _, sub := range c.commands {
  879. if sub.IsAvailableCommand() {
  880. return true
  881. }
  882. }
  883. // the command either has no sub comamnds, or no available (non deprecated/help/hidden)
  884. // sub commands
  885. return false
  886. }
  887. // Determine if the command is a child command
  888. func (c *Command) HasParent() bool {
  889. return c.parent != nil
  890. }
  891. // GlobalNormalizationFunc returns the global normalization function or nil if doesn't exists
  892. func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName {
  893. return c.globNormFunc
  894. }
  895. // Get the complete FlagSet that applies to this command (local and persistent declared here and by all parents)
  896. func (c *Command) Flags() *flag.FlagSet {
  897. if c.flags == nil {
  898. c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  899. if c.flagErrorBuf == nil {
  900. c.flagErrorBuf = new(bytes.Buffer)
  901. }
  902. c.flags.SetOutput(c.flagErrorBuf)
  903. }
  904. return c.flags
  905. }
  906. // Get the local FlagSet specifically set in the current command
  907. func (c *Command) LocalFlags() *flag.FlagSet {
  908. c.mergePersistentFlags()
  909. local := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  910. c.lflags.VisitAll(func(f *flag.Flag) {
  911. local.AddFlag(f)
  912. })
  913. if !c.HasParent() {
  914. flag.CommandLine.VisitAll(func(f *flag.Flag) {
  915. if local.Lookup(f.Name) == nil {
  916. local.AddFlag(f)
  917. }
  918. })
  919. }
  920. return local
  921. }
  922. // All Flags which were inherited from parents commands
  923. func (c *Command) InheritedFlags() *flag.FlagSet {
  924. c.mergePersistentFlags()
  925. inherited := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  926. local := c.LocalFlags()
  927. var rmerge func(x *Command)
  928. rmerge = func(x *Command) {
  929. if x.HasPersistentFlags() {
  930. x.PersistentFlags().VisitAll(func(f *flag.Flag) {
  931. if inherited.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil {
  932. inherited.AddFlag(f)
  933. }
  934. })
  935. }
  936. if x.HasParent() {
  937. rmerge(x.parent)
  938. }
  939. }
  940. if c.HasParent() {
  941. rmerge(c.parent)
  942. }
  943. return inherited
  944. }
  945. // All Flags which were not inherited from parent commands
  946. func (c *Command) NonInheritedFlags() *flag.FlagSet {
  947. return c.LocalFlags()
  948. }
  949. // Get the Persistent FlagSet specifically set in the current command
  950. func (c *Command) PersistentFlags() *flag.FlagSet {
  951. if c.pflags == nil {
  952. c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  953. if c.flagErrorBuf == nil {
  954. c.flagErrorBuf = new(bytes.Buffer)
  955. }
  956. c.pflags.SetOutput(c.flagErrorBuf)
  957. }
  958. return c.pflags
  959. }
  960. // For use in testing
  961. func (c *Command) ResetFlags() {
  962. c.flagErrorBuf = new(bytes.Buffer)
  963. c.flagErrorBuf.Reset()
  964. c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  965. c.flags.SetOutput(c.flagErrorBuf)
  966. c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  967. c.pflags.SetOutput(c.flagErrorBuf)
  968. }
  969. // Does the command contain any flags (local plus persistent from the entire structure)
  970. func (c *Command) HasFlags() bool {
  971. return c.Flags().HasFlags()
  972. }
  973. // Does the command contain persistent flags
  974. func (c *Command) HasPersistentFlags() bool {
  975. return c.PersistentFlags().HasFlags()
  976. }
  977. // Does the command has flags specifically declared locally
  978. func (c *Command) HasLocalFlags() bool {
  979. return c.LocalFlags().HasFlags()
  980. }
  981. func (c *Command) HasInheritedFlags() bool {
  982. return c.InheritedFlags().HasFlags()
  983. }
  984. // Climbs up the command tree looking for matching flag
  985. func (c *Command) Flag(name string) (flag *flag.Flag) {
  986. flag = c.Flags().Lookup(name)
  987. if flag == nil {
  988. flag = c.persistentFlag(name)
  989. }
  990. return
  991. }
  992. // recursively find matching persistent flag
  993. func (c *Command) persistentFlag(name string) (flag *flag.Flag) {
  994. if c.HasPersistentFlags() {
  995. flag = c.PersistentFlags().Lookup(name)
  996. }
  997. if flag == nil && c.HasParent() {
  998. flag = c.parent.persistentFlag(name)
  999. }
  1000. return
  1001. }
  1002. // Parses persistent flag tree & local flags
  1003. func (c *Command) ParseFlags(args []string) (err error) {
  1004. c.mergePersistentFlags()
  1005. err = c.Flags().Parse(args)
  1006. return
  1007. }
  1008. func (c *Command) Parent() *Command {
  1009. return c.parent
  1010. }
  1011. func (c *Command) mergePersistentFlags() {
  1012. var rmerge func(x *Command)
  1013. // Save the set of local flags
  1014. if c.lflags == nil {
  1015. c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
  1016. if c.flagErrorBuf == nil {
  1017. c.flagErrorBuf = new(bytes.Buffer)
  1018. }
  1019. c.lflags.SetOutput(c.flagErrorBuf)
  1020. addtolocal := func(f *flag.Flag) {
  1021. c.lflags.AddFlag(f)
  1022. }
  1023. c.Flags().VisitAll(addtolocal)
  1024. c.PersistentFlags().VisitAll(addtolocal)
  1025. }
  1026. rmerge = func(x *Command) {
  1027. if !x.HasParent() {
  1028. flag.CommandLine.VisitAll(func(f *flag.Flag) {
  1029. if x.PersistentFlags().Lookup(f.Name) == nil {
  1030. x.PersistentFlags().AddFlag(f)
  1031. }
  1032. })
  1033. }
  1034. if x.HasPersistentFlags() {
  1035. x.PersistentFlags().VisitAll(func(f *flag.Flag) {
  1036. if c.Flags().Lookup(f.Name) == nil {
  1037. c.Flags().AddFlag(f)
  1038. }
  1039. })
  1040. }
  1041. if x.HasParent() {
  1042. rmerge(x.parent)
  1043. }
  1044. }
  1045. rmerge(c)
  1046. }