0 Star 0 Fork 0

蒋佳李/vault

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
base_flags.go 16.46 KB
一键复制 编辑 原始数据 按行查看 历史
蒋佳李 提交于 2021-03-25 16:28 . 更新
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
package command
import (
"flag"
"fmt"
"os"
"sort"
"strconv"
"strings"
"time"
"gitee.com/jiangjiali/vault/sdk/helper/complete"
)
// FlagExample is an interface which declares an example value.
type FlagExample interface {
Example() string
}
// FlagVisibility is an interface which declares whether a flag should be
// hidden from help and completions. This is usually used for deprecations
// on "internal-only" flags.
type FlagVisibility interface {
Hidden() bool
}
// FlagBool is an interface which boolean flags implement.
type FlagBool interface {
IsBoolFlag() bool
}
// -- BoolVar and boolValue
type BoolVar struct {
Name string
Aliases []string
Usage string
Default bool
Hidden bool
EnvVar string
Target *bool
Completion complete.Predictor
}
func (f *FlagSet) BoolVar(i *BoolVar) {
def := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if b, err := strconv.ParseBool(v); err == nil {
def = b
}
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: strconv.FormatBool(i.Default),
EnvVar: i.EnvVar,
Value: newBoolValue(def, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type boolValue struct {
hidden bool
target *bool
}
func newBoolValue(def bool, target *bool, hidden bool) *boolValue {
*target = def
return &boolValue{
hidden: hidden,
target: target,
}
}
func (b *boolValue) Set(s string) error {
v, err := strconv.ParseBool(s)
if err != nil {
return err
}
*b.target = v
return nil
}
func (b *boolValue) Get() interface{} { return *b.target }
func (b *boolValue) String() string { return strconv.FormatBool(*b.target) }
func (b *boolValue) Example() string { return "" }
func (b *boolValue) Hidden() bool { return b.hidden }
func (b *boolValue) IsBoolFlag() bool { return true }
// -- IntVar and intValue
type IntVar struct {
Name string
Aliases []string
Usage string
Default int
Hidden bool
EnvVar string
Target *int
Completion complete.Predictor
}
func (f *FlagSet) IntVar(i *IntVar) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseInt(v, 0, 64); err == nil {
initial = int(i)
}
}
def := ""
if i.Default != 0 {
def = strconv.FormatInt(int64(i.Default), 10)
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newIntValue(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type intValue struct {
hidden bool
target *int
}
func newIntValue(def int, target *int, hidden bool) *intValue {
*target = def
return &intValue{
hidden: hidden,
target: target,
}
}
func (i *intValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
if err != nil {
return err
}
*i.target = int(v)
return nil
}
func (i *intValue) Get() interface{} { return *i.target }
func (i *intValue) String() string { return strconv.Itoa(*i.target) }
func (i *intValue) Example() string { return "int" }
func (i *intValue) Hidden() bool { return i.hidden }
// -- Int64Var and int64Value
type Int64Var struct {
Name string
Aliases []string
Usage string
Default int64
Hidden bool
EnvVar string
Target *int64
Completion complete.Predictor
}
func (f *FlagSet) Int64Var(i *Int64Var) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseInt(v, 0, 64); err == nil {
initial = i
}
}
def := ""
if i.Default != 0 {
def = strconv.FormatInt(i.Default, 10)
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newInt64Value(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type int64Value struct {
hidden bool
target *int64
}
func newInt64Value(def int64, target *int64, hidden bool) *int64Value {
*target = def
return &int64Value{
hidden: hidden,
target: target,
}
}
func (i *int64Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
if err != nil {
return err
}
*i.target = v
return nil
}
func (i *int64Value) Get() interface{} { return *i.target }
func (i *int64Value) String() string { return strconv.FormatInt(*i.target, 10) }
func (i *int64Value) Example() string { return "int" }
func (i *int64Value) Hidden() bool { return i.hidden }
// -- UintVar && uintValue
type UintVar struct {
Name string
Aliases []string
Usage string
Default uint
Hidden bool
EnvVar string
Target *uint
Completion complete.Predictor
}
func (f *FlagSet) UintVar(i *UintVar) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseUint(v, 0, 64); err == nil {
initial = uint(i)
}
}
def := ""
if i.Default != 0 {
def = strconv.FormatUint(uint64(i.Default), 10)
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newUintValue(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type uintValue struct {
hidden bool
target *uint
}
func newUintValue(def uint, target *uint, hidden bool) *uintValue {
*target = def
return &uintValue{
hidden: hidden,
target: target,
}
}
func (i *uintValue) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
if err != nil {
return err
}
*i.target = uint(v)
return nil
}
func (i *uintValue) Get() interface{} { return *i.target }
func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i.target), 10) }
func (i *uintValue) Example() string { return "uint" }
func (i *uintValue) Hidden() bool { return i.hidden }
// -- Uint64Var and uint64Value
type Uint64Var struct {
Name string
Aliases []string
Usage string
Default uint64
Hidden bool
EnvVar string
Target *uint64
Completion complete.Predictor
}
func (f *FlagSet) Uint64Var(i *Uint64Var) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseUint(v, 0, 64); err == nil {
initial = i
}
}
def := ""
if i.Default != 0 {
strconv.FormatUint(i.Default, 10)
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newUint64Value(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type uint64Value struct {
hidden bool
target *uint64
}
func newUint64Value(def uint64, target *uint64, hidden bool) *uint64Value {
*target = def
return &uint64Value{
hidden: hidden,
target: target,
}
}
func (i *uint64Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
if err != nil {
return err
}
*i.target = v
return nil
}
func (i *uint64Value) Get() interface{} { return *i.target }
func (i *uint64Value) String() string { return strconv.FormatUint(*i.target, 10) }
func (i *uint64Value) Example() string { return "uint" }
func (i *uint64Value) Hidden() bool { return i.hidden }
// -- StringVar and stringValue
type StringVar struct {
Name string
Aliases []string
Usage string
Default string
Hidden bool
EnvVar string
Target *string
Completion complete.Predictor
}
func (f *FlagSet) StringVar(i *StringVar) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
initial = v
}
def := ""
if i.Default != "" {
def = i.Default
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newStringValue(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type stringValue struct {
hidden bool
target *string
}
func newStringValue(def string, target *string, hidden bool) *stringValue {
*target = def
return &stringValue{
hidden: hidden,
target: target,
}
}
func (s *stringValue) Set(val string) error {
*s.target = val
return nil
}
func (s *stringValue) Get() interface{} { return *s.target }
func (s *stringValue) String() string { return *s.target }
func (s *stringValue) Example() string { return "string" }
func (s *stringValue) Hidden() bool { return s.hidden }
// -- Float64Var and float64Value
type Float64Var struct {
Name string
Aliases []string
Usage string
Default float64
Hidden bool
EnvVar string
Target *float64
Completion complete.Predictor
}
func (f *FlagSet) Float64Var(i *Float64Var) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if i, err := strconv.ParseFloat(v, 64); err == nil {
initial = i
}
}
def := ""
if i.Default != 0 {
def = strconv.FormatFloat(i.Default, 'e', -1, 64)
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newFloat64Value(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type float64Value struct {
hidden bool
target *float64
}
func newFloat64Value(def float64, target *float64, hidden bool) *float64Value {
*target = def
return &float64Value{
hidden: hidden,
target: target,
}
}
func (f *float64Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 64)
if err != nil {
return err
}
*f.target = v
return nil
}
func (f *float64Value) Get() interface{} { return *f.target }
func (f *float64Value) String() string { return strconv.FormatFloat(*f.target, 'g', -1, 64) }
func (f *float64Value) Example() string { return "float" }
func (f *float64Value) Hidden() bool { return f.hidden }
// -- DurationVar and durationValue
type DurationVar struct {
Name string
Aliases []string
Usage string
Default time.Duration
Hidden bool
EnvVar string
Target *time.Duration
Completion complete.Predictor
}
func (f *FlagSet) DurationVar(i *DurationVar) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
if d, err := time.ParseDuration(appendDurationSuffix(v)); err == nil {
initial = d
}
}
def := ""
if i.Default != 0 {
def = i.Default.String()
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newDurationValue(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type durationValue struct {
hidden bool
target *time.Duration
}
func newDurationValue(def time.Duration, target *time.Duration, hidden bool) *durationValue {
*target = def
return &durationValue{
hidden: hidden,
target: target,
}
}
func (d *durationValue) Set(s string) error {
// Maintain bc for people specifying "system" as the value.
if s == "system" {
s = "-1"
}
v, err := time.ParseDuration(appendDurationSuffix(s))
if err != nil {
return err
}
*d.target = v
return nil
}
func (d *durationValue) Get() interface{} { return *d.target }
func (d *durationValue) String() string { return (*d.target).String() }
func (d *durationValue) Example() string { return "duration" }
func (d *durationValue) Hidden() bool { return d.hidden }
// appendDurationSuffix is used as a backwards-compat tool for assuming users
// meant "seconds" when they do not provide a suffixed duration value.
func appendDurationSuffix(s string) string {
if strings.HasSuffix(s, "s") || strings.HasSuffix(s, "m") || strings.HasSuffix(s, "h") {
return s
}
return s + "s"
}
// -- StringSliceVar and stringSliceValue
type StringSliceVar struct {
Name string
Aliases []string
Usage string
Default []string
Hidden bool
EnvVar string
Target *[]string
Completion complete.Predictor
}
func (f *FlagSet) StringSliceVar(i *StringSliceVar) {
initial := i.Default
if v, exist := os.LookupEnv(i.EnvVar); exist {
parts := strings.Split(v, ",")
for i := range parts {
parts[i] = strings.TrimSpace(parts[i])
}
initial = parts
}
def := ""
if i.Default != nil {
def = strings.Join(i.Default, ",")
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
EnvVar: i.EnvVar,
Value: newStringSliceValue(initial, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type stringSliceValue struct {
hidden bool
target *[]string
}
func newStringSliceValue(def []string, target *[]string, hidden bool) *stringSliceValue {
*target = def
return &stringSliceValue{
hidden: hidden,
target: target,
}
}
func (s *stringSliceValue) Set(val string) error {
*s.target = append(*s.target, strings.TrimSpace(val))
return nil
}
func (s *stringSliceValue) Get() interface{} { return *s.target }
func (s *stringSliceValue) String() string { return strings.Join(*s.target, ",") }
func (s *stringSliceValue) Example() string { return "string" }
func (s *stringSliceValue) Hidden() bool { return s.hidden }
// -- StringMapVar and stringMapValue
type StringMapVar struct {
Name string
Aliases []string
Usage string
Default map[string]string
Hidden bool
Target *map[string]string
Completion complete.Predictor
}
func (f *FlagSet) StringMapVar(i *StringMapVar) {
def := ""
if i.Default != nil {
def = mapToKV(i.Default)
}
f.VarFlag(&VarFlag{
Name: i.Name,
Aliases: i.Aliases,
Usage: i.Usage,
Default: def,
Value: newStringMapValue(i.Default, i.Target, i.Hidden),
Completion: i.Completion,
})
}
type stringMapValue struct {
hidden bool
target *map[string]string
}
func newStringMapValue(def map[string]string, target *map[string]string, hidden bool) *stringMapValue {
*target = def
return &stringMapValue{
hidden: hidden,
target: target,
}
}
func (s *stringMapValue) Set(val string) error {
idx := strings.Index(val, "=")
if idx == -1 {
return fmt.Errorf("missing = in KV pair: %q", val)
}
if *s.target == nil {
*s.target = make(map[string]string)
}
k, v := val[0:idx], val[idx+1:]
(*s.target)[k] = v
return nil
}
func (s *stringMapValue) Get() interface{} { return *s.target }
func (s *stringMapValue) String() string { return mapToKV(*s.target) }
func (s *stringMapValue) Example() string { return "key=value" }
func (s *stringMapValue) Hidden() bool { return s.hidden }
func mapToKV(m map[string]string) string {
list := make([]string, 0, len(m))
for k := range m {
list = append(list, k)
}
sort.Strings(list)
for i, k := range list {
list[i] = k + "=" + m[k]
}
return strings.Join(list, ",")
}
// -- VarFlag
type VarFlag struct {
Name string
Aliases []string
Usage string
Default string
EnvVar string
Value flag.Value
Completion complete.Predictor
}
func (f *FlagSet) VarFlag(i *VarFlag) {
// If the flag is marked as hidden, just add it to the set and return to
// avoid unnecessary computations here. We do not want to add completions or
// generate help output for hidden flags.
if v, ok := i.Value.(FlagVisibility); ok && v.Hidden() {
f.Var(i.Value, i.Name, "")
return
}
// Calculate the full usage
usage := i.Usage
if len(i.Aliases) > 0 {
sentence := make([]string, len(i.Aliases))
for i, a := range i.Aliases {
sentence[i] = fmt.Sprintf(`"-%s"`, a)
}
aliases := ""
switch len(sentence) {
case 0:
// impossible...
case 1:
aliases = sentence[0]
case 2:
aliases = sentence[0] + " 和 " + sentence[1]
default:
sentence[len(sentence)-1] = "和 " + sentence[len(sentence)-1]
aliases = strings.Join(sentence, ",")
}
usage += fmt.Sprintf(" 别名为%s。", aliases)
}
if i.Default != "" {
usage += fmt.Sprintf(" 默认值是%s。", i.Default)
}
if i.EnvVar != "" {
usage += fmt.Sprintf(" 可以通过%s环境变量指定。", i.EnvVar)
}
// Add aliases to the main set
for _, a := range i.Aliases {
f.mainSet.Var(i.Value, a, "")
}
f.Var(i.Value, i.Name, usage)
f.completions["-"+i.Name] = i.Completion
}
// Var is a lower-level API for adding something to the flags. It should be used
// with caution, since it bypasses all validation. Consider VarFlag instead.
func (f *FlagSet) Var(value flag.Value, name, usage string) {
f.mainSet.Var(value, name, usage)
f.flagSet.Var(value, name, usage)
}
// -- helpers
func envDefault(key, def string) string {
if v, exist := os.LookupEnv(key); exist {
return v
}
return def
}
func envBoolDefault(key string, def bool) bool {
if v, exist := os.LookupEnv(key); exist {
b, err := strconv.ParseBool(v)
if err != nil {
panic(err)
}
return b
}
return def
}
func envDurationDefault(key string, def time.Duration) time.Duration {
if v, exist := os.LookupEnv(key); exist {
d, err := time.ParseDuration(v)
if err != nil {
panic(err)
}
return d
}
return def
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/jiangjiali/vault.git
git@gitee.com:jiangjiali/vault.git
jiangjiali
vault
vault
v1.1.10

搜索帮助