From 610109298af21b83af4d065e1fb28c9c576d666f Mon Sep 17 00:00:00 2001 From: Nathan Potter Date: Mon, 5 Aug 2019 15:07:12 -0500 Subject: [PATCH] Allow passing rawargs to commands --- command.go | 3 +++ run.go | 77 +++++++++++++++++++++++++++++------------------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/command.go b/command.go index 8f7f3c6..d99a365 100644 --- a/command.go +++ b/command.go @@ -19,6 +19,9 @@ type CommandSpec struct { // Desc is the description of the command. // The first line is used as an abbreviated description. Desc string + // RawArgs indicates that flags should not be parsed, and they should be deferred + // to the command. + RawArgs bool // Hidden indicates that this command should not show up in it's parent's // subcommand help. diff --git a/run.go b/run.go index d54f7c1..c136531 100644 --- a/run.go +++ b/run.go @@ -1,15 +1,15 @@ package cli import ( - "flag" - "os" + "flag" + "os" ) func appendParent(parent string, add string) string { - if parent == "" { - return add + " " - } - return parent + add + " " + if parent == "" { + return add + " " + } + return parent + add + " " } // Run sets up flags, helps, and executes the command with the provided @@ -20,38 +20,43 @@ func appendParent(parent string, add string) string { // // Use RunRoot if this package is managing the entire CLI. func Run(cmd Command, args []string, parent string) { - fl := flag.NewFlagSet(parent+""+cmd.Spec().Name, flag.ExitOnError) - - if fc, ok := cmd.(FlaggedCommand); ok { - fc.RegisterFlags(fl) - } - - fl.Usage = func() { - renderHelp(cmd, fl, os.Stderr) - } - _ = fl.Parse(args) - - subcommandArg := fl.Arg(0) - - // Route to subcommand. - if pc, ok := cmd.(ParentCommand); ok && subcommandArg != "" { - for _, subcommand := range pc.Subcommands() { - if subcommand.Spec().Name != subcommandArg { - continue - } - - Run( - subcommand, fl.Args()[1:], - appendParent(parent, cmd.Spec().Name), - ) - return - } - } - - cmd.Run(fl) + fl := flag.NewFlagSet(parent+""+cmd.Spec().Name, flag.ExitOnError) + + if fc, ok := cmd.(FlaggedCommand); ok { + fc.RegisterFlags(fl) + } + + fl.Usage = func() { + renderHelp(cmd, fl, os.Stderr) + } + + if cmd.Spec().RawArgs { + // Use `--` to return immediately when parsing the flags. + args = append([]string{"--"}, args...) + } + _ = fl.Parse(args) + + subcommandArg := fl.Arg(0) + + // Route to subcommand. + if pc, ok := cmd.(ParentCommand); ok && subcommandArg != "" { + for _, subcommand := range pc.Subcommands() { + if subcommand.Spec().Name != subcommandArg { + continue + } + + Run( + subcommand, fl.Args()[1:], + appendParent(parent, cmd.Spec().Name), + ) + return + } + } + + cmd.Run(fl) } // RunRoot calls Run with the process's arguments. func RunRoot(cmd Command) { - Run(cmd, os.Args[1:], "") + Run(cmd, os.Args[1:], "") }