diff --git a/cli.go b/cli.go index 64fb55c..b348fb6 100644 --- a/cli.go +++ b/cli.go @@ -296,7 +296,7 @@ func parseArgsToFlagSet(args []string, flagSet *flagSet, clr color.Color) { buff := bytes.NewBufferString("") for _, fl := range flagSet.flagSlice { - if !fl.isAssigned && fl.tag.isRequired { + if !fl.isAssigned && fl.tag.isRequired && !fl.tag.ignoreRequired { if buff.Len() > 0 { buff.WriteByte('\n') } diff --git a/cli_test.go b/cli_test.go index dcefd9b..aed4a15 100644 --- a/cli_test.go +++ b/cli_test.go @@ -58,8 +58,10 @@ type argT struct { Float32 float32 `cli:"f32" usage:"type float32"` Float64 float64 `cli:"f64" usage:"type float64"` - PtrBool *bool `cli:"ptrBool"` - PtrStr *string `cli:"ptrStr"` + PtrBool *bool `cli:"ptrBool"` + PtrStr *string `cli:"ptrStr"` + + RequiredNotEnforced string `cli:"*requiredNotEnforced" ignoreRequired:"true"` } func toStr(i interface{}) string { @@ -334,11 +336,11 @@ func TestParse(t *testing.T) { // Case: bool pointer { args: []string{"--required=0", "--ptrBool=true"}, - want: argT{Default: 102, PtrBool: func(b bool)*bool{return &b}(true)}, + want: argT{Default: 102, PtrBool: func(b bool) *bool { return &b }(true)}, }, { args: []string{"--required=0", "--ptrBool=false"}, - want: argT{Default: 102, PtrBool: func(b bool)*bool{return &b}(false)}, + want: argT{Default: 102, PtrBool: func(b bool) *bool { return &b }(false)}, }, { args: []string{"--required=0"}, @@ -347,16 +349,20 @@ func TestParse(t *testing.T) { // Case: str pointer { args: []string{"--required=0", "--ptrStr=true"}, - want: argT{Default: 102, PtrStr: func(b string)*string{return &b}("true")}, + want: argT{Default: 102, PtrStr: func(b string) *string { return &b }("true")}, }, { args: []string{"--required=0", "--ptrStr=false"}, - want: argT{Default: 102, PtrStr: func(b string)*string{return &b}("false")}, + want: argT{Default: 102, PtrStr: func(b string) *string { return &b }("false")}, }, { args: []string{"--required=0"}, want: argT{Default: 102, PtrStr: nil}, }, + { + args: []string{"--required=0", "--requiredNotEnforced=hikikomori"}, + want: argT{Default: 102, RequiredNotEnforced: "hikikomori"}, + }, } { if tab.args == nil { tab.args = []string{} diff --git a/tag.go b/tag.go index 46ec748..c992389 100644 --- a/tag.go +++ b/tag.go @@ -11,13 +11,14 @@ const ( tagPw = "pw" // password tagEdit = "edit" - tagUsage = "usage" - tagDefaut = "dft" - tagDefautInject = "ignoreDft" - tagName = "name" - tagPrompt = "prompt" - tagParser = "parser" - tagSep = "sep" // used to seperate key/value pair of map, default is `=` + tagUsage = "usage" + tagDefaut = "dft" + tagIgnoreDefault = "ignoreDft" + tagIgnoreRequired = "ignoreRequired" + tagName = "name" + tagPrompt = "prompt" + tagParser = "parser" + tagSep = "sep" // used to seperate key/value pair of map, default is `=` dashOne = "-" dashTwo = "--" @@ -41,13 +42,14 @@ type tagProperty struct { isEdit bool `edit:"xxx"` editFile string `edit:"FILE:xxx"` - usage string `usage:"usage string"` - dft string `dft:"default value or expression"` - ignoreDft bool `ignoreDft:"true/false, by default true"` - name string `name:"tag reference name"` - prompt string `prompt:"prompt string"` - sep string `sep:"string for seperate kay/value pair of map"` - parserCreator FlagParserCreator `parser:"parser for flag"` + usage string `usage:"usage string"` + dft string `dft:"default value or expression"` + ignoreDft bool `ignoreDft:"true/false, by default false"` + ignoreRequired bool `ignoreRequired:"true/false, by default false"` + name string `name:"tag reference name"` + prompt string `prompt:"prompt string"` + sep string `sep:"string for seperate kay/value pair of map"` + parserCreator FlagParserCreator `parser:"parser for flag"` // flag names shortNames []string @@ -101,8 +103,21 @@ func parseTag(fieldName string, structTag reflect.StructTag) (p *tagProperty, is p.dft = tag.Get(tagDefaut) // `ignoreDft` TAG - toIgnore, _ := strconv.ParseBool(tag.Get(tagDefautInject)) - p.ignoreDft = toIgnore + if tag := tag.Get(tagIgnoreDefault); tag != "" { + p.ignoreDft, err = strconv.ParseBool(tag) + + } + if err != nil { + return + } + + // `ignoreRequired` TAG + if tag := tag.Get(tagIgnoreRequired); tag != "" { + p.ignoreRequired, err = strconv.ParseBool(tag) + } + if err != nil { + return + } // `name` TAG p.name = tag.Get(tagName) diff --git a/tag_test.go b/tag_test.go index aba9e82..abf1ab0 100644 --- a/tag_test.go +++ b/tag_test.go @@ -23,7 +23,9 @@ func TestTag(t *testing.T) { dft:"dft-value"` StillPrintsDft string `cli:"stillDft" usage:"multi usage" dft:"dft-value" ignoreDft:"false"` - Required string `cli:"*r"` + Required string `cli:"*r"` + RequiredNotEnforced string `cli:"*re" ignoreRequired:"true"` + Force string `cli:"!f"` EditFile string `edit:"Filename:file"` ShortAndLong string `cli:"x,y,z,xy,yz,xyz"` @@ -110,7 +112,7 @@ func TestTag(t *testing.T) { assert.False(t, tag.isEdit) assert.Equal(t, tag.longNames, []string{"--sep"}) assert.Equal(t, tag.sep, ":") - case "Required": + case "Required", "RequiredNotEnforced": assert.True(t, tag.isRequired) assert.False(t, tag.isForce) assert.False(t, tag.isPassword)