## X-Flags ## What does this library? This library provides a simple way to use flags in your application. It extends the standard library to be able to define and use a structure with flags. It supports: * [X] Define flags in a structure * [X] Define callbacks for flags * [X] Define default values for flags * [X] Define aliases for flags * [X] Define required flags ## Installation ```shell go get gitlab.schukai.com/oss/libraries/go/network/xflags ``` **Note:** This library uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies. ## Usage ### Initialize A new flag set is created using the `xflags.New()` function. The structure passed is used as the type for the flags. ```go package main import ( "fmt" "os" "gitlab.schukai.com/oss/libraries/go/network/xflags" ) ``` ### Definition The flags are defined in the structure. The structure can be nested. The name of the field is used as the name of the flag. The type of the field is used as the type of the flag. ```go type Definition struct { Verbose bool `short:"v" long:"verbose" description:"Show verbose debug information"` Serve struct { Host string `short:"h" long:"host" description:"Host to bind to" default:"localhost"` Port int `short:"p" long:"port" description:"Port to bind to" default:"8080"` } `command:"serve" description:"Run the HTTP server" call:"DoServe"` } ``` The following tags are supported: | Tag | Context | Description | |---------------|---------|--------------------------------------------| | `short` | Value | Short name of the flag. | | `long` | Value | Long name of the flag. | | `description` | Value | Description of the flag. | | `required` | Value | Flag is required. | | `shadow` | Value | Copy the value to the shadow structure. | | `command` | Command | Flag is a command. | | `call` | Command | Function to call when the command is used. | | `ignore` | -/- | Property is ignored. | ### Callbacks The functions are called up with a receiver. The receiver is the configuration. The function must have the following signature: `func (d *Definition) DoServe(s *setting[Definition])` Let's assume we have the above definition. The Property `Serve` contains the command `serve`. Furthermore, the command has the tag `call` with the value `DoServe`. The function `DoServe` is called when the command `serve` is used. Important: The function must be exported, that means it must start with a capital letter. The function is called with the receiver `*Definition` An example for the function `DoServe`: ```go func (d *Definition) DoServe(_ *setting[Definition]) { fmt.Printf("Serving on %s:%d", d.Serve.Host, d.Serve.Port) } ``` In this example, the function is called with the receiver `*Definition`. The function is called with the setting `*setting[Definition]`. The setting is used to get the values of the flags. But in this example, we don't need the setting. So we use the underscore `_` to ignore the setting. ### New Setting The function `New` creates a new setting for the given definition. The function returns a pointer to the setting. The first argument is a name for the setting. The second argument is the definition. A good choice for the name is the argument `os.Args[0]`. ```go setting := New(os.Args[0], Definition{}) ``` ### Parse The flags are parsed using the `Parse()` function. The function returns the command and the setting. The command is the name of the command which was used. The setting is the setting of the flags. ```go setting.Parse(os.Args[1:]) ``` For testing, you can use the following arguments: ```go setting.Parse([]string{"--verbose", "serve", "--host", "localhost", "--port", "8080"}) ``` ### Get Values The values of the flags are available in the setting. The values are available in the structure. The structure is the same as the definition. ```go fmt.Printf("Host: %s", setting.GetValues().Serve.Host) fmt.Printf("Port: %d", setting.GetValues().Serve.Port) ``` ### Execute The function `Execute()` executes the command. See the section [Callbacks](#callbacks) for more information. ```go setting.Execute() ``` ### Shadow The shadow structure is used to copy the values of the flags to the shadow structure. The shadow structure is set using the `SetShadow()` and configured using the tag `shadow`. ```go type Shadow struct { Verbose bool Serve struct { Host string Port int } } func main() { setting := New(os.Args[0], Definition{}) setting.SetShadow(Shadow{}) setting.Parse(os.Args[1:]) setting.Execute() fmt.Printf("Shadow: %+v", setting.GetShadow()) } ``` ### Arguments the free arguments can be fetched with the method `Args()`. ### Check Status The execution result can be queried with the functions: - `HelpRequested() bool` - `WasExecuted() bool` - `Error() error` - `MissingCommand() bool` ## Contributing Merge requests are welcome. For major changes, please open an issue first to discuss what you would like to change. **Please make sure to update tests as appropriate.** Versioning is done with [SemVer](https://semver.org/). Changelog is generated with [git-chglog](https://github.com/git-chglog/git-chglog#git-chglog) Commit messages should follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. Messages are started with a type, which is one of the following: - **feat**: A new feature - **fix**: A bug fix - **doc**: Documentation only changes - **refactor**: A code change that neither fixes a bug nor adds a feature - **perf**: A code change that improves performance - **test**: Adding missing or correcting existing tests - **chore**: Other changes that don't modify src or test files The footer would be used for a reference to an issue or a breaking change. A commit that has a footer `BREAKING CHANGE:`, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in semantic versioning). A BREAKING CHANGE can be part of commits of any type. the following is an example of a commit message: ```text feat: add 'extras' field ``` ## License [AGPL-3.0](https://choosealicense.com/licenses/agpl-3.0/)