Command line interface

The command line interface

The command line interface (cli) makes it possible to create documents without a Go installation. It is built on the risor language, a small and simple programming language, yet powerful enough to handle all necessary tasks.

Installation

When you have a Go installation, just use go install github.com/boxesandglue/cli/bag@latest to get the binary bag.

You can also download the latest binaries at https://github.com/boxesandglue/cli/releases/latest. The ZIP files contain only a single binary, enough for using boxes and glue.

Sample document

Start with bag myfile.rsr, where the file myfile.rsr looks like this:

now := time.now()

// f is the frontend document
func setup_fonts(f) {
    ff := f.new_fontfamily("text")

    fs := frontend.new_fontsource({
        location: filepath.join("fonts","CrimsonPro-Regular.ttf"),
        features: ["kern","liga"],
        })

    ff.add_member({source: fs, weight: 400, style: "normal"})
    return ff
}

str := `The quick brown fox jumps
over the lazy dog with a very long line that should be wrapped
at some point. This is a test to see how the text is formatted
when it is too long to fit on one line. The quick brown fox jumps
over the lazy dog with a very long line that should be wrapped`

str = strings.join(strings.fields(str)," ")

f := frontend.new("out.pdf")
backend_doc := f.doc
backend_doc.language = frontend.get_language("en")

backend_doc.title = "A test document"

ff := setup_fonts(f)

p := f.doc.new_page()
para := frontend.new_text()
para.items = [str]
vlist := f.format_paragraph({
	text: para,
	width: bag.sp("225pt"),
	leading: bag.sp("14pt"),
	font_size: bag.sp("12pt"),
	family: ff,
})
p.output_at(bag.sp("1cm"), bag.sp("10cm"), vlist)
p.shipout()

f.doc.finish()

printf("finished in %.2fms\n",time.since(now) * 1000)

The documentation is split into three parts: some general information with code snippets, the frontend module reference and the backend module reference.

Attachments

a:= f.doc.attachments.append({
    filename: "img/ocean.pdf",
    mimetype: "application/pdf",
    description: "Test attachment",
    visiblename: "myocean.pdf",
})

Viewer preferences

f.doc.viewer_preferences = {NumCopies: "2", PrintScaling: "/None"}

Image inclusion

imgfile := f.doc.load_imagefile("img/ocean.pdf")
imgNode := f.doc.create_image_node_from_imagefile(imgfile, 1, "/MediaBox")
imgNode.width = bag.sp("100pt")
imgNode.height = bag.sp("100pt")
vl := node.vpack(imgNode)
p.output_at(bag.sp("1cm"), bag.sp("290mm"), vl)

Set the PDF format:

f.doc.format = "PDF/A-3b"

Where format is one of “”, “PDF/A-3b”, “PDF/X-3”, “PDF/X-4” or “PDF/UA”.

Set bleed / show cropmarks

f.doc.bleed = bag.sp("3mm")
f.doc.show_cutmarks = true

Page height and width

// the default:
f.doc.default_page_width = bag.sp("210mm")
f.doc.default_page_height = bag.sp("297mm")

Set creation date

f.doc.creation_date = time.parse(time.RFC3339, "2023-08-01T12:00:00-04:00")

Debugging output

f.doc.dump_output = true
...
f.doc.finish()
f.doc.output_xml_dump("out.xml")

The XML structure in out.xml represents the document.