Updated all vendor packages
parent
7a49268205
commit
9a71d8b3e4
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2017 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* 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.
|
||||
* Neither the name of Google, nor the names of other
|
||||
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
|
||||
OWNER 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.
|
@ -0,0 +1,36 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
// Bool creates a flag option that is a bool. Bools normally do not take a
|
||||
// value however one can be assigned by using the long form of the option:
|
||||
//
|
||||
// --option=true
|
||||
// --o=false
|
||||
//
|
||||
// The value is case insensitive and one of true, false, t, f, on, off, t and 0.
|
||||
func Bool(name rune, helpvalue ...string) *bool {
|
||||
var b bool
|
||||
CommandLine.Flag(&b, name, helpvalue...)
|
||||
return &b
|
||||
}
|
||||
|
||||
func BoolLong(name string, short rune, helpvalue ...string) *bool {
|
||||
var p bool
|
||||
CommandLine.FlagLong(&p, name, short, helpvalue...)
|
||||
return &p
|
||||
}
|
||||
|
||||
func (s *Set) Bool(name rune, helpvalue ...string) *bool {
|
||||
var b bool
|
||||
s.Flag(&b, name, helpvalue...)
|
||||
return &b
|
||||
}
|
||||
|
||||
func (s *Set) BoolLong(name string, short rune, helpvalue ...string) *bool {
|
||||
var p bool
|
||||
s.FlagLong(&p, name, short, helpvalue...)
|
||||
return &p
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type counterValue int
|
||||
|
||||
func (b *counterValue) Set(value string, opt Option) error {
|
||||
if value == "" {
|
||||
*b++
|
||||
} else {
|
||||
v, err := strconv.ParseInt(value, 0, strconv.IntSize)
|
||||
if err != nil {
|
||||
if e, ok := err.(*strconv.NumError); ok {
|
||||
switch e.Err {
|
||||
case strconv.ErrRange:
|
||||
err = fmt.Errorf("value out of range: %s", value)
|
||||
case strconv.ErrSyntax:
|
||||
err = fmt.Errorf("not a valid number: %s", value)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
*b = counterValue(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *counterValue) String() string {
|
||||
return strconv.Itoa(int(*b))
|
||||
}
|
||||
|
||||
// Counter creates a counting flag stored as an int. Each time the option
|
||||
// is seen while parsing the value is incremented. The value of the counter
|
||||
// may be explicitly set by using the long form:
|
||||
//
|
||||
// --counter=5
|
||||
// --c=5
|
||||
//
|
||||
// Further instances of the option will increment from the set value.
|
||||
func Counter(name rune, helpvalue ...string) *int {
|
||||
var p int
|
||||
CommandLine.FlagLong((*counterValue)(&p), "", name, helpvalue...).SetFlag()
|
||||
return &p
|
||||
}
|
||||
|
||||
func (s *Set) Counter(name rune, helpvalue ...string) *int {
|
||||
var p int
|
||||
s.FlagLong((*counterValue)(&p), "", name, helpvalue...).SetFlag()
|
||||
return &p
|
||||
}
|
||||
|
||||
func CounterLong(name string, short rune, helpvalue ...string) *int {
|
||||
var p int
|
||||
CommandLine.FlagLong((*counterValue)(&p), name, short, helpvalue...).SetFlag()
|
||||
return &p
|
||||
}
|
||||
|
||||
func (s *Set) CounterLong(name string, short rune, helpvalue ...string) *int {
|
||||
var p int
|
||||
s.FlagLong((*counterValue)(&p), name, short, helpvalue...).SetFlag()
|
||||
return &p
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import "time"
|
||||
|
||||
// Duration creates an option that parses its value as a time.Duration.
|
||||
func Duration(name rune, value time.Duration, helpvalue ...string) *time.Duration {
|
||||
CommandLine.FlagLong(&value, "", name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) Duration(name rune, value time.Duration, helpvalue ...string) *time.Duration {
|
||||
s.FlagLong(&value, "", name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func DurationLong(name string, short rune, value time.Duration, helpvalue ...string) *time.Duration {
|
||||
CommandLine.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) DurationLong(name string, short rune, value time.Duration, helpvalue ...string) *time.Duration {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type enumValue string
|
||||
|
||||
var (
|
||||
enumValuesMu sync.Mutex
|
||||
enumValues = make(map[*enumValue]map[string]struct{})
|
||||
)
|
||||
|
||||
func (s *enumValue) Set(value string, opt Option) error {
|
||||
enumValuesMu.Lock()
|
||||
es, ok := enumValues[s]
|
||||
enumValuesMu.Unlock()
|
||||
if !ok || es == nil {
|
||||
return errors.New("this option has no values")
|
||||
}
|
||||
if _, ok := es[value]; !ok {
|
||||
return errors.New("invalid value: " + value)
|
||||
}
|
||||
*s = enumValue(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *enumValue) String() string {
|
||||
return string(*s)
|
||||
}
|
||||
|
||||
// Enum creates an option that can only be set to one of the enumerated strings
|
||||
// passed in values. Passing nil or an empty slice results in an option that
|
||||
// will always fail. If not "", value is the default value of the enum. If
|
||||
// value is not listed in values then Enum will produce an error on standard
|
||||
// error and then exit the program with a status of 1.
|
||||
func Enum(name rune, values []string, value string, helpvalue ...string) *string {
|
||||
return CommandLine.Enum(name, values, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Enum(name rune, values []string, value string, helpvalue ...string) *string {
|
||||
var p enumValue
|
||||
p.define(values, value, &option{short: name})
|
||||
s.FlagLong(&p, "", name, helpvalue...)
|
||||
return (*string)(&p)
|
||||
}
|
||||
|
||||
func EnumLong(name string, short rune, values []string, value string, helpvalue ...string) *string {
|
||||
return CommandLine.EnumLong(name, short, values, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) EnumLong(name string, short rune, values []string, value string, helpvalue ...string) *string {
|
||||
var p enumValue
|
||||
p.define(values, value, &option{short: short, long: name})
|
||||
s.FlagLong(&p, name, short, helpvalue...)
|
||||
return (*string)(&p)
|
||||
}
|
||||
|
||||
func (e *enumValue) define(values []string, def string, opt Option) {
|
||||
m := make(map[string]struct{})
|
||||
for _, v := range values {
|
||||
m[v] = struct{}{}
|
||||
}
|
||||
enumValuesMu.Lock()
|
||||
enumValues[e] = m
|
||||
enumValuesMu.Unlock()
|
||||
if def != "" {
|
||||
if err := e.Set(def, nil); err != nil {
|
||||
fmt.Fprintf(stderr, "setting default for %s: %v\n", opt.Name(), err)
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import "fmt"
|
||||
|
||||
// An Error is returned by Getopt when it encounters an error.
|
||||
type Error struct {
|
||||
ErrorCode // General reason of failure.
|
||||
Err error // The actual error.
|
||||
Parameter string // Parameter passed to option, if any
|
||||
Name string // Option that cause error, if any
|
||||
}
|
||||
|
||||
// Error returns the error message, implementing the error interface.
|
||||
func (i *Error) Error() string { return i.Err.Error() }
|
||||
|
||||
// An ErrorCode indicates what sort of error was encountered.
|
||||
type ErrorCode int
|
||||
|
||||
const (
|
||||
NoError = ErrorCode(iota)
|
||||
UnknownOption // an invalid option was encountered
|
||||
MissingParameter // the options parameter is missing
|
||||
ExtraParameter // a value was set to a long flag
|
||||
Invalid // attempt to set an invalid value
|
||||
)
|
||||
|
||||
func (e ErrorCode) String() string {
|
||||
switch e {
|
||||
case UnknownOption:
|
||||
return "unknow option"
|
||||
case MissingParameter:
|
||||
return "missing argument"
|
||||
case ExtraParameter:
|
||||
return "unxpected value"
|
||||
case Invalid:
|
||||
return "error setting value"
|
||||
}
|
||||
return "unknown error"
|
||||
}
|
||||
|
||||
// unknownOption returns an Error indicating an unknown option was
|
||||
// encountered.
|
||||
func unknownOption(name interface{}) *Error {
|
||||
i := &Error{ErrorCode: UnknownOption}
|
||||
switch n := name.(type) {
|
||||
case rune:
|
||||
if n == '-' {
|
||||
i.Name = "-"
|
||||
} else {
|
||||
i.Name = "-" + string(n)
|
||||
}
|
||||
case string:
|
||||
i.Name = "--" + n
|
||||
}
|
||||
i.Err = fmt.Errorf("unknown option: %s", i.Name)
|
||||
return i
|
||||
}
|
||||
|
||||
// missingArg returns an Error inidicating option o was not passed
|
||||
// a required paramter.
|
||||
func missingArg(o Option) *Error {
|
||||
return &Error{
|
||||
ErrorCode: MissingParameter,
|
||||
Name: o.Name(),
|
||||
Err: fmt.Errorf("missing parameter for %s", o.Name()),
|
||||
}
|
||||
}
|
||||
|
||||
// extraArg returns an Error inidicating option o was passed the
|
||||
// unexpected paramter value.
|
||||
func extraArg(o Option, value string) *Error {
|
||||
return &Error{
|
||||
ErrorCode: ExtraParameter,
|
||||
Name: o.Name(),
|
||||
Parameter: value,
|
||||
Err: fmt.Errorf("unexpected parameter passed to %s: %q", o.Name(), value),
|
||||
}
|
||||
}
|
||||
|
||||
// setError returns an Error inidicating option o and the specified
|
||||
// error while setting it to value.
|
||||
func setError(o Option, value string, err error) *Error {
|
||||
return &Error{
|
||||
ErrorCode: Invalid,
|
||||
Name: o.Name(),
|
||||
Parameter: value,
|
||||
Err: err,
|
||||
}
|
||||
}
|
@ -0,0 +1,238 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type generic struct {
|
||||
p interface{}
|
||||
}
|
||||
|
||||
// Flag is shorthand for CommandLine.Flag.
|
||||
func Flag(v interface{}, short rune, helpvalue ...string) Option {
|
||||
return CommandLine.long(v, "", short, helpvalue...)
|
||||
}
|
||||
|
||||
// FlagLong is shorthand for CommandLine.LongFlag.
|
||||
func FlagLong(v interface{}, long string, short rune, helpvalue ...string) Option {
|
||||
return CommandLine.long(v, long, short, helpvalue...)
|
||||
}
|
||||
|
||||
// Flag calls FlagLong with only a short flag name.
|
||||
func (s *Set) Flag(v interface{}, short rune, helpvalue ...string) Option {
|
||||
return s.long(v, "", short, helpvalue...)
|
||||
}
|
||||
|
||||
// FlagLong returns an Option in Set s for setting v. If long is not "" then
|
||||
// the option has a long name, and if short is not 0, the option has a short
|
||||
// name. v must either be of type getopt.Value or a pointer to one of the
|
||||
// supported builtin types:
|
||||
//
|
||||
// bool, string, []string
|
||||
// int, int8, int16, int32, int64
|
||||
// uint, uint8, uint16, uint32, uint64
|
||||
// float32, float64
|
||||
// time.Duration
|
||||
//
|
||||
// FlagLong will panic if v is not a getopt.Value or one of the supported
|
||||
// builtin types.
|
||||
//
|
||||
// The default value of the flag is the value of v at the time FlagLong is
|
||||
// called.
|
||||
func (s *Set) FlagLong(v interface{}, long string, short rune, helpvalue ...string) Option {
|
||||
return s.long(v, long, short, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) long(v interface{}, long string, short rune, helpvalue ...string) (opt Option) {
|
||||
// Fix up our location when we return.
|
||||
if where := calledFrom(); where != "" {
|
||||
defer func() {
|
||||
if opt, ok := opt.(*option); ok {
|
||||
opt.where = where
|
||||
}
|
||||
}()
|
||||
}
|
||||
switch p := v.(type) {
|
||||
case Value:
|
||||
return s.addFlag(p, long, short, helpvalue...)
|
||||
case *bool:
|
||||
return s.addFlag(&generic{v}, long, short, helpvalue...).SetFlag()
|
||||
case *string, *[]string:
|
||||
return s.addFlag(&generic{v}, long, short, helpvalue...)
|
||||
case *int, *int8, *int16, *int32, *int64:
|
||||
return s.addFlag(&generic{v}, long, short, helpvalue...)
|
||||
case *uint, *uint8, *uint16, *uint32, *uint64:
|
||||
return s.addFlag(&generic{v}, long, short, helpvalue...)
|
||||
case *float32, *float64:
|
||||
return s.addFlag(&generic{v}, long, short, helpvalue...)
|
||||
case *time.Duration:
|
||||
return s.addFlag(&generic{v}, long, short, helpvalue...)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported flag type: %T", v))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generic) Set(value string, opt Option) error {
|
||||
strconvErr := func(err error) error {
|
||||
if e, ok := err.(*strconv.NumError); ok {
|
||||
switch e.Err {
|
||||
case strconv.ErrRange:
|
||||
err = fmt.Errorf("value out of range: %s", value)
|
||||
case strconv.ErrSyntax:
|
||||
err = fmt.Errorf("not a valid number: %s", value)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
switch p := g.p.(type) {
|
||||
case *bool:
|
||||
switch strings.ToLower(value) {
|
||||
case "", "1", "true", "on", "t":
|
||||
*p = true
|
||||
case "0", "false", "off", "f":
|
||||
*p = false
|
||||
default:
|
||||
return fmt.Errorf("invalid value for bool %s: %q", opt.Name(), value)
|
||||
}
|
||||
return nil
|
||||
case *string:
|
||||
*p = value
|
||||
return nil
|
||||
case *[]string:
|
||||
a := strings.Split(value, ",")
|
||||
// If this is the first time we are seen then nil out the
|
||||
// default value.
|
||||
if opt.Count() <= 1 {
|
||||
*p = nil
|
||||
}
|
||||
*p = append(*p, a...)
|
||||
return nil
|
||||
case *int:
|
||||
i64, err := strconv.ParseInt(value, 0, strconv.IntSize)
|
||||
if err == nil {
|
||||
*p = int(i64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *int8:
|
||||
i64, err := strconv.ParseInt(value, 0, 8)
|
||||
if err == nil {
|
||||
*p = int8(i64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *int16:
|
||||
i64, err := strconv.ParseInt(value, 0, 16)
|
||||
if err == nil {
|
||||
*p = int16(i64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *int32:
|
||||
i64, err := strconv.ParseInt(value, 0, 32)
|
||||
if err == nil {
|
||||
*p = int32(i64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *int64:
|
||||
i64, err := strconv.ParseInt(value, 0, 64)
|
||||
if err == nil {
|
||||
*p = i64
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *uint:
|
||||
u64, err := strconv.ParseUint(value, 0, strconv.IntSize)
|
||||
if err == nil {
|
||||
*p = uint(u64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *uint8:
|
||||
u64, err := strconv.ParseUint(value, 0, 8)
|
||||
if err == nil {
|
||||
*p = uint8(u64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *uint16:
|
||||
u64, err := strconv.ParseUint(value, 0, 16)
|
||||
if err == nil {
|
||||
*p = uint16(u64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *uint32:
|
||||
u64, err := strconv.ParseUint(value, 0, 32)
|
||||
if err == nil {
|
||||
*p = uint32(u64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *uint64:
|
||||
u64, err := strconv.ParseUint(value, 0, 64)
|
||||
if err == nil {
|
||||
*p = u64
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *float32:
|
||||
f64, err := strconv.ParseFloat(value, 32)
|
||||
if err == nil {
|
||||
*p = float32(f64)
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *float64:
|
||||
f64, err := strconv.ParseFloat(value, 64)
|
||||
if err == nil {
|
||||
*p = f64
|
||||
}
|
||||
return strconvErr(err)
|
||||
case *time.Duration:
|
||||
v, err := time.ParseDuration(value)
|
||||
if err == nil {
|
||||
*p = v
|
||||
}
|
||||
return err
|
||||
}
|
||||
panic("internal error")
|
||||
}
|
||||
|
||||
func (g *generic) String() string {
|
||||
switch p := g.p.(type) {
|
||||
case *bool:
|
||||
if *p {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
case *string:
|
||||
return *p
|
||||
case *[]string:
|
||||
return strings.Join([]string(*p), ",")
|
||||
case *int:
|
||||
return strconv.FormatInt(int64(*p), 10)
|
||||
case *int8:
|
||||
return strconv.FormatInt(int64(*p), 10)
|
||||
case *int16:
|
||||
return strconv.FormatInt(int64(*p), 10)
|
||||
case *int32:
|
||||
return strconv.FormatInt(int64(*p), 10)
|
||||
case *int64:
|
||||
return strconv.FormatInt(*p, 10)
|
||||
case *uint:
|
||||
return strconv.FormatUint(uint64(*p), 10)
|
||||
case *uint8:
|
||||
return strconv.FormatUint(uint64(*p), 10)
|
||||
case *uint16:
|
||||
return strconv.FormatUint(uint64(*p), 10)
|
||||
case *uint32:
|
||||
return strconv.FormatUint(uint64(*p), 10)
|
||||
case *uint64:
|
||||
return strconv.FormatUint(*p, 10)
|
||||
case *float32:
|
||||
return strconv.FormatFloat(float64(*p), 'g', -1, 32)
|
||||
case *float64:
|
||||
return strconv.FormatFloat(*p, 'g', -1, 64)
|
||||
case *time.Duration:
|
||||
return p.String()
|
||||
}
|
||||
panic("internal error")
|
||||
}
|
@ -0,0 +1,534 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package getopt (v2) provides traditional getopt processing for implementing
|
||||
// commands that use traditional command lines. The standard Go flag package
|
||||
// cannot be used to write a program that parses flags the way ls or ssh does,
|
||||
// for example. Version 2 of this package has a simplified API.
|
||||
//
|
||||
// See the github.com/pborman/options package for a simple structure based
|
||||
// interface to this package.
|
||||
//
|
||||
// USAGE
|
||||
//
|
||||
// Getopt supports functionality found in both the standard BSD getopt as well
|
||||
// as (one of the many versions of) the GNU getopt_long. Being a Go package,
|
||||
// this package makes common usage easy, but still enables more controlled usage
|
||||
// if needed.
|
||||
//
|
||||
// Typical usage:
|
||||
//
|
||||
// // Declare flags and have getopt return pointers to the values.
|
||||
// helpFlag := getopt.Bool('?', "display help")
|
||||
// cmdFlag := getopt.StringLong("command", 'c', "default", "the command")
|
||||
//
|
||||
// // Declare flags against existing variables.
|
||||
// var {
|
||||
// fileName = "/the/default/path"
|
||||
// timeout = time.Second * 5
|
||||
// verbose bool
|
||||
// }
|
||||
// func init() {
|
||||
// getopt.Flag(&verbose, 'v', "be verbose")
|
||||
// getopt.FlagLong(&fileName, "path", 0, "the path")
|
||||
// getopt.FlagLong(&timeout, "timeout", 't', "some timeout")
|
||||
// }
|
||||
//
|
||||
// func main() {
|
||||
// // Parse the program arguments
|
||||
// getopt.Parse()
|
||||
// // Get the remaining positional parameters
|
||||
// args := getopt.Args()
|
||||
// ...
|
||||
//
|
||||
// If you don't want the program to exit on error, use getopt.Getopt:
|
||||
//
|
||||
// err := getopt.Getopt(nil)
|
||||
// if err != nil {
|
||||
// // code to handle error
|
||||
// fmt.Fprintln(os.Stderr, err)
|
||||
// }
|
||||
//
|
||||
// FLAG SYNTAX
|
||||
//
|
||||
// Support is provided for both short (-f) and long (--flag) options. A single
|
||||
// option may have both a short and a long name. Each option may be a flag or a
|
||||
// value. A value takes an argument.
|
||||
//
|
||||
// Declaring no long names causes this package to process arguments like the
|
||||
// traditional BSD getopt.
|
||||
//
|
||||
// Short flags may be combined into a single parameter. For example, "-a -b -c"
|
||||
// may also be expressed "-abc". Long flags must stand on their own "--alpha
|
||||
// --beta"
|
||||
//
|
||||
// Values require an argument. For short options the argument may either be
|
||||
// immediately following the short name or as the next argument. Only one short
|
||||
// value may be combined with short flags in a single argument; the short value
|
||||
// must be after all short flags. For example, if f is a flag and v is a value,
|
||||
// then:
|
||||
//
|
||||
// -vvalue (sets v to "value")
|
||||
// -v value (sets v to "value")
|
||||
// -fvvalue (sets f, and sets v to "value")
|
||||
// -fv value (sets f, and sets v to "value")
|
||||
// -vf value (set v to "f" and value is the first parameter)
|
||||
//
|
||||
// For the long value option val:
|
||||
//
|
||||
// --val value (sets val to "value")
|
||||
// --val=value (sets val to "value")
|
||||
// --valvalue (invalid option "valvalue")
|
||||
//
|
||||
// Values with an optional value only set the value if the value is part of the
|
||||
// same argument. In any event, the option count is increased and the option is
|
||||
// marked as seen.
|
||||
//
|
||||
// -v -f (sets v and f as being seen)
|
||||
// -vvalue -f (sets v to "value" and sets f)
|
||||
// --val -f (sets v and f as being seen)
|
||||
// --val=value -f (sets v to "value" and sets f)
|
||||
//
|
||||
// There is no convenience function defined for making the value optional. The
|
||||
// SetOptional method must be called on the actual Option.
|
||||
//
|
||||
// v := String("val", 'v', "", "the optional v")
|
||||
// Lookup("v").SetOptional()
|
||||
//
|
||||
// var s string
|
||||
// FlagLong(&s, "val", 'v', "the optional v).SetOptional()
|
||||
//
|
||||
// Parsing continues until the first non-option or "--" is encountered.
|
||||
//
|
||||
// The short name "-" can be used, but it either is specified as "-" or as part
|
||||
// of a group of options, for example "-f-". If there are no long options
|
||||
// specified then "--f" could also be used. If "-" is not declared as an option
|
||||
// then the single "-" will also terminate the option processing but unlike
|
||||
// "--", the "-" will be part of the remaining arguments.
|
||||
//
|
||||
// ADVANCED USAGE
|
||||
//
|
||||
// Normally the parsing is performed by calling the Parse function. If it is
|
||||
// important to see the order of the options then the Getopt function should be
|
||||
// used. The standard Parse function does the equivalent of:
|
||||
//
|
||||
// func Parse() {
|
||||
// if err := getopt.Getopt(os.Args, nil); err != nil {
|
||||
// fmt.Fprintln(os.Stderr, err)
|
||||
// s.usage()
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//
|
||||
// When calling Getopt it is the responsibility of the caller to print any
|
||||
// errors.
|
||||
//
|
||||
// Normally the default option set, CommandLine, is used. Other option sets may
|
||||
// be created with New.
|
||||
//
|
||||
// After parsing, the sets Args will contain the non-option arguments. If an
|
||||
// error is encountered then Args will begin with argument that caused the
|
||||
// error.
|
||||
//
|
||||
// It is valid to call a set's Parse a second time to amen flags or values. As
|
||||
// an example:
|
||||
//
|
||||
// var a = getopt.Bool('a', "", "The a flag")
|
||||
// var b = getopt.Bool('b', "", "The a flag")
|
||||
// var cmd = ""
|
||||
//
|
||||
// var opts = getopt.CommandLine
|
||||
//
|
||||
// opts.Parse(os.Args)
|
||||
// if opts.NArgs() > 0 {
|
||||
// cmd = opts.Arg(0)
|
||||
// opts.Parse(opts.Args())
|
||||
// }
|
||||
//
|
||||
// If called with set to { "prog", "-a", "cmd", "-b", "arg" } then both and and
|
||||
// b would be set, cmd would be set to "cmd", and opts.Args() would return {
|
||||
// "arg" }.
|
||||
//
|
||||
// Unless an option type explicitly prohibits it, an option may appear more than
|
||||
// once in the arguments. The last value provided to the option is the value.
|
||||
//
|
||||
// BUILTIN TYPES
|
||||
//
|
||||
// The Flag and FlagLong functions support most standard Go types. For the
|
||||
// list, see the description of FlagLong below for a list of supported types.
|
||||
//
|
||||
// There are also helper routines to allow single line flag declarations. These
|
||||
// types are: Bool, Counter, Duration, Enum, Int16, Int32, Int64, Int, List,
|
||||
// Signed, String, Uint16, Uint32, Uint64, Uint, and Unsigned.
|
||||
//
|
||||
// Each comes in a short and long flavor, e.g., Bool and BoolLong and include
|
||||
// functions to set the flags on the standard command line or for a specific Set
|
||||
// of flags.
|
||||
//
|
||||
// Except for the Counter, Enum, Signed and Unsigned types, all of these types
|
||||
// can be declared using Flag and FlagLong by passing in a pointer to the
|
||||
// appropriate type.
|
||||
//
|
||||
// DECLARING NEW FLAG TYPES
|
||||
//
|
||||
// A pointer to any type that implements the Value interface may be passed to
|
||||
// Flag or FlagLong.
|
||||
//
|
||||
// VALUEHELP
|
||||
//
|
||||
// All non-flag options are created with a "valuehelp" as the last parameter.
|
||||
// Valuehelp should be 0, 1, or 2 strings. The first string, if provided, is
|
||||
// the usage message for the option. If the second string, if provided, is the
|
||||
// name to use for the value when displaying the usage. If not provided the
|
||||
// term "value" is assumed.
|
||||
//
|
||||
// The usage message for the option created with
|
||||
//
|
||||
// StringLong("option", 'o', "defval", "a string of letters")
|
||||
//
|
||||
// is
|
||||
//
|
||||
// -o, -option=value
|
||||
//
|
||||
// StringLong("option", 'o', "defval", "a string of letters", "string")
|
||||
//
|
||||
// is
|
||||
//
|
||||
// -o, -option=string
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// stderr allows tests to capture output to standard error.
|
||||
var stderr io.Writer = os.Stderr
|
||||
|
||||
// exit allows tests to capture an os.Exit call
|
||||
var exit = os.Exit
|
||||
|
||||
// DisplayWidth is used to determine where to split usage long lines.
|
||||
var DisplayWidth = 80
|
||||
|
||||
// HelpColumn is the maximum column position that help strings start to display
|
||||
// at. If the option usage is too long then the help string will be displayed
|
||||
// on the next line. For example:
|
||||
//
|
||||
// -a this is the a flag
|
||||
// -u, --under=location
|
||||
// the u flag's usage is quite long
|
||||
var HelpColumn = 20
|
||||
|
||||
// PrintUsage prints the usage line and set of options of set S to w.
|
||||
func (s *Set) PrintUsage(w io.Writer) {
|
||||
parts := make([]string, 2, 4)
|
||||
parts[0] = "Usage:"
|
||||
parts[1] = s.program
|
||||
if usage := s.UsageLine(); usage != "" {
|
||||
parts = append(parts, usage)
|
||||
}
|
||||
if s.parameters != "" {
|
||||
parts = append(parts, s.parameters)
|
||||
}
|
||||
fmt.Fprintln(w, strings.Join(parts, " "))
|
||||
s.PrintOptions(w)
|
||||
}
|
||||
|
||||
// UsageLine returns the usage line for the set s. The set's program name and
|
||||
// parameters, if any, are not included.
|
||||
func (s *Set) UsageLine() string {
|
||||
sort.Sort(s.options)
|
||||
flags := ""
|
||||
|
||||
// Build up the list of short flag names and also compute
|
||||
// how to display the option in the longer help listing.
|
||||
// We also keep track of the longest option usage string
|
||||
// that is no more than HelpColumn-3 bytes (at which point
|
||||
// we use two lines to display the help). The three
|
||||
// is for the leading space and the two spaces before the
|
||||
// help string.
|
||||
for _, opt := range s.options {
|
||||
if opt.name == "" {
|
||||
opt.name = "value"
|
||||
}
|
||||
if opt.uname == "" {
|
||||
opt.uname = opt.usageName()
|
||||
}
|
||||
if opt.flag && opt.short != 0 && opt.short != '-' {
|
||||
flags += string(opt.short)
|
||||
}
|
||||
}
|
||||
|
||||
var opts []string
|
||||
|
||||
// The short option - is special
|
||||
if s.shortOptions['-'] != nil {
|
||||
opts = append(opts, "-")
|
||||
}
|
||||
|
||||
// If we have a bundle of flags, add them to the list
|
||||
if flags != "" {
|
||||
opts = append(opts, "-"+flags)
|
||||
}
|
||||
|
||||
// Now append all the long options and options that require
|
||||
// values.
|
||||
for _, opt := range s.options {
|
||||
if opt.flag {
|
||||
if opt.short != 0 {
|
||||
continue
|
||||
}
|
||||
flags = "--" + opt.long
|
||||
} else if opt.short != 0 {
|
||||
flags = "-" + string(opt.short) + " " + opt.name
|
||||
} else {
|
||||
flags = "--" + string(opt.long) + " " + opt.name
|
||||
}
|
||||
opts = append(opts, flags)
|
||||
}
|
||||
flags = strings.Join(opts, "] [")
|
||||
if flags != "" {
|
||||
flags = "[" + flags + "]"
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
// PrintOptions prints the list of options in s to w.
|
||||
func (s *Set) PrintOptions(w io.Writer) {
|
||||
sort.Sort(s.options)
|
||||
max := 4
|
||||
for _, opt := range s.options {
|
||||
if opt.name == "" {
|
||||
opt.name = "value"
|
||||
}
|
||||
if opt.uname == "" {
|
||||
opt.uname = opt.usageName()
|
||||
}
|
||||
if max < len(opt.uname) && len(opt.uname) <= HelpColumn-3 {
|
||||
max = len(opt.uname)
|
||||
}
|
||||
}
|
||||
// Now print one or more usage lines per option.
|
||||
for _, opt := range s.options {
|
||||
if opt.uname != "" {
|
||||
opt.help = strings.TrimSpace(opt.help)
|
||||
if len(opt.help) == 0 {
|
||||
fmt.Fprintf(w, " %s\n", opt.uname)
|
||||
continue
|
||||
}
|
||||
help := strings.Split(opt.help, "\n")
|
||||
// If they did not put in newlines then we will insert
|
||||
// them to keep the help messages from wrapping.
|
||||
if len(help) == 1 {
|
||||
help = breakup(help[0], DisplayWidth-HelpColumn)
|
||||
}
|
||||
if len(opt.uname) <= max {
|
||||
fmt.Fprintf(w, " %-*s %s\n", max, opt.uname, help[0])
|
||||
help = help[1:]
|
||||
} else {
|
||||
fmt.Fprintf(w, " %s\n", opt.uname)
|
||||
}
|
||||
for _, s := range help {
|
||||
fmt.Fprintf(w, " %-*s %s\n", max, " ", s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// breakup breaks s up into strings no longer than max bytes.
|
||||
func breakup(s string, max int) []string {
|
||||
var a []string
|
||||
|
||||
for {
|
||||
// strip leading spaces
|
||||
for len(s) > 0 && s[0] == ' ' {
|
||||
s = s[1:]
|
||||
}
|
||||
// If the option is no longer than the max just return it
|
||||
if len(s) <= max {
|
||||
if len(s) != 0 {
|
||||
a = append(a, s)
|
||||
}
|
||||
return a
|
||||
}
|
||||
x := max
|
||||
for s[x] != ' ' {
|
||||
// the first word is too long?!
|
||||
if x == 0 {
|
||||
x = max
|
||||
for x < len(s) && s[x] != ' ' {
|
||||
x++
|
||||
}
|
||||
if x == len(s) {
|
||||
x--
|
||||
}
|
||||
break
|
||||
}
|
||||
x--
|
||||
}
|
||||
for s[x] == ' ' {
|
||||
x--
|
||||
}
|
||||
a = append(a, s[:x+1])
|
||||
s = s[x+1:]
|
||||
}
|
||||
}
|
||||
|
||||
// Parse uses Getopt to parse args using the options set for s. The first
|
||||
// element of args is used to assign the program for s if it is not yet set. On
|
||||
// error, Parse displays the error message as well as a usage message on
|
||||
// standard error and then exits the program.
|
||||
func (s *Set) Parse(args []string) {
|
||||
if err := s.Getopt(args, nil); err != nil {
|
||||
fmt.Fprintln(stderr, err)
|
||||
s.usage()
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse uses Getopt to parse args using the options set for s. The first
|
||||
// element of args is used to assign the program for s if it is not yet set.
|
||||
// Getop calls fn, if not nil, for each option parsed.
|
||||
//
|
||||
// Getopt returns nil when all options have been processed (a non-option
|
||||
// argument was encountered, "--" was encountered, or fn returned false).
|
||||
//
|
||||
// On error getopt returns a reference to an InvalidOption (which implements the
|
||||
// error interface).
|
||||
func (s *Set) Getopt(args []string, fn func(Option) bool) (err error) {
|
||||
s.setState(InProgress)
|
||||
defer func() {
|
||||
if s.State() == InProgress {
|
||||
switch {
|
||||
case err != nil:
|
||||
s.setState(Failure)
|
||||
case len(s.args) == 0:
|
||||
s.setState(EndOfArguments)
|
||||
default:
|
||||
s.setState(Unknown)
|
||||
}
|
||||
}
|
||||
}()
|
||||
if fn == nil {
|
||||
fn = func(Option) bool { return true }
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.program == "" {
|
||||
s.program = path.Base(args[0])
|
||||
}
|
||||
args = args[1:]
|
||||
Parsing:
|
||||
for len(args) > 0 {
|
||||
arg := args[0]
|
||||
s.args = args
|
||||
args = args[1:]
|
||||
|
||||
// end of options?
|
||||
if arg == "" || arg[0] != '-' {
|
||||
s.setState(EndOfOptions)
|
||||
return nil
|
||||
}
|
||||
|
||||
if arg == "-" {
|
||||
goto ShortParsing
|
||||
}
|
||||
|
||||
// explicitly request end of options?
|
||||
if arg == "--" {
|
||||
s.args = args
|
||||
s.setState(DashDash)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Long option processing
|
||||
if len(s.longOptions) > 0 && arg[1] == '-' {
|
||||
e := strings.IndexRune(arg, '=')
|
||||
var value string
|
||||
if e > 0 {
|
||||
value = arg[e+1:]
|
||||
arg = arg[:e]
|
||||
}
|
||||
opt := s.longOptions[arg[2:]]
|
||||
// If we are processing long options then --f is -f
|
||||
// if f is not defined as a long option.
|
||||
// This lets you say --f=false
|
||||
if opt == nil && len(arg[2:]) == 1 {
|
||||
opt = s.shortOptions[rune(arg[2])]
|
||||
}
|
||||
if opt == nil {
|
||||
return unknownOption(arg[2:])
|
||||
}
|
||||
opt.isLong = true
|
||||
// If we require an option and did not have an =
|
||||
// then use the next argument as an option.
|
||||
if !opt.flag && e < 0 && !opt.optional {
|
||||
if len(args) == 0 {
|
||||
return missingArg(opt)
|
||||
}
|
||||
value = args[0]
|
||||
args = args[1:]
|
||||
}
|
||||
opt.count++
|
||||
|
||||
if err := opt.value.Set(value, opt); err != nil {
|
||||
return setError(opt, value, err)
|
||||
}
|
||||
|
||||
if !fn(opt) {
|
||||
s.setState(Terminated)
|
||||
return nil
|
||||
}
|
||||
continue Parsing
|
||||
}
|
||||
|
||||
// Short option processing
|
||||
arg = arg[1:] // strip -
|
||||
ShortParsing:
|
||||
for i, c := range arg {
|
||||
opt := s.shortOptions[c]
|
||||
if opt == nil {
|
||||
// In traditional getopt, if - is not registered
|
||||
// as an option, a lone - is treated as
|
||||
// if there were a -- in front of it.
|
||||
if arg == "-" {
|
||||
s.setState(Dash)
|
||||
return nil
|
||||
}
|
||||
return unknownOption(c)
|
||||
}
|
||||
opt.isLong = false
|
||||
opt.count++
|
||||
var value string
|
||||
if !opt.flag {
|
||||
value = arg[1+i:]
|
||||
if value == "" && !opt.optional {
|
||||
if len(args) == 0 {
|
||||
return missingArg(opt)
|
||||
}
|
||||
value = args[0]
|
||||
args = args[1:]
|
||||
}
|
||||
}
|
||||
if err := opt.value.Set(value, opt); err != nil {
|
||||
return setError(opt, value, err)
|
||||
}
|
||||
if !fn(opt) {
|
||||
s.setState(Terminated)
|
||||
return nil
|
||||
}
|
||||
if !opt.flag {
|
||||
continue Parsing
|
||||
}
|
||||
}
|
||||
}
|
||||
s.args = []string{}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
// Int creates an option that parses its value as an integer.
|
||||
func Int(name rune, value int, helpvalue ...string) *int {
|
||||
return CommandLine.Int(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int(name rune, value int, helpvalue ...string) *int {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func IntLong(name string, short rune, value int, helpvalue ...string) *int {
|
||||
return CommandLine.IntLong(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) IntLong(name string, short rune, value int, helpvalue ...string) *int {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Int16 creates an option that parses its value as a 16 bit integer.
|
||||
func Int16(name rune, value int16, helpvalue ...string) *int16 {
|
||||
return CommandLine.Int16(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int16(name rune, value int16, helpvalue ...string) *int16 {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func Int16Long(name string, short rune, value int16, helpvalue ...string) *int16 {
|
||||
return CommandLine.Int16Long(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int16Long(name string, short rune, value int16, helpvalue ...string) *int16 {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Int32 creates an option that parses its value as a 32 bit integer.
|
||||
func Int32(name rune, value int32, helpvalue ...string) *int32 {
|
||||
return CommandLine.Int32(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int32(name rune, value int32, helpvalue ...string) *int32 {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func Int32Long(name string, short rune, value int32, helpvalue ...string) *int32 {
|
||||
return CommandLine.Int32Long(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int32Long(name string, short rune, value int32, helpvalue ...string) *int32 {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Int64 creates an option that parses its value as a 64 bit integer.
|
||||
func Int64(name rune, value int64, helpvalue ...string) *int64 {
|
||||
return CommandLine.Int64(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int64(name rune, value int64, helpvalue ...string) *int64 {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func Int64Long(name string, short rune, value int64, helpvalue ...string) *int64 {
|
||||
return CommandLine.Int64Long(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Int64Long(name string, short rune, value int64, helpvalue ...string) *int64 {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Uint creates an option that parses its value as an unsigned integer.
|
||||
func Uint(name rune, value uint, helpvalue ...string) *uint {
|
||||
return CommandLine.Uint(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint(name rune, value uint, helpvalue ...string) *uint {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func UintLong(name string, short rune, value uint, helpvalue ...string) *uint {
|
||||
return CommandLine.UintLong(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) UintLong(name string, short rune, value uint, helpvalue ...string) *uint {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Uint16 creates an option that parses its value as a 16 bit unsigned integer.
|
||||
func Uint16(name rune, value uint16, helpvalue ...string) *uint16 {
|
||||
return CommandLine.Uint16(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint16(name rune, value uint16, helpvalue ...string) *uint16 {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func Uint16Long(name string, short rune, value uint16, helpvalue ...string) *uint16 {
|
||||
return CommandLine.Uint16Long(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint16Long(name string, short rune, value uint16, helpvalue ...string) *uint16 {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Uint32 creates an option that parses its value as a 32 bit unsigned integer.
|
||||
func Uint32(name rune, value uint32, helpvalue ...string) *uint32 {
|
||||
return CommandLine.Uint32(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint32(name rune, value uint32, helpvalue ...string) *uint32 {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func Uint32Long(name string, short rune, value uint32, helpvalue ...string) *uint32 {
|
||||
return CommandLine.Uint32Long(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint32Long(name string, short rune, value uint32, helpvalue ...string) *uint32 {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
// Uint64 creates an option that parses its value as a 64 bit unsigned integer.
|
||||
func Uint64(name rune, value uint64, helpvalue ...string) *uint64 {
|
||||
return CommandLine.Uint64(name, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint64(name rune, value uint64, helpvalue ...string) *uint64 {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func Uint64Long(name string, short rune, value uint64, helpvalue ...string) *uint64 {
|
||||
return CommandLine.Uint64Long(name, short, value, helpvalue...)
|
||||
}
|
||||
|
||||
func (s *Set) Uint64Long(name string, short rune, value uint64, helpvalue ...string) *uint64 {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
// List creates an option that returns a slice of strings. The parameters
|
||||
// passed are converted from a comma separated value list into a slice.
|
||||
// Subsequent occurrences append to the list.
|
||||
func List(name rune, helpvalue ...string) *[]string {
|
||||
p := []string{}
|
||||
CommandLine.Flag(&p, name, helpvalue...)
|
||||
return &p
|
||||
}
|
||||
|
||||
func (s *Set) List(name rune, helpvalue ...string) *[]string {
|
||||
p := []string{}
|
||||
s.Flag(&p, name, helpvalue...)
|
||||
return &p
|
||||
}
|
||||
|
||||
func ListLong(name string, short rune, helpvalue ...string) *[]string {
|
||||
p := []string{}
|
||||
CommandLine.FlagLong(&p, name, short, helpvalue...)
|
||||
return &p
|
||||
}
|
||||
|
||||
func (s *Set) ListLong(name string, short rune, helpvalue ...string) *[]string {
|
||||
p := []string{}
|
||||
s.FlagLong(&p, name, short, helpvalue...)
|
||||
return &p
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// An Option can be either a Flag or a Value
|
||||
type Option interface {
|
||||
// Name returns the name of the option. If the option has been seen
|
||||
// then the last way it was referenced (short or long) is returned
|
||||
// otherwise if there is a short name then this will be the short name
|
||||
// as a string, else it will be the long name.
|
||||
Name() string
|
||||
|
||||
// ShortName always returns the short name of the option, or "" if there
|
||||
// is no short name. The name does not include the "-".
|
||||
ShortName() string
|
||||
|
||||
// LongName always returns the long name of the option, or "" if there
|
||||
// is no long name. The name does not include the "--".
|
||||
LongName() string
|
||||
|
||||
// IsFlag returns true if Option is a flag.
|
||||
IsFlag() bool
|
||||
|
||||
// Seen returns true if the flag was seen.
|
||||
Seen() bool
|
||||
|
||||
// Count returns the number of times the flag was seen.
|
||||
Count() int
|
||||
|
||||
// String returns the last value the option was set to.
|
||||
String() string
|
||||
|
||||
// Value returns the Value of the option.
|
||||
Value() Value
|
||||
|
||||
// SetOptional makes the value optional. The option and value are
|
||||
// always a single argument. Either --option or --option=value. In
|
||||
// the former case the value of the option does not change but the Set()
|
||||
// will return true and the value returned by Count() is incremented.
|
||||
// The short form is either -o or -ovalue. SetOptional returns
|
||||
// the Option
|
||||
SetOptional() Option
|
||||
|
||||
// SetFlag makes the value a flag. Flags are boolean values and
|
||||
// normally do not taken a value. They are set to true when seen.
|
||||
// If a value is passed in the long form then it must be on, case
|
||||
// insensitivinsensitive, one of "true", "false", "t", "f", "on", "off", "1", "0".
|
||||
// SetFlag returns the Option
|
||||
SetFlag() Option
|
||||
|
||||
// Reset resets the state of the option so it appears it has not
|
||||
// yet been seen, including resetting the value of the option
|
||||
// to its original default state.
|
||||
Reset()
|
||||
}
|
||||
|
||||
type option struct {
|
||||
short rune // 0 means no short name
|
||||
long string // "" means no long name
|
||||
isLong bool // True if they used the long name
|
||||
flag bool // true if a boolean flag
|
||||
defval string // default value
|
||||
optional bool // true if we take an optional value
|
||||
help string // help message
|
||||
where string // file where the option was defined
|
||||
value Value // current value of option
|
||||
count int // number of times we have seen this option
|
||||
name string // name of the value (for usage)
|
||||
uname string // name of the option (for usage)
|
||||
}
|
||||
|
||||
// usageName returns the name of the option for printing usage lines in one
|
||||
// of the following forms:
|
||||
//
|
||||
// -f
|
||||
// --flag
|
||||
// -f, --flag
|
||||
// -s value
|
||||
// --set=value
|
||||
// -s, --set=value
|
||||
func (o *option) usageName() string {
|
||||
// Don't print help messages if we have none and there is only one
|
||||
// way to specify the option.
|
||||
if o.help == "" && (o.short == 0 || o.long == "") {
|
||||
return ""
|
||||
}
|
||||
n := ""
|
||||
|
||||
switch {
|
||||
case o.short != 0 && o.long == "":
|
||||
n = "-" + string(o.short)
|
||||
case o.short == 0 && o.long != "":
|
||||
n = " --" + o.long
|
||||
case o.short != 0 && o.long != "":
|
||||
n = "-" + string(o.short) + ", --" + o.long
|
||||
}
|
||||
|
||||
switch {
|
||||
case o.flag:
|
||||
return n
|
||||
case o.optional:
|
||||
return n + "[=" + o.name + "]"
|
||||
case o.long != "":
|
||||
return n + "=" + o.name
|
||||
}
|
||||
return n + " " + o.name
|
||||
}
|
||||
|
||||
// sortName returns the name to sort the option on.
|
||||
func (o *option) sortName() string {
|
||||
if o.short != 0 {
|
||||
return string(o.short) + o.long
|
||||
}
|
||||
return o.long[:1] + o.long
|
||||
}
|
||||
|
||||
func (o *option) Seen() bool { return o.count > 0 }
|
||||
func (o *option) Count() int { return o.count }
|
||||
func (o *option) IsFlag() bool { return o.flag }
|
||||
func (o *option) String() string { return o.value.String() }
|
||||
func (o *option) SetOptional() Option { o.optional = true; return o }
|
||||
func (o *option) SetFlag() Option { o.flag = true; return o }
|
||||
|
||||
func (o *option) Value() Value {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
return o.value
|
||||
}
|
||||
|
||||
func (o *option) Name() string {
|
||||
if !o.isLong && o.short != 0 {
|
||||
return "-" + string(o.short)
|
||||
}
|
||||
return "--" + o.long
|
||||
}
|
||||
|
||||
func (o *option) ShortName() string {
|
||||
if o.short != 0 {
|
||||
return string(o.short)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (o *option) LongName() string {
|
||||
return o.long
|
||||
}
|
||||
|
||||
// Reset rests an option so that it appears it has not yet been seen.
|
||||
func (o *option) Reset() {
|
||||
o.isLong = false
|
||||
o.count = 0
|
||||
o.value.Set(o.defval, o)
|
||||
}
|
||||
|
||||
type optionList []*option
|
||||
|
||||
func (ol optionList) Len() int { return len(ol) }
|
||||
func (ol optionList) Swap(i, j int) { ol[i], ol[j] = ol[j], ol[i] }
|
||||
func (ol optionList) Less(i, j int) bool {
|
||||
// first check the short names (or the first letter of the long name)
|
||||
// If they are not equal (case insensitive) then we have our answer
|
||||
n1 := ol[i].sortName()
|
||||
n2 := ol[j].sortName()
|
||||
l1 := strings.ToLower(n1)
|
||||
l2 := strings.ToLower(n2)
|
||||
if l1 < l2 {
|
||||
return true
|
||||
}
|
||||
if l2 < l1 {
|
||||
return false
|
||||
}
|
||||
return n1 < n2
|
||||
}
|
||||
|
||||
// AddOption add the option o to set CommandLine if o is not already in set
|
||||
// CommandLine.
|
||||
func AddOption(o Option) {
|
||||
CommandLine.AddOption(o)
|
||||
}
|
||||
|
||||
// AddOption add the option o to set s if o is not already in set s.
|
||||
func (s *Set) AddOption(o Option) {
|
||||
opt := o.(*option)
|
||||
for _, eopt := range s.options {
|
||||
if opt == eopt {
|
||||
return
|
||||
}
|
||||
}
|
||||
if opt.short != 0 {
|
||||
if oo, ok := s.shortOptions[opt.short]; ok {
|
||||
fmt.Fprintf(stderr, "%s: -%c already declared at %s\n", opt.where, opt.short, oo.where)
|
||||
exit(1)
|
||||
}
|
||||
s.shortOptions[opt.short] = opt
|
||||
}
|
||||
if opt.long != "" {
|
||||
if oo, ok := s.longOptions[opt.long]; ok {
|
||||
fmt.Fprintf(stderr, "%s: --%s already declared at %s\n", opt.where, opt.long, oo.where)
|
||||
exit(1)
|
||||
}
|
||||
s.longOptions[opt.long] = opt
|
||||
}
|
||||
s.options = append(s.options, opt)
|
||||
}
|
@ -0,0 +1,291 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A State is why the Getopt returned.
|
||||
type State int
|
||||
|
||||
const (
|
||||
InProgress = State(iota) // Getopt is still running
|
||||
Dash // Returned on "-"
|
||||
DashDash // Returned on "--"
|
||||
EndOfOptions // End of options reached
|
||||
EndOfArguments // No more arguments
|
||||
Terminated // Terminated by callback function
|
||||
Failure // Terminated due to error
|
||||
Unknown // Indicates internal error
|
||||
)
|
||||
|
||||
type Set struct {
|
||||
stateMu sync.Mutex
|
||||
state State
|
||||
|
||||
// args are the parameters remaining after parsing the optoins.
|
||||
args []string
|
||||
|
||||
// program is the name of the program for usage and error messages.
|
||||
// If not set it will automatically be set to the base name of the
|
||||
// first argument passed to parse.
|
||||
program string
|
||||
|
||||
// parameters is what is displayed on the usage line after displaying
|
||||
// the various options.
|
||||
parameters string
|
||||
|
||||
usage func() // usage should print the programs usage and exit.
|
||||
|
||||
shortOptions map[rune]*option
|
||||
longOptions map[string]*option
|
||||
options optionList
|
||||
}
|
||||
|
||||
// New returns a newly created option set.
|
||||
func New() *Set {
|
||||
s := &Set{
|
||||
shortOptions: make(map[rune]*option),
|
||||
longOptions: make(map[string]*option),
|
||||
parameters: "[parameters ...]",
|
||||
}
|
||||
|
||||
s.usage = func() {
|
||||
s.PrintUsage(stderr)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Set) setState(state State) {
|
||||
s.stateMu.Lock()
|
||||
s.state = state
|
||||
s.stateMu.Unlock()
|
||||
}
|
||||
|
||||
// State returns the current state of the Set s. The state is normally the
|
||||
// reason the most recent call to Getopt returned.
|
||||
func (s *Set) State() State {
|
||||
s.stateMu.Lock()
|
||||
defer s.stateMu.Unlock()
|
||||
return s.state
|
||||
}
|
||||
|
||||
// The default set of command-line options.
|
||||
var CommandLine = New()
|
||||
|
||||
// PrintUsage calls PrintUsage in the default option set.
|
||||
func PrintUsage(w io.Writer) { CommandLine.PrintUsage(w) }
|
||||
|
||||
// Usage calls the usage function in the default option set.
|
||||
func Usage() { CommandLine.usage() }
|
||||
|
||||
// Parse calls Parse in the default option set with the command line arguments
|
||||
// found in os.Args.
|
||||
func Parse() { CommandLine.Parse(os.Args) }
|
||||
|
||||
// Getops returns the result of calling Getop in the default option set with the
|
||||
// command line arguments found in os.Args. The fn function, which may be nil,
|
||||
// is passed to Getopt.
|
||||
func Getopt(fn func(Option) bool) error { return CommandLine.Getopt(os.Args, fn) }
|
||||
|
||||
// Arg returns the n'th command-line argument. Arg(0) is the first remaining
|
||||
// argument after options have been processed.
|
||||
func Arg(n int) string {
|
||||
if n >= 0 && n < len(CommandLine.args) {
|
||||
return CommandLine.args[n]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Arg returns the n'th argument. Arg(0) is the first remaining
|
||||
// argument after options have been processed.
|
||||
func (s *Set) Arg(n int) string {
|
||||
if n >= 0 && n < len(s.args) {
|
||||
return s.args[n]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Args returns the non-option command line arguments.
|
||||
func Args() []string {
|
||||
return CommandLine.args
|
||||
}
|
||||
|
||||
// Args returns the non-option arguments.
|
||||
func (s *Set) Args() []string {
|
||||
return s.args
|
||||
}
|
||||
|
||||
// NArgs returns the number of non-option command line arguments.
|
||||
func NArgs() int {
|
||||
return len(CommandLine.args)
|
||||
}
|
||||
|
||||
// NArgs returns the number of non-option arguments.
|
||||
func (s *Set) NArgs() int {
|
||||
return len(s.args)
|
||||
}
|
||||
|
||||
// SetParameters sets the parameters string for printing the command line
|
||||
// usage. It defaults to "[parameters ...]"
|
||||
func SetParameters(parameters string) {
|
||||
CommandLine.parameters = parameters
|
||||
}
|
||||
|
||||
// SetParameters sets the parameters string for printing the s's usage.
|
||||
// It defaults to "[parameters ...]"
|
||||
func (s *Set) SetParameters(parameters string) {
|
||||
s.parameters = parameters
|
||||
}
|
||||
|
||||
// Parameters returns the parameters set by SetParameters on s.
|
||||
func (s *Set) Parameters() string { return s.parameters }
|
||||
|
||||
|
||||
// SetProgram sets the program name to program. Normally it is determined
|
||||
// from the zeroth command line argument (see os.Args).
|
||||
func SetProgram(program string) {
|
||||
CommandLine.program = program
|
||||
}
|
||||
|
||||
// SetProgram sets s's program name to program. Normally it is determined
|
||||
// from the zeroth argument passed to Getopt or Parse.
|
||||
func (s *Set) SetProgram(program string) {
|
||||
s.program = program
|
||||
}
|
||||
|
||||
// Program returns the program name associated with Set s.
|
||||
func (s *Set) Program() string { return s.program }
|
||||
|
||||
// SetUsage sets the function used by Parse to display the commands usage
|
||||
// on error. It defaults to calling PrintUsage(os.Stderr).
|
||||
func SetUsage(usage func()) {
|
||||
CommandLine.usage = usage
|
||||
}
|
||||
|
||||
// SetUsage sets the function used by Parse to display usage on error. It
|
||||
// defaults to calling f.PrintUsage(os.Stderr).
|
||||
func (s *Set) SetUsage(usage func()) {
|
||||
s.usage = usage
|
||||
}
|
||||
|
||||
// Lookup returns the Option associated with name. Name should either be
|
||||
// a rune (the short name) or a string (the long name).
|
||||
func Lookup(name interface{}) Option {
|
||||
return CommandLine.Lookup(name)
|
||||
}
|
||||
|
||||
// Lookup returns the Option associated with name in s. Name should either be
|
||||
// a rune (the short name) or a string (the long name).
|
||||
func (s *Set) Lookup(name interface{}) Option {
|
||||
switch v := name.(type) {
|
||||
case rune:
|
||||
return s.shortOptions[v]
|
||||
case int:
|
||||
return s.shortOptions[rune(v)]
|
||||
case string:
|
||||
return s.longOptions[v]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsSet returns true if the Option associated with name was seen while
|
||||
// parsing the command line arguments. Name should either be a rune (the
|
||||
// short name) or a string (the long name).
|
||||
func IsSet(name interface{}) bool {
|
||||
return CommandLine.IsSet(name)
|
||||
}
|
||||
|
||||
// IsSet returns true if the Option associated with name was seen while
|
||||
// parsing s. Name should either be a rune (the short name) or a string (the
|
||||
// long name).
|
||||
func (s *Set) IsSet(name interface{}) bool {
|
||||
if opt := s.Lookup(name); opt != nil {
|
||||
return opt.Seen()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetCount returns the number of times the Option associated with name has been
|
||||
// seen while parsing the command line arguments. Name should either be a rune
|
||||
// (the short name) or a string (the long name).
|
||||
func GetCount(name interface{}) int {
|
||||
return CommandLine.GetCount(name)
|
||||
}
|
||||
|
||||
// GetCount returns the number of times the Option associated with name has been
|
||||
// seen while parsing s's arguments. Name should either be a rune (the short
|
||||
// name) or a string (the long name).
|
||||
func (s *Set) GetCount(name interface{}) int {
|
||||
if opt := s.Lookup(name); opt != nil {
|
||||
return opt.Count()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetValue returns the final value set to the command-line Option with name.
|
||||
// If the option has not been seen while parsing s then the default value is
|
||||
// returned. Name should either be a rune (the short name) or a string (the
|
||||
// long name).
|
||||
func GetValue(name interface{}) string {
|
||||
return CommandLine.GetValue(name)
|
||||
}
|
||||
|
||||
// GetValue returns the final value set to the Option in s associated with name.
|
||||
// If the option has not been seen while parsing s then the default value is
|
||||
// returned. Name should either be a rune (the short name) or a string (the
|
||||
// long name).
|
||||
func (s *Set) GetValue(name interface{}) string {
|
||||
if opt := s.Lookup(name); opt != nil {
|
||||
return opt.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Visit visits the command-line options in lexicographical order, calling fn
|
||||
// for each. It visits only those options that have been set.
|
||||
func Visit(fn func(Option)) { CommandLine.Visit(fn) }
|
||||
|
||||
// Visit visits the options in s in lexicographical order, calling fn
|
||||
// for each. It visits only those options that have been set.
|
||||
func (s *Set) Visit(fn func(Option)) {
|
||||
sort.Sort(s.options)
|
||||
for _, opt := range s.options {
|
||||
if opt.count > 0 {
|
||||
fn(opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VisitAll visits the options in s in lexicographical order, calling fn
|
||||
// for each. It visits all options, even those not set.
|
||||
func VisitAll(fn func(Option)) { CommandLine.VisitAll(fn) }
|
||||
|
||||
// VisitAll visits the command-line flags in lexicographical order, calling fn
|
||||
// for each. It visits all flags, even those not set.
|
||||
func (s *Set) VisitAll(fn func(Option)) {
|
||||
sort.Sort(s.options)
|
||||
for _, opt := range s.options {
|
||||
fn(opt)
|
||||
}
|
||||
}
|
||||
|
||||
// Reset resets all the command line options to the initial state so it
|
||||
// appears none of them have been seen.
|
||||
func Reset() {
|
||||
CommandLine.Reset()
|
||||
}
|
||||
|
||||
// Reset resets all the options in s to the initial state so it
|
||||
// appears none of them have been seen.
|
||||
func (s *Set) Reset() {
|
||||
for _, opt := range s.options {
|
||||
opt.Reset()
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type signed int64
|
||||
|
||||
type SignedLimit struct {
|
||||
Base int // Base for conversion as per strconv.ParseInt
|
||||
Bits int // Number of bits as per strconv.ParseInt
|
||||
Min int64 // Minimum allowed value if both Min and Max are not 0
|
||||
Max int64 // Maximum allowed value if both Min and Max are not 0
|
||||
}
|
||||
|
||||
var (
|
||||
signedLimitsMu sync.Mutex
|
||||
signedLimits = make(map[*signed]*SignedLimit)
|
||||
)
|
||||
|
||||
func (n *signed) Set(value string, opt Option) error {
|
||||
signedLimitsMu.Lock()
|
||||
l := signedLimits[n]
|
||||
signedLimitsMu.Unlock()
|
||||
if l == nil {
|
||||
return fmt.Errorf("no limits defined for %s", opt.Name())
|
||||
}
|
||||
v, err := strconv.ParseInt(value, l.Base, l.Bits)
|
||||
if err != nil {
|
||||
if e, ok := err.(*strconv.NumError); ok {
|
||||
switch e.Err {
|
||||
case strconv.ErrRange:
|
||||
err = fmt.Errorf("value out of range: %s", value)
|
||||
case strconv.ErrSyntax:
|
||||
err = fmt.Errorf("not a valid number: %s", value)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
if l.Min != 0 || l.Max != 0 {
|
||||
if v < l.Min {
|
||||
return fmt.Errorf("value out of range (<%v): %s", l.Min, value)
|
||||
}
|
||||
if v > l.Max {
|
||||
return fmt.Errorf("value out of range (>%v): %s", l.Max, value)
|
||||
}
|
||||
}
|
||||
*n = signed(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *signed) String() string {
|
||||
signedLimitsMu.Lock()
|
||||
l := signedLimits[n]
|
||||
signedLimitsMu.Unlock()
|
||||
if l != nil && l.Base != 0 {
|
||||
return strconv.FormatInt(int64(*n), l.Base)
|
||||
}
|
||||
return strconv.FormatInt(int64(*n), 10)
|
||||
}
|
||||
|
||||
// Signed creates an option that is stored in an int64 and is constrained
|
||||
// by the limits pointed to by l. The Max and Min values are only used if
|
||||
// at least one of the values are not 0. If Base is 0, the base is implied by
|
||||
// the string's prefix: base 16 for "0x", base 8 for "0", and base 10 otherwise.
|
||||
func Signed(name rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
|
||||
CommandLine.signedOption(&value, "", name, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) Signed(name rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
|
||||
s.signedOption(&value, "", name, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func SignedLong(name string, short rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
|
||||
CommandLine.signedOption(&value, name, short, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) SignedLong(name string, short rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
|
||||
s.signedOption(&value, name, short, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) signedOption(p *int64, name string, short rune, l *SignedLimit, helpvalue ...string) {
|
||||
opt := s.FlagLong((*signed)(p), name, short, helpvalue...)
|
||||
if l.Base > 36 || l.Base == 1 || l.Base < 0 {
|
||||
fmt.Fprintf(stderr, "invalid base for %s: %d\n", opt.Name(), l.Base)
|
||||
exit(1)
|
||||
}
|
||||
if l.Bits < 0 || l.Bits > 64 {
|
||||
fmt.Fprintf(stderr, "invalid bit size for %s: %d\n", opt.Name(), l.Bits)
|
||||
exit(1)
|
||||
}
|
||||
if l.Min > l.Max {
|
||||
fmt.Fprintf(stderr, "min greater than max for %s\n", opt.Name())
|
||||
exit(1)
|
||||
}
|
||||
lim := *l
|
||||
signedLimitsMu.Lock()
|
||||
signedLimits[(*signed)(p)] = &lim
|
||||
signedLimitsMu.Unlock()
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
// String returns a value option that stores is value as a string. The
|
||||
// initial value of the string is passed in value.
|
||||
func String(name rune, value string, helpvalue ...string) *string {
|
||||
CommandLine.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) String(name rune, value string, helpvalue ...string) *string {
|
||||
s.Flag(&value, name, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func StringLong(name string, short rune, value string, helpvalue ...string) *string {
|
||||
CommandLine.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) StringLong(name string, short rune, value string, helpvalue ...string) *string {
|
||||
s.FlagLong(&value, name, short, helpvalue...)
|
||||
return &value
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type unsigned uint64
|
||||
|
||||
type UnsignedLimit struct {
|
||||
Base int // Base for conversion as per strconv.ParseInt
|
||||
Bits int // Number of bits as per strconv.ParseInt
|
||||
Min uint64 // Minimum allowed value if both Min and Max are not 0
|
||||
Max uint64 // Maximum allowed value if both Min and Max are not 0
|
||||
}
|
||||
|
||||
var (
|
||||
unsignedLimitsMu sync.Mutex
|
||||
unsignedLimits = make(map[*unsigned]*UnsignedLimit)
|
||||
)
|
||||
|
||||
func (n *unsigned) Set(value string, opt Option) error {
|
||||
unsignedLimitsMu.Lock()
|
||||
l := unsignedLimits[n]
|
||||
unsignedLimitsMu.Unlock()
|
||||
if l == nil {
|
||||
return fmt.Errorf("no limits defined for %s", opt.Name())
|
||||
}
|
||||
v, err := strconv.ParseUint(value, l.Base, l.Bits)
|
||||
if err != nil {
|
||||
if e, ok := err.(*strconv.NumError); ok {
|
||||
switch e.Err {
|
||||
case strconv.ErrRange:
|
||||
err = fmt.Errorf("value out of range: %s", value)
|
||||
case strconv.ErrSyntax:
|
||||
err = fmt.Errorf("not a valid number: %s", value)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
if l.Min != 0 || l.Max != 0 {
|
||||
if v < l.Min {
|
||||
return fmt.Errorf("value out of range (<%v): %s", l.Min, value)
|
||||
}
|
||||
if v > l.Max {
|
||||
return fmt.Errorf("value out of range (>%v): %s", l.Max, value)
|
||||
}
|
||||
}
|
||||
*n = unsigned(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *unsigned) String() string {
|
||||
unsignedLimitsMu.Lock()
|
||||
l := unsignedLimits[n]
|
||||
unsignedLimitsMu.Unlock()
|
||||
if l != nil && l.Base != 0 {
|
||||
return strconv.FormatUint(uint64(*n), l.Base)
|
||||
}
|
||||
return strconv.FormatUint(uint64(*n), 10)
|
||||
}
|
||||
|
||||
// Unsigned creates an option that is stored in a uint64 and is
|
||||
// constrained by the limits pointed to by l. The Max and Min values are only
|
||||
// used if at least one of the values are not 0. If Base is 0, the base is
|
||||
// implied by the string's prefix: base 16 for "0x", base 8 for "0", and base
|
||||
// 10 otherwise.
|
||||
func Unsigned(name rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
|
||||
CommandLine.unsignedOption(&value, "", name, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) Unsigned(name rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
|
||||
s.unsignedOption(&value, "", name, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func UnsignedLong(name string, short rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
|
||||
CommandLine.unsignedOption(&value, name, short, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) UnsignedLong(name string, short rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
|
||||
s.unsignedOption(&value, name, short, l, helpvalue...)
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s *Set) unsignedOption(p *uint64, name string, short rune, l *UnsignedLimit, helpvalue ...string) {
|
||||
opt := s.FlagLong((*unsigned)(p), name, short, helpvalue...)
|
||||
if l.Base > 36 || l.Base == 1 || l.Base < 0 {
|
||||
fmt.Fprintf(stderr, "invalid base for %s: %d\n", opt.Name(), l.Base)
|
||||
exit(1)
|
||||
}
|
||||
if l.Bits < 0 || l.Bits > 64 {
|
||||
fmt.Fprintf(stderr, "invalid bit size for %s: %d\n", opt.Name(), l.Bits)
|
||||
exit(1)
|
||||
}
|
||||
if l.Min > l.Max {
|
||||
fmt.Fprintf(stderr, "min greater than max for %s\n", opt.Name())
|
||||
exit(1)
|
||||
}
|
||||
lim := *l
|
||||
unsignedLimitsMu.Lock()
|
||||
unsignedLimits[(*unsigned)(p)] = &lim
|
||||
unsignedLimitsMu.Unlock()
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
// Copyright 2017 Google Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Value is the interface to the dynamic value stored in a flag. Flags of type
|
||||
// Value are declared using the Flag and FlagLong functions.
|
||||
type Value interface {
|
||||
// Set converts value into the appropriate type and assigns it to the
|
||||
// receiver value. Option details are provided via opt (such as the
|
||||
// flags name).
|
||||
//
|
||||
// Set is used to reset the value of an option to its default value
|
||||
// (which is stored in string form internally).
|
||||
Set(value string, opt Option) error
|
||||
|
||||
// String returns the value of the flag as a string.
|
||||
String() string
|
||||
}
|
||||
|
||||
var thisPackage string
|
||||
|
||||
// init initializes thisPackage to our full package with the trailing .
|
||||
// included.
|
||||
func init() {
|
||||
pc, _, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
f := runtime.FuncForPC(pc)
|
||||
if f == nil {
|
||||
return
|
||||
}
|
||||
thisPackage = f.Name()
|
||||
x := strings.LastIndex(thisPackage, "/")
|
||||
if x < 0 {
|
||||
return
|
||||
}
|
||||
y := strings.Index(thisPackage[x:], ".")
|
||||
if y < 0 {
|
||||
return
|
||||
}
|
||||
// thisPackage includes the trailing . after the package name.
|
||||
thisPackage = thisPackage[:x+y+1]
|
||||
}
|
||||
|
||||
// calledFrom returns a string containing the file and linenumber of the first
|
||||
// stack frame above us that is not part of this package and is not a test.
|
||||
// This is used to determine where a flag was initialized.
|
||||
func calledFrom() string {
|
||||
for i := 2; ; i++ {
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
if !strings.HasSuffix(file, "_test.go") {
|
||||
f := runtime.FuncForPC(pc)
|
||||
if f != nil && strings.HasPrefix(f.Name(), thisPackage) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", file, line)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Set) addFlag(p Value, name string, short rune, helpvalue ...string) Option {
|
||||
opt := &option{
|
||||
short: short,
|
||||
long: name,
|
||||
value: p,
|
||||
defval: p.String(),
|
||||
}
|
||||
|
||||
switch len(helpvalue) {
|
||||
case 2:
|
||||
opt.name = helpvalue[1]
|
||||
fallthrough
|
||||
case 1:
|
||||
opt.help = helpvalue[0]
|
||||
case 0:
|
||||
default:
|
||||
panic("Too many strings for String helpvalue")
|
||||
}
|
||||
if where := calledFrom(); where != "" {
|
||||
opt.where = where
|
||||
}
|
||||
if opt.short == 0 && opt.long == "" {
|
||||
fmt.Fprintf(stderr, opt.where+": no short or long option given")
|
||||
exit(1)
|
||||
}
|
||||
s.AddOption(opt)
|
||||
return opt
|
||||
}
|
Loading…
Reference in New Issue