Implement cloning of commands
This commit is contained in:
parent
bc38bd75fd
commit
1811949706
@ -36,7 +36,7 @@ func (self *Command) parse_args(ctx *Context, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for len(self.args) > 0 {
|
for len(self.Args) > 0 {
|
||||||
arg := consume_arg()
|
arg := consume_arg()
|
||||||
|
|
||||||
if expecting_arg_for == nil {
|
if expecting_arg_for == nil {
|
||||||
@ -67,7 +67,7 @@ func (self *Command) parse_args(ctx *Context, args []string) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle non option arg
|
// handle non option arg
|
||||||
if self.AllowOptionsAfterArgs <= len(self.args) {
|
if self.AllowOptionsAfterArgs <= len(self.Args) {
|
||||||
options_allowed = false
|
options_allowed = false
|
||||||
}
|
}
|
||||||
if self.HasSubCommands() {
|
if self.HasSubCommands() {
|
||||||
@ -80,7 +80,7 @@ func (self *Command) parse_args(ctx *Context, args []string) error {
|
|||||||
return sc.parse_args(ctx, args_to_parse)
|
return sc.parse_args(ctx, args_to_parse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.args = append(self.args, arg)
|
self.Args = append(self.Args, arg)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// handle option value
|
// handle option value
|
||||||
|
|||||||
@ -4,6 +4,7 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -132,24 +133,50 @@ type CommandGroup struct {
|
|||||||
Title string
|
Title string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommandGroup) Clone(parent *Command) *CommandGroup {
|
||||||
|
ans := CommandGroup{Title: self.Title, SubCommands: make([]*Command, 0, len(self.SubCommands))}
|
||||||
|
for i, o := range self.SubCommands {
|
||||||
|
self.SubCommands[i] = o.Clone(parent)
|
||||||
|
}
|
||||||
|
return &ans
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommandGroup) AddSubCommand(parent *Command, name string) (*Command, error) {
|
func (self *CommandGroup) AddSubCommand(parent *Command, name string) (*Command, error) {
|
||||||
for _, c := range self.SubCommands {
|
for _, c := range self.SubCommands {
|
||||||
if c.Name == name {
|
if c.Name == name {
|
||||||
return nil, fmt.Errorf("A subcommand with the name %#v already exists in the parent command: %#v", name, parent.Name)
|
return nil, fmt.Errorf("A subcommand with the name %#v already exists in the parent command: %#v", name, parent.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ans := Command{
|
ans := NewRootCommand()
|
||||||
Name: name,
|
ans.Parent = parent
|
||||||
Parent: parent,
|
self.SubCommands = append(self.SubCommands, ans)
|
||||||
}
|
return ans, nil
|
||||||
return &ans, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OptionGroup struct {
|
func (self *CommandGroup) FindSubCommand(name string) *Command {
|
||||||
|
for _, c := range self.SubCommands {
|
||||||
|
if c.Name == name {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type OptionGroup struct { // {{{
|
||||||
Options []*Option
|
Options []*Option
|
||||||
Title string
|
Title string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *OptionGroup) Clone(parent *Command) *OptionGroup {
|
||||||
|
ans := OptionGroup{Title: self.Title, Options: make([]*Option, 0, len(self.Options))}
|
||||||
|
for i, o := range self.Options {
|
||||||
|
c := *o
|
||||||
|
c.Parent = parent
|
||||||
|
self.Options[i] = &c
|
||||||
|
}
|
||||||
|
return &ans
|
||||||
|
}
|
||||||
|
|
||||||
func (self *OptionGroup) AddOption(parent *Command, items ...string) (*Option, error) {
|
func (self *OptionGroup) AddOption(parent *Command, items ...string) (*Option, error) {
|
||||||
ans, err := OptionFromString(items...)
|
ans, err := OptionFromString(items...)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -169,25 +196,53 @@ func (self *OptionGroup) FindOption(name_with_hyphens string) *Option {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Name string
|
Name string
|
||||||
Usage, HelpText string
|
Usage, HelpText string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
|
AllowOptionsAfterArgs int
|
||||||
|
SubCommandIsOptional bool
|
||||||
|
|
||||||
SubCommandGroups []*CommandGroup
|
SubCommandGroups []*CommandGroup
|
||||||
OptionGroups []*OptionGroup
|
OptionGroups []*OptionGroup
|
||||||
Parent *Command
|
Parent *Command
|
||||||
|
|
||||||
AllowOptionsAfterArgs int
|
Args []string
|
||||||
SubCommandIsOptional bool
|
}
|
||||||
|
|
||||||
args []string
|
func (self *Command) Clone(parent *Command) *Command {
|
||||||
|
ans := *self
|
||||||
|
ans.Args = make([]string, 0, 8)
|
||||||
|
ans.Parent = parent
|
||||||
|
ans.SubCommandGroups = make([]*CommandGroup, 0, len(self.SubCommandGroups))
|
||||||
|
ans.OptionGroups = make([]*OptionGroup, 0, len(self.OptionGroups))
|
||||||
|
|
||||||
|
for i, o := range self.OptionGroups {
|
||||||
|
ans.OptionGroups[i] = o.Clone(&ans)
|
||||||
|
}
|
||||||
|
for i, g := range self.SubCommandGroups {
|
||||||
|
ans.SubCommandGroups[i] = g.Clone(&ans)
|
||||||
|
}
|
||||||
|
return &ans
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Command) AddClone(group string, src *Command) (*Command, error) {
|
||||||
|
c := src.Clone(self)
|
||||||
|
g := self.AddSubCommandGroup(group)
|
||||||
|
if g.FindSubCommand(c.Name) != nil {
|
||||||
|
return nil, fmt.Errorf("A sub command with the name: %s already exists in %s", c.Name, self.Name)
|
||||||
|
}
|
||||||
|
g.SubCommands = append(g.SubCommands, c)
|
||||||
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRootCommand() *Command {
|
func NewRootCommand() *Command {
|
||||||
ans := Command{
|
ans := Command{
|
||||||
SubCommandGroups: make([]*CommandGroup, 0, 8),
|
SubCommandGroups: make([]*CommandGroup, 0, 8),
|
||||||
OptionGroups: make([]*OptionGroup, 0, 8),
|
OptionGroups: make([]*OptionGroup, 0, 8),
|
||||||
args: make([]string, 0, 8),
|
Args: make([]string, 0, 8),
|
||||||
}
|
}
|
||||||
return &ans
|
return &ans
|
||||||
}
|
}
|
||||||
@ -207,6 +262,18 @@ func (self *Command) AddSubCommand(group string, name string) (*Command, error)
|
|||||||
return self.AddSubCommandGroup(group).AddSubCommand(self, name)
|
return self.AddSubCommandGroup(group).AddSubCommand(self, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Command) ParseArgs(args []string) (*Command, error) {
|
||||||
|
if args == nil {
|
||||||
|
args = os.Args
|
||||||
|
}
|
||||||
|
ctx := Context{SeenCommands: make([]*Command, 0, 4)}
|
||||||
|
err := self.parse_args(&ctx, args[1:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ctx.SeenCommands[len(ctx.SeenCommands)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Command) HasSubCommands() bool {
|
func (self *Command) HasSubCommands() bool {
|
||||||
for _, g := range self.SubCommandGroups {
|
for _, g := range self.SubCommandGroups {
|
||||||
if len(g.SubCommands) > 0 {
|
if len(g.SubCommands) > 0 {
|
||||||
@ -218,10 +285,9 @@ func (self *Command) HasSubCommands() bool {
|
|||||||
|
|
||||||
func (self *Command) FindSubCommand(name string) *Command {
|
func (self *Command) FindSubCommand(name string) *Command {
|
||||||
for _, g := range self.SubCommandGroups {
|
for _, g := range self.SubCommandGroups {
|
||||||
for _, c := range g.SubCommands {
|
c := g.FindSubCommand(name)
|
||||||
if c.Name == name {
|
if c != nil {
|
||||||
return c
|
return c
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user