diff options
Diffstat (limited to 'command.go')
| -rw-r--r-- | command.go | 279 |
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 +} |
