Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to handle multiple sub-commands that use the same argument sets #36

Closed
wwalker opened this issue Apr 29, 2015 · 5 comments
Closed

Comments

@wwalker
Copy link

wwalker commented Apr 29, 2015

Currently, I have 3 sub commands that take the exact same flags and args. What follows is an example of defining two of them. Is there a cleaner way to do this?

  create               = app.Command("create", "initial create/deploy of an app")
  create_cpu           = create.Flag("cpu", "cpu share").Short('c').Required().Float()
  create_mem           = create.Flag("mem", "mem share (integer MB)").Short('m').Required().Int()
  create_instances     = create.Flag("instances", "instance count").Short('i').Required().Int()
  create_app_name      = create.Arg("app_name", "application name").Required().String()
  create_app_build     = create.Arg("app_build", "application build").Required().String()
  create_app_revision  = create.Arg("app_revision", "application revision name").Required().String()
  create_app_extension = create.Arg("app_extension", "application file extension").Required().String()
  create_app_run_as    = create.Arg("app_run_as", "application run as user").Required().String()

  update               = app.Command("update", "update definition of an app (automatically deploys new definition)")
  update_cpu           = update.Flag("cpu", "cpu share").Short('c').Required().Float()
  update_mem           = update.Flag("mem", "mem share (integer MB)").Short('m').Required().Int()
  update_instances     = update.Flag("instances", "instance count").Short('i').Required().Int()
  update_app_name      = update.Arg("app_name", "application name").Required().String()
  update_app_build     = update.Arg("app_build", "application build").Required().String()
  update_app_revision  = update.Arg("app_revision", "application revision name").Required().String()
  update_app_extension = update.Arg("app_extension", "application file extension").Required().String()
  update_app_run_as    = update.Arg("app_run_as", "application run as user").Required().String()
@wwalker
Copy link
Author

wwalker commented Apr 29, 2015

I could change them from sub-commands to a single command with a --comand flag...
It would clean up the implementation (greatly) but would not improve the user experience (which is clearly ugly enough as it stands...)

@alecthomas
Copy link
Owner

Hmm, yes. I've pondered how to do bundles of flags backed by a struct, which this would be a good use case for, but I haven't come up with an elegant solution. Any ideas?

The other option is to restructure your commands so there is a parent command, eg. "apply":

apply                = app.Command("apply", "apply changes to an app")
create_cpu           = apply.Flag("cpu", "cpu share").Short('c').Required().Float()
create_mem           = apply.Flag("mem", "mem share (integer MB)").Short('m').Required().Int()
create_instances     = apply.Flag("instances", "instance count").Short('i').Required().Int()
create_app_name      = apply.Arg("app_name", "application name").Required().String()
create_app_build     = apply.Arg("app_build", "application build").Required().String()
create_app_revision  = apply.Arg("app_revision", "application revision name").Required().String()
create_app_extension = apply.Arg("app_extension", "application file extension").Required().String()
create_app_run_as    = apply.Arg("app_run_as", "application run as user").Required().String()

create               = apply.Command("create", "initial create/deploy of an app")
update               = apply.Command("update", "update definition of an app (automatically deploys new definition)")

It's not great though :\

@alecthomas
Copy link
Owner

Actually sorry, that only works for flags anyway :(

@alecthomas
Copy link
Owner

Actually there is one solution that works now:

type CreateUpdateOptions struct {
    CPU       float64
    Memory    int
    Instances int
    Name      string
    Build     string
    Revision  string
    Extension string
    User      string
}

func NewCreateUpdateOptions(cmd *kingpin.CmdClause) *CreateUpdateOptions {
    options := &CreateUpdateOptions{}
    cmd.Flag("cpu", "cpu share").Short('c').Required().FloatVar(&options.CPU)
    cmd.Flag("mem", "mem share (integer MB)").Short('m').Required().IntVar(&options.Memory)
    cmd.Flag("instances", "instance count").Short('i').Required().IntVar(&options.Instances)
    cmd.Arg("app_name", "application name").Required().StringVar(&options.Name)
    cmd.Arg("app_build", "application build").Required().StringVar(&options.Build)
    cmd.Arg("app_revision", "application revision name").Required().StringVar(&options.Revision)
    cmd.Arg("app_extension", "application file extension").Required().StringVar(&options.Extension)
    cmd.Arg("app_run_as", "application run as user").Required().StringVar(&options.User)
    return options
}

var (
    app           = kingpin.New("myapp", "help")
    create        = app.Command("create", "initial create/deploy of an app")
    createOptions = NewCreateUpdateOptions(create)
    update        = app.Command("update", "update definition of an app (automatically deploys new definition)")
    updateOptions = NewCreateUpdateOptions(update)
)

@wwalker
Copy link
Author

wwalker commented Apr 30, 2015

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants