2019-11-13 22:51:44 -06:00
|
|
|
// Package compflag provides a handful of standard library-compatible flags with bash complition capabilities.
|
|
|
|
//
|
|
|
|
// Usage
|
|
|
|
//
|
2019-11-17 17:25:16 -06:00
|
|
|
// import "github.com/posener/complete/v2/compflag"
|
2019-11-13 22:51:44 -06:00
|
|
|
//
|
|
|
|
// var (
|
|
|
|
// // Define flags...
|
|
|
|
// foo = compflag.String("foo", "", "")
|
|
|
|
// )
|
|
|
|
//
|
|
|
|
// func main() {
|
|
|
|
// compflag.Parse("my-program")
|
|
|
|
// // Main function.
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// Alternatively, the library can just be used with the standard library flag package:
|
|
|
|
//
|
|
|
|
// import (
|
|
|
|
// "flag"
|
2019-11-17 17:25:16 -06:00
|
|
|
// "github.com/posener/complete/v2/compflag"
|
2019-11-13 22:51:44 -06:00
|
|
|
// )
|
|
|
|
//
|
|
|
|
// var (
|
|
|
|
// // Define flags...
|
|
|
|
// foo = compflag.String("foo", "", "")
|
|
|
|
// bar = flag.String("bar", "", "")
|
|
|
|
// )
|
|
|
|
//
|
|
|
|
// func main() {
|
|
|
|
// complete.CommandLine("my-program")
|
2019-11-27 13:21:30 -06:00
|
|
|
// flag.Parse()
|
2019-11-13 22:51:44 -06:00
|
|
|
// // Main function.
|
|
|
|
// }
|
|
|
|
package compflag
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
|
2019-11-17 17:25:16 -06:00
|
|
|
"github.com/posener/complete/v2"
|
2019-11-22 03:40:09 -06:00
|
|
|
"github.com/posener/complete/v2/predict"
|
2019-11-13 22:51:44 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// FlagSet is bash completion enabled flag.FlagSet.
|
|
|
|
type FlagSet flag.FlagSet
|
|
|
|
|
|
|
|
// Parse parses command line arguments.
|
|
|
|
func (fs *FlagSet) Parse(args []string) error {
|
|
|
|
return (*flag.FlagSet)(fs).Parse(args)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Complete performs bash completion if needed.
|
|
|
|
func (fs *FlagSet) Complete(name string) {
|
|
|
|
complete.Complete(name, complete.FlagSet((*flag.FlagSet)(CommandLine)))
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func (fs *FlagSet) String(name string, value string, usage string, options ...predict.Option) *string {
|
2019-11-13 22:51:44 -06:00
|
|
|
p := new(string)
|
2019-11-22 03:40:09 -06:00
|
|
|
(*flag.FlagSet)(fs).Var(newStringValue(value, p, predict.Options(options...)), name, usage)
|
2019-11-13 22:51:44 -06:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func (fs *FlagSet) Bool(name string, value bool, usage string, options ...predict.Option) *bool {
|
2019-11-13 22:51:44 -06:00
|
|
|
p := new(bool)
|
2019-11-22 03:40:09 -06:00
|
|
|
(*flag.FlagSet)(fs).Var(newBoolValue(value, p, predict.Options(options...)), name, usage)
|
2019-11-13 22:51:44 -06:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func (fs *FlagSet) Int(name string, value int, usage string, options ...predict.Option) *int {
|
2019-11-13 22:51:44 -06:00
|
|
|
p := new(int)
|
2019-11-22 03:40:09 -06:00
|
|
|
(*flag.FlagSet)(fs).Var(newIntValue(value, p, predict.Options(options...)), name, usage)
|
2019-11-13 22:51:44 -06:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
var CommandLine = (*FlagSet)(flag.CommandLine)
|
|
|
|
|
|
|
|
// Parse parses command line arguments. It also performs bash completion when needed.
|
|
|
|
func Parse(name string) {
|
|
|
|
CommandLine.Complete(name)
|
|
|
|
CommandLine.Parse(os.Args[1:])
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func String(name string, value string, usage string, options ...predict.Option) *string {
|
2019-11-13 22:51:44 -06:00
|
|
|
return CommandLine.String(name, value, usage, options...)
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func Bool(name string, value bool, usage string, options ...predict.Option) *bool {
|
2019-11-13 22:51:44 -06:00
|
|
|
return CommandLine.Bool(name, value, usage, options...)
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func Int(name string, value int, usage string, options ...predict.Option) *int {
|
2019-11-13 22:51:44 -06:00
|
|
|
return CommandLine.Int(name, value, usage, options...)
|
|
|
|
}
|
|
|
|
|
|
|
|
type boolValue struct {
|
|
|
|
v *bool
|
2019-11-22 03:40:09 -06:00
|
|
|
predict.Config
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func newBoolValue(val bool, p *bool, c predict.Config) *boolValue {
|
2019-11-13 22:51:44 -06:00
|
|
|
*p = val
|
2019-11-22 03:40:09 -06:00
|
|
|
return &boolValue{v: p, Config: c}
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
2019-11-22 03:40:09 -06:00
|
|
|
return b.Check(val)
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *boolValue) Get() interface{} { return bool(*b.v) }
|
|
|
|
|
|
|
|
func (b *boolValue) String() string {
|
|
|
|
if b == nil || b.v == nil {
|
|
|
|
return strconv.FormatBool(false)
|
|
|
|
}
|
|
|
|
return strconv.FormatBool(bool(*b.v))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *boolValue) IsBoolFlag() bool { return true }
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func (b *boolValue) Predict(prefix string) []string {
|
|
|
|
if b.Predictor != nil {
|
|
|
|
return b.Predictor.Predict(prefix)
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
// If false, typing the bool flag is expected to turn it on, so there is nothing to complete
|
|
|
|
// after the flag.
|
|
|
|
if !*b.v {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// Otherwise, suggest only to turn it off.
|
|
|
|
return []string{"false"}
|
|
|
|
}
|
|
|
|
|
|
|
|
type stringValue struct {
|
|
|
|
v *string
|
2019-11-22 03:40:09 -06:00
|
|
|
predict.Config
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func newStringValue(val string, p *string, c predict.Config) *stringValue {
|
2019-11-13 22:51:44 -06:00
|
|
|
*p = val
|
2019-11-22 03:40:09 -06:00
|
|
|
return &stringValue{v: p, Config: c}
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *stringValue) Set(val string) error {
|
|
|
|
*s.v = val
|
2019-11-22 03:40:09 -06:00
|
|
|
return s.Check(val)
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *stringValue) Get() interface{} {
|
|
|
|
return string(*s.v)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *stringValue) String() string {
|
|
|
|
if s == nil || s.v == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return string(*s.v)
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func (s *stringValue) Predict(prefix string) []string {
|
|
|
|
if s.Predictor != nil {
|
|
|
|
return s.Predictor.Predict(prefix)
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
return []string{""}
|
|
|
|
}
|
|
|
|
|
|
|
|
type intValue struct {
|
|
|
|
v *int
|
2019-11-22 03:40:09 -06:00
|
|
|
predict.Config
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func newIntValue(val int, p *int, c predict.Config) *intValue {
|
2019-11-13 22:51:44 -06:00
|
|
|
*p = val
|
2019-11-22 03:40:09 -06:00
|
|
|
return &intValue{v: p, Config: c}
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
2019-11-22 03:40:09 -06:00
|
|
|
return i.Check(val)
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *intValue) Get() interface{} { return int(*i.v) }
|
|
|
|
|
|
|
|
func (i *intValue) String() string {
|
|
|
|
if i == nil || i.v == nil {
|
|
|
|
return strconv.Itoa(0)
|
|
|
|
}
|
|
|
|
return strconv.Itoa(int(*i.v))
|
|
|
|
}
|
|
|
|
|
2019-11-22 03:40:09 -06:00
|
|
|
func (s *intValue) Predict(prefix string) []string {
|
|
|
|
if s.Predictor != nil {
|
|
|
|
return s.Predictor.Predict(prefix)
|
2019-11-13 22:51:44 -06:00
|
|
|
}
|
|
|
|
return []string{""}
|
|
|
|
}
|