easyflag

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 21, 2022 License: MIT Imports: 8 Imported by: 2

README

Easyflag package

The easyflag package simplifies working with the native go flag package by simplifying the flag definition and parsing process. The flags are defined as structure field tags:

type params struct {
    Str           string `flag:"str|Very important string||required"`
    Number        int    `flag:"num|Int with a default value|123|"`
    Boo           bool   `flag:"boo"`
    NotAFlagField string
}

and an instance of this structure is filled simply by using the following code snippet in the main function:

var p params
if err := easyflag.ParseAndLoad(&p); err != nil {
    [...]
}

Moreover, the package supports nested structures and user defined extensions executed immediately after the flag parsing.

Flag definition

Flags are defined as fields in a structure. The type of the flag corresponds to the type of the field and the additional flag details are described using the flag field tag. The currently supported field types are: string, bool, int, int64, uint, uint64, float64 and time.Duration.

The value of the flag field tag consists of four parts separated by the | character. Only the first value is mandatory.

  • The first value is the name of the matching CLI flag.
  • The second value is the flag's usage description.
  • The third value is the default value of this flag.
  • The fourth value is used to specify that a flag is required. This overrides the default value of the flag.

The fields without the flag field tag are ignored.

Nested structures

There is a support for nested structures as well. This reduces boilerplate code as it allows for the reuse of predefined blocks of CLI parameters.

Example of the usage:

type BuildVersionFlag struct {
    HasVersionPrintout bool `flag:"v|Prints out version"`
}

type Params struct {
    Str     string `flag:"str|Very important string||required"`
    Version BuildVersionFlag
}

User defined extensions

The passed structure can implement the Extender interface if there is a need for validation or modification of the flag values passed by the user. The structure's method Extend() error is then automatically called after the CLI flag values are loaded.

If any of the nested substructures implements the Extender interface, its Extend method is called as well.

Example of the usage:

type params struct {
    HourInDay int `flag:"h|Hour in a day|"`
}

func (p *params) Extend() error {
    if d := p.HourInDay; d < 0 || d > 23 {
        return fmt.Errorf("invalid hour in a day (%d)", d)
    }
    return nil
}

Usage notes

  • The package does not distinguish between the flag form with one and two leading hyphens (e.g. -help and --help are both valid, and they mean the same).

  • The allowed form of a boolean flag is either -boo without any value or -boo=true for an explicit value setup. This corresponds to the behavior of the native go flag package.

  • For any field type other than boolean both forms -str val and str=val are allowed.

  • There are two reserved flags -h and -help. If a user provides one of these, only the information about the available flags is printed and the program exits.

Documentation

Overview

The easyflag package simplifies working with the native go flag package (https://pkg.go.dev/flag) by simplifying the flag definition and parsing process. The flags are defined as structure field tags:

type params struct {
	Str           string `flag:"str|Very important string||required"`
	Number        int    `flag:"num|Int with a default value|123|"`
	Boo           bool   `flag:"boo"`
	NotAFlagField string
}

and an instance of this structure is filled simply by using the following code snippet in the main function:

var p params
if err := easyflag.ParseAndLoad(&p); err != nil {
	[...]
}

Moreover, the package supports nested structures and user defined extensions executed immediately after the flag parsing.

Flag definition

Flags are defined as fields in a structure. The type of the flag corresponds to the type of the field and the additional flag details are described using the `flag` field tag. The currently supported field types are: string, bool, int, int64, uint, uint64, float64 and time.Duration.

The value of the flag field tag consists of four parts separated by the '|' character. Only the first value is mandatory.

The first value is the name of the matching CLI flag.
The second value is the flag's usage description.
The third value is the default value of this flag.
The fourth value is used to specify that a flag is required. This overrides the default value of the flag.

The fields without the flag field tag are ignored.

Nested structures

There is a support for nested structures as well. This reduces boilerplate code as it allows for the reuse of predefined blocks of CLI parameters.

User defined extensions

The passed structure can implement the Extender interface if there is a need for validation or modification of the flag values passed by the user. The structure's Extend method is then automatically called after the CLI flag values are loaded.

If any of the nested substructures implements the Extender interface, its Extend method is called as well.

Usage notes

- The package does not distinguish between the flag form with one and two leading hyphens (e.g. -help and --help are both valid, and they mean the same).

- The allowed form of a boolean flag is either -boo without any value or -boo=true for an explicit value setup. This corresponds to the behavior of the native go flag package.

- For any field type other than boolean both forms -str val and str=val are allowed.

- There are two reserved flags -h and -help. If a user provides one of these, only the information about the available flags is printed and the program exits.

Example (Basic)

Example_basic demonstrates the basic usage of the package.

var p struct {
	InputPath string `flag:"in|Path to the input file||required"`
	OutputLen int64  `flag:"n|Maximum number of characters to read (-1 for all)|-1"`
}

if err := ParseAndLoad(&p); err != nil {
	log.Fatalf("error while parsing the cli parameters: %s", err.Error())
}
Output:

Example (Extension)

Example_extension demonstrates the usage of params structure implementing the Extender interface.

package main

import (
	"errors"
	"log"
	"strings"
)

type params struct {
	Username string `flag:"u|Username||required"`
	isAdmin  bool
}

func (p *params) Extend() error {
	// validation of username
	if strings.Index(p.Username, " ") != -1 {
		return errors.New("username cannot contain whitespaces")
	}
	// modification of the structure fields
	if p.Username == "admin" {
		p.isAdmin = true
	}
	return nil
}

// Example_extension demonstrates the usage of params structure implementing the Extender interface.
func main() {
	var p params
	if err := ParseAndLoad(&p); err != nil {
		log.Fatalf("error while parsing the cli parameters: %s", err.Error())
	}
}
Output:

Example (Nested)

Example_basic demonstrates the usage of nested structures.

type userAuth struct {
	Username string `flag:"user|Username||required"`
	Password string `flag:"pass|Passsword"`
}

type serverInfo struct {
	Host string `flag:"a|Server host address|127.0.0.1"`
	Port int    `flag:"p|Server port|80"`
}

var p struct {
	UserAuth   userAuth
	ServerInfo serverInfo
}

if err := ParseAndLoad(&p); err != nil {
	log.Fatalf("error while parsing the cli parameters: %s", err.Error())
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseAndLoad

func ParseAndLoad(params interface{}) (retErr error)

ParseAndLoad takes a pointer to a structure and fills it from the user defined CLI flags according to the flag metadata defined as structure field tags.

If the params type or any of its fields implements the Extender interface then its Extend method will be called at the end of the setup. This can be used for the validation or modification of the field values.

In case of an error during the flag parsing, the passed structure is set to its zero value and the error is returned.

Types

type Extender

type Extender interface {
	Extend() error
}

Extender is an interface that can be implemented by the type passed to the ParseAndLoad function. It can be used for additional validation or modification of the CLI arguments

type InvalidParamsError

type InvalidParamsError struct {
	Type reflect.Type
}

InvalidParamsError is an error returned in case that the params argument passed to the ParseAndLoad function is not a pointer to a structure.

func (*InvalidParamsError) Error

func (e *InvalidParamsError) Error() string

Error prints the description of the InvalidParamsError.

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL