77 "io"
88 "os"
99 "path/filepath"
10- "reflect"
1110 "sort"
1211 "time"
1312)
@@ -112,6 +111,8 @@ type App struct {
112111 Suggest bool
113112
114113 didSetup bool
114+
115+ rootCommand * Command
115116}
116117
117118type SuggestFlagFunc func (flags []Flag , provided string , hideHelp bool ) string
@@ -268,136 +269,35 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
268269 // always appends the completion flag at the end of the command
269270 shellComplete , arguments := checkShellCompleteFlag (a , arguments )
270271
271- set , err := a .newFlagSet ()
272- if err != nil {
273- return err
274- }
275-
276- err = parseIter (set , a , arguments [1 :], shellComplete )
277- nerr := normalizeFlags (a .Flags , set )
278- cCtx := NewContext (a , set , & Context {Context : ctx })
279- if nerr != nil {
280- _ , _ = fmt .Fprintln (a .Writer , nerr )
281- if ! a .HideHelp {
282- _ = ShowAppHelp (cCtx )
283- }
284- return nerr
285- }
272+ cCtx := NewContext (a , nil , & Context {Context : ctx })
286273 cCtx .shellComplete = shellComplete
287274
288- if checkCompletions (cCtx ) {
289- return nil
290- }
291-
292- if err != nil {
293- if a .OnUsageError != nil {
294- err := a .OnUsageError (cCtx , err , false )
295- a .handleExitCoder (cCtx , err )
296- return err
297- }
298- _ , _ = fmt .Fprintf (a .Writer , "%s %s\n \n " , "Incorrect Usage." , err .Error ())
299- if a .Suggest {
300- if suggestion , err := a .suggestFlagFromError (err , "" ); err == nil {
301- fmt .Fprintf (a .Writer , suggestion )
302- }
303- }
304- if ! a .HideHelp {
305- _ = ShowAppHelp (cCtx )
306- }
307- return err
308- }
309-
310- if a .After != nil && ! cCtx .shellComplete {
311- defer func () {
312- if afterErr := a .After (cCtx ); afterErr != nil {
313- if err != nil {
314- err = newMultiError (err , afterErr )
315- } else {
316- err = afterErr
317- }
318- }
319- }()
320- }
321-
322- if ! a .HideHelp && checkHelp (cCtx ) {
323- _ = ShowAppHelp (cCtx )
324- return nil
325- }
326-
327- if ! a .HideVersion && checkVersion (cCtx ) {
328- ShowVersion (cCtx )
329- return nil
330- }
331-
332- cerr := cCtx .checkRequiredFlags (a .Flags )
333- if cerr != nil {
334- _ = ShowAppHelp (cCtx )
335- return cerr
336- }
337-
338- if a .Before != nil && ! cCtx .shellComplete {
339- beforeErr := a .Before (cCtx )
340- if beforeErr != nil {
341- a .handleExitCoder (cCtx , beforeErr )
342- err = beforeErr
343- return err
344- }
345- }
346-
347- if err = runFlagActions (cCtx , a .Flags ); err != nil {
348- return err
349- }
350-
351- var c * Command
352- args := cCtx .Args ()
353- if args .Present () {
354- name := args .First ()
355- if a .validCommandName (name ) {
356- c = a .Command (name )
357- } else {
358- hasDefault := a .DefaultCommand != ""
359- isFlagName := checkStringSliceIncludes (name , cCtx .FlagNames ())
360-
361- var (
362- isDefaultSubcommand = false
363- defaultHasSubcommands = false
364- )
365-
366- if hasDefault {
367- dc := a .Command (a .DefaultCommand )
368- defaultHasSubcommands = len (dc .Subcommands ) > 0
369- for _ , dcSub := range dc .Subcommands {
370- if checkStringSliceIncludes (name , dcSub .Names ()) {
371- isDefaultSubcommand = true
372- break
373- }
374- }
375- }
376-
377- if isFlagName || (hasDefault && (defaultHasSubcommands && isDefaultSubcommand )) {
378- argsWithDefault := a .argsWithDefaultCommand (args )
379- if ! reflect .DeepEqual (args , argsWithDefault ) {
380- c = a .Command (argsWithDefault .First ())
381- }
382- }
383- }
384- } else if a .DefaultCommand != "" {
385- c = a .Command (a .DefaultCommand )
386- }
387-
388- if c != nil {
389- return c .Run (cCtx )
390- }
391-
392- if a .Action == nil {
393- a .Action = helpCommand .Action
394- }
395-
396- // Run default Action
397- err = a .Action (cCtx )
398-
399- a .handleExitCoder (cCtx , err )
400- return err
275+ a .rootCommand = & Command {
276+ HelpName : a .HelpName ,
277+ Subcommands : a .Commands ,
278+ flagCategories : a .flagCategories ,
279+ Flags : a .Flags ,
280+ Name : a .Name ,
281+ //Action: a.Action, // dont set this now
282+ UseShortOptionHandling : a .UseShortOptionHandling ,
283+ Before : a .Before ,
284+ After : a .After ,
285+ HideHelp : a .HideHelp ,
286+ HideHelpCommand : a .HideHelpCommand ,
287+ OnUsageError : a .OnUsageError ,
288+ CustomHelpTemplate : a .CustomAppHelpTemplate ,
289+ Usage : a .Usage ,
290+ UsageText : a .UsageText ,
291+ Description : a .Description ,
292+ ArgsUsage : a .ArgsUsage ,
293+ BashComplete : a .BashComplete ,
294+ categories : a .categories ,
295+ helpAction : helpCommand .Action ,
296+ isRoot : true ,
297+ }
298+ cCtx .Command = a .rootCommand
299+
300+ return a .rootCommand .Run (cCtx , arguments )
401301}
402302
403303func (a * App ) suggestFlagFromError (err error , command string ) (string , error ) {
@@ -407,15 +307,17 @@ func (a *App) suggestFlagFromError(err error, command string) (string, error) {
407307 }
408308
409309 flags := a .Flags
310+ hideHelp := a .HideHelp
410311 if command != "" {
411312 cmd := a .Command (command )
412313 if cmd == nil {
413314 return "" , err
414315 }
415316 flags = cmd .Flags
317+ hideHelp = hideHelp || cmd .HideHelp
416318 }
417319
418- suggestion := SuggestFlag (flags , flag , a . HideHelp )
320+ suggestion := SuggestFlag (flags , flag , hideHelp )
419321 if len (suggestion ) == 0 {
420322 return "" , err
421323 }
@@ -435,120 +337,6 @@ func (a *App) RunAndExitOnError() {
435337 }
436338}
437339
438- // RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
439- // generate command-specific flags
440- func (a * App ) RunAsSubcommand (ctx * Context ) (err error ) {
441- // Setup also handles HideHelp and HideHelpCommand
442- a .Setup ()
443-
444- var newCmds []* Command
445- for _ , c := range a .Commands {
446- if c .HelpName == "" {
447- c .HelpName = fmt .Sprintf ("%s %s" , a .HelpName , c .Name )
448- }
449- newCmds = append (newCmds , c )
450- }
451- a .Commands = newCmds
452-
453- set , err := a .newFlagSet ()
454- if err != nil {
455- return err
456- }
457-
458- err = parseIter (set , a , ctx .Args ().Tail (), ctx .shellComplete )
459- nerr := normalizeFlags (a .Flags , set )
460- cCtx := NewContext (a , set , ctx )
461-
462- if nerr != nil {
463- _ , _ = fmt .Fprintln (a .Writer , nerr )
464- _ , _ = fmt .Fprintln (a .Writer )
465- if len (a .Commands ) > 0 {
466- _ = ShowSubcommandHelp (cCtx )
467- } else {
468- _ = ShowCommandHelp (ctx , cCtx .Args ().First ())
469- }
470- return nerr
471- }
472-
473- if checkCompletions (cCtx ) {
474- return nil
475- }
476-
477- if err != nil {
478- if a .OnUsageError != nil {
479- err = a .OnUsageError (cCtx , err , true )
480- a .handleExitCoder (cCtx , err )
481- return err
482- }
483- _ , _ = fmt .Fprintf (a .Writer , "%s %s\n \n " , "Incorrect Usage." , err .Error ())
484- if a .Suggest {
485- if suggestion , err := a .suggestFlagFromError (err , cCtx .Command .Name ); err == nil {
486- fmt .Fprintf (a .Writer , suggestion )
487- }
488- }
489- _ = ShowSubcommandHelp (cCtx )
490- return err
491- }
492-
493- if len (a .Commands ) > 0 {
494- if checkSubcommandHelp (cCtx ) {
495- return nil
496- }
497- } else {
498- if checkCommandHelp (ctx , cCtx .Args ().First ()) {
499- return nil
500- }
501- }
502-
503- cerr := cCtx .checkRequiredFlags (a .Flags )
504- if cerr != nil {
505- _ = ShowSubcommandHelp (cCtx )
506- return cerr
507- }
508-
509- if a .After != nil && ! cCtx .shellComplete {
510- defer func () {
511- afterErr := a .After (cCtx )
512- if afterErr != nil {
513- a .handleExitCoder (cCtx , err )
514- if err != nil {
515- err = newMultiError (err , afterErr )
516- } else {
517- err = afterErr
518- }
519- }
520- }()
521- }
522-
523- if a .Before != nil && ! cCtx .shellComplete {
524- beforeErr := a .Before (cCtx )
525- if beforeErr != nil {
526- a .handleExitCoder (cCtx , beforeErr )
527- err = beforeErr
528- return err
529- }
530- }
531-
532- if err = runFlagActions (cCtx , a .Flags ); err != nil {
533- return err
534- }
535-
536- args := cCtx .Args ()
537- if args .Present () {
538- name := args .First ()
539- c := a .Command (name )
540- if c != nil {
541- return c .Run (cCtx )
542- }
543- }
544-
545- // Run default Action
546- err = a .Action (cCtx )
547-
548- a .handleExitCoder (cCtx , err )
549- return err
550- }
551-
552340// Command returns the named command on App. Returns nil if the command does not exist
553341func (a * App ) Command (name string ) * Command {
554342 for _ , c := range a .Commands {
0 commit comments