Allow explicitly setting boolean options in Go cli parser

Matches C parser
This commit is contained in:
Kovid Goyal 2025-04-28 11:54:51 +05:30
parent 39bf612071
commit d7fb143ee0
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 45 additions and 12 deletions

View file

@ -82,8 +82,10 @@ func (self *Option) FormatOptionForMan(output io.Writer) {
if self.IsList {
defval = ""
}
case BoolOption, CountOption:
case CountOption:
defval = ""
case BoolOption:
defval = utils.IfElse(self.Default == "true", "yes", "no")
}
if defval != "" {
@ -111,7 +113,11 @@ func (self *Option) FormatOption(output io.Writer, formatter *markup.Context, sc
if self.IsList {
defval = ""
}
case BoolOption, CountOption:
case CountOption:
defval = ""
case BoolOption:
yn := utils.IfElse(self.Default == "true", "yes", "no")
fmt.Fprintf(output, " %s", formatter.Italic("[="+yn+"]"))
defval = ""
}
if defval != "" {

View file

@ -160,16 +160,32 @@ func (self *Option) add_value(val string) error {
name_without_hyphens := NormalizeOptionName(self.seen_option)
switch self.OptionType {
case BoolOption:
for _, x := range self.Aliases {
if x.NameWithoutHyphens == name_without_hyphens {
if x.IsUnset {
self.values_from_cmdline = append(self.values_from_cmdline, "false")
self.parsed_values_from_cmdline = append(self.parsed_values_from_cmdline, false)
} else {
self.values_from_cmdline = append(self.values_from_cmdline, "true")
self.parsed_values_from_cmdline = append(self.parsed_values_from_cmdline, true)
if val == "" {
for _, x := range self.Aliases {
if x.NameWithoutHyphens == name_without_hyphens {
if x.IsUnset {
self.values_from_cmdline = append(self.values_from_cmdline, "false")
self.parsed_values_from_cmdline = append(self.parsed_values_from_cmdline, false)
} else {
self.values_from_cmdline = append(self.values_from_cmdline, "true")
self.parsed_values_from_cmdline = append(self.parsed_values_from_cmdline, true)
}
return nil
}
return nil
}
} else {
switch val {
case "y", "yes", "true":
self.values_from_cmdline = append(self.values_from_cmdline, "true")
self.parsed_values_from_cmdline = append(self.parsed_values_from_cmdline, true)
case "n", "no", "false":
self.values_from_cmdline = append(self.values_from_cmdline, "false")
self.parsed_values_from_cmdline = append(self.parsed_values_from_cmdline, false)
default:
return &ParseError{Option: self, Message: fmt.Sprintf(":yellow:`%s` is not a valid value for :bold:`%s`. Valid values: %s",
val, self.seen_option, "y, yes, true, n, no and false",
)}
}
}
case StringOption:

View file

@ -55,7 +55,13 @@ func (self *Command) parse_args(ctx *Context, args []string) error {
}
if has_val {
if !needs_arg {
return &ParseError{Message: fmt.Sprintf("The option: :yellow:`%s` does not take values", opt_str)}
if opt.OptionType == BoolOption {
if err := opt.add_value(opt_val); err != nil {
return err
}
} else {
return &ParseError{Message: fmt.Sprintf("The option: :yellow:`%s` does not take values", opt_str)}
}
}
return opt.add_value(opt_val)
} else if needs_arg {

View file

@ -86,6 +86,11 @@ func TestCLIParsing(t *testing.T) {
"one", "two",
)
rt(child1, "test child1", &options{})
rt(child1, "test child1 --set-me one", &options{SetMe: true}, "one")
rt(child1, "test child1 --set-me=y one", &options{SetMe: true}, "one")
rt(child1, "test child1 --set-me=n one", &options{SetMe: false}, "one")
rt(child1, "test child1 --set-me=n --set-me one", &options{SetMe: true}, "one")
rt(child1, "test child1 --set-me=y -b=n one", &options{SetMe: false}, "one")
rt(child1, "test child1 --set-me --simple-string=foo one", &options{SimpleString: "foo", SetMe: true}, "one")
rt(child1, "test child1 --set-me --simp=foo one", &options{SimpleString: "foo", SetMe: true}, "one")
rt(child1, "test child1 --set-me --simple-string= one", &options{SetMe: true}, "one")