Skip to content

Commit 5ca41e5

Browse files
authored
Merge pull request #1267 from afbjorklund/indent-list
Add template functions for list/inspect message
2 parents fcbf3d8 + f366543 commit 5ca41e5

File tree

4 files changed

+120
-6
lines changed

4 files changed

+120
-6
lines changed

cmd/limactl/list.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ func newListCommand() *cobra.Command {
4141
--format yaml - output in yaml format
4242
--format table - output in table format
4343
--format '{{ <go template> }}' - if the format begins and ends with '{{ }}', then it is used as a go template.
44-
44+
` + store.FormatHelp +
45+
`
4546
The following legacy flags continue to function:
4647
--json - equal to '--format json'
4748
`,

pkg/store/instance.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ type FormatData struct {
213213
IdentityFile string
214214
}
215215

216+
var FormatHelp = "\n" + textutil.PrefixString("\t\t",
217+
"These functions are available to go templates:\n\n"+
218+
textutil.IndentString(2,
219+
strings.Join(textutil.FuncHelp, "\n")+"\n"))
220+
216221
func AddGlobalFields(inst *Instance) (FormatData, error) {
217222
var data FormatData
218223
data.Instance = *inst
@@ -282,6 +287,7 @@ func PrintInstances(w io.Writer, instances []*Instance, format string) error {
282287
if err != nil {
283288
return err
284289
}
290+
data.Message = strings.TrimSuffix(instance.Message, "\n")
285291
err = tmpl.Execute(w, data)
286292
if err != nil {
287293
return err

pkg/textutil/textutil.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package textutil
33
import (
44
"bytes"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"strings"
89
"text/template"
@@ -23,6 +24,38 @@ func ExecuteTemplate(tmpl string, args interface{}) ([]byte, error) {
2324
return b.Bytes(), nil
2425
}
2526

27+
// PrefixString adds prefix to beginning of each line
28+
func PrefixString(prefix string, text string) string {
29+
result := []string{}
30+
for _, line := range strings.Split(text, "\n") {
31+
if line == "" {
32+
result = append(result, "")
33+
continue
34+
}
35+
result = append(result, prefix+line)
36+
}
37+
return strings.Join(result, "\n")
38+
}
39+
40+
// IndentString add spaces to beginning of each line
41+
func IndentString(size int, text string) string {
42+
prefix := strings.Repeat(" ", size)
43+
return PrefixString(prefix, text)
44+
}
45+
46+
// TrimString removes characters from beginning and end
47+
func TrimString(cutset string, text string) string {
48+
return strings.Trim(text, cutset)
49+
}
50+
51+
// MissingString returns message if the text is empty
52+
func MissingString(message string, text string) string {
53+
if text == "" {
54+
return message
55+
}
56+
return text
57+
}
58+
2659
// TemplateFuncMap is a text/template FuncMap.
2760
var TemplateFuncMap = template.FuncMap{
2861
"json": func(v interface{}) string {
@@ -42,4 +75,50 @@ var TemplateFuncMap = template.FuncMap{
4275
}
4376
return "---\n" + strings.TrimSuffix(b.String(), "\n")
4477
},
78+
"indent": func(a ...interface{}) (string, error) {
79+
if len(a) == 0 {
80+
return "", errors.New("function takes at at least one string argument")
81+
}
82+
if len(a) > 2 {
83+
return "", errors.New("function takes at most 2 arguments")
84+
}
85+
var ok bool
86+
size := 2
87+
if len(a) > 1 {
88+
if size, ok = a[0].(int); !ok {
89+
return "", errors.New("optional first argument must be an integer")
90+
}
91+
}
92+
text := ""
93+
if text, ok = a[len(a)-1].(string); !ok {
94+
return "", errors.New("last argument must be a string")
95+
}
96+
return IndentString(size, text), nil
97+
},
98+
"missing": func(a ...interface{}) (string, error) {
99+
if len(a) == 0 {
100+
return "", errors.New("function takes at at least one string argument")
101+
}
102+
if len(a) > 2 {
103+
return "", errors.New("function takes at most 2 arguments")
104+
}
105+
var ok bool
106+
message := "<missing>"
107+
if len(a) > 1 {
108+
if message, ok = a[0].(string); !ok {
109+
return "", errors.New("optional first argument must be a string")
110+
}
111+
}
112+
text := ""
113+
if text, ok = a[len(a)-1].(string); !ok {
114+
return "", errors.New("last argument must be a string")
115+
}
116+
return MissingString(message, text), nil
117+
},
118+
}
119+
120+
// TemplateFuncHelp is help for TemplateFuncMap.
121+
var FuncHelp = []string{
122+
"indent <size>: add spaces to beginning of each line",
123+
"missing <message>: return message if the text is empty",
45124
}

pkg/textutil/textutil_test.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,46 @@ import (
88
"gotest.tools/v3/assert"
99
)
1010

11+
func TestPrefixString(t *testing.T) {
12+
assert.Equal(t, "- foo", PrefixString("- ", "foo"))
13+
assert.Equal(t, "- foo\n- bar\n", PrefixString("- ", "foo\nbar\n"))
14+
}
15+
func TestIndentString(t *testing.T) {
16+
assert.Equal(t, " foo", IndentString(2, "foo"))
17+
assert.Equal(t, " foo\n bar\n", IndentString(2, "foo\nbar\n"))
18+
}
19+
20+
func TestTrimString(t *testing.T) {
21+
assert.Equal(t, "foo", TrimString("\n", "foo"))
22+
assert.Equal(t, "bar", TrimString("\n", "bar\n"))
23+
}
24+
25+
func TestMissingString(t *testing.T) {
26+
assert.Equal(t, "no", MissingString("no", ""))
27+
assert.Equal(t, "msg", MissingString("no", "msg"))
28+
}
29+
1130
func TestTemplateFuncs(t *testing.T) {
1231
type X struct {
13-
Foo int `json:"foo" yaml:"foo"`
14-
Bar string `json:"bar" yaml:"bar"`
32+
Foo int `json:"foo" yaml:"foo"`
33+
Bar string `json:"bar" yaml:"bar"`
34+
Message string `json:"message,omitempty" yaml:"message,omitempty"`
35+
Missing string `json:"missing,omitempty" yaml:"missing,omitempty"`
1536
}
16-
x := X{Foo: 42, Bar: "hello"}
37+
x := X{Foo: 42, Bar: "hello", Message: "One\nTwo\nThree", Missing: ""}
1738

1839
testCases := map[string]string{
19-
"{{json .}}": `{"foo":42,"bar":"hello"}`,
40+
"{{json .}}": `{"foo":42,"bar":"hello","message":"One\nTwo\nThree"}`,
2041
"{{yaml .}}": `---
2142
foo: 42
22-
bar: hello`,
43+
bar: hello
44+
message: |-
45+
One
46+
Two
47+
Three`,
48+
`{{.Bar}}{{"\n"}}{{.Message | missing "<no message>" | indent 2}}`: "hello\n One\n Two\n Three",
49+
`{{.Message | indent}}`: " One\n Two\n Three",
50+
`{{.Missing | missing}}`: "<missing>",
2351
}
2452

2553
for format, expected := range testCases {

0 commit comments

Comments
 (0)