#!/usr/bin/env lpg
function h1 (title)
return lpg.VBox {fontsize=18., fontweight=600,
title, lpg.HLine {2}, lpg.Filler {-1, 6}}
end
function h2 (title)
return lpg.VBox {fontsize=16., fontweight=600,
lpg.Filler {-1, 8}, title, lpg.HLine {1}, lpg.Filler {-1, 4}}
end
function h3 (title)
return lpg.VBox {fontsize=14., fontweight=600,
lpg.Filler {-1, 8}, title, lpg.HLine {.25}, lpg.Filler {-1, 4}}
end
function p (...)
return lpg.VBox {..., lpg.Filler {-1, 6}}
end
function pre (...)
return lpg.VBox {
lpg.Filler {-1, 4},
lpg.HBox {lpg.Filler {12}, lpg.VBox {...}, lpg.Filler {}},
lpg.Filler {-1, 6},
}
end
function define (name, ...)
return lpg.VBox {
lpg.Filler {-1, 2},
lpg.Text {fontweight=600, name}, lpg.Filler {-1, 2},
lpg.HBox {lpg.Filler {12}, lpg.VBox {...}, lpg.Filler {}},
lpg.Filler {-1, 2},
}
end
local page1 = lpg.VBox {fontfamily="sans serif", fontsize=12.,
h1("lpg User Manual"),
p("lpg is a Lua-based PDF document generator, exposing a trivial " ..
"layouting engine on top of the Cairo graphics library, " ..
"with manual paging."),
p("The author has primarily been using this system to typeset invoices."),
h2("Synopsis"),
p("lpg program.lua [args...]"),
h2("API"),
p("The Lua program receives lpg's and its own path joined " ..
"as arg[0]. Any remaining sequential elements " ..
"of this table represent the passed args."),
h3("Utilities"),
define("lpg.cm (centimeters)",
p("Returns how many document points are needed " ..
"for the given physical length.")),
define("lpg.ntoa {number [, precision=…]\n" ..
"\t[, thousands_sep=…] [, decimal_point=…] [, grouping=…]}",
p("Formats a number using the C++ localization " ..
"and I/O libraries. " ..
"For example, the following call results in “3 141,59”:"),
pre("ntoa {3141.592, precision=2,\n" ..
" thousands_sep=\" \", decimal_point=\",\", " ..
"grouping=\"\\003\"}")),
define("lpg.escape (values...)",
p("Interprets all values as strings, " ..
"and escapes them to be used as literal text—" ..
"all text within lpg is parsed Pango markup, " ..
"which is a subset of XML.")),
h3("PDF documents"),
define("lpg.Document (filename, width, height [, margin])",
p("Returns a new Document object, whose pages are all " ..
"the same size in 72 DPI points, as specified by width " ..
"and height. The margin is used by show " ..
"on all sides of pages."),
p("The file is finalized when the object is garbage collected.")),
define("Document.title, author, subject, keywords, " ..
"creator, create_date, mod_date",
p("Write-only PDF Info dictionary metadata strings.")),
define("Document:show ([widget...])",
p("Starts a new document page, and renders Widget trees over " ..
"the whole print area.")),
lpg.Filler {},
}
local page2 = lpg.VBox {fontfamily="sans serif", fontsize=12.,
h3("Widgets"),
p("The layouting system makes heavy use of composition, " ..
"and thus stays simple."),
p("For convenience, anywhere a Widget is expected but another " ..
"kind of value is received, lpg.Text widget will be invoked " ..
"on that value."),
p("Once a Widget is included in another Widget, " ..
"the original Lua object can no longer be used, " ..
"as its reference has been consumed."),
p("Widgets can be indexed by strings to get or set " ..
"their attributes. All Widget constructor tables " ..
"also accept attributes, for convenience. Attributes can be " ..
"either strings or numbers, mostly only act " ..
"on specific Widget kinds, and are hereditary. " ..
"Prefix their names with an underscore to set them ‘privately’."),
p("Widget sizes can be set negative, which signals to their " ..
"container that they should take any remaining space, " ..
"after all their siblings’ requests have been satisfied. " ..
"When multiple widgets make this request, that space is distributed " ..
"in proportion to these negative values."),
define("lpg.Filler {[width] [, height]}",
p("Returns a new blank widget with the given dimensions, " ..
"which default to -1, -1.")),
define("lpg.HLine {[thickness]}",
p("Returns a new widget that draws a simple horizontal line " ..
"of the given thickness.")),
define("lpg.VLine {[thickness]}",
p("Returns a new widget that draws a simple vertical line " ..
"of the given thickness.")),
define("lpg.Text {[value...]}",
p("Returns a new text widget that renders the concatenation of all " ..
"passed values filtered through Lua’s tostring function."),
define("Text.fontfamily, fontsize, fontweight, lineheight",
p("Various font properties, similar to their CSS counterparts."))),
define("lpg.Frame {widget}",
p("Returns a special container widget that can override " ..
"a few interesting properties."),
define("Frame.color",
p("Text and line colour, for example 0xff0000 for red.")),
define("Frame.w_override",
p("Forcefully changes the child Widget’s " ..
"requested width, such as to negative values.")),
define("Frame.h_override",
p("Forcefully changes the child Widget’s " ..
"requested height, such as to negative values."))),
lpg.Filler {},
}
local page3 = lpg.VBox {fontfamily="sans serif", fontsize=12.,
-- TODO: Link
-- TODO: HBox
-- TODO: VBox
-- TODO: Picture
-- TODO: QR
lpg.Filler {},
}
if #arg < 1 then
io.stderr:write("Usage: " .. arg[0] .. " OUTPUT-PDF..." .. "\n")
os.exit(false)
end
local width, height, margin = lpg.cm(21), lpg.cm(29.7), lpg.cm(2.0)
for i = 1, #arg do
local pdf = lpg.Document(arg[i], width, height, margin)
pdf.title = "lpg User Manual"
pdf.subject = "lpg User Manual"
pdf.author = "Přemysl Eric Janouch"
pdf.creator = "lpg"
pdf:show(page1)
pdf:show(page2)
pdf:show(page3)
end