Idiomatic Go input parsing with subcommands, positional values, and flags at any position. No required project or package layout and no external dependencies.
Switch branches/tags
Nothing to show
Clone or download
Latest commit 1056ce3 Oct 6, 2018
Permalink
Failed to load latest commit information.
examples added newline to example output Sep 2, 2018
.gitignore Initial commit Mar 5, 2018
.travis.yml Update and rename travis.yml to .travis.yml Mar 22, 2018
LICENSE unilicense Mar 22, 2018
README.md Update README.md Oct 7, 2018
argumentParser.go fixes some typos Jul 24, 2018
examples_test.go fixing go modules. we do not declare v1 software in modules Oct 7, 2018
flag.go fixes default output values being incorrect in #33 Sep 2, 2018
flag_test.go re-enable tests that crash flaggy to increase coverage Jul 25, 2018
flaggy_test.go fixing go modules. we do not declare v1 software in modules Oct 7, 2018
go.mod fixing go modules. we do not declare v1 software in modules Oct 7, 2018
help.go fixes #20. moves methods for help to parsers, not subcommands. added … Jul 12, 2018
helpValues.go fixes default output values being incorrect in #33 Sep 2, 2018
helpValues_test.go fixing go modules. we do not declare v1 software in modules Oct 7, 2018
logo.png logo resize Mar 23, 2018
main.go fixing go modules. we do not declare v1 software in modules Oct 7, 2018
main_test.go fixing go modules. we do not declare v1 software in modules Oct 7, 2018
parser.go removing unintended templating package from parser. back to stdlib Sep 20, 2018
parser_test.go expose default parser for tweaking and add more readme help Jun 30, 2018
positionalValue.go fixes default output values being incorrect in #33 Sep 2, 2018
subCommand.go fixes default output values being incorrect in #33 Sep 2, 2018
subcommand_test.go fixing go modules. we do not declare v1 software in modules Oct 7, 2018

README.md


Sensible and fast command-line flag parsing with excellent support for subcommands and positional values. Flags can be at any position. Flaggy has no required project or package layout like Cobra requires, and no external dependencies!

Check out the godoc, examples directory, and examples in this readme to get started quickly.

Installation

go get -u github.com/integrii/flaggy

Key Features

  • Very easy to use (see examples below)
  • 35 different flag types supported
  • Any flag can be at any position
  • Pretty and readable help output by default
  • Positional subcommands
  • Positional parameters
  • Suggested subcommands when a subcommand is typo'd
  • Nested subcommands
  • Both global and subcommand specific flags
  • Both global and subcommand specific positional parameters
  • Customizable help templates for both the global command and subcommands
  • Customizable appended/prepended help messages for both the global command and subcommands
  • Simple function that displays help followed by a custom message string
  • Flags and subcommands may have both a short and long name
  • Unlimited trailing arguments after a --
  • Flags can use a single dash or double dash (--flag, -flag, -f, --f)
  • Flags can have = assignment operators, or use a space (--flag=value, --flag value)
  • Flags support single quote globs with spaces (--flag 'this is all one value')
  • Flags of slice types can be passed multiple times (-f one -f two -f three)
  • Optional but default version output with --version
  • Optional but default help output with -h or --help
  • Optional but default help output when any invalid or unknown parameter is passed
  • It's fast. All flag and subcommand parsing takes less than 1ms in most programs.

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

Supported Flag Types:

  • string
  • []string
  • bool
  • []bool
  • time.Duration
  • []time.Duration
  • float32
  • []float32
  • float64
  • []float64
  • uint
  • uint64
  • []uint64
  • uint32
  • []uint32
  • uint16
  • []uint16
  • uint8
  • []uint8
  • []byte
  • int
  • []int
  • int64
  • []int64
  • int32
  • []int32
  • int16
  • []int16
  • int8
  • []int8
  • net.IP
  • []net.IP
  • net.HardwareAddr
  • []net.HardwareAddr
  • net.IPMask
  • []net.IPMask

Super Simple Example

./yourApp -f test

// 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)

Example with Subcommand

./yourApp subcommandExample -f test

// Declare variables and their defaults
var stringFlag = "defaultValue"

// Create the subcommand
subcommand := flaggy.NewSubcommand("subcommandExample")

// Add a flag to the subcommand
subcommand.String(&stringFlag, "f", "flag", "A test string flag")

// Add the subcommand to the parser at position 1
flaggy.AttachSubcommand(subcommand, 1)

// Parse the subcommand and all flags
flaggy.Parse()

// Use the flag
print(stringFlag)

Example with Nested Subcommands, Various Flags and Trailing Arguments

./yourApp subcommandExample --flag=5 nestedSubcommand -t test -y -- trailingArg

// Declare variables and their defaults
var stringFlagF = "defaultValueF"
var intFlagT = 3
var boolFlagB bool

// Create the subcommands
subcommandExample := flaggy.NewSubcommand("subcommandExample")
nestedSubcommand := flaggy.NewSubcommand("nestedSubcommand")

// Add a flag to both subcommands
subcommandExample.String(&stringFlagF, "t", "testFlag", "A test string flag")
nestedSubcommand.Int(&intFlagT, "f", "flag", "A test int flag")

// add a global bool flag for fun
flaggy.Bool(&boolFlagB, "y", "yes", "A sample boolean flag")

// attach the nested subcommand to the parent subcommand at position 1
subcommandExample.AttachSubcommand(nestedSubcommand, 1)
// attach the base subcommand to the parser at position 1
flaggy.AttachSubcommand(subcommandExample, 1)

// Parse everything, then use the flags and trailing arguments
flaggy.Parse()
print(stringFlagF)
print(intFlagT)
print(boolFlagB)
print(flaggy.TrailingArguments[0])

Recommended Program Structure

Best practice when using flaggy includes setting your program's name, description, and version (at build time).

package main

import "github.com/integrii/flaggy"

// make a variable for the version which will be set at build time
var version = "unknown"

// keep subcommands as globals so you can easily check if they were used later on
var mySubcommand *flaggy.Subcommand

func init() {
  // Set your program's name and description.  These appear in help output.
  flaggy.SetName("Test Program")
  flaggy.SetDescription("A little example program")

  // you can disable various things by changing bools on the default parser 
  // (or your own parser if you have created one)
  flaggy.DefaultParser.ShowHelpOnUnexpected = false

  // you can set a help prepend or append on the default parser
  flaggy.DefaultParser.AdditionalHelpPrepend = "http://github.com/integrii/flaggy"
  
  // create any subcommands and set their parameters
  mySubcommand = flaggy.NewSubcommand("mySubcommand")
  mySubcommand.Description = "My great subcommand!"

  // set the version and parse all inputs into variables
  flaggy.SetVersion(version)
  flaggy.Parse()
}
func main(){
    if mySubcommand.Used {
      ...
    }
}

Then, you can use the following build command to set the version variable in the above program at build time.

# build your app and set the version string
$ go build -ldflags='-X main.version=1.0.3-a3db3'
$ ./yourApp version
Version: 1.0.3-a3db3
$ ./yourApp --help
Test Program - A little example program
http://github.com/integrii/flaggy

Contributions

Please feel free to open an issue if you find any bugs or see any features that make sense. Pull requests will be reviewed and accepted if they make sense, but it is always wise to submit a proposal issue before any major changes.