Comments (11)
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.
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.
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.
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.
In that case you can still of course just define a struct somewhere and reuse it in each command by either:
- Making it an option group
- Embedding that struct in each command
from go-flags.
"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.
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.
Many thanks! I'll give these options a try.
This really needs to be documented :-)
from go-flags.
I've added some basic documentation.
from go-flags.
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.
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)
- Documentation: Add more Examples HOT 1
- Help Displayed for func(bool) should be as for bool
- 1.5.0 tag, but no release HOT 1
- Allow to specify default value for a positional argument
- Add a working completion example for 'zsh' shell
- Add a man generator for markup (ronn-style)
- Need proper documentation on how to correctly handle errors HOT 13
- Can flags be used to parse command line arguments from 'go test' ? HOT 2
- Is this an abandoned project?
- Is this an abandoned project? HOT 21
- Program description
- A little leverage
- help format default posix in windows, I don't want to use -tags=forceposix, let them use -tags=forcewindows HOT 2
- Fix CVE-2022-29526 vulnerability caused by golang.org/x/sys? HOT 2
- How to group subcommands HOT 3
- Is it possible to have dynamically generated help descriptions?
- Passing options as argument to other options without using positional-args HOT 1
- custom type positional argument ValueValidator implementation is ignored
- How do I add a flag and pass the value there?
- Multiple short options are not detected with `IgnoreUnknown` flag.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-flags.