Skip to content

Commit 117f536

Browse files
authored
Merge pull request #4032 from jandubois/list-json
Change `limactl list --format json` not to include empty objects
2 parents 36de594 + 7a7795a commit 117f536

File tree

3 files changed

+37
-37
lines changed

3 files changed

+37
-37
lines changed

cmd/limactl/list.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,25 +249,43 @@ func listAction(cmd *cobra.Command, args []string) error {
249249
}
250250

251251
if format == "json" {
252+
// The JSON encoder will create empty objects (YAML maps), even when they have the ",omitempty" tag.
253+
deleteEmptyObjects := `del(.. | select(tag == "!!map" and length == 0))`
254+
yqExpr += " | " + deleteEmptyObjects
255+
252256
encoderPrefs := yqlib.ConfiguredJSONPreferences.Copy()
253-
if isTTY {
254-
// Using non-0 indent means the instance will be printed over multiple lines,
255-
// so is no longer in JSON Lines format. This is a compromise for readability.
256-
encoderPrefs.Indent = 4
257-
encoderPrefs.ColorsEnabled = true
258-
} else {
259-
encoderPrefs.Indent = 0
260-
encoderPrefs.ColorsEnabled = false
261-
}
262-
encoder := yqlib.NewJSONEncoder(encoderPrefs)
257+
encoderPrefs.ColorsEnabled = false
258+
encoderPrefs.Indent = 0
259+
plainEncoder := yqlib.NewJSONEncoder(encoderPrefs)
260+
// Using non-0 indent means the instance will be printed over multiple lines,
261+
// so is no longer in JSON Lines format. This is a compromise for readability.
262+
encoderPrefs.Indent = 4
263+
encoderPrefs.ColorsEnabled = true
264+
colorEncoder := yqlib.NewJSONEncoder(encoderPrefs)
263265

264266
// Each line contains the JSON object for one Lima instance.
265267
scanner := bufio.NewScanner(buf)
266268
for scanner.Scan() {
267269
var str string
268-
if str, err = yqutil.EvaluateExpressionWithEncoder(yqExpr, scanner.Text(), encoder); err != nil {
270+
if str, err = yqutil.EvaluateExpressionWithEncoder(yqExpr, scanner.Text(), plainEncoder); err != nil {
269271
return err
270272
}
273+
// Repeatedly delete empty objects until there are none left.
274+
for {
275+
length := len(str)
276+
if str, err = yqutil.EvaluateExpressionWithEncoder(deleteEmptyObjects, str, plainEncoder); err != nil {
277+
return err
278+
}
279+
if len(str) >= length {
280+
break
281+
}
282+
}
283+
if isTTY {
284+
// pretty-print and colorize the output
285+
if str, err = yqutil.EvaluateExpressionWithEncoder(".", str, colorEncoder); err != nil {
286+
return err
287+
}
288+
}
271289
if _, err = fmt.Fprint(cmd.OutOrStdout(), str); err != nil {
272290
return err
273291
}

hack/bats/helpers/load.bash

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,3 @@ teardown() {
6060
assert_output_lines_count() {
6161
assert_equal "${#lines[@]}" "$1"
6262
}
63-
64-

hack/bats/tests/01-list.bats

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,6 @@ local_setup() {
2020
export LIMA_HOME="${LOCAL_LIMA_HOME:?}"
2121
}
2222

23-
# In Go templates "{{json .}}" will encode empty maps (e.g. "foo": {}) even if the
24-
# map has the "json:",omitempty" tag. "{{yaml .}}" does omit empty maps, so remove
25-
# them from the JSON output to make it comparable to the YAML one.
26-
#
27-
# TODO should we modify `limactl list` to remove empty maps by default
28-
# since we pass the output through yq anyways?
29-
canonical_json() {
30-
local empty_maps='.. | select(tag == "!!map" and length == 0)'
31-
while limactl yq --exit-status --input-format json "[${empty_maps}] | length > 0" <<<"$output" >/dev/null 2>&1; do
32-
run -0 limactl yq --input-format json --output-format json --indent 0 "del(${empty_maps})" <<<"$output"
33-
done
34-
35-
}
36-
3723
@test 'list with no running instances shows a warning and exits without error' {
3824
export LIMA_HOME="$BATS_TEST_TMPDIR"
3925
run_e -0 limactl list
@@ -93,20 +79,19 @@ canonical_json() {
9379
}
9480

9581
@test '--json is shorthand for --format json' {
96-
run -0 limactl ls --format json foo bar
82+
run -0 limactl ls foo bar --format json
9783
format_json=$output
9884

99-
run -0 limactl ls --json foo bar
85+
run -0 limactl ls foo bar --json
10086
assert_output "$format_json"
10187
}
10288

10389
@test '--format YAML returns YAML documents' {
104-
# save canonical JSON output with empty maps removed, for comparison
90+
# save JSON output for comparison
10591
run -0 limactl ls foo bar --format json
106-
canonical_json
10792
json=$output
10893

109-
run -0 limactl ls --format yaml foo bar
94+
run -0 limactl ls foo bar --format yaml
11095
yaml=$output
11196

11297
assert_line --regexp '^name: foo'
@@ -121,7 +106,7 @@ canonical_json() {
121106
run -0 limactl yq --input-format yaml --output-format json --indent 0 "." <<<"$yaml"
122107
assert_output_lines_count 2
123108

124-
# verify it matches the canonical JSON output
109+
# verify it matches the JSON output
125110
assert_output "$json"
126111

127112
}
@@ -148,14 +133,13 @@ canonical_json() {
148133
run -0 limactl yq --input-format json --output-format json --indent 0 "." <<<"$output"
149134
assert_output_lines_count 2
150135

151-
# compare to the regular --format json output
136+
# compare to the plain (uncolorized) json output
152137
assert_output "$json"
153138
}
154139

155140
@test 'YAML output to terminal is colorized, but semantically identical' {
156-
# save canonical output without colors and empty maps removed
141+
# save uncolorized JSON output
157142
run -0 limactl ls foo bar --format json
158-
canonical_json
159143
json=$output
160144

161145
# colorize output even when stdout is not a tty
@@ -179,7 +163,7 @@ canonical_json() {
179163
run -0 limactl yq --indent 0 --input-format yaml --output-format json "." <<<"$yaml"
180164
assert_output_lines_count 2
181165

182-
# verify it matches the canonical JSON output
166+
# verify it matches the JSON output
183167
assert_output "$json"
184168
}
185169

0 commit comments

Comments
 (0)