mirror of
https://github.com/strongdm/comply
synced 2025-12-06 14:24:12 +00:00
chore: migrate to go modules
This commit is contained in:
2
vendor/github.com/voxelbrain/goptions/.gitignore
generated
vendored
Normal file
2
vendor/github.com/voxelbrain/goptions/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.swp
|
||||
.DS_Store
|
||||
96
vendor/github.com/voxelbrain/goptions/CHANGELOG.md
generated
vendored
Normal file
96
vendor/github.com/voxelbrain/goptions/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
# Changelog
|
||||
## 2.5.6
|
||||
### Bug fixes
|
||||
|
||||
* Unexported fields are now ignored
|
||||
|
||||
### Minor changes
|
||||
|
||||
* Examples for Verbs and Remainder in documentation
|
||||
|
||||
## 2.5.4
|
||||
### Bugfixes
|
||||
|
||||
* Fix typo in documentation
|
||||
|
||||
## 2.5.3
|
||||
### Bugfixes
|
||||
|
||||
* Remove placeholders from LICENSE
|
||||
* Add CONTROBUTORS
|
||||
|
||||
## 2.5.2
|
||||
### Bugfixes
|
||||
|
||||
* Bring `examples/readme_example.go` and `README.md` up to date
|
||||
* Rewrite formatter
|
||||
|
||||
## 2.5.1
|
||||
### Bugfixes
|
||||
|
||||
* Make arrays of `goptions.Marshaler` work
|
||||
|
||||
## 2.5.0
|
||||
### New features
|
||||
|
||||
* Add support for `int32` and `int64`
|
||||
* Add support for `float32` and `float64`
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix a bug where the name of a unknown type would not be properly
|
||||
printed
|
||||
* Fix checks whether to use `os.Stdin` or `os.Stdout` when "-" is given for a
|
||||
`*os.File`
|
||||
* Fix an test example where the output to `os.Stderr` is apparently
|
||||
not evaluated anymore.
|
||||
|
||||
## 2.4.1
|
||||
### Bugfixes
|
||||
|
||||
* Code was not compilable due to temporary [maintainer](http://github.com/surma) idiocy
|
||||
(Thanks [akrennmair](http://github.com/akrennmair))
|
||||
|
||||
## 2.4.0
|
||||
### New features
|
||||
|
||||
* Gave `goptions.FlagSet` a `ParseAndFail()` method
|
||||
|
||||
## 2.3.0
|
||||
### New features
|
||||
|
||||
* Add support for `time.Duration`
|
||||
|
||||
## 2.2.0
|
||||
### New features
|
||||
|
||||
* Add support for `*net.TCPAddr`
|
||||
* Add support for `*net/url.URL`
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix behaviour of `[]bool` fields
|
||||
|
||||
## 2.1.0
|
||||
### New features
|
||||
|
||||
* `goptions.Verbs` is of type `string` and will have selected verb name as value
|
||||
after parsing.
|
||||
|
||||
## 2.0.0
|
||||
### Breaking changes
|
||||
|
||||
* Disallow multiple flag names for one member
|
||||
* Remove `accumulate` option in favor of generic array support
|
||||
|
||||
### New features
|
||||
|
||||
* Add convenience function `ParseAndFail` to make common usage of the library
|
||||
a one-liner (see `readme_example.go`)
|
||||
* Add a `Marshaler` interface to enable thrid-party types
|
||||
* Add support for slices (and thereby for mutiple flag definitions)
|
||||
|
||||
### Minor changes
|
||||
|
||||
* Refactoring to get more flexibility
|
||||
* Make a flag's default value accessible in the template context
|
||||
7
vendor/github.com/voxelbrain/goptions/CONTRIBUTORS.md
generated
vendored
Normal file
7
vendor/github.com/voxelbrain/goptions/CONTRIBUTORS.md
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Contributors
|
||||
============
|
||||
|
||||
These people have contributed to goptions's design and implementation:
|
||||
|
||||
* Andreas Krennmair <https://github.com/akrennmair>
|
||||
* GDG Berlin Golang <https://gplus.to/gdgberlingolang>
|
||||
24
vendor/github.com/voxelbrain/goptions/LICENSE.txt
generated
vendored
Normal file
24
vendor/github.com/voxelbrain/goptions/LICENSE.txt
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2012-2013, voxelbrain UG, Germany
|
||||
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 the voxelbrain UG 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 voxelbrain UG 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.
|
||||
114
vendor/github.com/voxelbrain/goptions/README.md
generated
vendored
Normal file
114
vendor/github.com/voxelbrain/goptions/README.md
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
`goptions` implements a flexible parser for command line options.
|
||||
|
||||
Key targets were the support for both long and short flag versions, mutually
|
||||
exclusive flags, and verbs. Flags and their corresponding variables are defined
|
||||
by the tags in a (possibly anonymous) struct.
|
||||
|
||||

|
||||
|
||||
# Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/voxelbrain/goptions"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
options := struct {
|
||||
Servers []string `goptions:"-s, --server, obligatory, description='Servers to connect to'"`
|
||||
Password string `goptions:"-p, --password, description='Don\\'t prompt for password'"`
|
||||
Timeout time.Duration `goptions:"-t, --timeout, description='Connection timeout in seconds'"`
|
||||
Help goptions.Help `goptions:"-h, --help, description='Show this help'"`
|
||||
|
||||
goptions.Verbs
|
||||
Execute struct {
|
||||
Command string `goptions:"--command, mutexgroup='input', description='Command to exectute', obligatory"`
|
||||
Script *os.File `goptions:"--script, mutexgroup='input', description='Script to exectute', rdonly"`
|
||||
} `goptions:"execute"`
|
||||
Delete struct {
|
||||
Path string `goptions:"-n, --name, obligatory, description='Name of the entity to be deleted'"`
|
||||
Force bool `goptions:"-f, --force, description='Force removal'"`
|
||||
} `goptions:"delete"`
|
||||
}{ // Default values goes here
|
||||
Timeout: 10 * time.Second,
|
||||
}
|
||||
goptions.ParseAndFail(&options)
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
$ go run examples/readme_example.go --help
|
||||
Usage: a.out [global options] <verb> [verb options]
|
||||
|
||||
Global options:
|
||||
-s, --server Servers to connect to (*)
|
||||
-p, --password Don't prompt for password
|
||||
-t, --timeout Connection timeout in seconds (default: 10s)
|
||||
-h, --help Show this help
|
||||
|
||||
Verbs:
|
||||
delete:
|
||||
-n, --name Name of the entity to be deleted (*)
|
||||
-f, --force Force removal
|
||||
execute:
|
||||
--command Command to exectute (*)
|
||||
--script Script to exectute
|
||||
```
|
||||
|
||||
# Quick Reference
|
||||
|
||||
## goptions
|
||||
|
||||
Each field of your struct can be tagged with a `goptions`
|
||||
|
||||
```go
|
||||
FieldName type `goptions:"-S, --long, options..."`
|
||||
```
|
||||
|
||||
Where the short options (`-S`) are declared with a single dash and
|
||||
long options (`--long`) are declared with two dashes. Either or
|
||||
both may be declared.
|
||||
|
||||
After the short/long option names are one or more of the following:
|
||||
|
||||
### Global Options
|
||||
|
||||
* description='...'
|
||||
* obligatory
|
||||
* mutexgroup='GROUP_NAME'
|
||||
|
||||
### os.File specific
|
||||
|
||||
* create
|
||||
* append
|
||||
* rdonly
|
||||
* wronly
|
||||
* rdwr
|
||||
* excl
|
||||
* sync
|
||||
* trunc
|
||||
* perm=0777
|
||||
|
||||
## Supported Types
|
||||
|
||||
* bool
|
||||
* string
|
||||
* float64
|
||||
* float32
|
||||
* int
|
||||
* int64
|
||||
* int32
|
||||
* goptions.Help
|
||||
* *os.File
|
||||
* *net.TCPAddr
|
||||
* *url.URL
|
||||
* time.Duration
|
||||
|
||||
|
||||
|
||||
---
|
||||
Version 2.5.11
|
||||
9
vendor/github.com/voxelbrain/goptions/circle.yml
generated
vendored
Normal file
9
vendor/github.com/voxelbrain/goptions/circle.yml
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/golang
|
||||
steps:
|
||||
- checkout
|
||||
- run: go get -d .
|
||||
- run: go test
|
||||
90
vendor/github.com/voxelbrain/goptions/flag.go
generated
vendored
Normal file
90
vendor/github.com/voxelbrain/goptions/flag.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Flag represents a single flag of a FlagSet.
|
||||
type Flag struct {
|
||||
Short string
|
||||
Long string
|
||||
MutexGroups []string
|
||||
Description string
|
||||
Obligatory bool
|
||||
WasSpecified bool
|
||||
value reflect.Value
|
||||
optionMeta map[string]interface{}
|
||||
DefaultValue interface{}
|
||||
}
|
||||
|
||||
// Return the name of the flag preceding the right amount of dashes.
|
||||
// The long name is preferred. If no name has been specified, "<unspecified>"
|
||||
// will be returned.
|
||||
func (f *Flag) Name() string {
|
||||
if len(f.Long) > 0 {
|
||||
return "--" + f.Long
|
||||
}
|
||||
if len(f.Short) > 0 {
|
||||
return "-" + f.Short
|
||||
}
|
||||
return "<unspecified>"
|
||||
}
|
||||
|
||||
// NeedsExtraValue returns true if the flag expects a separate value.
|
||||
func (f *Flag) NeedsExtraValue() bool {
|
||||
// Explicit over implicit
|
||||
if f.value.Type() == reflect.TypeOf(new([]bool)).Elem() ||
|
||||
f.value.Type() == reflect.TypeOf(new(bool)).Elem() {
|
||||
return false
|
||||
}
|
||||
if _, ok := f.value.Interface().(Help); ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsMulti returns true if the flag can be specified multiple times.
|
||||
func (f *Flag) IsMulti() bool {
|
||||
if f.value.Kind() == reflect.Slice {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isShort(arg string) bool {
|
||||
return strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "--") && len(arg) >= 2
|
||||
}
|
||||
|
||||
func isLong(arg string) bool {
|
||||
return strings.HasPrefix(arg, "--") && len(arg) >= 3
|
||||
}
|
||||
|
||||
func (f *Flag) Handles(arg string) bool {
|
||||
return (isShort(arg) && arg[1:2] == f.Short) ||
|
||||
(isLong(arg) && arg[2:] == f.Long)
|
||||
|
||||
}
|
||||
|
||||
func (f *Flag) Parse(args []string) ([]string, error) {
|
||||
param, value := args[0], ""
|
||||
if f.NeedsExtraValue() &&
|
||||
(len(args) < 2 || (isShort(param) && len(param) > 2)) {
|
||||
return args, fmt.Errorf("Flag %s needs an argument", f.Name())
|
||||
}
|
||||
if f.WasSpecified && !f.IsMulti() {
|
||||
return args, fmt.Errorf("Flag %s can only be specified once", f.Name())
|
||||
}
|
||||
if isShort(param) && len(param) > 2 {
|
||||
// Short flag cluster
|
||||
args[0] = "-" + param[2:]
|
||||
} else if f.NeedsExtraValue() {
|
||||
value = args[1]
|
||||
args = args[2:]
|
||||
} else {
|
||||
args = args[1:]
|
||||
}
|
||||
f.WasSpecified = true
|
||||
return args, f.setValue(value)
|
||||
}
|
||||
240
vendor/github.com/voxelbrain/goptions/flagset.go
generated
vendored
Normal file
240
vendor/github.com/voxelbrain/goptions/flagset.go
generated
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A FlagSet represents one set of flags which belong to one particular program.
|
||||
// A FlagSet is also used to represent a subset of flags belonging to one verb.
|
||||
type FlagSet struct {
|
||||
// This HelpFunc will be called when PrintHelp() is called.
|
||||
HelpFunc
|
||||
// Name of the program. Might be used by HelpFunc.
|
||||
Name string
|
||||
helpFlag *Flag
|
||||
remainderFlag *Flag
|
||||
shortMap map[string]*Flag
|
||||
longMap map[string]*Flag
|
||||
verbFlag *Flag
|
||||
// Global option flags
|
||||
Flags []*Flag
|
||||
// Verbs and corresponding FlagSets
|
||||
Verbs map[string]*FlagSet
|
||||
parent *FlagSet
|
||||
}
|
||||
|
||||
// NewFlagSet returns a new FlagSet containing all the flags which result from
|
||||
// parsing the tags of the struct. Said struct as to be passed to the function
|
||||
// as a pointer.
|
||||
// If a tag line is erroneous, NewFlagSet() panics as this is considered a
|
||||
// compile time error rather than a runtme error.
|
||||
func NewFlagSet(name string, v interface{}) *FlagSet {
|
||||
structValue := reflect.ValueOf(v)
|
||||
if structValue.Kind() != reflect.Ptr {
|
||||
panic("Value type is not a pointer to a struct")
|
||||
}
|
||||
structValue = structValue.Elem()
|
||||
if structValue.Kind() != reflect.Struct {
|
||||
panic("Value type is not a pointer to a struct")
|
||||
}
|
||||
return newFlagset(name, structValue, nil)
|
||||
}
|
||||
|
||||
// Internal version which skips type checking and takes the "parent"'s
|
||||
// remainder flag as a parameter.
|
||||
func newFlagset(name string, structValue reflect.Value, parent *FlagSet) *FlagSet {
|
||||
var once sync.Once
|
||||
r := &FlagSet{
|
||||
Name: name,
|
||||
Flags: make([]*Flag, 0),
|
||||
HelpFunc: DefaultHelpFunc,
|
||||
parent: parent,
|
||||
}
|
||||
|
||||
if parent != nil && parent.remainderFlag != nil {
|
||||
r.remainderFlag = parent.remainderFlag
|
||||
}
|
||||
|
||||
var i int
|
||||
// Parse Option fields
|
||||
for i = 0; i < structValue.Type().NumField(); i++ {
|
||||
// Skip unexported fields
|
||||
if StartsWithLowercase(structValue.Type().Field(i).Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldValue := structValue.Field(i)
|
||||
tag := structValue.Type().Field(i).Tag.Get("goptions")
|
||||
flag, err := parseStructField(fieldValue, tag)
|
||||
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Invalid struct field: %s", err))
|
||||
}
|
||||
if fieldValue.Type().Name() == "Verbs" {
|
||||
r.verbFlag = flag
|
||||
break
|
||||
}
|
||||
if fieldValue.Type().Name() == "Help" {
|
||||
r.helpFlag = flag
|
||||
}
|
||||
if fieldValue.Type().Name() == "Remainder" && r.remainderFlag == nil {
|
||||
r.remainderFlag = flag
|
||||
}
|
||||
|
||||
if len(tag) != 0 {
|
||||
r.Flags = append(r.Flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse verb fields
|
||||
for i++; i < structValue.Type().NumField(); i++ {
|
||||
once.Do(func() {
|
||||
r.Verbs = make(map[string]*FlagSet)
|
||||
})
|
||||
fieldValue := structValue.Field(i)
|
||||
tag := structValue.Type().Field(i).Tag.Get("goptions")
|
||||
r.Verbs[tag] = newFlagset(tag, fieldValue, r)
|
||||
}
|
||||
r.createMaps()
|
||||
return r
|
||||
}
|
||||
|
||||
var (
|
||||
ErrHelpRequest = errors.New("Request for Help")
|
||||
)
|
||||
|
||||
// Parse takes the command line arguments and sets the corresponding values
|
||||
// in the FlagSet's struct.
|
||||
func (fs *FlagSet) Parse(args []string) (err error) {
|
||||
// Parse global flags
|
||||
for len(args) > 0 {
|
||||
if !((isLong(args[0]) && fs.hasLongFlag(args[0][2:])) ||
|
||||
(isShort(args[0]) && fs.hasShortFlag(args[0][1:2]))) {
|
||||
break
|
||||
}
|
||||
f := fs.FlagByName(args[0])
|
||||
args, err = f.Parse(args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if f == fs.helpFlag && f.WasSpecified {
|
||||
return ErrHelpRequest
|
||||
}
|
||||
}
|
||||
|
||||
// Process verb
|
||||
if len(args) > 0 {
|
||||
if verb, ok := fs.Verbs[args[0]]; ok {
|
||||
fs.verbFlag.value.Set(reflect.ValueOf(Verbs(args[0])))
|
||||
err := verb.Parse(args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args = args[0:0]
|
||||
}
|
||||
}
|
||||
|
||||
// Process remainder
|
||||
if len(args) > 0 {
|
||||
if fs.remainderFlag == nil {
|
||||
return fmt.Errorf("Invalid trailing arguments: %v", args)
|
||||
}
|
||||
remainder := reflect.MakeSlice(fs.remainderFlag.value.Type(), len(args), len(args))
|
||||
reflect.Copy(remainder, reflect.ValueOf(args))
|
||||
fs.remainderFlag.value.Set(remainder)
|
||||
}
|
||||
|
||||
// Check for unset, obligatory, single Flags
|
||||
for _, f := range fs.Flags {
|
||||
if f.Obligatory && !f.WasSpecified && len(f.MutexGroups) == 0 {
|
||||
return fmt.Errorf("%s must be specified", f.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// Check for multiple set Flags in one mutex group
|
||||
// Check also for unset, obligatory mutex groups
|
||||
mgs := fs.MutexGroups()
|
||||
for _, mg := range mgs {
|
||||
if !mg.IsValid() {
|
||||
return fmt.Errorf("Exactly one of %s must be specified", strings.Join(mg.Names(), ", "))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *FlagSet) createMaps() {
|
||||
fs.longMap = make(map[string]*Flag)
|
||||
fs.shortMap = make(map[string]*Flag)
|
||||
for _, flag := range fs.Flags {
|
||||
fs.longMap[flag.Long] = flag
|
||||
fs.shortMap[flag.Short] = flag
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *FlagSet) hasLongFlag(fname string) bool {
|
||||
_, ok := fs.longMap[fname]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (fs *FlagSet) hasShortFlag(fname string) bool {
|
||||
_, ok := fs.shortMap[fname]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (fs *FlagSet) FlagByName(fname string) *Flag {
|
||||
if isShort(fname) && fs.hasShortFlag(fname[1:2]) {
|
||||
return fs.shortMap[fname[1:2]]
|
||||
} else if isLong(fname) && fs.hasLongFlag(fname[2:]) {
|
||||
return fs.longMap[fname[2:]]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MutexGroups returns a map of Flag lists which contain mutually
|
||||
// exclusive flags.
|
||||
func (fs *FlagSet) MutexGroups() map[string]MutexGroup {
|
||||
r := make(map[string]MutexGroup)
|
||||
for _, f := range fs.Flags {
|
||||
for _, mg := range f.MutexGroups {
|
||||
if len(mg) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := r[mg]; !ok {
|
||||
r[mg] = make(MutexGroup, 0)
|
||||
}
|
||||
r[mg] = append(r[mg], f)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Prints the FlagSet's help to the given writer.
|
||||
func (fs *FlagSet) PrintHelp(w io.Writer) {
|
||||
fs.HelpFunc(w, fs)
|
||||
}
|
||||
|
||||
func (fs *FlagSet) ParseAndFail(w io.Writer, args []string) {
|
||||
err := fs.Parse(args)
|
||||
if err != nil {
|
||||
errCode := 0
|
||||
if err != ErrHelpRequest {
|
||||
errCode = 1
|
||||
fmt.Fprintf(w, "Error: %s\n", err)
|
||||
}
|
||||
fs.PrintHelp(w)
|
||||
os.Exit(errCode)
|
||||
}
|
||||
}
|
||||
|
||||
func StartsWithLowercase(s string) bool {
|
||||
if len(s) <= 0 {
|
||||
return false
|
||||
}
|
||||
return strings.ToLower(s)[0] == s[0]
|
||||
}
|
||||
99
vendor/github.com/voxelbrain/goptions/goptions.go
generated
vendored
Normal file
99
vendor/github.com/voxelbrain/goptions/goptions.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
package goptions implements a flexible parser for command line options.
|
||||
|
||||
Key targets were the support for both long and short flag versions, mutually
|
||||
exclusive flags, and verbs. Flags and their corresponding variables are defined
|
||||
by the tags in a (possibly anonymous) struct.
|
||||
|
||||
var options struct {
|
||||
Name string `goptions:"-n, --name"`
|
||||
Force bool `goptions:"-f, --force"`
|
||||
Verbosity int `goptions:"-v, --verbose"`
|
||||
}
|
||||
|
||||
Short flags can be combined (e.g. `-nfv`). Long flags take their value after a
|
||||
separating space. The equals notation (`--long-flag=value`) is NOT supported
|
||||
right now.
|
||||
|
||||
Every member of the struct which is supposed to catch a command line value
|
||||
has to have a "goptions" tag. The contains the short and long flag names for this
|
||||
member but can additionally specify any of these options below.
|
||||
|
||||
obligatory - Flag must be specified. Otherwise an error will be returned
|
||||
when Parse() is called.
|
||||
description='...' - Set the description for this particular flag. Will be
|
||||
used by the HelpFunc.
|
||||
mutexgroup='...' - Add this flag to a MutexGroup. Only one flag of the
|
||||
ones sharing a MutexGroup can be set. Otherwise an error
|
||||
will be returned when Parse() is called. If one flag in a
|
||||
MutexGroup is `obligatory` one flag of the group must be
|
||||
specified. A flag can be in multiple MutexGroups at once.
|
||||
|
||||
Depending on the type of the struct member, additional options might become available:
|
||||
|
||||
Type: *os.File
|
||||
The given string is interpreted as a path to a file. If the string is "-"
|
||||
os.Stdin or os.Stdout will be used. os.Stdin will be returned, if the
|
||||
`rdonly` flag was set. os.Stdout will be returned, if `wronly` was set.
|
||||
Available options:
|
||||
Any combination of create, append, rdonly, wronly, rdwr,
|
||||
excl, sync, trunc and perm can be specified and correspond directly with
|
||||
the combination of the homonymous flags in the os package.
|
||||
|
||||
Type: *net.TCPAddr
|
||||
The given string is interpreted as a tcp address. It is passed to
|
||||
net.ResolvTCPAddr() with "tcp" as the network type identifier.
|
||||
|
||||
Type: *net/url.URL
|
||||
The given string is parsed by net/url.Parse()
|
||||
|
||||
Type: time.Duration
|
||||
The given string is parsed by time.ParseDuration()
|
||||
|
||||
If a member is a slice type, multiple definitions of the flags are possible. For each
|
||||
specification the underlying type will be used.
|
||||
|
||||
var options struct {
|
||||
Servers []string `goptions:"-s, --server, description='Servers to connect to'"`
|
||||
}{}
|
||||
|
||||
goptions also has support for verbs. Each verb accepts its own set of flags which
|
||||
take exactly the same tag format as global options. For an usage example of verbs
|
||||
see the PrintHelp() example.
|
||||
*/
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
VERSION = "2.5.11"
|
||||
)
|
||||
|
||||
var (
|
||||
globalFlagSet *FlagSet
|
||||
)
|
||||
|
||||
// ParseAndFail is a convenience function to parse os.Args[1:] and print
|
||||
// the help if an error occurs. This should cover 90% of this library's
|
||||
// applications.
|
||||
func ParseAndFail(v interface{}) {
|
||||
globalFlagSet = NewFlagSet(filepath.Base(os.Args[0]), v)
|
||||
globalFlagSet.ParseAndFail(os.Stderr, os.Args[1:])
|
||||
}
|
||||
|
||||
// Parse parses the command-line flags from os.Args[1:].
|
||||
func Parse(v interface{}) error {
|
||||
globalFlagSet = NewFlagSet(filepath.Base(os.Args[0]), v)
|
||||
return globalFlagSet.Parse(os.Args[1:])
|
||||
}
|
||||
|
||||
// PrintHelp renders the default help to os.Stderr.
|
||||
func PrintHelp() {
|
||||
if globalFlagSet == nil {
|
||||
panic("Must call Parse() before PrintHelp()")
|
||||
}
|
||||
globalFlagSet.PrintHelp(os.Stderr)
|
||||
}
|
||||
72
vendor/github.com/voxelbrain/goptions/helpfunc.go
generated
vendored
Normal file
72
vendor/github.com/voxelbrain/goptions/helpfunc.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// HelpFunc is the signature of a function responsible for printing the help.
|
||||
type HelpFunc func(w io.Writer, fs *FlagSet)
|
||||
|
||||
// Generates a new HelpFunc taking a `text/template.Template`-formatted
|
||||
// string as an argument. The resulting template will be executed with the FlagSet
|
||||
// as its data.
|
||||
func NewTemplatedHelpFunc(tpl string) HelpFunc {
|
||||
var once sync.Once
|
||||
var t *template.Template
|
||||
return func(w io.Writer, fs *FlagSet) {
|
||||
once.Do(func() {
|
||||
t = template.Must(template.New("helpTemplate").Parse(tpl))
|
||||
})
|
||||
err := t.Execute(w, fs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
_DEFAULT_HELP = "\xffUsage: {{.Name}} [global options] {{with .Verbs}}<verb> [verb options]{{end}}\n" +
|
||||
"\n" +
|
||||
"Global options:\xff" +
|
||||
"{{range .Flags}}" +
|
||||
"\n\t" +
|
||||
"\t{{with .Short}}" + "-{{.}}," + "{{end}}" +
|
||||
"\t{{with .Long}}" + "--{{.}}" + "{{end}}" +
|
||||
"\t{{.Description}}" +
|
||||
"{{with .DefaultValue}}" +
|
||||
" (default: {{.}})" +
|
||||
"{{end}}" +
|
||||
"{{if .Obligatory}}" +
|
||||
" (*)" +
|
||||
"{{end}}" +
|
||||
"{{end}}" +
|
||||
"\xff\n\n{{with .Verbs}}Verbs:\xff" +
|
||||
"{{range .}}" +
|
||||
"\xff\n {{.Name}}:\xff" +
|
||||
"{{range .Flags}}" +
|
||||
"\n\t" +
|
||||
"\t{{with .Short}}" + "-{{.}}," + "{{end}}" +
|
||||
"\t{{with .Long}}" + "--{{.}}" + "{{end}}" +
|
||||
"\t{{.Description}}" +
|
||||
"{{with .DefaultValue}}" +
|
||||
" (default: {{.}})" +
|
||||
"{{end}}" +
|
||||
"{{if .Obligatory}}" +
|
||||
" (*)" +
|
||||
"{{end}}" +
|
||||
"{{end}}" +
|
||||
"{{end}}" +
|
||||
"{{end}}" +
|
||||
"\n"
|
||||
)
|
||||
|
||||
// DefaultHelpFunc is a HelpFunc which renders the default help template and pipes
|
||||
// the output through a text/tabwriter.Writer before flushing it to the output.
|
||||
func DefaultHelpFunc(w io.Writer, fs *FlagSet) {
|
||||
tw := tabwriter.NewWriter(w, 4, 4, 1, ' ', tabwriter.StripEscape|tabwriter.DiscardEmptyColumns)
|
||||
NewTemplatedHelpFunc(_DEFAULT_HELP)(tw, fs)
|
||||
tw.Flush()
|
||||
}
|
||||
5
vendor/github.com/voxelbrain/goptions/marshaler.go
generated
vendored
Normal file
5
vendor/github.com/voxelbrain/goptions/marshaler.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
package goptions
|
||||
|
||||
type Marshaler interface {
|
||||
MarshalGoption(s string) error
|
||||
}
|
||||
48
vendor/github.com/voxelbrain/goptions/mutexgroup.go
generated
vendored
Normal file
48
vendor/github.com/voxelbrain/goptions/mutexgroup.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package goptions
|
||||
|
||||
// A MutexGroup holds a set of flags which are mutually exclusive and cannot
|
||||
// be specified at the same time.
|
||||
type MutexGroup []*Flag
|
||||
|
||||
// IsObligatory returns true if exactly one of the flags in the MutexGroup has
|
||||
// to be specified
|
||||
func (mg MutexGroup) IsObligatory() bool {
|
||||
for _, flag := range mg {
|
||||
if flag.Obligatory {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (mg MutexGroup) WasSpecified() bool {
|
||||
for _, flag := range mg {
|
||||
if flag.WasSpecified {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsValid checks if the flags in the MutexGroup describe a valid state.
|
||||
// I.e. At most one has been specified or – if it is an obligatory MutexGroup –
|
||||
// exactly one has been specified.
|
||||
func (mg MutexGroup) IsValid() bool {
|
||||
c := 0
|
||||
for _, flag := range mg {
|
||||
if flag.WasSpecified {
|
||||
c++
|
||||
}
|
||||
}
|
||||
return c <= 1 && (!mg.IsObligatory() || c == 1)
|
||||
}
|
||||
|
||||
// Names is a convenience function to return the array of names of the flags
|
||||
// in the MutexGroup.
|
||||
func (mg MutexGroup) Names() []string {
|
||||
r := make([]string, len(mg))
|
||||
for i, flag := range mg {
|
||||
r[i] = flag.Name()
|
||||
}
|
||||
return r
|
||||
}
|
||||
136
vendor/github.com/voxelbrain/goptions/options.go
generated
vendored
Normal file
136
vendor/github.com/voxelbrain/goptions/options.go
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type optionFunc func(f *Flag, option, value string) error
|
||||
type optionMap map[string]optionFunc
|
||||
|
||||
var (
|
||||
typeOptionMap = map[reflect.Type]optionMap{
|
||||
// Global options
|
||||
nil: optionMap{
|
||||
"description": description,
|
||||
"obligatory": obligatory,
|
||||
"mutexgroup": mutexgroup,
|
||||
},
|
||||
reflect.TypeOf(new(time.Time)).Elem(): optionMap{
|
||||
"format": time_format,
|
||||
},
|
||||
reflect.TypeOf(new(*os.File)).Elem(): optionMap{
|
||||
"create": initOptionMeta(file_create, "file_mode", 0),
|
||||
"append": initOptionMeta(file_append, "file_mode", 0),
|
||||
"rdonly": initOptionMeta(file_rdonly, "file_mode", 0),
|
||||
"wronly": initOptionMeta(file_wronly, "file_mode", 0),
|
||||
"rdwr": initOptionMeta(file_rdwr, "file_mode", 0),
|
||||
"excl": initOptionMeta(file_excl, "file_mode", 0),
|
||||
"sync": initOptionMeta(file_sync, "file_mode", 0),
|
||||
"trunc": initOptionMeta(file_trunc, "file_mode", 0),
|
||||
"perm": file_perm,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Wraps another optionFunc and inits optionMeta[field] with value if it does
|
||||
// not have one already.
|
||||
func initOptionMeta(fn optionFunc, field string, init_value interface{}) optionFunc {
|
||||
return func(f *Flag, option, value string) error {
|
||||
if _, ok := f.optionMeta[field]; !ok {
|
||||
f.optionMeta[field] = init_value
|
||||
}
|
||||
return fn(f, option, value)
|
||||
}
|
||||
}
|
||||
|
||||
func description(f *Flag, option, value string) error {
|
||||
f.Description = strings.Replace(value, `\`, ``, -1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func obligatory(f *Flag, option, value string) error {
|
||||
f.Obligatory = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func mutexgroup(f *Flag, option, value string) error {
|
||||
if len(value) <= 0 {
|
||||
return fmt.Errorf("Mutexgroup option needs a value")
|
||||
}
|
||||
for _, group := range strings.Split(value, ",") {
|
||||
f.MutexGroups = append(f.MutexGroups, group)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_create(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_CREATE
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_append(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_APPEND
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_rdonly(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_RDONLY
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_wronly(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_WRONLY
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_rdwr(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_RDWR
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_excl(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_EXCL
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_sync(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_SYNC
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_trunc(f *Flag, option, value string) error {
|
||||
f.optionMeta["file_mode"] = f.optionMeta["file_mode"].(int) | os.O_TRUNC
|
||||
return nil
|
||||
}
|
||||
|
||||
func file_perm(f *Flag, option, value string) error {
|
||||
perm, err := strconv.ParseInt(value, 8, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.optionMeta["file_perm"] = uint32(perm)
|
||||
return nil
|
||||
}
|
||||
|
||||
func time_format(f *Flag, option, value string) error {
|
||||
f.optionMeta["format"] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func optionMapForType(t reflect.Type) optionMap {
|
||||
g := typeOptionMap[nil]
|
||||
m, _ := typeOptionMap[t]
|
||||
r := make(optionMap)
|
||||
for k, v := range g {
|
||||
r[k] = v
|
||||
}
|
||||
for k, v := range m {
|
||||
r[k] = v
|
||||
}
|
||||
return r
|
||||
}
|
||||
14
vendor/github.com/voxelbrain/goptions/special_types.go
generated
vendored
Normal file
14
vendor/github.com/voxelbrain/goptions/special_types.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package goptions
|
||||
|
||||
// Help Defines the common help flag. It is handled separately as it will cause
|
||||
// Parse() to return ErrHelpRequest.
|
||||
type Help bool
|
||||
|
||||
// Verbs marks the point in the struct where the verbs start. Its value will be
|
||||
// the name of the selected verb.
|
||||
type Verbs string
|
||||
|
||||
// A remainder catches all excessive arguments. If both a verb and
|
||||
// the containing options struct have a remainder field, only the latter one
|
||||
// will be used.
|
||||
type Remainder []string
|
||||
68
vendor/github.com/voxelbrain/goptions/tagparser.go
generated
vendored
Normal file
68
vendor/github.com/voxelbrain/goptions/tagparser.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
_LONG_FLAG_REGEXP = `--[[:word:]-]+`
|
||||
_SHORT_FLAG_REGEXP = `-[[:alnum:]]`
|
||||
_QUOTED_STRING_REGEXP = `'((?:\\'|[^\\'])+)'`
|
||||
_OPTION_REGEXP = `([[:word:]-]+)(?:=` + _QUOTED_STRING_REGEXP + `)?`
|
||||
)
|
||||
|
||||
var (
|
||||
optionRegexp = regexp.MustCompile(`^(` + strings.Join([]string{_SHORT_FLAG_REGEXP, _LONG_FLAG_REGEXP, _OPTION_REGEXP}, "|") + `)(?:,|$)`)
|
||||
)
|
||||
|
||||
func parseStructField(fieldValue reflect.Value, tag string) (*Flag, error) {
|
||||
f := &Flag{
|
||||
value: fieldValue,
|
||||
DefaultValue: fieldValue.Interface(),
|
||||
optionMeta: make(map[string]interface{}),
|
||||
}
|
||||
for {
|
||||
tag = strings.TrimSpace(tag)
|
||||
if len(tag) == 0 {
|
||||
break
|
||||
}
|
||||
idx := optionRegexp.FindStringSubmatchIndex(tag)
|
||||
if idx == nil {
|
||||
return nil, fmt.Errorf("Could not find a valid flag definition at the beginning of \"%s\"", tag)
|
||||
}
|
||||
option := tag[idx[2]:idx[3]]
|
||||
|
||||
if strings.HasPrefix(option, "--") {
|
||||
if f.Long != "" {
|
||||
return nil, fmt.Errorf("Multiple flags assigned to a member: %s", strings.Join([]string{"--" + f.Long, option}, ", "))
|
||||
}
|
||||
f.Long = option[2:]
|
||||
} else if strings.HasPrefix(option, "-") {
|
||||
if f.Short != "" {
|
||||
return nil, fmt.Errorf("Multiple flags assigned to a member: %s", strings.Join([]string{"-" + f.Short, option}, ", "))
|
||||
}
|
||||
f.Short = option[1:]
|
||||
} else {
|
||||
option := tag[idx[4]:idx[5]]
|
||||
value := ""
|
||||
if idx[6] != -1 {
|
||||
value = tag[idx[6]:idx[7]]
|
||||
}
|
||||
optionmap := optionMapForType(fieldValue.Type())
|
||||
opf, ok := optionmap[option]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Unknown option %s", option)
|
||||
}
|
||||
err := opf(f, option, value)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Option %s invalid: %s", option, err)
|
||||
}
|
||||
}
|
||||
// Keep remainder
|
||||
tag = tag[idx[1]:]
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
163
vendor/github.com/voxelbrain/goptions/valueparser.go
generated
vendored
Normal file
163
vendor/github.com/voxelbrain/goptions/valueparser.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
package goptions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type valueParser func(f *Flag, val string) (reflect.Value, error)
|
||||
|
||||
var (
|
||||
parserMap = map[reflect.Type]valueParser{
|
||||
reflect.TypeOf(new(bool)).Elem(): boolValueParser,
|
||||
reflect.TypeOf(new(string)).Elem(): stringValueParser,
|
||||
reflect.TypeOf(new(float64)).Elem(): float64ValueParser,
|
||||
reflect.TypeOf(new(float32)).Elem(): float32ValueParser,
|
||||
reflect.TypeOf(new(int)).Elem(): intValueParser,
|
||||
reflect.TypeOf(new(int64)).Elem(): int64ValueParser,
|
||||
reflect.TypeOf(new(int32)).Elem(): int32ValueParser,
|
||||
reflect.TypeOf(new(Help)).Elem(): helpValueParser,
|
||||
reflect.TypeOf(new(*os.File)).Elem(): fileValueParser,
|
||||
reflect.TypeOf(new(*net.TCPAddr)).Elem(): tcpAddrValueParser,
|
||||
reflect.TypeOf(new(*url.URL)).Elem(): urlValueParser,
|
||||
reflect.TypeOf(new(time.Duration)).Elem(): durationValueParser,
|
||||
reflect.TypeOf(new(time.Time)).Elem(): timeValueParser,
|
||||
}
|
||||
)
|
||||
|
||||
func parseMarshalValue(value reflect.Value, s string) error {
|
||||
newval := reflect.New(value.Type()).Elem()
|
||||
if newval.Kind() == reflect.Ptr {
|
||||
newptrval := reflect.New(value.Type().Elem())
|
||||
newval.Set(newptrval)
|
||||
}
|
||||
err := newval.Interface().(Marshaler).MarshalGoption(s)
|
||||
value.Set(newval)
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *Flag) setValue(s string) (err error) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
err = x.(error)
|
||||
return
|
||||
}
|
||||
}()
|
||||
if f.value.Type().Implements(reflect.TypeOf(new(Marshaler)).Elem()) {
|
||||
return parseMarshalValue(f.value, s)
|
||||
}
|
||||
vtype := f.value.Type()
|
||||
newval := reflect.New(vtype).Elem()
|
||||
if f.value.Kind() == reflect.Slice {
|
||||
vtype = f.value.Type().Elem()
|
||||
if vtype.Implements(reflect.TypeOf(new(Marshaler)).Elem()) {
|
||||
newval = reflect.New(vtype).Elem()
|
||||
err := parseMarshalValue(newval, s)
|
||||
f.value.Set(reflect.Append(f.value, newval))
|
||||
return err
|
||||
}
|
||||
}
|
||||
if parser, ok := parserMap[vtype]; ok {
|
||||
val, err := parser(f, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.value.Kind() == reflect.Slice {
|
||||
f.value.Set(reflect.Append(f.value, val))
|
||||
} else {
|
||||
f.value.Set(val)
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("Unsupported flag type: %s", f.value.Type())
|
||||
}
|
||||
panic("Invalid execution path")
|
||||
}
|
||||
|
||||
func boolValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
return reflect.ValueOf(true), nil
|
||||
}
|
||||
|
||||
func stringValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
return reflect.ValueOf(val), nil
|
||||
}
|
||||
|
||||
func float64ValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
floatval, err := strconv.ParseFloat(val, 64)
|
||||
return reflect.ValueOf(float64(floatval)), err
|
||||
}
|
||||
|
||||
func float32ValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
floatval, err := strconv.ParseFloat(val, 32)
|
||||
return reflect.ValueOf(float32(floatval)), err
|
||||
}
|
||||
|
||||
func int64ValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
intval, err := strconv.ParseInt(val, 10, 64)
|
||||
return reflect.ValueOf(int64(intval)), err
|
||||
}
|
||||
|
||||
func int32ValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
intval, err := strconv.ParseInt(val, 10, 32)
|
||||
return reflect.ValueOf(int32(intval)), err
|
||||
}
|
||||
|
||||
func intValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
intval, err := strconv.ParseInt(val, 10, 64)
|
||||
return reflect.ValueOf(int(intval)), err
|
||||
}
|
||||
|
||||
func fileValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
mode := 0
|
||||
if v, ok := f.optionMeta["file_mode"]; ok {
|
||||
mode = v.(int)
|
||||
}
|
||||
if val == "-" {
|
||||
if mode&1 == os.O_RDONLY {
|
||||
return reflect.ValueOf(os.Stdin), nil
|
||||
} else if mode&1 == os.O_WRONLY {
|
||||
return reflect.ValueOf(os.Stdout), nil
|
||||
}
|
||||
} else {
|
||||
perm := uint32(0644)
|
||||
if v, ok := f.optionMeta["file_perm"].(uint32); ok {
|
||||
perm = v
|
||||
}
|
||||
f, e := os.OpenFile(val, mode, os.FileMode(perm))
|
||||
return reflect.ValueOf(f), e
|
||||
}
|
||||
panic("Invalid execution path")
|
||||
}
|
||||
|
||||
func tcpAddrValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
addr, err := net.ResolveTCPAddr("tcp", val)
|
||||
return reflect.ValueOf(addr), err
|
||||
}
|
||||
|
||||
func urlValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
url, err := url.Parse(val)
|
||||
return reflect.ValueOf(url), err
|
||||
}
|
||||
|
||||
func durationValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
d, err := time.ParseDuration(val)
|
||||
return reflect.ValueOf(d), err
|
||||
}
|
||||
|
||||
func timeValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
format := time.RFC3339
|
||||
if altFormat, ok := f.optionMeta["format"]; ok {
|
||||
format = altFormat.(string)
|
||||
}
|
||||
d, err := time.Parse(format, val)
|
||||
return reflect.ValueOf(d), err
|
||||
}
|
||||
|
||||
func helpValueParser(f *Flag, val string) (reflect.Value, error) {
|
||||
return reflect.Value{}, ErrHelpRequest
|
||||
}
|
||||
Reference in New Issue
Block a user