GithubHelp home page GithubHelp logo

cyberflamego / go-flagsfiller Goto Github PK

View Code? Open in Web Editor NEW

This project forked from itzg/go-flagsfiller

0.0 2.0 0.0 84 KB

Bring your own struct and make Go's flag package pleasant to use

License: MIT License

Go 100.00%

go-flagsfiller's Introduction

go-flagsfiller

Bring your own struct and make Go's flag package pleasant to use.

Install

go get github.com/itzg/go-flagsfiller

Import

import "github.com/itzg/go-flagsfiller"

Features

  • Populates Go's flag.FlagSet from a struct of your choosing
  • By default, field names are converted to flag names using kebab-case, but can be configured.
  • Use nested structs where flag name is prefixed by the nesting struct field names
  • Allows defaults to be given via struct tag default
  • Falls back to using instance field values as declared default
  • Declare flag usage via struct tag usage
  • Can be combined with other modules, such as google/subcommands for sub-command processing. Can also be integrated with spf13/cobra by using pflag's AddGoFlagSet
  • Beyond the standard types supported by flag.FlagSet also includes support for:
    • []string where repetition of the argument appends to the slice and/or an argument value can contain a comma-separated list of values. For example: --arg one --arg two,three
    • map[string]string where each entry is a key=value and/or repetition of the arguments adds to the map or multiple entries can be comma-separated in a single argument value. For example: --arg k1=v1 --arg k2=v2,k3=v3
  • Optionally set flag values from environment variables. Similar to flag names, environment variable names are derived automatically from the field names

Quick example

package main

import (
	"flag"
	"fmt"
	"github.com/itzg/go-flagsfiller"
	"log"
	"time"
)

type Config struct {
	Host         string        `default:"localhost" usage:"The remote host"`
	DebugEnabled bool          `default:"true" usage:"Show debugs"`
	MaxTimeout   time.Duration `default:"5s" usage:"How long to wait"`
	Feature      struct {
		Faster         bool `usage:"Go faster"`
		LudicrousSpeed bool `usage:"Go even faster"`
	}
}

func main() {
	var config Config
    
    // create a FlagSetFiller
	filler := flagsfiller.New()
    // fill and map struct fields to flags
	err := filler.Fill(flag.CommandLine, &config)
	if err != nil {
		log.Fatal(err)
	}

    // parse command-line like usual
	flag.Parse()

	fmt.Printf("Loaded: %+v\n", config)
}

The following shows an example of the usage provided when passing --help:

  -debug-enabled
    	Show debugs (default true)
  -feature-faster
    	Go faster
  -feature-ludicrous-speed
    	Go even faster
  -host string
    	The remote host (default "localhost")
  -max-timeout duration
    	How long to wait (default 5s)

Real world example

saml-auth-proxy shows an end-to-end usage of flagsfiller where the main function fills the flags, maps those to environment variables with envy, and parses the command line:

func main() {
	var serverConfig server.Config

	filler := flagsfiller.New()
	err := filler.Fill(flag.CommandLine, &serverConfig)
	if err != nil {
		log.Fatal(err)
	}

	envy.Parse("SAML_PROXY")
	flag.Parse()

where server.Config is declared as

type Config struct {
	Version                 bool              `usage:"show version and exit"`
	Bind                    string            `default:":8080" usage:"host:port to bind for serving HTTP"`
	BaseUrl                 string            `usage:"External URL of this proxy"`
	BackendUrl              string            `usage:"URL of the backend being proxied"`
	IdpMetadataUrl          string            `usage:"URL of the IdP's metadata XML"`
	IdpCaPath               string            `usage:"Optional path to a CA certificate PEM file for the IdP"`
    // ...see https://github.com/itzg/saml-auth-proxy/blob/master/server/server.go for full set
}

Using with google/subcommands

Flagsfiller can be used in combination with google/subcommands to fill both global command-line flags and subcommand flags.

For the global flags, it is best to declare a struct type, such as

type GlobalConfig struct {
	Debug bool `usage:"enable debug logging"`
}

Prior to calling Execute on the subcommands' Commander, fill and parse the global flags like normal:

func main() {
    //... register subcommands here

	var globalConfig GlobalConfig

	err := flagsfiller.Parse(&globalConfig)
	if err != nil {
		log.Fatal(err)
	}

    //... execute subcommands but pass global config
	os.Exit(int(subcommands.Execute(context.Background(), &globalConfig)))
}

Each of your subcommand struct types should contain the flag fields to fill and parse, such as:

type connectCmd struct {
	Host string `usage:"the hostname of the server" env:"GITHUB_TOKEN"`
	Port int `usage:"the port of the server" default:"8080"`
}

Your implementation of SetFlags will use flagsfiller to fill the definition of the subcommand's flagset, such as:

func (c *connectCmd) SetFlags(f *flag.FlagSet) {
	filler := flagsfiller.New()
	err := filler.Fill(f, c)
	if err != nil {
		log.Fatal(err)
	}
}

Finally, your subcommand's Execute function can accept the global config passed from the main Execute call and access its own fields populated from the subcommand flags:

func (c *loadFromGitCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
	globalConfig := args[0].(*GlobalConfig)
    if globalConfig.Debug {
        //... enable debug logs
    }

    // ...operate on subcommand flags, such as
    conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", c.Host, c.Port))
}

More information

Refer to the GoDocs for more information about this module.

go-flagsfiller's People

Contributors

itzg avatar wesdean avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.