From e21eb5b04c3068d7b0f6c787cea774fb1df2272b Mon Sep 17 00:00:00 2001
From: Kevin Lyda <kevin@lyda.ie>
Date: Tue, 6 May 2025 12:04:11 +0100
Subject: [PATCH] Move commands into a map.

---
 dclish/dclish.go | 57 ++++++++++++++++++++++++++++++++++++------------
 repl/help.go     | 11 ++++++++++
 2 files changed, 54 insertions(+), 14 deletions(-)
 create mode 100644 repl/help.go

diff --git a/dclish/dclish.go b/dclish/dclish.go
index f7fbe85..6849830 100644
--- a/dclish/dclish.go
+++ b/dclish/dclish.go
@@ -11,17 +11,16 @@ type ActionFunc func(*Command) error
 
 // Flag is a flag for a command.
 type Flag struct {
-	Name        string
 	Value       string
+	Default     string
 	Description string
 }
 
 // Flags is the list of flags.
-type Flags []*Flag
+type Flags map[string]*Flag
 
 // Command contains the definition of a command, it's flags and subcommands.
 type Command struct {
-	Command     string
 	Flags       Flags
 	Args        []string
 	Commands    []*Command
@@ -30,24 +29,54 @@ type Command struct {
 }
 
 // Commands is the full list of commands.
-type Commands []*Command
+type Commands map[string]*Command
 
 // ParseAndRun parses a command line and runs the command.
 func (c Commands) ParseAndRun(line string) error {
 	// TODO: this doesn't handle a DCL command line completely.
 	words := strings.Fields(line)
 	fmt.Printf("TODO ParseAndRun need to parse flags: %s\n", words)
-	cmd := strings.ToUpper(words[0])
-	for i := range c {
-		if c[i].Command == cmd {
-			if c[i].Action == nil {
-				fmt.Printf("Command not implemented:\n%s\n", c[i].Description)
-				return nil
+	cmd, ok := c[strings.ToUpper(words[0])]
+	if !ok {
+		fmt.Printf("ERROR: Unknown command '%s'\n", words[0])
+		return nil
+	}
+	if cmd.Action == nil {
+		fmt.Printf("ERROR: Command not implemented:\n%s\n", cmd.Description)
+		return nil
+	}
+	for flg := range cmd.Flags {
+		cmd.Flags[flg].Value = cmd.Flags[flg].Default
+	}
+	cmd.Args = []string{}
+	if len(words) == 1 {
+		return cmd.Action(cmd)
+	}
+	for i := range words[1:] {
+		if strings.HasPrefix(words[i], "/") {
+			flag, val, assigned := strings.Cut(words[i], "=")
+			if assigned {
+				wordup := strings.ToUpper(flag)
+				flg, ok := cmd.Flags[wordup]
+				if !ok {
+					fmt.Printf("ERROR: Flag '%s' not recognised.", words[i])
+				}
+				flg.Value = val
+			} else {
+				// TODO: handle toggle flag.
+				wordup := strings.ToUpper(words[i])
+				value := "true"
+				if strings.HasPrefix(wordup, "/NO") {
+					wordup = strings.Replace(wordup, "/NO", "/", 1)
+					value = "false"
+				}
+				flg, ok := cmd.Flags[wordup]
+				if !ok {
+					fmt.Printf("ERROR: Flag '%s' not recognised.", words[i])
+				}
+				flg.Value = value
 			}
-			err := c[i].Action(c[i])
-			return err
 		}
 	}
-	fmt.Printf("ERROR: Unknown command '%s'\n", cmd)
-	return nil
+	return cmd.Action(cmd)
 }
diff --git a/repl/help.go b/repl/help.go
new file mode 100644
index 0000000..4322c57
--- /dev/null
+++ b/repl/help.go
@@ -0,0 +1,11 @@
+// Package repl implements the main event loop.
+package repl
+
+import (
+	"git.lyda.ie/kevin/bulletin/dclish"
+)
+
+// ActionHelp handles the `HELP` command.
+func ActionHelp(_ *dclish.Command) error {
+	return nil
+}
-- 
GitLab