Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bool value for spf13 #3

Merged
merged 3 commits into from
Jan 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import (
"strconv"
)

// optional interface to indicate boolean flags that can be
// supplied without "=value" text
type boolFlag interface {
Value
IsBoolFlag() bool
}

// -- bool Value
type boolValue bool

Expand All @@ -25,6 +32,8 @@ func (b *boolValue) Type() string {

func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }

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

// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
Expand Down
163 changes: 163 additions & 0 deletions bool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package pflag_test

import (
"fmt"
"strconv"
"testing"

. "github.com/ogier/pflag"
)

// This value can be a boolean ("true", "false") or "maybe"
type triStateValue int

const (
triStateFalse triStateValue = 0
triStateTrue triStateValue = 1
triStateMaybe triStateValue = 2
)

const strTriStateMaybe = "maybe"

func (v *triStateValue) IsBoolFlag() bool {
return true
}

func (v *triStateValue) Get() interface{} {
return triStateValue(*v)
}

func (v *triStateValue) Set(s string) error {
if s == strTriStateMaybe {
*v = triStateMaybe
return nil
}
boolVal, err := strconv.ParseBool(s)
if boolVal {
*v = triStateTrue
} else {
*v = triStateFalse
}
return err
}

func (v *triStateValue) String() string {
if *v == triStateMaybe {
return strTriStateMaybe
}
return fmt.Sprintf("%v", bool(*v == triStateTrue))
}

// The type of the flag as requred by the pflag.Value interface
func (v *triStateValue) Type() string {
return "version"
}

func setUpFlagSet(tristate *triStateValue) *FlagSet {
f := NewFlagSet("test", ContinueOnError)
*tristate = triStateFalse
f.VarP(tristate, "tristate", "t", "tristate value (true, maybe or false)")
return f
}

func TestExplicitTrue(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{"--tristate=true"})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateTrue {
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
}
}

func TestImplicitTrue(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{"--tristate"})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateTrue {
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
}
}

func TestShortFlag(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{"-t"})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateTrue {
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
}
}

func TestShortFlagExtraArgument(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
// The"maybe"turns into an arg, since short boolean options will only do true/false
err := f.Parse([]string{"-t", "maybe"})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateTrue {
t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead")
}
args := f.Args()
if len(args) != 1 || args[0] != "maybe" {
t.Fatal("expected an extra 'maybe' argument to stick around")
}
}

func TestExplicitMaybe(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{"--tristate=maybe"})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateMaybe {
t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead")
}
}

func TestExplicitFalse(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{"--tristate=false"})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateFalse {
t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
}
}

func TestImplicitFalse(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{})
if err != nil {
t.Fatal("expected no error; got", err)
}
if tristate != triStateFalse {
t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead")
}
}

func TestInvalidValue(t *testing.T) {
var tristate triStateValue
f := setUpFlagSet(&tristate)
err := f.Parse([]string{"--tristate=invalid"})
if err == nil {
t.Fatal("expected an error but did not get any, tristate has value", tristate)
}
}
4 changes: 4 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func (i *interval) String() string {
return fmt.Sprint(*i)
}

func (i *interval) Type() string {
return "interval"
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
Expand Down
4 changes: 2 additions & 2 deletions flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
return
}
if len(split) == 1 {
if _, ok := flag.Value.(*boolValue); !ok {
if bv, ok := flag.Value.(boolFlag); !ok || !bv.IsBoolFlag() {
err = f.failf("flag needs an argument: %s", s)
return
}
Expand Down Expand Up @@ -500,7 +500,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
}
}
if alreadythere {
if _, ok := flag.Value.(*boolValue); ok {
if bv, ok := flag.Value.(boolFlag); ok && bv.IsBoolFlag() {
f.setFlag(flag, "true", s)
continue
}
Expand Down
4 changes: 4 additions & 0 deletions flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ func (f *flagVar) Set(value string) error {
return nil
}

func (f *flagVar) Type() string {
return "flagVar"
}

func TestUserDefined(t *testing.T) {
var flags FlagSet
flags.Init("test", ContinueOnError)
Expand Down