Skip to content

Commit

Permalink
Update README and changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidGamba committed Jan 5, 2024
1 parent ea576ff commit 023a4a9
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 49 deletions.
125 changes: 76 additions & 49 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,14 @@ opt.String("string", "default_value",
)
----

You can also define arguments:

[source, go]
----
opt.HelpSynopsisArg("<arg1>", "arg1 description")
opt.HelpSynopsisArg("<arg2>", "arg2 description")
----

Define the function for the program:

----
Expand All @@ -371,16 +379,17 @@ opt.SetCommandFn(Run)

If no function is defined and `opt.Dispatch` is called, the program will show a help message with any commands or subcommands.

Define any commands and their options and functions:
Define any commands and their options, arguments and functions:

[source, go]
----
cmd := opt.NewCommand("command", "command description")
cmd.String("int", 123)
cmd.HelpSynopsisArg("<arg1>", "arg1 description")
cmd.SetCommandFn(CommandRun)
----

NOTE: Options defined at a parent level will be interited by the command unless `cmd.UnsetOptions()` is called.
NOTE: Options defined at a parent level will be inherited by the command unless `cmd.UnsetOptions()` is called.

After defining options and commands declare the help command, it must be the last one defined.

Expand All @@ -405,7 +414,7 @@ err = opt.Dispatch(ctx, remaining)

Dispatch requires a `context.Context` to be passed which can be used to propagate cancellation signals or configuration values.

A built in helper to create a context with cancellation support is provided:
A built in helper to create a context with cancellation support (`os.Interrupt`, `syscall.SIGHUP`, `syscall.SIGTERM`) is provided:

[source, go]
----
Expand Down Expand Up @@ -446,6 +455,23 @@ func Name(ctx context.Context, opt *getoptions.GetOpt, args []string) error {
NOTE: The `opt.Value` function returns an `interface{}` so it needs to be type casted to the proper type.
The type cast will panic if trying to read an option that is not defined.

Read the received arguments from the `args` slice.
Additionally, use the `opt.GetRequiredArg` (with int and float64 variants) to simplify handling required arguments and providing error messages.

[source, go]
----
func Name(ctx context.Context, opt *getoptions.GetOpt, args []string) error {
arg1, args, err := opt.GetRequiredArgInt(args)
if err != nil {
return err
}
// logic
return nil
}
----

=== Boolean options

Opposite of default when passed on the command line.
Expand Down Expand Up @@ -794,7 +820,7 @@ a|option: `"o"`, argument: `"pt=arg"` footnote:[Argument gets type casted depend

== Automatically generate help

For a proper man page for your program consider link:http://asciidoctor.org/[asciidoctor] that can generate manpages written in the Asciidoc markup.
For a proper extended man page for your program consider link:http://asciidoctor.org/[asciidoctor] that can generate manpages written in the Asciidoc markup.

For the built-in help, you can add a description to your program:

Expand All @@ -816,21 +842,34 @@ Optionally you can print only given sections of the Help.

For example:

[source, go]
----
fmt.Fprintf(os.Stderr, "%s", opt.Help(getoptions.HelpSynopsis))
----

Or through a helper:

[source, go]
----
func ForceUnlock(ctx context.Context, opt *getoptions.GetOpt, args []string) error {
if len(args) < 1 {
fmt.Fprintf(os.Stderr, "ERROR: missing <lock-id>\n")
fmt.Fprintf(os.Stderr, "%s", opt.Help(getoptions.HelpSynopsis))
return getoptions.ErrorHelpCalled
lockID, args, err := opt.GetRequiredArg(args)
if err != nil {
return err
}
lockID := args[0]
args = slices.Delete(args, 0, 1)
----

In the code above, the return is `getoptions.ErrorHelpCalled` which signals the help is already printed.
In the code above, if there is no argument passed, the `GetRequiredArg` will print an error plus the synopsis:

----
ERROR: Missing <lock-id>
SYNOPSIS:
program [--help] <lock-id>
----

The error return is `getoptions.ErrorHelpCalled` which signals the help is already printed.
The dispatch error handling can handle this error and not print and additional error message.


[source, go]
----
err = opt.Dispatch(ctx, remaining)
Expand All @@ -847,76 +886,64 @@ The dispatch error handling can handle this error and not print and additional e
return 0
----

Another helpful error to check for is `getoptions.ErrorParsing`, as shown above, which indicates there was a problem parsing the CLI arguments.
This can be used, to print the help only in cases where the user didn't enter valid CLI options or arguments.

The built in help shows default values and environment variables when available.

It separates required parameters from options.

For example, the following is a script using the built in help:

----
$ ./aws-configure -h
$ bt terraform force-unlock help
NAME:
aws-configure - Generate default ~/.aws/config and ~/.aws/credentials configuration.
When a role is passed, it allows the use of the role in the default profile.
NOTE: Remember to unset AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY after use.
bt terraform force-unlock
SYNOPSIS:
aws-configure --access-key-id <string> --region <string>
--secret-access-key <string> [--debug] [--help|-?]
[--output-dir <string>] [--role-arn <string>] [--version|-V]
[<args>]
REQUIRED PARAMETERS:
--access-key-id <string> AWS Access Key ID. (env: AWS_ACCESS_KEY_ID)
bt terraform force-unlock [--help|-?] [--profile <string>] [--quiet]
[--ws <string>] <lock-id>
--region <string> Default Region. (env: AWS_DEFAULT_REGION)
--secret-access-key <string> AWS Secret Access Key. (env: AWS_SECRET_ACCESS_KEY)
ARGUMENTS:
<lock-id> Lock ID
OPTIONS:
--debug (default: false)
--help|-? (default: false)
--help|-? (default: false)
--output-dir <string> Where to place the config and credentials file. (default: "/home/david/.aws")
--profile <string> BT Terraform Profile to use (default: "default", env: AWS_PROFILE)
--role-arn <string> Role ARN. (default: "", env: AWS_ROLE_ARN)
--quiet (default: false, env: QUIET)
--version|-V (default: false)
--ws <string> Workspace to use (default: "")
----

And below is the output of the automated help of a program with multiple commands:

----
$ menu
$ tz help
SYNOPSIS:
menu [--config <string>] [--debug] [--help|-?] [--profile <string>]
[--region <string>] [--role <string>] [--version|-V] <command> [<args>]
tz [--config|-c <string>] [--format-standard|--format-12-hour|--format-12h]
[--group <string>] [--help|-?] [--short|-s] [--verbose] <command> [<args>]
COMMANDS:
docker docker tasks
help Use 'menu help <command>' for extra details.
instance Actions on your deployed instances
terraform Run terraform commands from inside the container
cities filter cities list
list list all timezones
version show version
OPTIONS:
--config <string> (default: "config.yml")
--config|-c <string> Config file (default: "")
--debug (default: false)
--help|-? (default: false)
--format-standard|--format-12-hour|--format-12h Use standard 12 hour AM/PM time format (default: false)
--profile <string> (default: "default")
--group <string> Group to show (default: "")
--region <string> (default: "us-west-2")
--help|-? (default: false)
--role <string> (default: "")
--short|-s Don't show timezone bars (default: false)
--version|-V (default: false)
--verbose Enable logging (default: false, env: TZ_VERBOSE)
Use 'menu help <command>' for extra details.
Use 'tz help <command>' for extra details.
----

Any built-in string in `go-getoptions`, like titles, is exposed as a public variable so it can be overridden for internationalization.
Expand Down
46 changes: 46 additions & 0 deletions changelog.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,52 @@
= Changelog
:toc:

== wip v0.30.0: New Features

As the releases before, this release has 100% test coverage.
Tested with Go 1.16, 1.17, 1.18, 1.19, 1.20 and 1.21.

=== New Features

* Add `opt.SuggestedValues` ModifyFn to allow setting autocompletion suggestions for an option.
+
Works just like the existing `opt.ValidValues` but it doesn't error out if the value is not in the list of suggestions.

* Add `opt.GetRequiredArg`, `opt.GetRequiredArgInt` and `opt.GetRequiredArgFloat64` to simplify handling required arguments and providing error messages.
+
For example:
+
[source,go]
----
opt := getoptions.New()
opt.SetCommandFn(Run)
opt.HelpSynopsisArg("<arg1>", "arg1 desc")
opt.HelpSynopsisArg("<arg2>", "arg2 desc")
...
func Run(ctx context.Context, opt *getoptions.GetOpt, args []string) error {
i, args, err := opt.GetRequiredArgInt(args)
if err != nil {
return err
}
...
return nil
}
----
+
If the argument is not provided, the error message will be:
+
----
ERROR: Missing required argument: <arg1>
----
+
If the argument is provided but it is not an integer, the error message will be:
+
----
ERROR: Argument error: Can't convert string to int: 'x'
----

== v0.29.0: New Features

As the releases before, this release has 100% test coverage.
Expand Down

0 comments on commit 023a4a9

Please sign in to comment.