glu
Lua script mode

Lua script mode

When you pass a .lua file to glu, it executes it as a Lua script with full control over the PDF output. This mode is for advanced use cases that require programmatic typesetting — custom layouts, generated documents, or anything beyond what Markdown and HTML mode provide.

glu hello.lua    # → hello.pdf

Hello world

This example creates a PDF with a single paragraph on an A4 page:

local frontend = require("glu.frontend")

-- Load a font
local doc = frontend.new("hello.pdf")
local ff = doc:new_font_family("text")
local fs = frontend.fontsource({ location = "fonts/CrimsonPro-Regular.ttf" })
ff:add_member(fs, "regular", "normal")

-- Create text content
local txt = frontend.text({
    font_family = ff,
    font_size = "12pt",
    color = "black"
})

local 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.]]

-- Remove newlines
str = str:gsub("\n", " ")
txt:append(str)

-- Format paragraph and create page
local vlist = doc:format_paragraph(txt, "225pt", { leading = "14pt" })

local page = doc:new_page()
page.width = "210mm"
page.height = "297mm"
page:output_at("1cm", "28cm", vlist)
page:shipout()

doc:finish()
print("Created hello.pdf")

Run with:

glu hello.lua

Step-by-step explanation

local frontend = require("glu.frontend")

Loads the frontend module. All glu modules must be loaded with require().

local doc = frontend.new("hello.pdf")

Creates a new PDF document with the filename hello.pdf. The glu.frontend module is the main API for creating PDF documents with glu.

local ff = doc:new_font_family("text")
local fs = frontend.fontsource({ location = "fonts/CrimsonPro-Regular.ttf" })
ff:add_member(fs, "regular", "normal")

Fonts are organized in font families. A font family can have multiple members with different weights (regular, bold, etc.) and styles (normal, italic). Here we create a font family named “text” and add a single regular font.

local txt = frontend.text({
    font_family = ff,
    font_size = "12pt",
    color = "black"
})

Creates a text object with styling. Settings can be passed directly to the constructor. Text objects can contain strings and other text objects, allowing for nested formatting (e.g., italic text within a paragraph).

local str = [[The quick brown fox jumps over the lazy dog...]]
str = str:gsub("\n", " ")
txt:append(str)

Adds the text content to the text object. The append method accepts strings, other Text objects, VLists, or Tables.

local vlist = doc:format_paragraph(txt, "225pt", { leading = "14pt" })

The format_paragraph() function turns the text object into a vertical list (vlist) that can be placed on the page. The width is specified as the second argument, and optional settings like leading (line height) can be passed in a table.

local page = doc:new_page()
page.width = "210mm"
page.height = "297mm"
page:output_at("1cm", "28cm", vlist)
page:shipout()

Creates a new page, sets its dimensions to A4 size, and places the vertical list at the specified coordinates (1cm from the left, 28cm from the bottom).

All dimension parameters accept either numbers (interpreted as points) or strings with units like "12pt", "1cm", "10mm", or "1in".

doc:finish()

Finalizes the PDF document and writes it to the file.

Available modules

Module Description
glu Scaled point operations and logging
glu.frontend High-level typesetting API (documents, text, fonts, tables)
glu.pdf Low-level PDF writing module (baseline-pdf wrapper)
glu.node Node types (glyph, glue, kern, etc.) and list operations
glu.font Font instances and text shaping

All modules must be loaded with require():

local glu = require("glu")
local frontend = require("glu.frontend")
local pdf = require("glu.pdf")
local node = require("glu.node")
local font = require("glu.font")

The glu.frontend and glu.pdf modules are for document creation. The glu, glu.node, and glu.font modules provide low-level access to the typesetting engine for advanced use cases. See glu.frontend module for the full API reference.