GithubHelp home page GithubHelp logo

Comments (11)

jessevdk avatar jessevdk commented on August 24, 2024

So, just to explain a bit the situation about commands and the lack of documentation. Commands were indeed implemented in go-flags, but at the time I wasn't sure if it was implemented in the best way possible, or if the exposed API was the best thing possible. So, I didn't yet write any documentation for this feature as I was planning to have a critical review. Then, similar to how many things go, I didn't yet get to do that.

That said, just to save you some time, the way I use commands for now is to have one go file per command. These go files define a struct (which represents the command and its options) and defines the Execute method on it (implementing the flags.Command interface). Then you define an init func in this file which registers the command in the flags package. For example

type CommandDaemon struct {
    // Define any options here as you would normally do for flags
}

func (x *CommandDaemon) Execute(args []string) error {
    // Do your thingie here
    return nil   
}

func init() {
    parser.AddCommand("daemon", "Short description", "Long description", &CommandDaemon{})
}

Where the parser variable is some global variable containing an instance of flags.Parser

from go-flags.

orenbenkiki avatar orenbenkiki commented on August 24, 2024

Thanks, that helps a lot!

So if I understand it right, parser.AddCommand adds to the global parser, which is then accessed by the actual main program?

The 2nd issue I didn't see in the docs was the proper use of groups. I assume groups are unrelated to command, that is, each command can specify its arguments as the sum of some option groups, so the same group can be used by several commands. It isn't clear on how to do that from the documentation.

from go-flags.

jessevdk avatar jessevdk commented on August 24, 2024

For the first thing, basically yes. For example, I have the following in by main entry point:

package main

import (
    "os"
)

var parser = flags.NewParser(options, flags.Default)

func main() {
    if _, err := parser.Parse(); err != nil {
        os.Exit(1)
    }
}

This works, because things declared globally with "var" are initialized before the init() funcs run.

For the second issue, you're right that groups are also not very well documented. Option groups are pretty much independent from commands. They just provide a way to semantically group various options. The builtin help then shows options per option group, but that's it.

Option groups are not shared in some way between commands. The way it works right now is that you can specify options common to commands in the parent level. In most cases, this means the options provided to the parser instance. When calling your program, these options can only appear before specifying the command. So if -x is a top level option and add a command, then program -x add is correct, but program add -x won't work.

from go-flags.

orenbenkiki avatar orenbenkiki commented on August 24, 2024

Ah, got it. Hmmm. In my case I want the options to behave like normal options (after the command), so I guess I'll just repeat them in each command options structure. There aren't that many of them in my case (both command and options), so it isn't that big a deal.

Thanks for the help!

from go-flags.

jessevdk avatar jessevdk commented on August 24, 2024

In that case you can still of course just define a struct somewhere and reuse it in each command by either:

  1. Making it an option group
  2. Embedding that struct in each command

from go-flags.

orenbenkiki avatar orenbenkiki commented on August 24, 2024

"No good deed goes unpunished" - The punishment for creating a good system with rich features is that one has to document them all :-)

My understanding so far is that:

I can define an options struct and use it in NewGroup, and then call parser.AddGroup. The options would become global. If no commands are used, then the sum of all groups is just the set of total options for the program.

If I use commands, than all the AddGroup options are global application options and must appear before the command name in the invocation. I need to define a command-specific struct and give it to parser.AddCommand to get command-specific options (which appear before the command name).

There is no way to say parser.AddCommandGroup which adds a group just for a specific command. Instead one must list all the fields directly in the command-specific options structure.

Did I get it right?

from go-flags.

jessevdk avatar jessevdk commented on August 24, 2024

Almost. There is another way to add groups. parser.AddGroup is usually not used. Instead, you can add a field to your options with the type being the option group. You then tag that field with the group:"group-name" tag. The other thing you can do is just embedding a struct:

type CommonOptions struct {
    DoIt bool `short:"d"`
}

// Option 1: using it as an option group
type MyCommand struct {
    Options CommonOptions `group:"common"`
}

// Option 2: embedding it directly
type MyCommand struct {
    CommonOptions
}

The only noticeable difference being in the help output (you can document the option group separately, but not the embedded struct).

from go-flags.

orenbenkiki avatar orenbenkiki commented on August 24, 2024

Many thanks! I'll give these options a try.

This really needs to be documented :-)

from go-flags.

jessevdk avatar jessevdk commented on August 24, 2024

I've added some basic documentation.

from go-flags.

calmh avatar calmh commented on August 24, 2024

Followup question: is there a way to show Usage with arguments for a command? I.e. if I have a command that takes a filename (think "git add foo"), I'd like "git add --help" to show something along the lines of:

Usage:
  git [OPTIONS] add <filename> [add-OPTIONS]

however I see no way to get the "<filename>" string in there? I can set the Usage field of the Parser returned by AddCommand, but that seems to set the usage of the main application (i.e. "git") from above.

from go-flags.

jessevdk avatar jessevdk commented on August 24, 2024

That's a good point. We should have a per-command optional usage string. Could you please file a separate issue for it?

from go-flags.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.