Various fixes to CLI parsing
This commit is contained in:
parent
79cfc1e70a
commit
04022ed363
@ -117,15 +117,18 @@ func option_from_spec(spec OptionSpec) (*Option, error) {
|
|||||||
ans.Depth = spec.Depth
|
ans.Depth = spec.Depth
|
||||||
if spec.Choices != "" {
|
if spec.Choices != "" {
|
||||||
parts := strings.Split(spec.Choices, ",")
|
parts := strings.Split(spec.Choices, ",")
|
||||||
ans.Choices = make(map[string]bool, len(parts))
|
if len(parts) == 1 {
|
||||||
ans.OptionType = StringOption
|
parts = strings.Split(spec.Choices, " ")
|
||||||
for i, x := range parts {
|
} else {
|
||||||
x = strings.TrimSpace(x)
|
for i, x := range parts {
|
||||||
ans.Choices[x] = true
|
parts[i] = strings.TrimSpace(x)
|
||||||
if i == 0 && ans.Default == "" {
|
|
||||||
ans.Default = x
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ans.Choices = parts
|
||||||
|
ans.OptionType = StringOption
|
||||||
|
if ans.Default == "" {
|
||||||
|
ans.Default = parts[0]
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch spec.Type {
|
switch spec.Type {
|
||||||
case "choice", "choices":
|
case "choice", "choices":
|
||||||
@ -151,7 +154,7 @@ func option_from_spec(spec OptionSpec) (*Option, error) {
|
|||||||
case "list":
|
case "list":
|
||||||
ans.IsList = true
|
ans.IsList = true
|
||||||
fallthrough
|
fallthrough
|
||||||
case "str", "string":
|
case "str", "string", "":
|
||||||
ans.OptionType = StringOption
|
ans.OptionType = StringOption
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unknown option type: %s", spec.Type)
|
return nil, fmt.Errorf("Unknown option type: %s", spec.Type)
|
||||||
|
|||||||
@ -19,13 +19,16 @@ func (self *Command) parse_args(ctx *Context, args []string) error {
|
|||||||
|
|
||||||
consume_arg := func() string { ans := args_to_parse[0]; args_to_parse = args_to_parse[1:]; return ans }
|
consume_arg := func() string { ans := args_to_parse[0]; args_to_parse = args_to_parse[1:]; return ans }
|
||||||
|
|
||||||
handle_option := func(opt_str string, has_val bool, opt_val string) error {
|
handle_option := func(opt_str string, has_val bool, opt_val string, val_not_allowed bool) error {
|
||||||
opt := self.FindOption(opt_str)
|
opt := self.FindOption(opt_str)
|
||||||
if opt == nil {
|
if opt == nil {
|
||||||
return &ParseError{Message: fmt.Sprintf("Unknown option: :yellow:`%s`", opt_str)}
|
return &ParseError{Message: fmt.Sprintf("Unknown option: :yellow:`%s`", opt_str)}
|
||||||
}
|
}
|
||||||
opt.seen_option = opt_str
|
opt.seen_option = opt_str
|
||||||
needs_arg := opt.needs_argument()
|
needs_arg := opt.needs_argument()
|
||||||
|
if needs_arg && val_not_allowed {
|
||||||
|
return &ParseError{Message: fmt.Sprintf("The option : :yellow:`%s` must be followed by a value not another option", opt_str)}
|
||||||
|
}
|
||||||
if has_val {
|
if has_val {
|
||||||
if !needs_arg {
|
if !needs_arg {
|
||||||
return &ParseError{Message: fmt.Sprintf("The option: :yellow:`%s` does not take values", opt_str)}
|
return &ParseError{Message: fmt.Sprintf("The option: :yellow:`%s` does not take values", opt_str)}
|
||||||
@ -59,10 +62,14 @@ func (self *Command) parse_args(ctx *Context, args []string) error {
|
|||||||
opt_val = parts[1]
|
opt_val = parts[1]
|
||||||
}
|
}
|
||||||
opt_str = parts[0]
|
opt_str = parts[0]
|
||||||
handle_option(opt_str, has_val, opt_val)
|
err := handle_option(opt_str, has_val, opt_val, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, sl := range opt_str[1:] {
|
runes := []rune(opt_str[1:])
|
||||||
err := handle_option("-"+string(sl), false, "")
|
for i, sl := range runes {
|
||||||
|
err := handle_option("-"+string(sl), false, "", i < len(runes)-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"kitty/tools/utils"
|
"kitty/tools/utils"
|
||||||
|
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
var _ = fmt.Print
|
||||||
@ -52,7 +54,7 @@ type OptionSpec struct {
|
|||||||
type Option struct {
|
type Option struct {
|
||||||
Name string
|
Name string
|
||||||
Aliases []Alias
|
Aliases []Alias
|
||||||
Choices map[string]bool
|
Choices []string
|
||||||
Default string
|
Default string
|
||||||
OptionType OptionType
|
OptionType OptionType
|
||||||
Hidden bool
|
Hidden bool
|
||||||
@ -157,13 +159,9 @@ func (self *Option) add_value(val string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case StringOption:
|
case StringOption:
|
||||||
if self.Choices != nil && !self.Choices[val] {
|
if self.Choices != nil && !slices.Contains(self.Choices, val) {
|
||||||
c := make([]string, len(self.Choices))
|
|
||||||
for k := range self.Choices {
|
|
||||||
c = append(c, k)
|
|
||||||
}
|
|
||||||
return &ParseError{Option: self, Message: fmt.Sprintf(":yellow:`%s` is not a valid value for :bold:`%s`. Valid values: %s",
|
return &ParseError{Option: self, Message: fmt.Sprintf(":yellow:`%s` is not a valid value for :bold:`%s`. Valid values: %s",
|
||||||
val, self.seen_option, strings.Join(c, ", "),
|
val, self.seen_option, strings.Join(self.Choices, ", "),
|
||||||
)}
|
)}
|
||||||
}
|
}
|
||||||
self.values_from_cmdline = append(self.values_from_cmdline, val)
|
self.values_from_cmdline = append(self.values_from_cmdline, val)
|
||||||
@ -377,20 +375,14 @@ func (self *Command) Validate() error {
|
|||||||
if seen_flags["-h"] || seen_flags["--help"] {
|
if seen_flags["-h"] || seen_flags["--help"] {
|
||||||
return &ParseError{Message: fmt.Sprintf("The --help or -h flags are assigned to an option other than Help in %s", self.Name)}
|
return &ParseError{Message: fmt.Sprintf("The --help or -h flags are assigned to an option other than Help in %s", self.Name)}
|
||||||
}
|
}
|
||||||
_, err := self.Add(OptionSpec{Name: "--help -h", Type: "bool-set", Help: "Show help for this command"})
|
self.Add(OptionSpec{Name: "--help -h", Type: "bool-set", Help: "Show help for this command"})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.Parent == nil && !seen_dests["Version"] {
|
if self.Parent == nil && !seen_dests["Version"] {
|
||||||
if seen_flags["--version"] {
|
if seen_flags["--version"] {
|
||||||
return &ParseError{Message: fmt.Sprintf("The --version flag is assigned to an option other than Version in %s", self.Name)}
|
return &ParseError{Message: fmt.Sprintf("The --version flag is assigned to an option other than Version in %s", self.Name)}
|
||||||
}
|
}
|
||||||
_, err := self.Add(OptionSpec{Name: "--version", Type: "bool-set", Help: "Show version"})
|
self.Add(OptionSpec{Name: "--version", Type: "bool-set", Help: "Show version"})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -522,20 +514,29 @@ func (self *Command) AddOptionGroup(title string) *OptionGroup {
|
|||||||
return &ans
|
return &ans
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Command) AddOptionFromString(items ...string) (*Option, error) {
|
func (self *Command) AddOptionToGroupFromString(group string, items ...string) *Option {
|
||||||
return self.AddOptionGroup("").AddOptionFromString(self, items...)
|
ans, err := self.AddOptionGroup(group).AddOptionFromString(self, items...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ans
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Command) Add(s OptionSpec) (*Option, error) {
|
func (self *Command) AddToGroup(group string, s OptionSpec) *Option {
|
||||||
return self.AddOptionGroup("").AddOption(self, s)
|
ans, err := self.AddOptionGroup(group).AddOption(self, s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ans
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Command) AddOptionToGroupFromString(group string, items ...string) (*Option, error) {
|
func (self *Command) AddOptionFromString(items ...string) *Option {
|
||||||
return self.AddOptionGroup(group).AddOptionFromString(self, items...)
|
return self.AddOptionToGroupFromString("", items...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Command) AddToGroup(group string, s OptionSpec) (*Option, error) {
|
func (self *Command) Add(s OptionSpec) *Option {
|
||||||
return self.AddOptionGroup(group).AddOption(self, s)
|
return self.AddToGroup("", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Command) FindOption(name_with_hyphens string) *Option {
|
func (self *Command) FindOption(name_with_hyphens string) *Option {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user