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.pdfHello 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.luaStep-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.