Skip to content

Commit

Permalink
Merge pull request #122 from posener/gen
Browse files Browse the repository at this point in the history
Autogenerate compflag code
  • Loading branch information
posener authored May 9, 2020
2 parents e6d850d + 41182b0 commit be08f3c
Show file tree
Hide file tree
Showing 4 changed files with 419 additions and 172 deletions.
182 changes: 10 additions & 172 deletions compflag/compflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,11 @@ package compflag

import (
"flag"
"fmt"
"os"
"strconv"
"time"

"github.com/posener/complete/v2"
"github.com/posener/complete/v2/predict"
)

// FlagSet is bash completion enabled flag.FlagSet.
Expand All @@ -69,30 +67,6 @@ func (fs *FlagSet) Complete() {
complete.Complete(fs.Name(), complete.FlagSet((*flag.FlagSet)(CommandLine)))
}

func (fs *FlagSet) String(name string, value string, usage string, options ...predict.Option) *string {
p := new(string)
(*flag.FlagSet)(fs).Var(newStringValue(value, p, predict.Options(options...)), name, usage)
return p
}

func (fs *FlagSet) Bool(name string, value bool, usage string, options ...predict.Option) *bool {
p := new(bool)
(*flag.FlagSet)(fs).Var(newBoolValue(value, p, predict.Options(options...)), name, usage)
return p
}

func (fs *FlagSet) Int(name string, value int, usage string, options ...predict.Option) *int {
p := new(int)
(*flag.FlagSet)(fs).Var(newIntValue(value, p, predict.Options(options...)), name, usage)
return p
}

func (fs *FlagSet) Duration(name string, value time.Duration, usage string, options ...predict.Option) *time.Duration {
p := new(time.Duration)
(*flag.FlagSet)(fs).Var(newDurationValue(value, p, predict.Options(options...)), name, usage)
return p
}

var CommandLine = (*FlagSet)(flag.CommandLine)

// Parse parses command line arguments. It also performs bash completion when needed.
Expand All @@ -101,164 +75,28 @@ func Parse() {
CommandLine.Parse(os.Args[1:])
}

func String(name string, value string, usage string, options ...predict.Option) *string {
return CommandLine.String(name, value, usage, options...)
}

func Bool(name string, value bool, usage string, options ...predict.Option) *bool {
return CommandLine.Bool(name, value, usage, options...)
}

func Int(name string, value int, usage string, options ...predict.Option) *int {
return CommandLine.Int(name, value, usage, options...)
}

func Duration(name string, value time.Duration, usage string, options ...predict.Option) *time.Duration {
return CommandLine.Duration(name, value, usage, options...)
}

type boolValue struct {
v *bool
predict.Config
}

func newBoolValue(val bool, p *bool, c predict.Config) *boolValue {
*p = val
return &boolValue{v: p, Config: c}
}

func (b *boolValue) Set(val string) error {
v, err := strconv.ParseBool(val)
*b.v = v
if err != nil {
return fmt.Errorf("bad value for bool flag")
}
return b.Check(val)
}

func (b *boolValue) Get() interface{} { return *b.v }

func (b *boolValue) String() string {
if b == nil || b.v == nil {
return strconv.FormatBool(false)
}
return strconv.FormatBool(*b.v)
}

func (b *boolValue) IsBoolFlag() bool { return true }

func (b *boolValue) Predict(prefix string) []string {
if b.Predictor != nil {
return b.Predictor.Predict(prefix)
}
func predictBool(value bool, prefix string) []string {
// If false, typing the bool flag is expected to turn it on, so there is nothing to complete
// after the flag.
if !*b.v {
if !value {
return nil
}
// Otherwise, suggest only to turn it off.
return []string{"false"}
}

type stringValue struct {
v *string
predict.Config
}
func parseString(s string) (string, error) { return s, nil }

func newStringValue(val string, p *string, c predict.Config) *stringValue {
*p = val
return &stringValue{v: p, Config: c}
}
func formatString(v string) string { return v }

func (s *stringValue) Set(val string) error {
*s.v = val
return s.Check(val)
}
func parseInt(s string) (int, error) { return strconv.Atoi(s) }

func (s *stringValue) Get() interface{} {
return *s.v
}

func (s *stringValue) String() string {
if s == nil || s.v == nil {
return ""
}
return *s.v
}

func (s *stringValue) Predict(prefix string) []string {
if s.Predictor != nil {
return s.Predictor.Predict(prefix)
}
return []string{""}
}

type intValue struct {
v *int
predict.Config
}

func newIntValue(val int, p *int, c predict.Config) *intValue {
*p = val
return &intValue{v: p, Config: c}
}
func formatInt(v int) string { return strconv.Itoa(v) }

func (i *intValue) Set(val string) error {
v, err := strconv.ParseInt(val, 0, strconv.IntSize)
*i.v = int(v)
if err != nil {
return fmt.Errorf("bad value for int flag")
}
return i.Check(val)
}
func parseBool(s string) (bool, error) { return strconv.ParseBool(s) }

func (i *intValue) Get() interface{} { return *i.v }
func formatBool(v bool) string { return strconv.FormatBool(v) }

func (i *intValue) String() string {
if i == nil || i.v == nil {
return strconv.Itoa(0)
}
return strconv.Itoa(*i.v)
}
func parseDuration(s string) (time.Duration, error) { return time.ParseDuration(s) }

func (s *intValue) Predict(prefix string) []string {
if s.Predictor != nil {
return s.Predictor.Predict(prefix)
}
return []string{""}
}

type durationValue struct {
v *time.Duration
predict.Config
}

func newDurationValue(val time.Duration, p *time.Duration, c predict.Config) *durationValue {
*p = val
return &durationValue{v: p, Config: c}
}

func (i *durationValue) Set(val string) error {
v, err := time.ParseDuration(val)
*i.v = v
if err != nil {
return fmt.Errorf("bad value for duration flag")
}
return i.Check(val)
}

func (i *durationValue) Get() interface{} { return *i.v }

func (i *durationValue) String() string {
if i == nil || i.v == nil {
return time.Duration(0).String()
}
return i.v.String()
}

func (s *durationValue) Predict(prefix string) []string {
if s.Predictor != nil {
return s.Predictor.Predict(prefix)
}
return []string{""}
}
func formatDuration(v time.Duration) string { return v.String() }
Loading

0 comments on commit be08f3c

Please sign in to comment.