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
|
||||
}
|
||||
15
argtype.go
Normal file
15
argtype.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package parser
|
||||
|
||||
type ArgType int
|
||||
|
||||
const (
|
||||
NoneType ArgType = iota
|
||||
StringType
|
||||
IntType
|
||||
BoolType
|
||||
Float32Type
|
||||
Float64Type
|
||||
MatchType
|
||||
)
|
||||
|
||||
|
||||
250
command.go
Normal file
250
command.go
Normal file
@@ -0,0 +1,250 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"errors"
|
||||
"git.arcanium.tech/tristan/go_logging"
|
||||
)
|
||||
|
||||
|
||||
type RunHook func(*Command)
|
||||
type WorkFunc func(*Context) error
|
||||
|
||||
var commands []*Command
|
||||
|
||||
type CommandOptions struct {
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
Name string
|
||||
Description string
|
||||
SubCommands []*Command
|
||||
Flags []*ArgFlag
|
||||
App *App
|
||||
Work WorkFunc
|
||||
preRunHooks []RunHook
|
||||
postRunHooks []RunHook
|
||||
}
|
||||
|
||||
func (c *Command) getFlag(name string) (*ArgFlag, error) {
|
||||
for _, flag := range c.Flags {
|
||||
if flag.Matches(name) {
|
||||
return flag, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Command(%s) : ERROR : there is no flag by name %s", c.Name, name)
|
||||
}
|
||||
|
||||
func (c *Command) Run(args []string) error {
|
||||
if len(c.preRunHooks) > 0 {
|
||||
for _, hook := range c.preRunHooks {
|
||||
hook(c)
|
||||
}
|
||||
}
|
||||
|
||||
err := c.run(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(c.postRunHooks) > 0 {
|
||||
for _, hook := range c.postRunHooks {
|
||||
hook(c)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Command) isSubCommand(name string) (bool) {
|
||||
for _, subcommand := range c.SubCommands {
|
||||
if subcommand.Name == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Command) getSubCommand(name string) (*Command, error) {
|
||||
for _, subcommand := range c.SubCommands {
|
||||
if subcommand.Name == name {
|
||||
return subcommand, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("ERROR : Command(%s) has no subcommand named %s", c.Name, name)
|
||||
}
|
||||
|
||||
func (c *Command) 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 {
|
||||
_, err := c.getFlag(arg)
|
||||
if err != nil {
|
||||
return unknownFlagMatch, nil
|
||||
}
|
||||
return flagMatch, nil
|
||||
}
|
||||
|
||||
subcommand := c.isSubCommand(arg)
|
||||
if subcommand == true {
|
||||
return commandMatch, nil
|
||||
}
|
||||
|
||||
return noMatch, nil
|
||||
}
|
||||
|
||||
func (c *Command) run (args []string) error {
|
||||
logging.Debug("Command(%s) : Entering Run", c.Name)
|
||||
|
||||
if c.Work == nil && len(args) == 0 {
|
||||
logging.Debug("Command(%s) : No arguments. Assuming help", c.Name)
|
||||
c.Help()
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
|
||||
logging.Debug("Command(%s) : Iterating on provided args (i: %d, arg: %s)", c.Name, i, arg)
|
||||
|
||||
match_type, err := c.determineMatch(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch match_type {
|
||||
case noMatch:
|
||||
return fmt.Errorf("No match found for Arg(%s) for Command(%s)", arg, c.Name)
|
||||
case helpMatch:
|
||||
c.Help()
|
||||
return nil
|
||||
case unknownFlagMatch:
|
||||
return fmt.Errorf("Command(%s) : ERROR : Unconfigured Flag(%s) detected", c.Name, arg)
|
||||
case flagMatch:
|
||||
flag, err := c.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", c.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:
|
||||
remaining_args := args[i+1:]
|
||||
subcommand, err := c.getSubCommand(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return subcommand.Run(remaining_args)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if c.Work != nil {
|
||||
flagmap := make(map[string]*ArgFlag)
|
||||
for _, flag := range c.Flags {
|
||||
flagmap[flag.Name] = flag
|
||||
}
|
||||
|
||||
ctx := Context{
|
||||
Command: c,
|
||||
Flags: flagmap,
|
||||
App: c.App,
|
||||
Args: args,
|
||||
}
|
||||
return c.Work(&ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Command) Help () error {
|
||||
commandHelpTemplate.Execute(os.Stdout, c)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Command) Check() error {
|
||||
if c.Name == "" {
|
||||
return errors.New("ERROR : Command Name wasn't set")
|
||||
}
|
||||
|
||||
if c.Description == "" {
|
||||
return fmt.Errorf("Command(%s) : ERROR : Description wasn't set", c.Name)
|
||||
}
|
||||
|
||||
if len(c.SubCommands) == 0 && c.Work == nil {
|
||||
return fmt.Errorf("Command(%s) : ERROR : Command was configured with neither commands (SubCommands) nor a work function (Work)", c.Name)
|
||||
}
|
||||
|
||||
if len(c.SubCommands) > 0 && c.Work != nil {
|
||||
return fmt.Errorf("Command(%s) : ERROR : Command was defined with both subcommands & a work function", c.Name)
|
||||
}
|
||||
|
||||
subcommands := make(map[string]bool)
|
||||
for _, subcommand := range c.SubCommands {
|
||||
err := subcommand.Check()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, exist := subcommands[subcommand.Name]; exist {
|
||||
return fmt.Errorf("Command(%s) : SubCommand(%s) : SubCommand Name was found as duplicate", c.Name, subcommand.Name)
|
||||
}
|
||||
subcommands[subcommand.Name]=true
|
||||
}
|
||||
for _, flag := range c.Flags {
|
||||
err := flag.Check()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
shorts := make(map[string]bool)
|
||||
longs := make(map[string]bool)
|
||||
names := make(map[string]bool)
|
||||
for _, flag := range c.Flags {
|
||||
if _, exist := shorts[flag.Short]; exist {
|
||||
return fmt.Errorf("Command(%s) : ArgFlag(%s) : flag short duplicate found (%s)", c.Name, flag.Name, flag.Short)
|
||||
}
|
||||
shorts[flag.Short] = true
|
||||
if _, exist := longs[flag.Long]; exist {
|
||||
return fmt.Errorf("Command(%s) : ArgFlag(%s) : flag long duplicate found (%s)", c.Name, flag.Name, flag.Long)
|
||||
}
|
||||
longs[flag.Long] = true
|
||||
if _, exist := names[flag.Name]; exist {
|
||||
return fmt.Errorf("Command(%s) : ArgFlag(Long: %s) : flag name duplicate found (%s)", c.Name, flag.Long, flag.Name)
|
||||
}
|
||||
names[flag.Name] = true
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
88
context.go
Normal file
88
context.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package parser
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Context struct {
|
||||
Command *Command
|
||||
App *App
|
||||
Flags map[string]*ArgFlag
|
||||
Args []string
|
||||
}
|
||||
|
||||
func (c *Context) GetFlag(name string) (*ArgFlag, error) {
|
||||
flag, exists := c.Flags[name]
|
||||
if ! exists {
|
||||
return nil, fmt.Errorf("Context : ERROR : Flag(%s) not found", name)
|
||||
}
|
||||
return flag, nil
|
||||
}
|
||||
|
||||
func (c *Context) GetValueInt(name string) (int64, error){
|
||||
flag, err := c.GetFlag(name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
value, err := flag.GetValueInt()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (c *Context) GetValueBool(name string) (bool, error){
|
||||
flag, err := c.GetFlag(name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
value, err := flag.GetValueBool()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (c *Context) GetValueFloat32(name string) (float32, error){
|
||||
flag, err := c.GetFlag(name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
value, err := flag.GetValueFloat32()
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (c *Context) GetValueFloat64(name string) (float64, error){
|
||||
flag, err := c.GetFlag(name)
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
value, err := flag.GetValueFloat64()
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (c *Context) GetValueString(name string) (string, error){
|
||||
flag, err := c.GetFlag(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
value, err := flag.GetValueString()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
175
flag.go
Normal file
175
flag.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type ArgFlag struct {
|
||||
Name string
|
||||
Short string
|
||||
Long string
|
||||
Description string
|
||||
Type ArgType
|
||||
Arg string
|
||||
Args []string
|
||||
OnMatch func () error
|
||||
}
|
||||
|
||||
var flags = make(map[string]*ArgFlag)
|
||||
|
||||
func (f *ArgFlag) requireArg() bool {
|
||||
return f.Type != NoneType && f.Type != BoolType && f.Type != MatchType
|
||||
}
|
||||
|
||||
func (f *ArgFlag) invalid() bool {
|
||||
return f.Name != ""
|
||||
}
|
||||
|
||||
func (f *ArgFlag) Matches(identifier string) bool {
|
||||
if f.Name == identifier || f.Short == identifier || f.Long == identifier {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *ArgFlag) GetIndex() (int, error) {
|
||||
for i, arg := range f.Args {
|
||||
if arg == f.Short || arg == f.Long {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("ERROR : Flag(%s) not found in arguments", f.Name)
|
||||
}
|
||||
|
||||
func (f *ArgFlag) GetValueInt() (int64, error) {
|
||||
if f.Type != IntType {
|
||||
return 0, fmt.Errorf("ERROR : Flag(%s) is not a IntType flag", f.symbol())
|
||||
}
|
||||
|
||||
return strconv.ParseInt(f.Arg, 10, 64)
|
||||
}
|
||||
|
||||
func (f *ArgFlag) GetValueString() (string, error) {
|
||||
if f.Type != StringType {
|
||||
return "", fmt.Errorf("ERROR : Flag(%s) is not a StringType flag", f.Name)
|
||||
}
|
||||
|
||||
return f.Arg, nil
|
||||
}
|
||||
|
||||
func (f *ArgFlag) symbol() string {
|
||||
index, err := f.GetIndex()
|
||||
if err != nil {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
return f.Args[index]
|
||||
}
|
||||
|
||||
func (f *ArgFlag) GetValueFloat32() (float32, error) {
|
||||
if f.Type != Float32Type {
|
||||
return 0.0, fmt.Errorf("ERROR : Flag(%s) is not a Float32Type flag", f.symbol())
|
||||
}
|
||||
|
||||
float, err := strconv.ParseFloat(f.Arg, 32)
|
||||
|
||||
if err != nil {
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
return float32(float), nil
|
||||
}
|
||||
|
||||
func (f *ArgFlag) GetValueFloat64() (float64, error) {
|
||||
if f.Type != Float64Type {
|
||||
return 0.0, fmt.Errorf("ERROR : Flag(%s) is not a Float64Type flag", f.symbol())
|
||||
}
|
||||
return strconv.ParseFloat(f.Arg, 64)
|
||||
}
|
||||
|
||||
func (f *ArgFlag) GetValueBool() (bool, error) {
|
||||
if f.Type != BoolType {
|
||||
return false, fmt.Errorf("ERROR : Flag(%s) is not a BoolType flag", f.symbol())
|
||||
}
|
||||
|
||||
_, err := f.GetIndex()
|
||||
if err != nil {
|
||||
return false, nil
|
||||
} else {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
type CheckFunc func(string) (bool,error)
|
||||
|
||||
func (f *ArgFlag) doCheck(arg string, check CheckFunc, error_string string) error {
|
||||
is_true, err := check(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ! is_true {
|
||||
return fmt.Errorf(error_string, f.symbol())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *ArgFlag) CheckArg(args []string) error {
|
||||
// Just checking if the argument provided to this flag is a valid one based on the ArgType
|
||||
f.Args = args
|
||||
if f.Type == NoneType {
|
||||
return fmt.Errorf("ArgFlag(%s) : ERROR : Flag not configured with a type", f.symbol())
|
||||
}
|
||||
|
||||
if len(args) < 2 {
|
||||
return fmt.Errorf("ArgFlag(%s) : ERROR : Not enough arguments", f.Name)
|
||||
}
|
||||
|
||||
arg := args[1]
|
||||
|
||||
switch f.Type {
|
||||
case StringType:
|
||||
is_flag, err := isFlag(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if is_flag {
|
||||
return fmt.Errorf("Flag(%s) : ERROR : Argument is a flag", f.symbol())
|
||||
}
|
||||
case IntType:
|
||||
err := f.doCheck(arg, isInt, "Flag(%s) : ERROR : Argument is not a valid number")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case Float32Type, Float64Type:
|
||||
err := f.doCheck(arg, isFloat, "Flag(%s) : ERROR : Argument is not a valid float")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
f.Arg = arg
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *ArgFlag) Check() error {
|
||||
if f.Name == "" {
|
||||
return errors.New("ERROR : Flag was not configured with Name")
|
||||
}
|
||||
if f.Type == NoneType {
|
||||
return fmt.Errorf("ArgFlag(%s) : ERROR : No type has been set", f.Name)
|
||||
}
|
||||
|
||||
if f.Description == "" {
|
||||
return fmt.Errorf("ArgFlag(%s) : ERROR : No Description has been set", f.Name)
|
||||
}
|
||||
|
||||
if f.Short == "" && f.Long == "" {
|
||||
return fmt.Errorf("ArgFlag(%s) : ERROR : No Short or Long flags were provided", f.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module git.arcanium.tech/tristan/go_parser
|
||||
|
||||
go 1.25.7
|
||||
|
||||
require git.arcanium.tech/tristan/logging v0.0.0-20260227204521-e3cf814e9bbc // indirect
|
||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
git.arcanium.tech/tristan/logging v0.0.0-20260227204521-e3cf814e9bbc h1:xYUrw+admjakl6rYrz5Rgmq/Q4vLa441pSwNaNQMfQs=
|
||||
git.arcanium.tech/tristan/logging v0.0.0-20260227204521-e3cf814e9bbc/go.mod h1:EfwBbpW5osQp3nlbKhQRY/jogmh2yPW1Y+5/DgWxe0Q=
|
||||
12
matchtype.go
Normal file
12
matchtype.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package parser
|
||||
|
||||
type matchType int
|
||||
const (
|
||||
noMatch matchType = iota
|
||||
flagMatch
|
||||
unknownFlagMatch
|
||||
commandMatch
|
||||
helpMatch
|
||||
)
|
||||
|
||||
|
||||
5
regex.go
Normal file
5
regex.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package parser
|
||||
|
||||
var flagRegex = "^-+[a-z-]+$"
|
||||
var intRegex = "^[0-9]+$"
|
||||
var floatRegex = "^[0-9]+(.[0-9]+)?$"
|
||||
40
templates.go
Normal file
40
templates.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package parser
|
||||
|
||||
import "text/template"
|
||||
|
||||
const commandHelpTemplateText = `
|
||||
App: {{.App.Name}}
|
||||
Command Usage: {{.Name}} [OPTIONS]
|
||||
|
||||
SubCommmands:
|
||||
-----------------------------------------------------------
|
||||
help : Show this help output
|
||||
{{range .SubCommands}} {{.Name | printf "%-12s" }} : {{.Description}}
|
||||
{{end}}
|
||||
|
||||
Flags:
|
||||
-----------------------------------------------------------
|
||||
-h --help : Show this help output
|
||||
{{range .Flags}}{{if .Short}}{{.Short}}{{end}} {{if .Long}}{{.Long}}{{end}} : {{.Description}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
var commandHelpTemplate = template.Must(template.New("command_help").Parse(commandHelpTemplateText))
|
||||
|
||||
const appHelpTemplateText = `
|
||||
App Usage: {{.Name}} [OPTIONS]
|
||||
|
||||
Commmands:
|
||||
-----------------------------------------------------------
|
||||
help : Show this help output
|
||||
{{range .Commands}} {{.Name | printf "%-12s" }} : {{.Description}}
|
||||
{{end}}
|
||||
|
||||
Flags:
|
||||
-----------------------------------------------------------
|
||||
-h --help : Show this help output
|
||||
{{range .Flags}}{{if .Short}}{{.Short}}{{end}}{{if .Long}} {{.Long}}{{end}} : {{.Description}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
var appHelpTemplate = template.Must(template.New("app_help").Parse(appHelpTemplateText))
|
||||
28
utils.go
Normal file
28
utils.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package parser
|
||||
|
||||
import "regexp"
|
||||
func doCheck(pattern string, arg string) (bool, error){
|
||||
match, err := regexp.MatchString(pattern, arg)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if match {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func isFlag(arg string) (bool, error) {
|
||||
return doCheck(flagRegex, arg)
|
||||
}
|
||||
|
||||
|
||||
func isInt(arg string) (bool, error) {
|
||||
return doCheck(intRegex, arg)
|
||||
}
|
||||
|
||||
func isFloat(arg string) (bool, error) {
|
||||
return doCheck(floatRegex, arg)
|
||||
}
|
||||
Reference in New Issue
Block a user