-
Notifications
You must be signed in to change notification settings - Fork 0
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
Add support for command-line flags #2
Comments
flags-first package by Peter Bourgon supports all of these configuration file formats and command-line and environment variables. |
see also atc0005/golang-oracle#12 |
Simple package main
import "github.com/integrii/flaggy"
func main() {
// Declare variables and their defaults
var stringFlag = "defaultValue"
// Add a flag
flaggy.String(&stringFlag, "f", "flag", "A test string flag")
// Parse the flag
flaggy.Parse()
// Use the flag
print(stringFlag)
} |
Note to self: Whatever I opt to use, it should make it very clear to the user what the defaults are, particularly in Help or Error output. Relying on zero/default values for the config struct is not a good idea, even during development work. |
Note: Not a big fan of the flags-first help output: $ go run *.go -recurse -bob
flag provided but not defined: -bob
Usage of elbow:
-config string
config file (optional)
-ext string
file extension to match against to limit search
-keep int
keep specified number of matching files
-keep-oldest
keep oldest files instead of newer
-path string
path to process
-pattern string
file pattern to match against
-recurse
recurse into subdirectories
-remove
remove matched files
exit status 2 The defaults are specified in the flag set, but not stressed in this output. |
Going to test https://github.com/integrii/flaggy#example-help-output testCommand - Description goes here. Get more information at http://flaggy.
This is a prepend for help
Usage:
testCommand [subcommandA|subcommandB|subcommandC] [testPositionalA] [testPositionalB]
Positional Variables:
testPositionalA - (Required) Test positional A does some things with a positional value. (default: defaultValue)
testPositionalB - Test positional B does some less than serious things with a positional value.
Subcommands:
subcommandA (a) - Subcommand A is a command that does stuff
subcommandB (b) - Subcommand B is a command that does other stuff
subcommandC (c) - Subcommand C is a command that does SERIOUS stuff
Flags:
--version Displays the program version string.
-h --help Displays help with available flag, subcommand, and positional value parameters.
-s --stringFlag This is a test string flag that does some stringy string stuff.
-i --intFlg This is a test int flag that does some interesting int stuff. (default: 5)
-b --boolFlag This is a test bool flag that does some booly bool stuff. (default: true)
-d --durationFlag This is a test duration flag that does some untimely stuff. (default: 1h23s)
This is an append for help
This is a help add-on message |
I don't see how to specify the default values programatically when using |
On a different note, this package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli"
)
func main() {
app := cli.NewApp()
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "lang",
Value: "english",
Usage: "language for the greeting",
},
}
app.Action = func(c *cli.Context) error {
name := "Nefertiti"
if c.NArg() > 0 {
name = c.Args().Get(0)
}
if c.String("lang") == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
} Output: $ go run main.go --help
NAME:
main.exe - A new cli application
USAGE:
main.exe [global options] command [command options] [arguments...]
VERSION:
0.0.0
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--lang value language for the greeting (default: "english")
--help, -h show help
--version, -v print the version |
I opened issue 46 in the integrii/flaggy repo and provided a sample program that replicates my findings. |
The developer confirmed the bug report and is looking into it. |
The developer reports that the issue has been fixed in version 1.2.2. Initially the release was without a semantic 'v' prefix, but he went back and adjusted all tags to include the leading character to make them semver compliant. Regarding the bug I ran into, the developer noted that string and integer values were intended to have their default values displayed in the help text, but not boolean flags. In their own words:
|
Note: flaggy supports specifying the same config option multiple times, presumably to populate a slice:
|
I started drafting an issue for the flaggy repo, but stopped once I asked the question, "Does it matter?". Recording the details here in case i decide to submit the issue later. Issue title: Body:
We can do as proposed; if the final custom object doesn't match the default, then we can assume that the flag wasn't passed and do something about it. |
I opted to go ahead and submit the question anyway. For now, I'll assume that I will wish to create a default Config object and then compare the two. |
Dev's response:
Looks like I'm on the right path with comparing a default config struct against one that I expect to be modified. Worth noting: https://github.com/r3labs/diff#basic-example That package is pretty useful for making the comparison. It's probably overkill, but it appears useful for prototype work. |
Example output from the current variation of the test file: $ go run test.go -path="C:\Users"
2019/08/22 13:41:22 User specified command-line options
Changes to default settings: [{Type:update Path:[startpath] From: To:C:\Users}]
2019/08/22 13:41:22 Processing path: C:\Users Ignore the last line as it is irrelevant to this example. |
Further work re Config object handling, support methods. I found lots of good examples here: Another example here which just reaffirms that returning a pointer to a Config object is the way to go. Seems that this approach allows for method chaining in order to set multiple configuration options. More examples of how the https://github.com/aws/aws-sdk-go/search?q=flag&unscoped_q=flag |
Will probably cleanup the While researching logging, I saw that the https://github.com/spf13/viper package handles environment variables, config files and command-line flags. Using this package could tick-off multiple TODO items for this project. |
With validation applied, the earlier call (not yet mentioned here) of Earlier code block: if reflect.DeepEqual(*defaultConfig, *config) {
// DEBUG
log.Println("User did not provide command-line flags; current configuration matches default settings")
// KEEP
flaggy.ShowHelpAndExit("Required command-line options not provided.")
} else {
// DEBUG
log.Println("User provided command-line flags, proceeding ...")
} Current approach: if !pathExists(config.StartPath) {
flaggy.ShowHelpAndExit(fmt.Sprintf("Error processing requested path: %q", config.StartPath))
} This seems to get the point across without having to use what is purported to be a very expensive function call. While it wouldn't matter much here, perhaps it is good to not rely upon it? |
This initial prototype supports: - Matching on specified file patterns - Flat (single-level) or recursive search - Keeping a specified number of older or newer matches - Limiting search to specified list of extensions - Toggling file removal (read-only by default) - Go modules (vs classic GOPATH setup) refs #2, #4, #6
In addition to |
Yet another command-line flag package: https://github.com/DavidGamba/go-getoptions Many good features. Here are a couple cherry-picked items:
|
Very small CLI support package: https://github.com/jaffee/commandeer This package builds out the help text directly from struct tags, which is a nice annotation approach (that I've not spent enough time with yet to truly "get"). |
Note to self: Initial command-line flag support will be in v0.1, but still keeping this issue assigned to v0.2 as I hope to make further refinements and test other "flag" packages that also provide support for environment variables, config files, etc. |
This initial prototype supports: - Matching on specified file patterns - Flat (single-level) or recursive search - Keeping a specified number of older or newer matches - Limiting search to specified list of extensions - Toggling file removal (read-only by default) - Go modules (vs classic GOPATH setup) refs #2, #4, #6
This initial prototype supports: - Matching on specified file patterns - Flat (single-level) or recursive search - Keeping a specified number of older or newer matches - Limiting search to specified list of extensions - Toggling file removal (read-only by default) - Go modules (vs classic GOPATH setup) refs #2, #4, #6
This initial prototype supports: - Matching on specified file patterns - Flat (single-level) or recursive search - Keeping a specified number of older or newer matches - Limiting search to specified list of extensions - Toggling file removal (read-only by default) - Go modules (vs classic GOPATH setup) - Brief overview, examples for testing purposes refs #2, #4, #6
Just for later reference, here is what the help output looks like when using the
|
Regarding https://godoc.org/github.com/jessevdk/go-flags?importers I ended up not using the list directly, but lucked out and found this StackOverflow Q/A thread: https://stackoverflow.com/questions/38709768/understanding-subcommands-with-go-flags That thread linked to the old repo for this project: https://github.com/concourse/concourse They seem to make heavy use of commands, but the general idea is there. |
As of this point I think I like |
https://github.com/alexflint/go-arg This supports options similar to |
$ cd /mnt/t/github/elbow; go build; cp -vf elbow /tmp/; cd /tmp/; ./elbow --path /tmp --extension ".war" --pattern "-masterdev-" --keep 2
'elbow' -> '/tmp/elbow'
expected argument for flag `--pattern', but got option `-masterdev-' The Single or double-quotes, it doesn't seem to matter. |
At this point I'm strongly considering locking in the current functionality set:
I need to rework the two feature branches (likely prune one), rebase, then merge and tag. I will likely close this issue, but reopen later if I opt to try another flag package for this project (will probably try a different package for another project). |
Will use the |
New packages tracked by go.mod: - `sirupsen/logrus` v1.4.2 - `jessevdk/go-flags` v1.4.0 Packages removed: - `integrii/flaggy` v1.2.2 Overall changes: - Add sirupsen/logrus package to provide leveled, syslog and structured logging support - Remove duplicate logging - Apply leveled logging to better filter desired logging levels - Add config validation (light) - Add `String()` to meet `Stringer{}` interface requirements for `Config{}` struct - Add OS-specific handling of syslog hook configuration by way of `*_windows.go` and `*_unix.go` files - (Ab)use `Config{}` to carry a `*os.File` file handle for an optional log file (so that it can be freed from `main()` via `defer`) - Add (optional on Linux, unavailable on Windows) syslog logging support - Additional polish for "feedback" log statements; work towards having all required information set to INFO log level (which is the default) - Short flags dropped. - There are some issues with `go-flags` misdetecting leading dashes in file patterns as short flags, so instead of dealing with that right now I've opted to only support long flag names - `go-flags` only supports single letter short flags, and with the number of flags that we're using I decided to keep things simple for now and only use long flag names New optional configuration options: - Ignore errors when removing files - Log format (text or json, defaults to text) - Log level (large list, mapped where possible to syslog logging levels) - Console output toggle (stdout or stderr) - Log file path (logging to a log file mutes console output) refs #2, #7
New packages tracked by go.mod: - `sirupsen/logrus` v1.4.2 - `jessevdk/go-flags` v1.4.0 Packages removed: - `integrii/flaggy` v1.2.2 Overall changes: - Add sirupsen/logrus package to provide leveled, syslog and structured logging support - Remove duplicate logging - Apply leveled logging to better filter desired logging levels - Add config validation (light) - Add `String()` to meet `Stringer{}` interface requirements for `Config{}` struct - Add OS-specific handling of syslog hook configuration by way of `*_windows.go` and `*_unix.go` files - (Ab)use `Config{}` to carry a `*os.File` file handle for an optional log file (so that it can be freed from `main()` via `defer`) - Add (optional on Linux, unavailable on Windows) syslog logging support - Additional polish for "feedback" log statements; work towards having all required information set to INFO log level (which is the default) - Short flags dropped. - There are some issues with `go-flags` misdetecting leading dashes in file patterns as short flags, so instead of dealing with that right now I've opted to only support long flag names - `go-flags` only supports single letter short flags, and with the number of flags that we're using I decided to keep things simple for now and only use long flag names Configuration options: - (new, optional) Ignore errors when removing files - (new, optional) Log format (text or json, defaults to text) - (new, optional) Log level (large list, mapped where possible to syslog logging levels) - (new, optional) Console output toggle (stdout or stderr) - (new, optional) Log file path (logging to a log file mutes console output) - (changed, required) Number of files to keep out of matches list is now a required flag refs #2, #7
New packages tracked by go.mod: - `sirupsen/logrus` v1.4.2 - `jessevdk/go-flags` v1.4.0 Packages removed: - `integrii/flaggy` v1.2.2 Overall changes: - Add sirupsen/logrus package to provide leveled, syslog and structured logging support - Remove duplicate logging - Apply leveled logging to better filter desired logging levels - Add config validation (light) - Add `String()` to meet `Stringer{}` interface requirements for `Config{}` struct - Add OS-specific handling of syslog hook configuration by way of `*_windows.go` and `*_unix.go` files - (Ab)use `Config{}` to carry a `*os.File` file handle for an optional log file (so that it can be freed from `main()` via `defer`) - Add (optional on Linux, unavailable on Windows) syslog logging support - Additional polish for "feedback" log statements; work towards having all required information set to INFO log level (which is the default) - Short flags dropped. - There are some issues with `go-flags` misdetecting leading dashes in file patterns as short flags, so instead of dealing with that right now I've opted to only support long flag names - `go-flags` only supports single letter short flags, and with the number of flags that we're using I decided to keep things simple for now and only use long flag names Configuration options: - (new, optional) Ignore errors when removing files - (new, optional) Log format (text or json, defaults to text) - (new, optional) Log level (large list, mapped where possible to syslog logging levels) - (new, optional) Console output toggle (stdout or stderr) - (new, optional) Log file path (logging to a log file mutes console output) - (changed, required) Number of files to keep out of matches list is now a required flag refs #2, #7
New packages: - `sirupsen/logrus` v1.4.2 - `jessevdk/go-flags` v1.4.0 Packages removed: - `integrii/flaggy` v1.2.2 - `r3labs/diff` a71de73c46ad Overall changes: - Add sirupsen/logrus package to provide leveled, syslog and structured logging support - Remove duplicate logging - Apply leveled logging to better filter desired logging levels - Add config validation (light) - Add `String()` to meet `Stringer{}` interface requirements for `Config{}` struct - Add OS-specific handling of syslog hook configuration by way of `*_windows.go` and `*_unix.go` files - (Ab)use `Config{}` to carry a `*os.File` file handle for an optional log file (so that it can be freed from `main()` via `defer`) - Add (optional on Linux, unavailable on Windows) syslog logging support - Additional polish for "feedback" log statements; work towards having all required information set to INFO log level (which is the default) - Short flags dropped. - There are some issues with `go-flags` misdetecting leading dashes in file patterns as short flags, so instead of dealing with that right now I've opted to only support long flag names - `go-flags` only supports single letter short flags, and with the number of flags that we're using I decided to keep things simple for now and only use long flag names Configuration options: - (new, optional) Ignore errors when removing files - (new, optional) Log format (text or json, defaults to text) - (new, optional) Log level (large list, mapped where possible to syslog logging levels) - (new, optional) Console output toggle (stdout or stderr) - (new, optional) Log file path (logging to a log file mutes console output) - (changed, required) Number of files to keep out of matches list is now a required flag refs #2, #7
Worth noting: As of this writing, the The I'll stick with |
Not yet sure which package, but this tool will need to be heavily command-line driven.
Standard library
https://golang.org/pkg/flag/
https://gobyexample.com/command-line-arguments
Third-party
Implementation / Examples
The text was updated successfully, but these errors were encountered: