Skip to content

Commit

Permalink
Further work
Browse files Browse the repository at this point in the history
  • Loading branch information
tjayrush committed Jan 11, 2025
1 parent d3a2813 commit 0178603
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 182 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
xx
.vscode/launch.json
*.exe
*.exe~
Expand Down
65 changes: 0 additions & 65 deletions app/app.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package app

import (
"log"
"log/slog"
"os"

"github.com/TrueBlocks/trueblocks-khedra/v2/pkg/types"
"github.com/urfave/cli/v2"
Expand All @@ -17,17 +15,8 @@ type KhedraApp struct {
}

func NewKhedraApp() *KhedraApp {
os.Args = cleanArgs(os.Args)
k := &KhedraApp{}
k.Cli = initializeCli(k)

cfg, err := LoadConfig()
if err != nil {
log.Fatalf("failed to load config: %v", err)
}
k.config = &cfg
k.fileLogger, k.progLogger = types.NewLoggers(cfg.Logging)

return k
}

Expand Down Expand Up @@ -152,57 +141,3 @@ func (a *App) Fatal(err error) {
os.Exit(1)
}
*/

func parseArgsInternal(args []string) (hasHelp bool, hasVersion bool, commands []string, nonFlagCount int) {
commands = []string{}
if len(args) == 0 {
hasHelp = true
return
}

helpForms := map[string]bool{
"--help": true, "-help": true, "help": true,
"--h": true, "-h": true,
}

versionForms := map[string]bool{
"--version": true, "-version": true, "version": true,
"--v": true, "-v": true,
}

for i, arg := range args {
if helpForms[arg] {
hasHelp = true
continue
}
if versionForms[arg] {
hasVersion = true
continue
}
commands = append(commands, arg)
if i != 0 && len(arg) == 0 || arg[0] != '-' {
nonFlagCount++
}
}

return
}

func cleanArgs(args []string) []string {
programName := args[:1] // program name

hasHelp, hasVersion, commands, _ := parseArgsInternal(args[1:])
if hasHelp {
result := append(programName, "help")
if len(commands) > 0 {
return append(result, commands[0])
}
return result
}

if hasVersion {
return append(programName, "version")
}

return append(programName, commands...)
}
76 changes: 76 additions & 0 deletions app/app_args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package app

import (
"fmt"
)

func parseArgsInternal(args []string) (hasHelp bool, hasVersion bool, commands []string, nonFlagCount int) {
commands = []string{}
if len(args) == 0 {
hasHelp = true
return
}

helpForms := map[string]bool{
"--help": true, "-help": true, "help": true,
"--h": true, "-h": true,
}

versionForms := map[string]bool{
"--version": true, "-version": true, "version": true,
"--v": true, "-v": true,
}

for i, arg := range args {
if helpForms[arg] {
hasHelp = true
continue
}
if versionForms[arg] {
hasVersion = true
continue
}
commands = append(commands, arg)
if i != 0 && len(arg) == 0 || arg[0] != '-' {
nonFlagCount++
}
}

return
}

func cleanArgs(args []string) []string {
programName := args[:1] // program name

hasHelp, hasVersion, commands, _ := parseArgsInternal(args[1:])
if hasHelp {
result := append(programName, "help")
if len(commands) > 0 {
return append(result, commands[0])
}
return result
}

if hasVersion {
return append(programName, "version")
}

return append(programName, commands...)
}

func validateArgs(args []string, expectedCmdCount, expectedFlagCount int) error {
_, _, flags, cmdCnt := parseArgsInternal(args)
if cmdCnt != expectedCmdCount || len(flags) != expectedFlagCount {
if cmdCnt > expectedCmdCount {
var err error
if unknown := getUnknownCmd(args); len(unknown) > 0 {
err = fmt.Errorf("command '%s' not found", unknown)
} else {
err = fmt.Errorf("use only one command at a time")
}
return err
}
return fmt.Errorf("argument mismatch: %v %v %d %d", args, flags, cmdCnt, len(flags))
}
return nil
}
64 changes: 64 additions & 0 deletions app/app_test.go → app/app_args_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package app

import (
"errors"
"fmt"
"os"
"reflect"
"testing"

"github.com/TrueBlocks/trueblocks-khedra/v2/pkg/types"
)

func TestParseArgsInternal(t *testing.T) {
Expand Down Expand Up @@ -141,3 +146,62 @@ func TestCleanArgs(t *testing.T) {
})
}
}

func TestValidateArgs(t *testing.T) {
types.SetupTest([]string{})
tests := []struct {
name string
args []string
expectedCmdCount int
expectedFlagCount int
expectedErr error
}{
{
name: "Valid single command",
args: []string{"khedra", "init"},
expectedCmdCount: 1,
expectedFlagCount: 1,
expectedErr: nil,
},
{
name: "Valid multi-word command",
args: []string{"khedra", "config", "edit"},
expectedCmdCount: 2,
expectedFlagCount: 2,
expectedErr: nil,
},
{
name: "Unknown command",
args: []string{"khedra", "unknown"},
expectedCmdCount: 1,
expectedFlagCount: 0,
expectedErr: fmt.Errorf("argument mismatch: %v %v %d %d", []string{"unknown"}, []string{"unknown"}, 1, 1),
},
{
name: "Extra command",
args: []string{"khedra", "init", "daemon"},
expectedCmdCount: 1,
expectedFlagCount: 0,
expectedErr: fmt.Errorf("use only one command at a time"),
},
{
name: "Argument mismatch",
args: []string{"khedra", "init"},
expectedCmdCount: 1,
expectedFlagCount: 2, // wrong on purpose for testing
expectedErr: fmt.Errorf("argument mismatch: %v %v %d %d", []string{"init"}, []string{"init"}, 1, 1),
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
os.Args = tt.args
err := validateArgs(tt.args[1:], tt.expectedCmdCount, tt.expectedFlagCount)
fmt.Println(tt.args, tt.expectedErr, err)

if !errors.Is(err, tt.expectedErr) && (err == nil || tt.expectedErr == nil || err.Error() != tt.expectedErr.Error()) {
t.Errorf("expected [ %v ], got [ %v ]", tt.expectedErr, err)
}
})
}
}
30 changes: 7 additions & 23 deletions app/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
var execCommand = exec.Command

func initializeCli(k *KhedraApp) *cli.App {
os.Args = cleanArgs(os.Args)

showError := func(c *cli.Context, showHelp bool, err error) {
_, _ = c.App.Writer.Write([]byte("\n" + colors.Red + "Error: " + err.Error() + colors.Off + "\n\n"))
if showHelp {
Expand All @@ -36,7 +38,7 @@ func initializeCli(k *KhedraApp) *cli.App {
Usage: "Initializes Khedra",
OnUsageError: onUsageError,
Action: func(c *cli.Context) error {
if _, _, err := validateArgs(os.Args[1:], 1, 1); err != nil {
if err := validateArgs(os.Args[1:], 1, 1); err != nil {
return err
}
return k.initAction(c)
Expand All @@ -47,7 +49,7 @@ func initializeCli(k *KhedraApp) *cli.App {
Usage: "Runs Khedra's services",
OnUsageError: onUsageError,
Action: func(c *cli.Context) error {
if _, _, err := validateArgs(os.Args[1:], 1, 1); err != nil {
if err := validateArgs(os.Args[1:], 1, 1); err != nil {
return err
}
return k.daemonAction(c)
Expand All @@ -59,7 +61,7 @@ func initializeCli(k *KhedraApp) *cli.App {
Hidden: true,
OnUsageError: onUsageError,
Action: func(c *cli.Context) error {
if _, _, err := validateArgs(os.Args[1:], 0, 0); err != nil {
if err := validateArgs(os.Args[1:], 0, 0); err != nil {
return err
}
return k.versionAction(c)
Expand All @@ -74,7 +76,7 @@ func initializeCli(k *KhedraApp) *cli.App {
Usage: "Opens the configuration file for editing",
OnUsageError: onUsageError,
Action: func(c *cli.Context) error {
if _, _, err := validateArgs(os.Args[1:], 2, 2); err != nil {
if err := validateArgs(os.Args[1:], 2, 2); err != nil {
return err
}
return k.configEditAction(c)
Expand All @@ -85,7 +87,7 @@ func initializeCli(k *KhedraApp) *cli.App {
Usage: "Displays the current configuration",
OnUsageError: onUsageError,
Action: func(c *cli.Context) error {
if _, _, err := validateArgs(os.Args[1:], 2, 2); err != nil {
if err := validateArgs(os.Args[1:], 2, 2); err != nil {
return err
}
return k.configShowAction(c)
Expand Down Expand Up @@ -113,24 +115,6 @@ func initializeCli(k *KhedraApp) *cli.App {
}
}

func validateArgs(args []string, expectedCmdCount, expectedFlagCount int) ([]string, int, error) {
_, _, flags, cmdCnt := parseArgsInternal(args)
if cmdCnt != expectedCmdCount || len(flags) != expectedFlagCount {
if cmdCnt > expectedCmdCount {
var err error
if unknown := getUnknownCmd(os.Args[1:]); len(unknown) > 0 {
err = fmt.Errorf("command '%s' not found", unknown)
} else {
err = fmt.Errorf("use only one command at a time")
}
return nil, 0, err
}
return nil, 0, fmt.Errorf("argument mismatch: %v %v %d %d", args, flags, cmdCnt, len(flags))
}

return flags, cmdCnt, nil
}

/*
var (
ErrMissingArgument = errors.New("missing argument")
Expand Down
Loading

0 comments on commit 0178603

Please sign in to comment.