getopt: init module
This commit is contained in:
parent
8290a04536
commit
30ccc33f34
17 changed files with 1076 additions and 3 deletions
2
cli.go
2
cli.go
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.baxters.nz/jeremy/cli/getopt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var undef = "(undefined)"
|
var undef = "(undefined)"
|
||||||
|
|
|
||||||
4
getopt/.LICENSE.~undo-tree~
Normal file
4
getopt/.LICENSE.~undo-tree~
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
(undo-tree-save-format-version . 1)
|
||||||
|
"ea9995832c3e0239223cbc9357def034cfcdda62"
|
||||||
|
[nil current nil nil (27067 8166 957871 684000) 0 nil]
|
||||||
|
nil
|
||||||
26
getopt/LICENSE
Normal file
26
getopt/LICENSE
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
Copyright 2019 Drew DeVault <sir@cmpwn.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
43
getopt/bool.go
Normal file
43
getopt/bool.go
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type boolFlag interface {
|
||||||
|
flag.Value
|
||||||
|
IsBoolFlag() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type boolVal bool
|
||||||
|
|
||||||
|
func (b *boolVal) String() string {
|
||||||
|
return strconv.FormatBool(bool(*b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *boolVal) Set(val string) error {
|
||||||
|
*b = boolVal(true)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *boolVal) IsBoolFlag() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolVar defines a bool flag with specified name, default value, and
|
||||||
|
// usage string. The argument p points to a bool variable in which to
|
||||||
|
// store the value of the flag.
|
||||||
|
func (set *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*boolVal)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool defines a bool flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a bool variable that
|
||||||
|
// stores the value of the flag.
|
||||||
|
func (set *FlagSet) Bool(name string, value bool, usage string) *bool {
|
||||||
|
var b bool
|
||||||
|
set.BoolVar(&b, name, value, usage)
|
||||||
|
return &b
|
||||||
|
}
|
||||||
180
getopt/commandline.go
Normal file
180
getopt/commandline.go
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommandLine is the default set of command-line flags, parsed from
|
||||||
|
// os.Args. The top-level functions such as BoolVar, Arg, and so on are
|
||||||
|
// wrappers for the methods of CommandLine.
|
||||||
|
var CommandLine = NewFlagSet(os.Args[0], flag.ExitOnError)
|
||||||
|
|
||||||
|
// Usage prints a usage message documenting all defined command-line
|
||||||
|
// flags to os.Stderr. It is called when an error occurs while parsing
|
||||||
|
// flags. The function is a variable that may be changed to point to a
|
||||||
|
// custom function. By default it prints a simple header and calls
|
||||||
|
// PrintDefaults; for details about the format of the output and how to
|
||||||
|
// control it, see the documentation for PrintDefaults. Custom usage
|
||||||
|
// functions may choose to exit the program; by default exiting happens
|
||||||
|
// anyway as the command line's error handling strategy is set to
|
||||||
|
// ExitOnError.
|
||||||
|
var Usage = CommandLine.Usage
|
||||||
|
|
||||||
|
// PrintDefaults prints, to standard error unless configured otherwise,
|
||||||
|
// a usage message showing the default settings of all defined
|
||||||
|
// command-line flags.
|
||||||
|
func PrintDefaults() { CommandLine.PrintDefaults() }
|
||||||
|
|
||||||
|
// Arg returns the i'th command-line argument. Arg(0) is the first
|
||||||
|
// remaining argument after flags have been processed. Arg returns an
|
||||||
|
// empty string if the requested element does not exist.
|
||||||
|
func Arg(i int) string { return CommandLine.Arg(i) }
|
||||||
|
|
||||||
|
// Args returns the non-flag command-line arguments.
|
||||||
|
func Args() []string { return CommandLine.Args() }
|
||||||
|
|
||||||
|
// NArg is the number of arguments remaining after flags have been
|
||||||
|
// processed.
|
||||||
|
func NArg() int { return CommandLine.NArg() }
|
||||||
|
|
||||||
|
// NFlag returns the number of command-line flags that have been set.
|
||||||
|
func NFlag() int { return CommandLine.NFlag() }
|
||||||
|
|
||||||
|
// Parsed reports whether the command-line flags have been parsed.
|
||||||
|
func Parsed() bool { return CommandLine.Parsed() }
|
||||||
|
|
||||||
|
// Parse parses the command-line flags from os.Args. Must be called
|
||||||
|
// after all flags are defined and before flags are accessed by the
|
||||||
|
// program.
|
||||||
|
func Parse() error { return CommandLine.Parse() }
|
||||||
|
|
||||||
|
// Var defines a flag with the specified name and usage string. The type
|
||||||
|
// and value of the flag are represented by the first argument, of type
|
||||||
|
// Value, which typically holds a user-defined implementation of Value.
|
||||||
|
// For instance, the caller could create a flag that turns a
|
||||||
|
// comma-separated string into a slice of strings by giving the slice
|
||||||
|
// the methods of Value; in particular, Set would decompose the
|
||||||
|
// comma-separated string into the slice.
|
||||||
|
func Var(value flag.Value, name string, usage string) {
|
||||||
|
CommandLine.Var(value, name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the Flag structure of the named flag, returning nil if
|
||||||
|
// none exists.
|
||||||
|
func Lookup(name string) *Flag {
|
||||||
|
return CommandLine.Lookup(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOutput sets the destination for usage and error messages. If
|
||||||
|
// output is nil, os.Stderr is used.
|
||||||
|
func SetOutput(output io.Writer) {
|
||||||
|
CommandLine.SetOutput(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolVar defines a bool flag with specified name, default value, and
|
||||||
|
// usage string. The argument p points to a bool variable in which to
|
||||||
|
// store the value of the flag.
|
||||||
|
func BoolVar(p *bool, name string, value bool, usage string) {
|
||||||
|
CommandLine.BoolVar(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool defines a bool flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a bool variable that
|
||||||
|
// stores the value of the flag.
|
||||||
|
func Bool(name string, value bool, usage string) *bool {
|
||||||
|
return CommandLine.Bool(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationVar defines a time.Duration flag with specified name, default
|
||||||
|
// value, and usage string. The argument p points to a time.Duration
|
||||||
|
// variable in which to store the value of the flag. The flag accepts a
|
||||||
|
// value acceptable to time.ParseDuration.
|
||||||
|
func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
|
||||||
|
CommandLine.DurationVar(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration defines a time.Duration flag with specified name, default
|
||||||
|
// value, and usage string. The return value is the address of a
|
||||||
|
// time.Duration variable that stores the value of the flag. The flag
|
||||||
|
// accepts a value acceptable to time.ParseDuration.
|
||||||
|
func Duration(name string, value time.Duration, usage string) *time.Duration {
|
||||||
|
return CommandLine.Duration(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Var defines a float64 flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a float64 variable in
|
||||||
|
// which to store the value of the flag.
|
||||||
|
func Float64Var(p *float64, name string, value float64, usage string) {
|
||||||
|
CommandLine.Float64Var(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 defines a float64 flag with specified name, default value,
|
||||||
|
// and usage string. The return value is the address of a float64
|
||||||
|
// variable that stores the value of the flag.
|
||||||
|
func Float64(name string, value float64, usage string) *float64 {
|
||||||
|
return CommandLine.Float64(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntVar defines a int flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a int variable in
|
||||||
|
// which to store the value of the flag.
|
||||||
|
func IntVar(p *int, name string, value int, usage string) {
|
||||||
|
CommandLine.IntVar(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int defines an int flag with specified name, default value, and usage
|
||||||
|
// string. The return value is the address of an int variable that
|
||||||
|
// stores the value of the flag.
|
||||||
|
func Int(name string, value int, usage string) *int {
|
||||||
|
return CommandLine.Int(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Var defines an int64 flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to an int64 variable in which
|
||||||
|
// to store the value of the flag.
|
||||||
|
func Int64Var(p *int64, name string, value int64, usage string) {
|
||||||
|
CommandLine.Int64Var(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 defines an int64 flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of an int64 variable
|
||||||
|
// that stores the value of the flag.
|
||||||
|
func Int64(name string, value int64, usage string) *int64 {
|
||||||
|
return CommandLine.Int64(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringVar defines a string flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a string variable in which
|
||||||
|
// to store the value of the flag.
|
||||||
|
func StringVar(p *string, name string, value string, usage string) {
|
||||||
|
CommandLine.StringVar(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a string flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a string variable
|
||||||
|
// that stores the value of the flag.
|
||||||
|
func String(name string, value string, usage string) *string {
|
||||||
|
return CommandLine.String(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64Var defines a uint64 flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a uint64 variable in which
|
||||||
|
// to store the value of the flag.
|
||||||
|
func Uint64Var(p *uint64, name string, value uint64, usage string) {
|
||||||
|
CommandLine.Uint64Var(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 defines a uint64 flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a uint64 variable
|
||||||
|
// that stores the value of the flag.
|
||||||
|
func Uint64(name string, value uint64, usage string) *uint64 {
|
||||||
|
return CommandLine.Uint64(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the value of the named flag.
|
||||||
|
func Set(name, value string) error {
|
||||||
|
return CommandLine.Set(name, value)
|
||||||
|
}
|
||||||
39
getopt/duration.go
Normal file
39
getopt/duration.go
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type durationVal time.Duration
|
||||||
|
|
||||||
|
func (d *durationVal) String() string {
|
||||||
|
return time.Duration(*d).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *durationVal) Set(val string) error {
|
||||||
|
v, err := time.ParseDuration(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*d = durationVal(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationVar defines a time.Duration flag with specified name, default
|
||||||
|
// value, and usage string. The argument p points to a time.Duration
|
||||||
|
// variable in which to store the value of the flag. The flag accepts a
|
||||||
|
// value acceptable to time.ParseDuration.
|
||||||
|
func (set *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*durationVal)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration defines a time.Duration flag with specified name, default
|
||||||
|
// value, and usage string. The return value is the address of a
|
||||||
|
// time.Duration variable that stores the value of the flag. The flag
|
||||||
|
// accepts a value acceptable to time.ParseDuration.
|
||||||
|
func (set *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
|
||||||
|
var d time.Duration
|
||||||
|
set.DurationVar(&d, name, value, usage)
|
||||||
|
return &d
|
||||||
|
}
|
||||||
74
getopt/flag_test.go
Normal file
74
getopt/flag_test.go
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInt(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
p := NewFlagSet("", 0)
|
||||||
|
var k int
|
||||||
|
p.IntVar(&k, "k", 16, "set k")
|
||||||
|
i := p.Int64("i", -1, "set i")
|
||||||
|
j := p.Uint("j", 64, "set j")
|
||||||
|
|
||||||
|
err := p.parse([]string{"bin", "-i", "32", "normal arg"})
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(3, p.optindex, "Expected to only parse two arguments")
|
||||||
|
assert.Equal(int64(32), *i, "Expected -i argument to equal 32")
|
||||||
|
assert.Equal(uint(64), *j, "Expected -j argument to equal 64, since unset")
|
||||||
|
assert.Equal(16, k, "Expected -k argument to equal 16, since unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBool(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
p := NewFlagSet("", 0)
|
||||||
|
var a bool
|
||||||
|
p.BoolVar(&a, "a", false, "set a")
|
||||||
|
b := p.Bool("b", false, "set b")
|
||||||
|
|
||||||
|
err := p.parse([]string{"bin", "-a", "normal arg"})
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(2, p.optindex, "Expected to only parse two arguments")
|
||||||
|
assert.Equal(true, a, "Expected -a argument to be set")
|
||||||
|
assert.Equal(false, *b, "Expected -b argument to not be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestString(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
p := NewFlagSet("", 0)
|
||||||
|
get := p.String("c", "default", "get -c")
|
||||||
|
|
||||||
|
opt := "some options"
|
||||||
|
err := p.parse([]string{"bin", "-c", opt, "normal arg"})
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(opt, *get, "Expected argument to be parsed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFloat64(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
p := NewFlagSet("", 0)
|
||||||
|
f := p.Float64("f", -3.14, "get -f")
|
||||||
|
|
||||||
|
err := p.parse([]string{"bin", "-f", "3.14", "normal arg"})
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(3.14, *f, "Expected -f to equal 3.14")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDuration(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
p := NewFlagSet("", 0)
|
||||||
|
d := p.Duration("d", 0, "get -d")
|
||||||
|
|
||||||
|
err := p.parse([]string{"bin", "-d", "1h3m", "normal arg"})
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(time.Hour+3*time.Minute, *d, "Expected -d to equal 1 hour and 3 minutes")
|
||||||
|
}
|
||||||
259
getopt/flagset.go
Normal file
259
getopt/flagset.go
Normal file
|
|
@ -0,0 +1,259 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
typeBool = iota
|
||||||
|
typeString
|
||||||
|
typeInt
|
||||||
|
typeUint
|
||||||
|
typeInt64
|
||||||
|
typeUint64
|
||||||
|
typeFloat64
|
||||||
|
typeDuration
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Flag represents the state of a flag.
|
||||||
|
type Flag struct {
|
||||||
|
Name string
|
||||||
|
Rune rune
|
||||||
|
Value flag.Value
|
||||||
|
Usage string
|
||||||
|
used bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// A FlagSet represents a set of defined flags. The zero value of a
|
||||||
|
// FlagSet has no name and has ContinueOnError error handling.
|
||||||
|
type FlagSet struct {
|
||||||
|
parsed bool
|
||||||
|
optindex int
|
||||||
|
|
||||||
|
flags map[rune]*Flag
|
||||||
|
output io.Writer
|
||||||
|
|
||||||
|
name string
|
||||||
|
errorHandling flag.ErrorHandling
|
||||||
|
|
||||||
|
Usage func()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFlagSet returns a new, empty flag set.
|
||||||
|
func NewFlagSet(name string, err flag.ErrorHandling) *FlagSet {
|
||||||
|
set := FlagSet{
|
||||||
|
name: name,
|
||||||
|
flags: make(map[rune]*Flag),
|
||||||
|
output: os.Stderr,
|
||||||
|
errorHandling: err,
|
||||||
|
}
|
||||||
|
set.Usage = func() {
|
||||||
|
if set.name != "" {
|
||||||
|
fmt.Fprintf(set.output, "Usage of %s:\n\n", set.name)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(set.output, "Usage:\n\n")
|
||||||
|
}
|
||||||
|
set.PrintDefaults()
|
||||||
|
}
|
||||||
|
return &set
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *FlagSet) parse(args []string) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for r, f := range set.flags {
|
||||||
|
buf.WriteRune(r)
|
||||||
|
if f, ok := f.Value.(boolFlag); !ok || !f.IsBoolFlag() {
|
||||||
|
buf.WriteByte(':')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
options, optind, err := Getopts(args, buf.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
set.optindex = optind
|
||||||
|
|
||||||
|
for _, opt := range options {
|
||||||
|
err = set.Set(fmt.Sprintf("%c", opt.Option), opt.Value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set.parsed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the value of the named flag.
|
||||||
|
func (set *FlagSet) Set(name, value string) error {
|
||||||
|
r, _ := utf8.DecodeRuneInString(name)
|
||||||
|
flag, ok := set.flags[r]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("no such flag -%v", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.used = true
|
||||||
|
return flag.Value.Set(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arg returns the i'th command-line argument. Arg(0) is the first
|
||||||
|
// remaining argument after flags have been processed. Arg returns an
|
||||||
|
// empty string if the requested element does not exist.
|
||||||
|
func (set *FlagSet) Arg(i int) string {
|
||||||
|
var arg string
|
||||||
|
if len(set.Args()) < i {
|
||||||
|
arg = set.Args()[i]
|
||||||
|
}
|
||||||
|
return arg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Args returns the non-flag command-line arguments.
|
||||||
|
func (set *FlagSet) Args() []string {
|
||||||
|
return os.Args[set.optindex:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NArg is the number of arguments remaining after flags have been
|
||||||
|
// processed.
|
||||||
|
func (set *FlagSet) NArg() int {
|
||||||
|
return len(set.Args())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NFlag returns the number of command-line flags that have been set.
|
||||||
|
func (set *FlagSet) NFlag() int {
|
||||||
|
return len(set.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsed reports whether the command-line flags have been parsed.
|
||||||
|
func (set *FlagSet) Parsed() bool {
|
||||||
|
return set.parsed
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSlice parses the command-line flags from args. Must be called
|
||||||
|
// after all flags are defined and before flags are accessed by the
|
||||||
|
// program.
|
||||||
|
func (set *FlagSet) ParseSlice(args []string) (err error) {
|
||||||
|
err = set.parse(args)
|
||||||
|
if err != nil {
|
||||||
|
switch set.errorHandling {
|
||||||
|
case flag.PanicOnError:
|
||||||
|
panic(err)
|
||||||
|
case flag.ExitOnError:
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses the command-line flags from os.Args. Must be called
|
||||||
|
// after all flags are defined and before flags are accessed by the
|
||||||
|
// program.
|
||||||
|
func (set *FlagSet) Parse() error {
|
||||||
|
return set.ParseSlice(os.Args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrorHandling returns the error handling behavior of the flag set.
|
||||||
|
func (set *FlagSet) ErrorHandling() flag.ErrorHandling {
|
||||||
|
return set.errorHandling
|
||||||
|
}
|
||||||
|
|
||||||
|
// Var defines a flag with the specified name and usage string. The type
|
||||||
|
// and value of the flag are represented by the first argument, of type
|
||||||
|
// Value, which typically holds a user-defined implementation of Value.
|
||||||
|
// For instance, the caller could create a flag that turns a
|
||||||
|
// comma-separated string into a slice of strings by giving the slice
|
||||||
|
// the methods of Value; in particular, Set would decompose the
|
||||||
|
// comma-separated string into the slice.
|
||||||
|
func (set *FlagSet) Var(value flag.Value, name string, usage string) {
|
||||||
|
r, _ := utf8.DecodeRuneInString(name)
|
||||||
|
set.flags[r] = &Flag{
|
||||||
|
Name: name,
|
||||||
|
Rune: r,
|
||||||
|
Value: value,
|
||||||
|
Usage: usage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *FlagSet) visitIf(cond func(*Flag) bool, fn func(*Flag)) {
|
||||||
|
var runes []rune
|
||||||
|
for r := range set.flags {
|
||||||
|
runes = append(runes, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range runes {
|
||||||
|
for j := i; j > 0; j-- {
|
||||||
|
if runes[j] < runes[j-1] {
|
||||||
|
runes[j], runes[j-1] = runes[j-1], runes[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range runes {
|
||||||
|
if cond == nil || cond(set.flags[r]) {
|
||||||
|
fn(set.flags[r])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VisitAll visits the command-line flags in lexicographical order,
|
||||||
|
// calling fn for each. It visits all flags, even those not set.
|
||||||
|
func (set *FlagSet) VisitAll(fn func(*Flag)) {
|
||||||
|
set.visitIf(nil, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visit visits the command-line flags in lexicographical order,
|
||||||
|
// calling fn for each.
|
||||||
|
func (set *FlagSet) Visit(fn func(*Flag)) {
|
||||||
|
set.visitIf(func(flag *Flag) bool { return flag.used }, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the Flag structure of the named flag, returning nil if
|
||||||
|
// none exists.
|
||||||
|
func (set *FlagSet) Lookup(name string) *Flag {
|
||||||
|
r, _ := utf8.DecodeRuneInString(name)
|
||||||
|
return set.flags[r]
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrintDefaults prints, to standard error unless configured otherwise,
|
||||||
|
// a usage message showing the default settings of all defined
|
||||||
|
// command-line flags.
|
||||||
|
func (set *FlagSet) PrintDefaults() {
|
||||||
|
out := set.output
|
||||||
|
set.VisitAll(func(flag *Flag) {
|
||||||
|
fmt.Fprintf(out, " -%c", flag.Rune)
|
||||||
|
|
||||||
|
val := flag.Value
|
||||||
|
|
||||||
|
usage := strings.Replace(flag.Usage, "\n", "\n \t", -1)
|
||||||
|
fmt.Fprintf(out, "\t%s", usage)
|
||||||
|
|
||||||
|
if _, ok := val.(*stringVal); ok {
|
||||||
|
fmt.Fprintf(out, " (default %q)", val)
|
||||||
|
} else if _, ok := val.(*boolVal); !ok {
|
||||||
|
fmt.Fprintf(out, " (default %s)", val)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(out, "\n")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOutput sets the destination for usage and error messages. If
|
||||||
|
// output is nil, os.Stderr is used.
|
||||||
|
func (set *FlagSet) SetOutput(output io.Writer) {
|
||||||
|
if output == nil {
|
||||||
|
set.output = os.Stderr
|
||||||
|
} else {
|
||||||
|
set.output = output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output returns the destination for usage and error messages.
|
||||||
|
// os.Stderr is returned if output was not set or was set to nil.
|
||||||
|
func (set *FlagSet) Output() io.Writer {
|
||||||
|
return set.output
|
||||||
|
}
|
||||||
33
getopt/float.go
Normal file
33
getopt/float.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type floatVal float64
|
||||||
|
|
||||||
|
func (f *floatVal) String() string {
|
||||||
|
return fmt.Sprint(float64(*f))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *floatVal) Set(val string) error {
|
||||||
|
_, err := fmt.Sscanf(val, "%g", f)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Var defines a float64 flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a float64 variable in
|
||||||
|
// which to store the value of the flag.
|
||||||
|
func (set *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*floatVal)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 defines a float64 flag with specified name, default value,
|
||||||
|
// and usage string. The return value is the address of a float64
|
||||||
|
// variable that stores the value of the flag.
|
||||||
|
func (set *FlagSet) Float64(name string, value float64, usage string) *float64 {
|
||||||
|
var f float64
|
||||||
|
set.Float64Var(&f, name, value, usage)
|
||||||
|
return &f
|
||||||
|
}
|
||||||
155
getopt/getopt.go
Normal file
155
getopt/getopt.go
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
// getopt is a POSIX-compatible implementation of getopt(3) for Go.
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "os"
|
||||||
|
// "git.sr.ht/~sircmpwn/getopt"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func main() {
|
||||||
|
// opts, optind, err := getopt.Getopts(os.Args, "abc:d:")
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// for _, opt := range opts {
|
||||||
|
// switch opt.Option {
|
||||||
|
// case 'a':
|
||||||
|
// println("Option -a specified")
|
||||||
|
// case 'b':
|
||||||
|
// println("Option -b specified")
|
||||||
|
// case 'c':
|
||||||
|
// println("Option -c specified: " + opt.Value)
|
||||||
|
// case 'd':
|
||||||
|
// println("Option -d specified: " + opt.Value)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// println("Remaining arguments:")
|
||||||
|
// for _, arg := range os.Args[optind:] {
|
||||||
|
// println(arg)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// A flag[0]-like interface is also supported.
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "git.sr.ht/~sircmpwn/getopt"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func main() {
|
||||||
|
// a := getopt.Bool("a", false, "turn on option a")
|
||||||
|
// b := getopt.Int("b", 1, "set b to a numerical value")
|
||||||
|
// var opt string
|
||||||
|
// getopt.StringVar(&opt, "c", "", "let c be specified string")
|
||||||
|
//
|
||||||
|
// err := getopt.Parse()
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// print("Value of a: ")
|
||||||
|
// println(*a)
|
||||||
|
// print("Value of b: ")
|
||||||
|
// println(*b)
|
||||||
|
// println("Value of c: " + opt)
|
||||||
|
//
|
||||||
|
// println("Remaining arguments:")
|
||||||
|
// for _, arg := range getopt.Args() {
|
||||||
|
// println(arg)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// [0]: https://golang.org/pkg/flag/
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// In the case of "-o example", Option is 'o' and "example" is Value. For
|
||||||
|
// options which do not take an argument, Value is "".
|
||||||
|
type Option struct {
|
||||||
|
Option rune
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is returned when an unknown option is found in argv, but not in the
|
||||||
|
// option spec.
|
||||||
|
type UnknownOptionError rune
|
||||||
|
|
||||||
|
func (e UnknownOptionError) Error() string {
|
||||||
|
return fmt.Sprintf("%s: unknown option -%c", os.Args[0], rune(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is returned when an option with a mandatory argument is missing that
|
||||||
|
// argument.
|
||||||
|
type MissingOptionError rune
|
||||||
|
|
||||||
|
func (e MissingOptionError) Error() string {
|
||||||
|
return fmt.Sprintf("%s: expected argument for -%c", os.Args[0], rune(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getopts implements a POSIX-compatible options interface.
|
||||||
|
//
|
||||||
|
// Returns a slice of options and the index of the first non-option argument.
|
||||||
|
//
|
||||||
|
// If an error is returned, you must print it to stderr to be POSIX complaint.
|
||||||
|
func Getopts(argv []string, spec string) ([]Option, int, error) {
|
||||||
|
optmap := make(map[rune]bool)
|
||||||
|
runes := []rune(spec)
|
||||||
|
for i, rn := range spec {
|
||||||
|
if rn == ':' {
|
||||||
|
if i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
optmap[runes[i-1]] = true
|
||||||
|
} else {
|
||||||
|
optmap[rn] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
i int
|
||||||
|
opts []Option
|
||||||
|
)
|
||||||
|
for i = 1; i < len(argv); i++ {
|
||||||
|
arg := argv[i]
|
||||||
|
runes = []rune(arg)
|
||||||
|
if len(arg) == 0 || arg == "-" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if arg[0] != '-' {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if arg == "--" {
|
||||||
|
i++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for j, opt := range runes[1:] {
|
||||||
|
if optopt, ok := optmap[opt]; !ok {
|
||||||
|
opts = append(opts, Option{'?', ""})
|
||||||
|
return opts, i, UnknownOptionError(opt)
|
||||||
|
} else if optopt {
|
||||||
|
if j+1 < len(runes)-1 {
|
||||||
|
opts = append(opts, Option{opt, string(runes[j+2:])})
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
if i+1 >= len(argv) {
|
||||||
|
if len(spec) >= 1 && spec[0] == ':' {
|
||||||
|
opts = append(opts, Option{':', string(opt)})
|
||||||
|
} else {
|
||||||
|
return opts, i, MissingOptionError(opt)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
opts = append(opts, Option{opt, argv[i+1]})
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
opts = append(opts, Option{opt, ""})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return opts, i, nil
|
||||||
|
}
|
||||||
89
getopt/getopt_test.go
Normal file
89
getopt/getopt_test.go
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSimpleCase(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
opts, i, err := Getopts([]string{
|
||||||
|
"test_bin", "-afo", "output-file", "normal arg"}, "afo:")
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(len(opts), 3, "Expected 3 options to be parsed")
|
||||||
|
assert.Equal(i, 3, "Expected non-option args to start at index 2")
|
||||||
|
assert.Equal(opts[0], Option{'a', ""})
|
||||||
|
assert.Equal(opts[1], Option{'f', ""})
|
||||||
|
assert.Equal(opts[2], Option{'o', "output-file"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShortFormArgument(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
opts, i, err := Getopts([]string{
|
||||||
|
"test_bin", "-afooutput-file", "normal arg"}, "afo:")
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(len(opts), 3, "Expected 3 options to be parsed")
|
||||||
|
assert.Equal(i, 2, "Expected non-option args to start at index 2")
|
||||||
|
assert.Equal(opts[0], Option{'a', ""})
|
||||||
|
assert.Equal(opts[1], Option{'f', ""})
|
||||||
|
assert.Equal(opts[2], Option{'o', "output-file"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeparateArgs(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
opts, i, err := Getopts([]string{
|
||||||
|
"test_bin", "-a", "-f", "-o", "output-file", "normal arg"}, "afo:")
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(len(opts), 3, "Expected 3 options to be parsed")
|
||||||
|
assert.Equal(i, 5, "Expected non-option args to start at index 5")
|
||||||
|
assert.Equal(opts[0], Option{'a', ""})
|
||||||
|
assert.Equal(opts[1], Option{'f', ""})
|
||||||
|
assert.Equal(opts[2], Option{'o', "output-file"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTwoDashes(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
opts, i, err := Getopts([]string{
|
||||||
|
"test_bin", "-afo", "output-file", "--", "-f", "normal arg"}, "afo:")
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(len(opts), 3, "Expected 3 options to be parsed")
|
||||||
|
assert.Equal(i, 4, "Expected non-option args to start at index 4")
|
||||||
|
assert.Equal(opts[0], Option{'a', ""})
|
||||||
|
assert.Equal(opts[1], Option{'f', ""})
|
||||||
|
assert.Equal(opts[2], Option{'o', "output-file"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnknownOption(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
_, _, err := Getopts([]string{"test_bin", "-x"}, "y")
|
||||||
|
var errt UnknownOptionError
|
||||||
|
assert.IsType(err, errt, "Expected unknown option error")
|
||||||
|
assert.Equal(err.Error(), fmt.Sprintf("%s: unknown option -x", os.Args[0]),
|
||||||
|
"Expected POSIX-compatible error message")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMissingOption(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
_, _, err := Getopts([]string{"test_bin", "-x"}, "x:")
|
||||||
|
var errt MissingOptionError
|
||||||
|
assert.IsType(err, errt, "Expected missing option error")
|
||||||
|
assert.Equal(err.Error(), fmt.Sprintf("%s: expected argument for -x",
|
||||||
|
os.Args[0]), "Expected POSIX-compatible error message")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExpectedMissingOption(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
opts, _, err := Getopts([]string{"test_bin", "-x"}, ":x:")
|
||||||
|
assert.Nil(err, "Expected err to be nil")
|
||||||
|
assert.Equal(len(opts), 1, "Expected 1 option to be parsed")
|
||||||
|
assert.Equal(opts[0], Option{':', "x"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoOption(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
_, i, _ := Getopts([]string{"test_bin"}, "")
|
||||||
|
assert.Equal(i, 1, "Expected non-option args to start at index 1")
|
||||||
|
}
|
||||||
3
getopt/go.mod
Normal file
3
getopt/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module git.sr.ht/~sircmpwn/getopt
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.3.0
|
||||||
7
getopt/go.sum
Normal file
7
getopt/go.sum
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
61
getopt/int.go
Normal file
61
getopt/int.go
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type intVal int
|
||||||
|
|
||||||
|
func (i *intVal) String() string {
|
||||||
|
return fmt.Sprint(*i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *intVal) Set(val string) error {
|
||||||
|
_, err := fmt.Sscanf(val, "%d", i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntVar defines a int flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a int variable in
|
||||||
|
// which to store the value of the flag.
|
||||||
|
func (set *FlagSet) IntVar(p *int, name string, value int, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*intVal)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int defines an int flag with specified name, default value, and usage
|
||||||
|
// string. The return value is the address of an int variable that
|
||||||
|
// stores the value of the flag.
|
||||||
|
func (set *FlagSet) Int(name string, value int, usage string) *int {
|
||||||
|
p := new(int)
|
||||||
|
set.IntVar(p, name, value, usage)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
type int64Val int64
|
||||||
|
|
||||||
|
func (i *int64Val) String() string {
|
||||||
|
return fmt.Sprint(int64(*i))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *int64Val) Set(val string) error {
|
||||||
|
_, err := fmt.Sscanf(val, "%d", i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Var defines an int64 flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to an int64 variable in which
|
||||||
|
// to store the value of the flag.
|
||||||
|
func (set *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*int64Val)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 defines an int64 flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of an int64 variable
|
||||||
|
// that stores the value of the flag.
|
||||||
|
func (set *FlagSet) Int64(name string, value int64, usage string) *int64 {
|
||||||
|
var i int64
|
||||||
|
set.Int64Var(&i, name, value, usage)
|
||||||
|
return &i
|
||||||
|
}
|
||||||
29
getopt/string.go
Normal file
29
getopt/string.go
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
type stringVal string
|
||||||
|
|
||||||
|
func (s *stringVal) String() string {
|
||||||
|
return string(*s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringVal) Set(val string) error {
|
||||||
|
*s = stringVal(val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringVar defines a string flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a string variable in which
|
||||||
|
// to store the value of the flag.
|
||||||
|
func (set *FlagSet) StringVar(p *string, name string, value string, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*stringVal)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a string flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a string variable
|
||||||
|
// that stores the value of the flag.
|
||||||
|
func (set *FlagSet) String(name string, value string, usage string) *string {
|
||||||
|
var s string
|
||||||
|
set.StringVar(&s, name, value, usage)
|
||||||
|
return &s
|
||||||
|
}
|
||||||
73
getopt/uint.go
Normal file
73
getopt/uint.go
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
package getopt
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type uintVal uint
|
||||||
|
|
||||||
|
func (i *uintVal) String() string {
|
||||||
|
return fmt.Sprint(uint(*i))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *uintVal) Set(val string) error {
|
||||||
|
_, err := fmt.Sscanf(val, "%d", i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintVar defines a uint flag with specified name, default value, and
|
||||||
|
// usage string. The argument p points to a uint variable in which to
|
||||||
|
// store the value of the flag.
|
||||||
|
func (set *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*uintVal)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintVar defines a uint flag with specified name, default value, and
|
||||||
|
// usage string. The argument p points to a uint variable in which to
|
||||||
|
// store the value of the flag.
|
||||||
|
func UintVar(p *uint, name string, value uint, usage string) {
|
||||||
|
CommandLine.UintVar(p, name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint defines a uint flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a uint variable that
|
||||||
|
// stores the value of the flag.
|
||||||
|
func (set *FlagSet) Uint(name string, value uint, usage string) *uint {
|
||||||
|
var b uint
|
||||||
|
set.UintVar(&b, name, value, usage)
|
||||||
|
return &b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint defines a uint flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a uint variable that
|
||||||
|
// stores the value of the flag.
|
||||||
|
func Uint(name string, value uint, usage string) *uint {
|
||||||
|
return CommandLine.Uint(name, value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
type uint64Val uint64
|
||||||
|
|
||||||
|
func (i *uint64Val) String() string {
|
||||||
|
return fmt.Sprint(uint64(*i))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *uint64Val) Set(val string) error {
|
||||||
|
_, err := fmt.Sscanf(val, "%d", i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64Var defines a uint64 flag with specified name, default value,
|
||||||
|
// and usage string. The argument p points to a uint64 variable in which
|
||||||
|
// to store the value of the flag.
|
||||||
|
func (set *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
|
||||||
|
*p = value
|
||||||
|
set.Var((*uint64Val)(p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 defines a uint64 flag with specified name, default value, and
|
||||||
|
// usage string. The return value is the address of a uint64 variable
|
||||||
|
// that stores the value of the flag.
|
||||||
|
func (set *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
|
||||||
|
var b uint64
|
||||||
|
set.Uint64Var(&b, name, value, usage)
|
||||||
|
return &b
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
|
|
@ -1,5 +1,3 @@
|
||||||
module git.baxters.nz/jeremy/cli
|
module git.baxters.nz/jeremy/cli
|
||||||
|
|
||||||
go 1.26.1
|
go 1.26.1
|
||||||
|
|
||||||
require git.sr.ht/~sircmpwn/getopt v1.0.0
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue