1package palette
2
3import (
4 "strings"
5
6 "github.com/bnema/vev/internal/usecase/command"
7)
8
9// Action is the exact command token and its unmodified, whitespace-delimited
10// arguments. It is deliberately independent of palette state.
11type Action struct {
12 Command command.Command
13 Args []string
14}
15
16// ParseAction recognizes an exact effective command result token. It accepts
17// outer and repeated whitespace but never treats a prefix or concatenated token
18// as a command. Static commands reject arguments.
19func ParseAction(results []Result, input string) (Action, bool) {
20 fields := strings.Fields(input)
21 if len(fields) == 0 {
22 return Action{}, false
23 }
24 for _, result := range results {
25 cmd, ok := result.Command()
26 if !ok || !strings.EqualFold(fields[0], cmd.Code) {
27 continue
28 }
29 args := append([]string(nil), fields[1:]...)
30 switch cmd.Arguments {
31 case command.ArgumentsNone:
32 if len(args) != 0 {
33 return Action{}, false
34 }
35 case command.ArgumentsRequired:
36 if len(args) == 0 {
37 return Action{}, false
38 }
39 }
40 return Action{Command: cmd, Args: args}, true
41 }
42 return Action{}, false
43}
44
45// ArgumentCommand returns the exact argument-taking command whose token is
46// being typed, including the whitespace-before-argument state.
47func ArgumentCommand(results []Result, input string) (command.Command, bool) {
48 _, cmd, ok := argumentResult(results, input)
49 return cmd, ok
50}
51
52// argumentResult finds the exact argument-taking command and its source row in
53// one pass so callers can reuse the immutable result without another scan.
54func argumentResult(results []Result, input string) (Result, command.Command, bool) {
55 fields := strings.Fields(input)
56 if len(fields) == 0 {
57 return Result{}, command.Command{}, false
58 }
59 for _, result := range results {
60 cmd, ok := result.Command()
61 if ok && cmd.Arguments == command.ArgumentsRequired && strings.EqualFold(fields[0], cmd.Code) {
62 return result, cmd, true
63 }
64 }
65 return Result{}, command.Command{}, false
66}