Awesome
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 domain.
<!-- TOC --> <!-- /TOC -->Example
package main
import (
"flag"
"fmt"
"github.com/sgreben/flagvar"
)
var (
fruit = flagvar.Enum{Choices: []string{"apple", "banana"}}
urls flagvar.URLs
settings flagvar.Assignments
)
func main() {
flag.Var(&fruit, "fruit", fmt.Sprintf("set a fruit (%s)", fruit.Help()))
flag.Var(&urls, "url", "add a URL")
flag.Var(&settings, "set", fmt.Sprintf("specify a setting (%s)", settings.Help()))
flag.Parse()
}
$ go run main.go -set abc=xyz -url https://github.com
# no error
$ go run main.go -set abc=xyz -url ://github.com
invalid value "://github.com" for flag -url: parse ://github.com: missing protocol scheme
$ go run main.go -fruit kiwi
invalid value "kiwi" for flag -fruit: "kiwi" must be one of [apple banana]
$ go run main.go -h
Usage:
-fruit value
set a fruit (one of [apple banana])
-set value
specify a setting (a key/value pair KEY=VALUE)
-url value
add a URL
Conventions
- Pluralized argument types (e.g.
Strings
,Assignments
) can be specified repeatedly, the values are collected in a slice. - The resulting value is stored in
.Value
for singular types and in.Values
for plural types - The original argument string is stored in
.Text
for singular types and in.Texts
for plural types - -Set types (
EnumSet
,StringSet
) de-duplicate provided values. - -CSV types (
IntsCSV
,EnumsCSV
) accept comma-separated values and accumulate values across flag instances if their.Accumulate
field is set totrue
. - Most types implement
interface{ Help() string }
, which produces a string suitable for inclusion in a help message.
Types
Here's a compact overview:
flagvar type | example CLI arg | type of resulting Go value |
---|---|---|
Alternative | ||
Assignment | KEY=VALUE | struct{Key,Value} |
Assignments | KEY=VALUE | []struct{Key,Value} |
AssignmentsMap | KEY=VALUE | map[string]string |
CIDR | 127.0.0.1/24 | struct{IPNet,IP} |
CIDRs | 127.0.0.1/24 | []struct{IPNet,IP} |
CIDRsCSV | 127.0.0.1/16,10.1.2.3/8 | []struct{IPNet,IP} |
Enum | apple | string |
Enums | apple | []string |
EnumsCSV | apple,banana | []string |
EnumSet | apple | []string |
EnumSetCSV | apple,banana | []string |
File | ./README.md | string |
Files | ./README.md | []string |
Floats | 1.234 | []float64 |
FloatsCSV | 1.234,5.0 | []float64 |
Glob | src/**.js | glob.Glob |
Globs | src/**.js | []glob.Glob |
Ints | 1002 | []int64 |
IntsCSV | 123,1002 | []int64 |
IP | 127.0.0.1 | net.IP |
IPs | 127.0.0.1 | []net.IP |
IPsCSV | 127.0.0.1,10.1.2.3 | []net.IP |
JSON | '{"a":1}' | interface{} |
JSONs | '{"a":1}' | []interface{} |
Regexp | [a-z]+ | *regexp.Regexp |
Regexps | [a-z]+ | []*regexp.Regexp |
Strings | "xyxy" | []string |
StringSet | "xyxy" | []string |
StringSetCSV | y,x,y | []string |
TCPAddr | 127.0.0.1:10 | net.TCPAddr |
TCPAddrs | 127.0.0.1:10 | []net.TCPAddr |
TCPAddrsCSV | 127.0.0.1:10,:123 | []net.TCPAddr |
Template | "{{.Size}}" | *template.Template |
Templates | "{{.Size}}" | []*template.Template |
TemplateFile | "/path/to/template.file" | string |
Time | "10:30 AM" | time.Time |
Times | "10:30 AM" | []time.Time |
TimeFormat | "RFC3339" | string |
UDPAddr | 127.0.0.1:10 | net.UDPAddr |
UDPAddrs | 127.0.0.1:10 | []net.UDPAddr |
UDPAddrsCSV | 127.0.0.1:10,:123 | []net.UDPAddr |
UnixAddr | /example.sock | net.UnixAddr |
UnixAddrs | /example.sock | []net.UnixAddr |
UnixAddrsCSV | /example.sock,/other.sock | []net.UnixAddr |
URL | https://github.com | *url.URL |
URLs | https://github.com | []*url.URL |
Wrap | ||
WrapCSV | ||
WrapFunc | ||
WrapPointer |
Goals / design principles
- Help avoid dependencies
- Self-contained > DRY
- Explicitly support copy & paste workflow
- Copyable units should be easy to determine
- Anonymous structs > shared types
- "Code-you-own" feeling, even when imported as a package
- No private fields / methods
- No magic
- Simple built-in types used wherever possible
- Avoid introducing new concepts
- Support "blind" usage
- Zero values should be useful
- Avoid introducing failure cases, handle any combination of parameters gracefully.
- All "obvious things to try" should work.