Drop-in replacement for Go's flag package, implementing POSIX/GNU-style --flags.

Build Status Go Report Card GoDoc

Description

pflag is a drop-in replacement for Go's flag package, implementing POSIX/GNU-style --flags.

pflag is compatible with the GNU extensions to the POSIX recommendations for command-line options. For a more precise description, see the "Command-line flag syntax" section below.

pflag is available under the same style of BSD license as the Go language, which can be found in the LICENSE file.

Installation

pflag is available using the standard go get command.

Install by running:

go get github.com/spf13/pflag

Run tests by running:

go test github.com/spf13/pflag

Usage

pflag is a drop-in replacement of Go's native flag package. If you import pflag under the name "flag" then all code should continue to function with no changes.

import flag "github.com/spf13/pflag"

There is one exception to this: if you directly instantiate the Flag struct there is one more field "Shorthand" that you will need to set. Most code never instantiates this struct directly, and instead uses functions such as String(), BoolVar(), and Var(), and is therefore unaffected.

Define flags using flag.String(), Bool(), Int(), etc.

This declares an integer flag, -flagname, stored in the pointer ip, with type *int.

var ip *int = flag.Int("flagname", 1234, "help message for flagname")

If you like, you can bind the flag to a variable using the Var() functions.

var flagvar int
func init() {
    flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}

Or you can create custom flags that satisfy the Value interface (with pointer receivers) and couple them to flag parsing by

flag.Var(&flagVal, "name", "help message for flagname")

For such flags, the default value is just the initial value of the variable.

After all flags are defined, call

flag.Parse()

to parse the command line into the defined flags.

Flags may then be used directly. If you're using the flags themselves, they are all pointers; if you bind to variables, they're values.

fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)

There are helper functions available to get the value stored in a Flag if you have a FlagSet but find it difficult to keep up with all of the pointers in your code. If you have a pflag.FlagSet with a flag called 'flagname' of type int you can use GetInt() to get the int value. But notice that 'flagname' must exist and it must be an int. GetString("flagname") will fail.

i, err := flagset.GetInt("flagname")

After parsing, the arguments after the flag are available as the slice flag.Args() or individually as flag.Arg(i). The arguments are indexed from 0 through flag.NArg()-1.

The pflag package also defines some new functions that are not in flag, that give one-letter shorthands for flags. You can use these by appending 'P' to the name of any function that defines a flag.

var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
	flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
}
flag.VarP(&flagVal, "varname", "v", "help message")

Shorthand letters can be used with single dashes on the command line. Boolean shorthand flags can be combined with other shorthand flags.

The default set of command-line flags is controlled by top-level functions. The FlagSet type allows one to define independent sets of flags, such as to implement subcommands in a command-line interface. The methods of FlagSet are analogous to the top-level functions for the command-line flag set.

Setting no option default values for flags

After you create a flag it is possible to set the pflag.NoOptDefVal for the given flag. Doing this changes the meaning of the flag slightly. If a flag has a NoOptDefVal and the flag is set on the command line without an option the flag will be set to the NoOptDefVal. For example given:

var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"

Would result in something like

Parsed Arguments Resulting Value
--flagname=1357 ip=1357
--flagname ip=4321
[nothing] ip=1234

Command line flag syntax

--flag    // boolean flags, or flags with no option default values
--flag x  // only on flags without a default value
--flag=x

Unlike the flag package, a single dash before an option means something different than a double dash. Single dashes signify a series of shorthand letters for flags. All but the last shorthand letter must be boolean flags or a flag with a default value

// boolean or flags where the 'no option default value' is set
-f
-f=true
-abc
but
-b true is INVALID

// non-boolean and flags without a 'no option default value'
-n 1234
-n=1234
-n1234

// mixed
-abcs "hello"
-absd="hello"
-abcs1234

Flag parsing stops after the terminator "--". Unlike the flag package, flags can be interspersed with arguments anywhere on the command line before this terminator.

Integer flags accept 1234, 0664, 0x1234 and may be negative. Boolean flags (in their long form) accept 1, 0, t, f, true, false, TRUE, FALSE, True, False. Duration flags accept any input valid for time.ParseDuration.

Mutating or "Normalizing" Flag names

It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow.

Example #1: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag

func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
	from := []string{"-", "_"}
	to := "."
	for _, sep := range from {
		name = strings.Replace(name, sep, to, -1)
	}
	return pflag.NormalizedName(name)
}

myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc)

Example #2: You want to alias two flags. aka --old-flag-name == --new-flag-name

func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
	switch name {
	case "old-flag-name":
		name = "new-flag-name"
		break
	}
	return pflag.NormalizedName(name)
}

myFlagSet.SetNormalizeFunc(aliasNormalizeFunc)

Deprecating a flag or its shorthand

It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used.

Example #1: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead.

// deprecate a flag by specifying its name and a usage message
flags.MarkDeprecated("badflag", "please use --good-flag instead")

This hides "badflag" from help text, and prints Flag --badflag has been deprecated, please use --good-flag instead when "badflag" is used.

Example #2: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n".

// deprecate a flag shorthand by specifying its flag name and a usage message
flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only")

This hides the shortname "n" from help text, and prints Flag shorthand -n has been deprecated, please use --noshorthandflag only when the shorthand "n" is used.

Note that usage message is essential here, and it should not be empty.

Hidden flags

It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text.

Example: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available.

// hide a flag by specifying its name
flags.MarkHidden("secretFlag")

Disable sorting of flags

pflag allows you to disable sorting of flags for help and usage message.

Example:

flags.BoolP("verbose", "v", false, "verbose output")
flags.String("coolflag", "yeaah", "it's really cool flag")
flags.Int("usefulflag", 777, "sometimes it's very useful")
flags.SortFlags = false
flags.PrintDefaults()

Output:

  -v, --verbose           verbose output
      --coolflag string   it's really cool flag (default "yeaah")
      --usefulflag int    sometimes it's very useful (default 777)

Supporting Go flags when using pflag

In order to support flags defined using Go's flag package, they must be added to the pflag flagset. This is usually necessary to support flags defined by third-party dependencies (e.g. golang/glog).

Example: You want to add the Go flags to the CommandLine flagset

import (
	goflag "flag"
	flag "github.com/spf13/pflag"
)

var ip *int = flag.Int("flagname", 1234, "help message for flagname")

func main() {
	flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
	flag.Parse()
}

More info

You can see the full reference documentation of the pflag package at godoc.org, or through go's standard documentation system by running godoc -http=:6060 and browsing to http://localhost:6060/pkg/github.com/spf13/pflag after installation.

Owner
Steve Francia
@golang product lead at @google • Author, Speaker, Developer • Creator of @gohugoio, Cobra, Viper & spf13-vim • former @docker & @mongodb
Steve Francia
Comments
  • add ability to ignore unknown flags

    add ability to ignore unknown flags

    It will be nice if we can add ability to ignore unknown flags. This can be useful when writing wrappers on other commands where exposing all downstream flags is un-necessary.

  • Allows any flag to expect optional arguments

    Allows any flag to expect optional arguments

    The motivation for this change is to allow any flag or flag type (not only boolean) to support optional arguments as long as they are declared to do so. Example:

    git diff --stat[=<width>]
    

    The logic around flags with empty arguments (e.g. --debug) were detached from the boolean type and moved to a separate attribute called Optional. This allows to mark any flag type as supporting optional arguments.

    The difference in comparison to not providing the flag at all is that the Changed attribute is set, so it allows to control the difference of not providing the flag or providing but without an argument.

    A possible use case would be:

    flag.IntVar(&flagvar, "list", 10, "list the number of items")
    flag.MarkOptional("list")
    

    So when using the flag users could either provide the number of items to display in the list, or not provide any argument to use the default int value:

    deploy           // perform a deployment
    deploy --list    // will list 10 deployments (default value)
    deploy --list=20 // will list 20 deployments
    

    The behavior for default types were not changed (the only flags that allow empty arguments by default are boolean).

  • allow lookup by shorthand

    allow lookup by shorthand

    @eparis I take your advice at https://github.com/kubernetes/kubernetes/pull/35030, I found that it's simple to parse long flag using flags.Lookup() , but there is no method for short flag. I can't get flag.NoOptDefVal to make a distinction between "--flag" and "--flag arg". Would we add a new function for short flag?

  • Question about optional params

    Question about optional params

    Hi, I need to implement an optional param in my programs and I am wondering if there is a way to do it using this library. The use case is to mimic MySQL behavior for -p -p can be used as -p<password here> or just -p and in that case, the param is marked as set but empty and MySQL client will ask for a password. This way, you can avoid using a password in the command line.

    Regards

  • Add support for specifying only a shortflag

    Add support for specifying only a shortflag

    This PR seeks to add support for specifying flags with only a short flag. Tests have been adjusted and added, but suggestions for any additional validation are welcome.

    Fixes #139 Closes #165 Fixes spf13/cobra#679

  • Update flag.go, add secret option

    Update flag.go, add secret option

    I think we could add a new option for flag to make a distinction between secret flag and normal flag, let people can hide the value of flag by "******". just like --username=****** --password=******

  • Grouping flags?

    Grouping flags?

    Hi,

    is it possible to group flags so that they appear together in the --help text? I'm using pflag in my backup program, there I have for example the options to expire backups according to a policy. Before (with the go-flags) library the options were nicely grouped together (in the order they were defined):

    $ restic forget --help
    Usage:
      restic [OPTIONS] forget [snapshot ID] ...
    [...]
    [forget command options]
          -l, --keep-last=    keep the last n snapshots
          -H, --keep-hourly=  keep the last n hourly snapshots
          -d, --keep-daily=   keep the last n daily snapshots
          -w, --keep-weekly=  keep the last n weekly snapshots
          -m, --keep-monthly= keep the last n monthly snapshots
          -y, --keep-yearly=  keep the last n yearly snapshots
              --keep-tag=     alwaps keep snapshots with this tag (can be specified multiple times)
              --hostname=     only forget snapshots for the given hostname
              --tag=          only forget snapshots with the tag (can be specified multiple times)
          -n, --dry-run       do not delete anything, just print what would be done
    

    Now with pflag and cobra they are printed in alphabetical order:

    [...]
    Usage:
      restic forget [flags] [snapshot ID] [...]
    
    Flags:
      -n, --dry-run                do not delete anything, just print what would be done
          --hostname string        only forget snapshots for the given hostname
      -d, --keep-daily int         keep the last n daily snapshots
      -H, --keep-hourly int        keep the last n hourly snapshots
      -l, --keep-last int          keep the last n snapshots
      -m, --keep-monthly int       keep the last n monthly snapshots
          --keep-tag stringSlice   always keep snapshots with this tag (can be specified multiple times)
      -w, --keep-weekly int        keep the last n weekly snapshots
      -y, --keep-yearly int        keep the last n yearly snapshots
          --tag stringSlice        only forget snapshots with the tag (can be specified multiple times)
    [...]
    

    Is there a way to group some flags so that they are printed together?

  • Issue #55: implement Go 1.5-style default usage formatting.

    Issue #55: implement Go 1.5-style default usage formatting.

    Compare to 1.4, the main difference in formatting is the placement of default values. Moreover, UnquoteUsage() is now added (and exported, for full API compatibility with the standard flag package), so backtick words in usage messages can be used to set the placeholder name.

    Compared to the standard flag package, this patch always prints usage in one-line, with automatic alignment, because I feel that the 1.4 output is very confusing when modified to include also dash-dash flags.

  • v1.0.4 Has a Broken Path

    v1.0.4 Has a Broken Path

    edit: updated how to recreate

    go get -u github.com/golangci/golangci-lint/cmd/golangci-lint will fail when hitting this dep

    go get: github.com/spf13/[email protected] updating to
            github.com/spf13/[email protected]: parsing go.mod:
            module declares its path as: github.com/spf13/pflags
                    but was required as: github.com/spf13/pflag
    
  • fix mixed named and positional argument parsing

    fix mixed named and positional argument parsing

    • Prefer a given argument over the default value
    • Look ahead to detect given arguments that are not specified with the connectint = to the argument name

    Fixes #32.

  • Fix handling of -- termination

    Fix handling of -- termination

    Fix handling of -- termination. Previously, if you ran

    $command -flag1 -etc -- some args after
    

    the command's args would be doubled (some args after some args after). Additionally, if there were items after the -- termination that looked like flags, the parser would throw an error. It's better to terminate parsing when -- is seen, because that usually indicates the caller wants to pass the remainder of the arguments (including flags) as-is to something else.

  • can't use double quote in values passed inside a string slice

    can't use double quote in values passed inside a string slice

    When using a string slice StringSliceVar it is impossible to pass values with double quotes "

    The reason is that a CSVReader is used in the implementation (here) and it does not support ".

    One possible solution would be to give the ability to the user to set the LazyQuote mode on the reader. https://pkg.go.dev/encoding/csv#Reader.LazyQuotes

    I faced this problem as I was using a string slice to pass some small piece of json.

    Here is a simple program to reproduce the problem:

    package main
    
    import (
    	"github.com/spf13/pflag"
    	"os"
    )
    
    func main() {
    	fs := pflag.NewFlagSet("Example", pflag.PanicOnError)
    	var ss []string
    	fs.StringSliceVar(&ss, "slice", []string{}, "test slice")
    
    	if err := fs.Parse(os.Args); err != nil {
    		panic(err)
    	}
    }
    

    To be launched with:

    go run main.go --slice='{"delay":"6h"}'
    

    or

    go run cmd/test/main.go --slice="{\"delay\":\"6h\"}"
    

    The result should be:

    panic: invalid argument "{\"delay\":\"6h\"}" for "--slice" flag: parse error on line 1, column 2: bare " in non-quoted-field
    
  • Fix TestPrintDefaults with go >= 1.18

    Fix TestPrintDefaults with go >= 1.18

    It no longer accepts Println with a constant ending with a newline:

    Fixes #368

    ./flag_test.go:1242:3: fmt.Println arg list ends with redundant newline FAIL github.com/spf13/pflag [build failed]

    Also changing the previous line ven if it si not constant for consistency.

  • = 1.18">

    "./flag_test.go:1242:3: fmt.Println arg list ends with redundant newline" with go >= 1.18

    I get a test failure with go 1.19.4 (amd64):

    # github.com/spf13/pflag
    ./flag_test.go:1242:3: fmt.Println arg list ends with redundant newline
    FAIL	github.com/spf13/pflag [build failed]
    

    The behaviour changed in 1.18 https://github.com/golang/go/issues/57059

    Changing the line to fmt.Print("\n" + defaultOutput + "\n") fixes it.

  • Print Default Values of String-to-String in Sorted Order

    Print Default Values of String-to-String in Sorted Order

    Motivation

    Issue 362 reported by @SOF3

    Changes

    Sort keys before stringifying string-to-string flag values.

    Summary

    String-to-string default values in usage would print in sorted order of keys. Eg. --foo stringToString usage (default [a=b,c=d]) In the example as per #362, now, the order will be always default [a=b,c=d]

    Related Issues

    Closes #362

  • Remove Redundant

    Remove Redundant "Unknown-Flag" Error

    Motivation

    Issue 352 reported by @wimglenn

    Changes

    Remove redundant error print function call in failf.

    Summary

    This deletes the extra error log which gets printed when opted for ExitOnError or PanicOnError.

    Related Issues

    Closes #352

Related tags
Golang library with POSIX-compliant command-line UI (CLI) and Hierarchical-configuration. Better substitute for stdlib flag.
Golang library with POSIX-compliant command-line UI (CLI) and Hierarchical-configuration. Better substitute for stdlib flag.

cmdr cmdr is a POSIX-compliant, command-line UI (CLI) library in Golang. It is a getopt-like parser of command-line options, be compatible with the ge

Oct 28, 2022
Dependency-free replacement for GNU parallel, perfect fit for usage in an initramfs.

coshell v0.2.5 A no-frills dependency-free replacement for GNU parallel, perfect for initramfs usage. Licensed under GNU/GPL v2. How it works An sh -c

Dec 19, 2022
The standard library flag package with its missing features

cmd Package cmd is a minimalistic library that enables easy sub commands with the standard flag library. This library extends the standard library fla

Oct 4, 2022
A collection of CLI argument types for the Go `flag` package.

flagvar A collection of CLI argument types for the flag package. import "github.com/sgreben/flagvar" Or just copy & paste what you need. It's public d

Sep 26, 2022
Idiomatic Go input parsing with subcommands, positional values, and flags at any position. No required project or package layout and no external dependencies.
Idiomatic Go input parsing with subcommands, positional values, and flags at any position. No required project or package layout and no external dependencies.

Sensible and fast command-line flag parsing with excellent support for subcommands and positional values. Flags can be at any position. Flaggy has no

Jan 1, 2023
Argparse for golang. Just because `flag` sucks

Golang argparse Let's be honest -- Go's standard command line arguments parser flag terribly sucks. It cannot come anywhere close to the Python's argp

Dec 28, 2022
Flag is a simple but powerful command line option parsing library for Go support infinite level subcommand

Flag Flag is a simple but powerful commandline flag parsing library for Go. Documentation Documentation can be found at Godoc Supported features bool

Sep 26, 2022
CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser

CONTRIBUTIONS ONLY What does this mean? I do not have time to fix issues myself. The only way fixes or new features will be added is by people submitt

Dec 29, 2022
Go binding configuration and command flag made easy✨✨
Go binding configuration and command flag made easy✨✨

✨ Binding configuration and command flag made easy! ✨ You can use multiple keys tag to simplify the look like this (supported feature**): // single ta

Sep 18, 2022
A golang library for building interactive prompts with full support for windows and posix terminals.
A golang library for building interactive prompts with full support for windows and posix terminals.

Survey A library for building interactive prompts on terminals supporting ANSI escape sequences. package main import ( "fmt" "github.com/Alec

Jan 6, 2023
A simple posix shell created in golang

Fox-Shell Description Fox-Shell is a simple posix shell builded with golang Features - chdir works perfectly - mkdir works, but need bug fix To-Do Li

Dec 13, 2021
A lightweight replacement for the standard fmt package, reduces binary size by roughly 400kb in a hello world

console This is a lightweight replacement for the fmt package, reduces the binary size by roughly 400kb in a hello world program. Please note: This pa

Nov 7, 2021
Readline is a pure go(golang) implementation for GNU-Readline kind library
Readline is a pure go(golang) implementation for GNU-Readline kind library

A powerful readline library in Linux macOS Windows Solaris Guide Demo Shortcut Repos using readline Feedback If you have any questions, please submit

Jan 8, 2023
GNU coreutils remade in Go for RosetteOS

Rosebush GNU and POSIX coreutils remade in Go for RosetteOS Build To compile the Rosebush, simply make -B This will compile all the utils one by one.

Oct 4, 2021
GDScript Syntax Highlighting in GNU Nano

nano-gdscript GDScript Syntax Highlighting in GNU Nano. Updated regularly every minor updates. Contributions are welcomed Installation This is 100% fr

Dec 20, 2022
A Go implementation of gnu-coreutils programs

Go-Coreutils A Go implementation of gnu-coreutils programs (https://www.gnu.org/software/coreutils/manual/coreutils.html) Build and Run In the root di

Jan 15, 2022
Automatically sets up command line flags based on struct fields and tags.
Automatically sets up command line flags based on struct fields and tags.

Commandeer Commandeer sets up command line flags based on struct fields and tags. Do you... like to develop Go apps as libraries with tiny main packag

Dec 1, 2022
Generate flags by parsing structures

Flags based on structures. The sflags package uses structs, reflection and struct field tags to allow you specify command line options. It supports di

Nov 24, 2022
A rich tool for parsing flags and values in pure Golang

A rich tool for parsing flags and values in pure Golang. No additional library is required and you can use everywhere.

Jan 25, 2022