Formatting Cue



In the last section, we printed Cue using the default options and fmt.Println. When we run cue eval and cue def, we have more options to control what gets displayed. The options which match the flags are supplied to cue.Value.Syntx and gives us back the Abstract Syntax Tree (AST) for the value. We then use Cue’s format package which allows us to pretty print a Cue AST.

cue.Value.Syntax - cue.Value function for returning AST
cue.Option - options for Syntax (and other funcs)
cue/format.Node - function for pretty-printing an AST

Pretty printing Cue values

This first example shows how to load, build, and validate Cue.

code/api/format.go

package main

import (
	"fmt"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/format"
	"cuelang.org/go/cue/load"
)

func main() {
	// We need a Cue.Runtime, the zero value is ready to use
	var RT cue.Runtime

	// The entrypoints are the same as the files you'd specify at the command line
	entrypoints := []string{"format.cue"}

	// Load Cue files into Cue build.Instances slice
	// the second arg is a configuration object, we'll see this later
	bis := load.Instances(entrypoints, nil)

	// Loop over the instances, checking for errors and printing
	for _, bi := range bis {
		// check for errors on the instance
		// these are typically parsing errors
		if bi.Err != nil {
			fmt.Println("Error during load:", bi.Err)
			continue
		}

		// Use cue.Runtime to build.Instance to cue.Instance
		I, err := RT.Build(bi)
		if err != nil {
			fmt.Println("Error during build:", bi.Err)
			continue
		}

		// get the root value
		value := I.Value()

		// Validate the value
		err = value.Validate()
		if err != nil {
			fmt.Println("Error during validate:", err)
			continue
		}

		// Generate an AST
		//   try out different options
		syn := value.Syntax(
			cue.Final(), // close structs and lists
			cue.Concrete(false),   // allow incomplete values
			cue.Definitions(false),
			cue.Hidden(true),
			cue.Optional(true),
			cue.Attributes(true),
			cue.Docs(true),
		)

		// Pretty print the AST, returns ([]byte, error)
		bs, err := format.Node(
			syn,
			format.TabIndent(false),
			format.UseSpaces(2),
			// format.Simplify(),
		)
		if err != nil {
			fmt.Println("Error during format:", err)
			continue
		}

		fmt.Println(string(bs))
	}

}

code/api/format.cue

package format

hello: "world"

#A: {
	foo: string
}

_hid: {
	see: false
}

// to cause a load error, remove the '&'
// to cause a build error, change '#A' to '#B'
// to cause a validation error, change foo to '1'
a: #A & {
	foo: "bar"
}

2021 Hofstadter, Inc