❯ go-clikit
v0.10.0 pkg.go.dev ↗

guides › write a result

Write a result

Write a command's result as a table aligned by display width, or as JSON, with every string escaped.

A result goes to standard output, for a person or for a script. cliout writes it in two forms. Both escape every string, because a cell often holds text from elsewhere, such as the reason a node gave.

A table for a person#

  1. Make a cliout.Table with its cliout.Columns. Mark the columns that only -o wide shows.
  2. Add a row for each item with cliout.Table.Add.
  3. Write it with cliout.Table.Write, and say if the wide columns show.
table := &cliout.Table{
	Columns: []cliout.Column{{Name: "NODE"}, {Name: "CPUS", Right: true}, {Name: "STATE"}, {Name: "REASON", Wide: true}},
	Caption: "3 nodes, 1 drained",
}
table.Add("exe0001", "128", "drained", "fan failure\nexe0002 idle")
table.Add("exe0002", "64", "idle")
table.Add("exe10", "8", "idle")

for _, wide := range []bool{false, true} {
	if err := table.Write(os.Stdout, wide); err != nil {
		fmt.Println(err)
	}
	fmt.Println("--")
}
NODE     CPUS  STATE
exe0001   128  drained
exe0002    64  idle
exe10       8  idle

3 nodes, 1 drained
--
NODE     CPUS  STATE    REASON
exe0001   128  drained  fan failure\nexe0002 idle
exe0002    64  idle
exe10       8  idle

3 nodes, 1 drained
--
ExampleTable in cliout/example_test.go. CI runs it and checks its output.

The columns align by the columns that a terminal gives the text, so a name in Japanese or with accents does not move the next column.

JSON for a script#

cliout.WriteJSON writes a value as JSON. It escapes the runes that termtext escapes and encoding/json does not, so a string cannot act on the terminal that it is read in. A slice is written one element at a time.

type node struct {
	Name   string `json:"name"`
	State  string `json:"state"`
	Reason string `json:"reason,omitempty"`
}
nodes := []node{
	{Name: "exe0001", State: "drained", Reason: "fan <1> failure\u009b2J"},
	{Name: "exe0002", State: "idle"},
}
if err := cliout.WriteJSON(os.Stdout, nodes); err != nil {
	fmt.Println(err)
}
[
  {
    "name": "exe0001",
    "state": "drained",
    "reason": "fan <1> failure\u009b2J"
  },
  {
    "name": "exe0002",
    "state": "idle"
  }
]
ExampleWriteJSON in cliout/example_test.go. CI runs it and checks its output.
NOTE

The package parses no flag. The words of -o, and which form each one writes, are the program’s to decide.