2024-10-29 07:22:28 +01:00
|
|
|
package command
|
|
|
|
|
2024-10-31 07:26:03 +01:00
|
|
|
import (
|
2024-11-04 09:49:41 +01:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2024-11-05 07:21:43 +01:00
|
|
|
"strings"
|
2024-10-31 07:26:03 +01:00
|
|
|
)
|
2024-10-30 07:25:05 +01:00
|
|
|
|
2024-11-04 09:49:41 +01:00
|
|
|
var (
|
2024-11-06 07:29:29 +01:00
|
|
|
ErrWrongCommand = errors.New("wrong command")
|
|
|
|
ErrInvalidArg = errors.New("invalid argument")
|
2024-10-30 07:25:05 +01:00
|
|
|
)
|
|
|
|
|
2024-11-06 07:29:29 +01:00
|
|
|
type ArgSet struct {
|
|
|
|
Main string
|
|
|
|
Flags map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *ArgSet) HasFlag(name string) bool {
|
|
|
|
_, ok := as.Flags[name]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *ArgSet) Flag(name string) string {
|
|
|
|
return as.Flags[name]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (as *ArgSet) SetFlag(name, value string) {
|
|
|
|
as.Flags[name] = value
|
|
|
|
}
|
|
|
|
|
2024-11-04 09:49:41 +01:00
|
|
|
type Command interface {
|
2024-11-06 07:29:29 +01:00
|
|
|
Parse(args []string) (*ArgSet, error)
|
|
|
|
Do(args *ArgSet) error
|
2024-10-29 07:22:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type CLI struct {
|
2024-11-04 09:49:41 +01:00
|
|
|
Commands []Command
|
2024-10-30 07:25:05 +01:00
|
|
|
}
|
|
|
|
|
2024-11-04 09:49:41 +01:00
|
|
|
func (cli *CLI) Run(args []string) error {
|
|
|
|
for _, c := range cli.Commands {
|
2024-11-06 07:29:29 +01:00
|
|
|
as, err := c.Parse(args)
|
|
|
|
switch {
|
|
|
|
case errors.Is(err, ErrWrongCommand):
|
|
|
|
continue
|
|
|
|
case err != nil:
|
2024-11-04 09:49:41 +01:00
|
|
|
return err
|
2024-11-06 07:29:29 +01:00
|
|
|
default:
|
|
|
|
return c.Do(as)
|
2024-10-31 07:26:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-05 07:21:43 +01:00
|
|
|
return fmt.Errorf("could not find matching command")
|
|
|
|
}
|
|
|
|
|
2024-11-06 07:29:29 +01:00
|
|
|
func ParseArgs(args []string) (*ArgSet, error) {
|
2024-11-05 07:21:43 +01:00
|
|
|
flags := make(map[string]string)
|
2024-11-06 07:29:29 +01:00
|
|
|
main := make([]string, 0)
|
|
|
|
var inMain bool
|
2024-11-05 07:21:43 +01:00
|
|
|
for i := 0; i < len(args); i++ {
|
|
|
|
if strings.HasPrefix(args[i], "-") {
|
2024-11-06 07:29:29 +01:00
|
|
|
inMain = false
|
2024-11-05 07:21:43 +01:00
|
|
|
if i+1 >= len(args) {
|
2024-11-06 07:29:29 +01:00
|
|
|
return &ArgSet{}, fmt.Errorf("flag wihout value")
|
2024-11-05 07:21:43 +01:00
|
|
|
}
|
|
|
|
flags[strings.TrimPrefix(args[i], "-")] = args[i+1]
|
|
|
|
i++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2024-11-06 07:29:29 +01:00
|
|
|
if !inMain && len(main) > 0 {
|
|
|
|
return &ArgSet{}, fmt.Errorf("two mains")
|
2024-11-05 07:21:43 +01:00
|
|
|
}
|
2024-11-06 07:29:29 +01:00
|
|
|
inMain = true
|
|
|
|
main = append(main, args[i])
|
2024-11-05 07:21:43 +01:00
|
|
|
}
|
|
|
|
|
2024-11-06 07:29:29 +01:00
|
|
|
return &ArgSet{
|
|
|
|
Main: strings.Join(main, " "),
|
|
|
|
Flags: flags,
|
|
|
|
}, nil
|
2024-10-30 07:25:05 +01:00
|
|
|
}
|