summaryrefslogtreecommitdiff
path: root/command.go
diff options
context:
space:
mode:
Diffstat (limited to 'command.go')
-rw-r--r--command.go279
1 files changed, 279 insertions, 0 deletions
diff --git a/command.go b/command.go
new file mode 100644
index 0000000..760ee25
--- /dev/null
+++ b/command.go
@@ -0,0 +1,279 @@
+package main
+
+import (
+ "errors"
+ "os"
+ "strconv"
+ "strings"
+)
+
+var (
+ ErrInvalidArgs = errors.New("bad command arguments")
+ ErrUnknownCommand = errors.New("don't know that one")
+)
+
+type Command struct {
+ Name string
+ Args []string
+}
+
+func ParseCommand(line string) (*Command, error) {
+ line = strings.TrimSpace(line)
+ if line == "" {
+ return &Command{Name: "print"}, nil
+ }
+
+ cmd, rest, _ := strings.Cut(line, " ")
+
+ switch line[0] {
+ case 'r':
+ if strings.HasPrefix("root", cmd) {
+ return &Command{Name: "root"}, nil
+ }
+ if strings.HasPrefix("reload", cmd) {
+ return &Command{Name: "reload"}, nil
+ }
+ case 'R':
+ if strings.HasPrefix("Root", cmd) {
+ return &Command{Name: "Root"}, nil
+ }
+ case 'b':
+ if strings.HasPrefix("back", cmd) {
+ return &Command{Name: "back"}, nil
+ }
+ case 'f':
+ if strings.HasPrefix("forward", cmd) {
+ return &Command{Name: "forward"}, nil
+ }
+ case 'n':
+ if strings.HasPrefix("next", cmd) {
+ return &Command{Name: "next"}, nil
+ }
+ case 'p':
+ if strings.HasPrefix("print", cmd) {
+ return &Command{Name: "print"}, nil
+ }
+ if strings.HasPrefix("previous", cmd) {
+ return &Command{Name: "previous"}, nil
+ }
+ case 'u':
+ if strings.HasPrefix("up", cmd) {
+ return &Command{Name: "up"}, nil
+ }
+ case 'g':
+ if strings.HasPrefix("go", cmd) {
+ if rest == "" {
+ return nil, ErrInvalidArgs
+ }
+ return &Command{Name: "go", Args: []string{rest}}, nil
+ }
+ case 'h':
+ if strings.HasPrefix("help", cmd) {
+ return &Command{
+ Name: "help",
+ Args: []string{rest},
+ }, nil
+ }
+ if strings.HasPrefix("history", cmd) {
+ return &Command{Name: "history"}, nil
+ }
+ case '|':
+ return &Command{
+ Name: "pipe",
+ Args: []string{strings.TrimSpace(line[1:])},
+ }, nil
+ case 's':
+ if strings.HasPrefix("save", cmd) {
+ return &Command{
+ Name: "save",
+ Args: []string{rest},
+ }, nil
+ }
+ case 'l':
+ if strings.HasPrefix("links", cmd) {
+ return &Command{Name: "links"}, nil
+ }
+ case 'm':
+ if strings.HasPrefix("mark", cmd) {
+ args, err := parseMarkArgs(rest)
+ if err != nil {
+ return nil, err
+ }
+ return &Command{Name: "mark", Args: args}, nil
+ }
+ case 't':
+ if strings.HasPrefix("tour", cmd) {
+ args, err := parseTourArgs(rest)
+ if err != nil {
+ return nil, err
+ }
+ return &Command{Name: "tour", Args: args}, nil
+ }
+ case 'q':
+ if strings.HasPrefix("quit", cmd) {
+ return &Command{Name: "quit"}, nil
+ }
+ }
+
+ if rest == "" {
+ return &Command{Name: "go", Args: []string{cmd}}, nil
+ }
+
+ return nil, ErrUnknownCommand
+}
+
+func parseMarkArgs(line string) ([]string, error) {
+ if line == "" {
+ return nil, ErrInvalidArgs
+ }
+
+ fields := strings.Fields(line)
+ switch fields[0][0] {
+ case 'a':
+ if strings.HasPrefix("add", fields[0]) {
+ fields[0] = "add"
+ if len(fields) != 3 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ case 'g':
+ if strings.HasPrefix("go", fields[0]) {
+ fields[0] = "go"
+ if len(fields) != 2 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ case 'l':
+ if strings.HasPrefix("list", fields[0]) {
+ fields[0] = "list"
+ if len(fields) != 1 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ }
+
+ if len(fields) != 1 {
+ return nil, ErrInvalidArgs
+ }
+
+ return []string{"go", fields[0]}, nil
+}
+
+func parseTourArgs(line string) ([]string, error) {
+ if line == "" {
+ return []string{"next"}, nil
+ }
+
+ fields := strings.Fields(line)
+ switch fields[0][0] {
+ case 'a':
+ if strings.HasPrefix("add", fields[0]) {
+ fields[0] = "add"
+ if len(fields) == 1 {
+ return nil, ErrInvalidArgs
+ }
+ if strings.HasPrefix("next", fields[1]) {
+ fields[1] = "next"
+ }
+ return fields, nil
+ }
+ case 'n':
+ if strings.HasPrefix("next", fields[0]) {
+ fields[0] = "next"
+ if len(fields) != 1 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ case 's':
+ if strings.HasPrefix("set", fields[0]) {
+ fields[0] = "set"
+ if len(fields) == 1 {
+ return fields, nil
+ }
+ if len(fields) != 2 {
+ return nil, ErrInvalidArgs
+ }
+ if len(fields[1]) != 1 || fields[1][0] < 'a' || fields[1][0] > 'z' {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ if strings.HasPrefix("show", fields[0]) {
+ fields[0] = "show"
+ if len(fields) != 1 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ case 'l':
+ if strings.HasPrefix("list", fields[0]) {
+ fields[0] = "list"
+ if len(fields) != 1 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ case 'p':
+ if strings.HasPrefix("previous", fields[0]) {
+ fields[0] = "previous"
+ if len(fields) != 1 {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ case 'g':
+ if strings.HasPrefix("go", fields[0]) {
+ fields[0] = "go"
+ if len(fields) != 2 {
+ return nil, ErrInvalidArgs
+ }
+ if _, err := strconv.Atoi(fields[1]); err != nil {
+ return nil, ErrInvalidArgs
+ }
+ return fields, nil
+ }
+ }
+
+ return nil, ErrInvalidArgs
+}
+
+func RunCommand(conf *Config, cmd *Command, state *BrowserState) error {
+ switch cmd.Name {
+ case "root":
+ return Root(state, true, conf)
+ case "Root":
+ return Root(state, false, conf)
+ case "reload":
+ return Reload(state, conf)
+ case "back":
+ return Back(state)
+ case "forward":
+ return Forward(state)
+ case "next":
+ return Next(state, conf)
+ case "previous":
+ return Previous(state, conf)
+ case "up":
+ return Up(state, conf)
+ case "go":
+ return Go(state, cmd.Args[0], conf)
+ case "print":
+ return Print(state)
+ case "links":
+ return Links(state, conf)
+ case "history":
+ return HistoryCmd(state)
+ case "save":
+ return Save(state, cmd.Args[0], conf)
+ case "mark":
+ return Mark(state, cmd.Args, conf)
+ case "quit":
+ os.Exit(0)
+ }
+
+ return ErrUnknownCommand
+}