summaryrefslogtreecommitdiffstats
path: root/pkg/gui/services/custom_commands/resolver.go
blob: 1b80987c10d5d5f80c5cf397ed0e845c28ae814d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package custom_commands

import (
	"bytes"
	"fmt"
	"text/template"

	"github.com/jesseduffield/lazygit/pkg/common"
	"github.com/jesseduffield/lazygit/pkg/config"
)

// takes a prompt that is defined in terms of template strings and resolves the templates to contain actual values
type Resolver struct {
	c *common.Common
}

func NewResolver(c *common.Common) *Resolver {
	return &Resolver{c: c}
}

func (self *Resolver) resolvePrompt(
	prompt *config.CustomCommandPrompt,
	resolveTemplate func(string) (string, error),
) (*config.CustomCommandPrompt, error) {
	var err error
	result := &config.CustomCommandPrompt{
		ValueFormat: prompt.ValueFormat,
		LabelFormat: prompt.LabelFormat,
	}

	result.Title, err = resolveTemplate(prompt.Title)
	if err != nil {
		return nil, err
	}

	result.InitialValue, err = resolveTemplate(prompt.InitialValue)
	if err != nil {
		return nil, err
	}

	result.Body, err = resolveTemplate(prompt.Body)
	if err != nil {
		return nil, err
	}

	result.Command, err = resolveTemplate(prompt.Command)
	if err != nil {
		return nil, err
	}

	result.Filter, err = resolveTemplate(prompt.Filter)
	if err != nil {
		return nil, err
	}

	if prompt.Type == "menu" {
		result.Options, err = self.resolveMenuOptions(prompt, resolveTemplate)
		if err != nil {
			return nil, err
		}
	}

	return result, nil
}

func (self *Resolver) resolveMenuOptions(prompt *config.CustomCommandPrompt, resolveTemplate func(string) (string, error)) ([]config.CustomCommandMenuOption, error) {
	newOptions := make([]config.CustomCommandMenuOption, 0, len(prompt.Options))
	for _, option := range prompt.Options {
		option := option
		newOption, err := self.resolveMenuOption(&option, resolveTemplate)
		if err != nil {
			return nil, err
		}
		newOptions = append(newOptions, *newOption)
	}

	return newOptions, nil
}

func (self *Resolver) resolveMenuOption(option *config.CustomCommandMenuOption, resolveTemplate func(string) (string, error)) (*config.CustomCommandMenuOption, error) {
	nameTemplate := option.Name
	if nameTemplate == "" {
		// this allows you to only pass values rather than bother with names/descriptions
		nameTemplate = option.Value
	}

	name, err := resolveTemplate(nameTemplate)
	if err != nil {
		return nil, err
	}

	description, err := resolveTemplate(option.Description)
	if err != nil {
		return nil, err
	}

	value, err := resolveTemplate(option.Value)
	if err != nil {
		return nil, err
	}

	return &config.CustomCommandMenuOption{
		Name:        name,
		Description: description,
		Value:       value,
	}, nil
}

func main() {
	fmt.Println(ResolveTemplate("old approach: {{index .PromptResponses 0}}, new approach: {{ .Form.a }}", CustomCommandObject{
		PromptResponses: []string{"a"},
		Form:            map[string]string{"a": "B"},
	}))
}

type CustomCommandObject struct {
	// deprecated. Use Responses instead
	PromptResponses []string
	Form            map[string]string
}

func ResolveTemplate(templateStr string, object interface{}) (string, error) {
	tmpl, err := template.New("template").Parse(templateStr)
	if err != nil {
		return "", err
	}

	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, object); err != nil {
		return "", err
	}

	return buf.String(), nil
}