From 5c39f1c93de210ea0c44af2c0591c4d1b625c205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=A1=D1=8B=D1=81?= =?UTF-8?q?=D0=BE=D0=B5=D0=B2?= Date: Sun, 31 Dec 2023 16:16:38 +0800 Subject: [PATCH] Adds possibility to pass arguments to macro commands --- pkg/command/commands.go | 7 +++- pkg/command/macro.go | 80 +++++++++++++++++++++++++++++---------- pkg/command/macro_test.go | 39 +++++++++---------- 3 files changed, 87 insertions(+), 39 deletions(-) diff --git a/pkg/command/commands.go b/pkg/command/commands.go index 9874664..bef8da7 100644 --- a/pkg/command/commands.go +++ b/pkg/command/commands.go @@ -122,8 +122,13 @@ func Factory(raw string, macro *Macro) (Executer, error) { return NewSleepCommand(time.Duration(sec) * time.Second), nil default: + args := "" + if len(parts) > 1 { + args = parts[1] + } + if macro != nil { - return macro.Get(cmd) + return macro.Get(cmd, args) } return nil, &ErrUnknownCommand{cmd} diff --git a/pkg/command/macro.go b/pkg/command/macro.go index cade9c2..89d0b86 100644 --- a/pkg/command/macro.go +++ b/pkg/command/macro.go @@ -1,10 +1,12 @@ package command import ( + "bytes" "fmt" "log" "os" "strings" + "text/template" "gopkg.in/yaml.v3" ) @@ -16,7 +18,7 @@ type Config struct { } type Macro struct { - macro map[string]Executer + macro map[string]*MacroTemplates domains []string } @@ -25,7 +27,7 @@ type Macro struct { // Returns a pointer to the newly created Macro instance. func NewMacro(domains []string) *Macro { return &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: domains, } } @@ -40,25 +42,17 @@ func (m *Macro) AddCommands(name string, rawCommands []string) error { return &ErrDuplicateMacro{name} } - commands := []Executer{} + if len(rawCommands) == 0 { + return ErrEmptyMacro{name} + } - for _, rawCommand := range rawCommands { - cmd, err := Factory(rawCommand, nil) - if err != nil { - return err - } + templs, err := NewMacroTemplates(rawCommands) - commands = append(commands, cmd) + if err != nil { + return err } - switch len(commands) { - case 0: - return ErrEmptyMacro{name} - case 1: - m.macro[name] = commands[0] - default: - m.macro[name] = NewSequence(commands) - } + m.macro[name] = templs return nil } @@ -78,9 +72,10 @@ func (m *Macro) merge(macro *Macro) error { } // Get returns the Executer associated with the given name, or an error if the name is not found. -func (m *Macro) Get(name string) (Executer, error) { +func (m *Macro) Get(name, argString string) (Executer, error) { if cmd, ok := m.macro[name]; ok { - return cmd, nil + args := strings.Fields(argString) + return cmd.GetExecuter(args) } return nil, &ErrUnknownCommand{name} @@ -172,3 +167,50 @@ func LoadMacroForDomain(macroDir, domain string) (*Macro, error) { return macro, nil } + +type MacroTemplates struct { + list []*template.Template +} + +func NewMacroTemplates(templates []string) (*MacroTemplates, error) { + tmpls := &MacroTemplates{} + tmpls.list = make([]*template.Template, len(templates)) + + for i, rawTempl := range templates { + tmpl, err := template.New("macro").Parse(rawTempl) + if err != nil { + return nil, err + } + + tmpls.list[i] = tmpl + } + + return tmpls, nil +} + +func (t *MacroTemplates) GetExecuter(args []string) (Executer, error) { + data := struct { + Args []string + }{args} + cmds := make([]Executer, len(t.list)) + + for i, tmpl := range t.list { + var output bytes.Buffer + if err := tmpl.Execute(&output, data); err != nil { + return nil, err + } + + cmd, err := Factory(output.String(), nil) + if err != nil { + return nil, err + } + + cmds[i] = cmd + } + + if len(cmds) == 1 { + return cmds[0], nil + } + + return NewSequence(cmds), nil +} diff --git a/pkg/command/macro_test.go b/pkg/command/macro_test.go index 4caf4d3..cfd8204 100644 --- a/pkg/command/macro_test.go +++ b/pkg/command/macro_test.go @@ -15,7 +15,7 @@ func TestNewMacro(t *testing.T) { name: "empty domains", domains: []string{}, want: &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: []string{}, }, }, @@ -23,7 +23,7 @@ func TestNewMacro(t *testing.T) { name: "non-empty domains", domains: []string{"example.com", "google.com"}, want: &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: []string{"example.com", "google.com"}, }, }, @@ -58,7 +58,7 @@ func TestMacro_AddCommands(t *testing.T) { }, { name: "add existing macro", - macro: &Macro{macro: map[string]Executer{"test": nil}}, + macro: &Macro{macro: map[string]*MacroTemplates{"test": nil}}, commandName: "test", commands: []string{"send hello"}, wantErr: true, @@ -106,11 +106,11 @@ func TestMacro_Merge(t *testing.T) { { name: "merge empty macro with empty macro", macro: &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: []string{}, }, otherMacro: &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: []string{}, }, wantErr: false, @@ -119,13 +119,13 @@ func TestMacro_Merge(t *testing.T) { { name: "merge non-empty macro with empty macro", macro: &Macro{ - macro: map[string]Executer{ + macro: map[string]*MacroTemplates{ "test": nil, }, domains: []string{}, }, otherMacro: &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: []string{}, }, wantErr: false, @@ -134,11 +134,11 @@ func TestMacro_Merge(t *testing.T) { { name: "merge empty macro with non-empty macro", macro: &Macro{ - macro: make(map[string]Executer), + macro: make(map[string]*MacroTemplates), domains: []string{}, }, otherMacro: &Macro{ - macro: map[string]Executer{ + macro: map[string]*MacroTemplates{ "test": nil, }, domains: []string{}, @@ -149,13 +149,13 @@ func TestMacro_Merge(t *testing.T) { { name: "merge non-empty macro with non-empty macro", macro: &Macro{ - macro: map[string]Executer{ + macro: map[string]*MacroTemplates{ "test": nil, }, domains: []string{}, }, otherMacro: &Macro{ - macro: map[string]Executer{ + macro: map[string]*MacroTemplates{ "test2": nil, }, domains: []string{}, @@ -166,13 +166,13 @@ func TestMacro_Merge(t *testing.T) { { name: "merge macro with duplicate macro name", macro: &Macro{ - macro: map[string]Executer{ + macro: map[string]*MacroTemplates{ "test": nil, }, domains: []string{}, }, otherMacro: &Macro{ - macro: map[string]Executer{ + macro: map[string]*MacroTemplates{ "test": nil, }, domains: []string{}, @@ -194,6 +194,7 @@ func TestMacro_Merge(t *testing.T) { } } func TestMacro_Get(t *testing.T) { + testTemplate, _ := NewMacroTemplates([]string{"exit"}) tests := []struct { name string macro *Macro @@ -204,7 +205,7 @@ func TestMacro_Get(t *testing.T) { }{ { name: "get existing command", - macro: &Macro{macro: map[string]Executer{"test": NewExit()}}, + macro: &Macro{macro: map[string]*MacroTemplates{"test": testTemplate}}, cmdName: "test", wantCmd: NewExit(), wantErr: false, @@ -212,7 +213,7 @@ func TestMacro_Get(t *testing.T) { }, { name: "get non-existing command", - macro: &Macro{macro: map[string]Executer{}}, + macro: &Macro{macro: map[string]*MacroTemplates{}}, cmdName: "test", wantCmd: nil, wantErr: true, @@ -220,7 +221,7 @@ func TestMacro_Get(t *testing.T) { }, { name: "get command with empty macro", - macro: &Macro{macro: map[string]Executer{}}, + macro: &Macro{macro: map[string]*MacroTemplates{}}, cmdName: "", wantCmd: nil, wantErr: true, @@ -228,7 +229,7 @@ func TestMacro_Get(t *testing.T) { }, { name: "get command with non-empty macro", - macro: &Macro{macro: map[string]Executer{"test": nil}}, + macro: &Macro{macro: map[string]*MacroTemplates{"test": nil}}, cmdName: "", wantCmd: nil, wantErr: true, @@ -238,7 +239,7 @@ func TestMacro_Get(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - cmd, err := tt.macro.Get(tt.cmdName) + cmd, err := tt.macro.Get(tt.cmdName, "") if (err != nil) != tt.wantErr { t.Errorf("Macro.Get() error = %v, wantErr %v", err, tt.wantErr) } @@ -297,7 +298,7 @@ macro: t.Errorf("LoadFromFile() domain = %s, want %s", macro.domains[0], domain) } - cmd, err := macro.Get("test") + cmd, err := macro.Get("test", "") if err != nil { t.Errorf("LoadFromFile() error = %v, want nil", err)