Made change
This commit is contained in:
174
app.go
Normal file
174
app.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"git.arcanium.tech/tristan/logging"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
Name string
|
||||
Commands []*Command
|
||||
Flags []*ArgFlag
|
||||
}
|
||||
|
||||
func (a *App) addRootCommand(cmd *Command){
|
||||
a.Commands = append(a.Commands, cmd)
|
||||
}
|
||||
|
||||
func (a *App) NewRootCommand(info CommandOptions) *Command {
|
||||
cmd := &Command{
|
||||
Name: info.Name,
|
||||
Description: info.Description,
|
||||
}
|
||||
a.addRootCommand( cmd )
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (a *App) Help() {
|
||||
appHelpTemplate.Execute(os.Stdout, a)
|
||||
}
|
||||
|
||||
func (a *App) getFlag(name string) (*ArgFlag, error) {
|
||||
for _, flag := range a.Flags {
|
||||
if flag.Matches(name) {
|
||||
return flag, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("App(%s) : ERROR : there is no flag by name %s", a.Name, name)
|
||||
}
|
||||
|
||||
func (a *App) isCommand(name string) bool {
|
||||
for _, command := range a.Commands {
|
||||
if command.Name == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *App) getCommand(name string) (*Command, error) {
|
||||
for _, command := range a.Commands {
|
||||
if command.Name == name {
|
||||
return command, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("App(%s) : ERROR : No command named \"%s\"", a.Name, name)
|
||||
}
|
||||
|
||||
func (a *App) determineMatch(arg string) (matchType, error) {
|
||||
if arg == "-h" || arg == "--help" || arg == "help" {
|
||||
return helpMatch, nil
|
||||
}
|
||||
flag_match, err := isFlag(arg)
|
||||
if err != nil {
|
||||
return noMatch, err
|
||||
}
|
||||
|
||||
if flag_match {
|
||||
return flagMatch, nil
|
||||
}
|
||||
|
||||
command := a.isCommand(arg)
|
||||
if command == true {
|
||||
return commandMatch, nil
|
||||
}
|
||||
|
||||
return noMatch, nil
|
||||
}
|
||||
|
||||
func (a *App) doChecks() error {
|
||||
for _, command := range a.Commands{
|
||||
err := command.Check()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, flag := range a.Flags {
|
||||
err := flag.Check()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) registerSelf(commands []*Command) {
|
||||
for _, command := range commands {
|
||||
command.App = a
|
||||
if len(command.SubCommands) > 0 {
|
||||
a.registerSelf(command.SubCommands)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (a *App) Run(args []string) error {
|
||||
logging.Debug("App(%s) : Beginning Run", a.Name)
|
||||
a.registerSelf(a.Commands)
|
||||
err := a.doChecks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
a.Help()
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
logging.Debug("App(%s) : Iterating on provided args (i: %d, arg: %s)", a.Name, i, arg)
|
||||
remaining_args := args[i+1:]
|
||||
match, err := a.determineMatch(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch match {
|
||||
case noMatch:
|
||||
return fmt.Errorf("No match found for Arg(%s) for App(%s)", arg, a.Name)
|
||||
case helpMatch:
|
||||
a.Help()
|
||||
return nil
|
||||
case flagMatch:
|
||||
flag, err := a.getFlag(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if flag.requireArg(){
|
||||
if len(args[i:]) <= 1 {
|
||||
return fmt.Errorf("Command(%s) : ArgFlag(%s) : Required argument not found", a.Name, flag.Name)
|
||||
}
|
||||
arglist := args[i:i+2]
|
||||
i++
|
||||
// want to call the flag with itself & the argument it wants
|
||||
err = flag.CheckArg(arglist)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Since we want to preserve that they were called at all. (particularly for BoolType)
|
||||
flag.Args = args[i:i+1]
|
||||
}
|
||||
|
||||
if flag.OnMatch != nil {
|
||||
err := flag.OnMatch()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case commandMatch:
|
||||
command, err := a.getCommand(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return command.Run(remaining_args)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user