aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Krewinkel <[email protected]>2022-02-05 10:56:59 +0100
committerJohn MacFarlane <[email protected]>2022-02-06 16:01:24 -0800
commit49f1e7608ead7a9bc0e73e99b24e47a9a8cf0400 (patch)
treeb12bb6e742e5d84b4a910848dc22234969c4fb3d
parentae846381c33866a6c5646d82da455182bca4fcc5 (diff)
Lua: add module `pandoc.layout` to format and layout text
-rw-r--r--doc/lua-filters.md576
-rw-r--r--pandoc.cabal1
-rw-r--r--src/Text/Pandoc/Lua/Init.hs1
-rw-r--r--src/Text/Pandoc/Lua/Packages.hs2
-rw-r--r--stack.yaml1
-rw-r--r--tools/update-lua-module-docs.lua10
6 files changed, 587 insertions, 4 deletions
diff --git a/doc/lua-filters.md b/doc/lua-filters.md
index 10c31b24c..bcaa1c5b2 100644
--- a/doc/lua-filters.md
+++ b/doc/lua-filters.md
@@ -2179,6 +2179,25 @@ Fields:
`verbosity`
: Verbosity level; one of `INFO`, `WARNING`, `ERROR` (string)
+## Doc {#type-doc}
+
+Reflowable plain-text document. A Doc value can be rendered and
+reflown to fit a given column width.
+
+The [`pandoc.layout`](#module-pandoc.layout) module can be used to
+create and modify Doc values. All functions in that module that
+take a Doc value as their first argument are also available as Doc
+methods. E.g., `(pandoc.layout.literal 'text'):render()`.
+
+If a string is passed to a function expecting a Doc, then the
+string is treated as a literal value. I.e., the following two
+lines are equivalent:
+
+``` lua
+test = pandoc.layout.quotes(pandoc.layout.literal 'this')
+test = pandoc.layout.quotes('this')
+```
+
## List {#type-list}
A list is any Lua table with integer indices. Indices start at
@@ -4378,6 +4397,563 @@ Returns:
- The result(s) of the call to `callback`
+# Module pandoc.layout
+
+Plain-text document layouting.
+
+## Fields {#pandoc.layout-fields}
+
+### blankline {#pandoc.layout.blankline}
+
+Inserts a blank line unless one exists already.
+
+### cr {#pandoc.layout.cr}
+
+A carriage return. Does nothing if we\'re at the beginning of a
+line; otherwise inserts a newline.
+
+### empty {#pandoc.layout.empty}
+
+The empty document.
+
+### space {#pandoc.layout.space}
+
+A breaking (reflowable) space.
+
+## Functions {#pandoc.layout-functions}
+
+### after_break {#pandoc.layout.after_break}
+
+`after_break (text)`
+
+Creates a `Doc` which is conditionally included only if it comes
+at the beginning of a line.
+
+An example where this is useful is for escaping line-initial `.`
+in roff man.
+
+Parameters
+
+`text`
+
+: content to include when placed after a break (string)
+
+Returns
+
+- new doc (Doc)
+
+### before_non_blank {#pandoc.layout.before_non_blank}
+
+`before_non_blank (doc)`
+
+Conditionally includes the given `doc` unless it is followed by a
+blank space.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- conditional doc (Doc)
+
+### blanklines {#pandoc.layout.blanklines}
+
+`blanklines (n)`
+
+Inserts blank lines unless they exist already.
+
+Parameters
+
+`n`
+
+: number of blank lines (integer)
+
+Returns
+
+- conditional blank lines (Doc)
+
+### braces {#pandoc.layout.braces}
+
+`braces (doc)`
+
+Puts the `doc` in curly braces.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- doc enclosed by {}. (Doc)
+
+### brackets {#pandoc.layout.brackets}
+
+`brackets (doc)`
+
+Puts the `doc` in square brackets
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- doc enclosed by \[\]. (Doc)
+
+### cblock {#pandoc.layout.cblock}
+
+`cblock (doc, width)`
+
+Creates a block with the given width and content, aligned
+centered.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`width`
+
+: block width in chars (integer)
+
+Returns
+
+- doc, aligned centered in a block with max`width` chars per
+ line. (Doc)
+
+### chomp {#pandoc.layout.chomp}
+
+`chomp (doc)`
+
+Chomps trailing blank space off of the `doc`.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- `doc` without trailing blanks (Doc)
+
+### concat {#pandoc.layout.concat}
+
+`concat (docs[, sep])`
+
+Concatenates a list of `Doc`s.
+
+Parameters
+
+`docs`
+
+: list of Docs (`{Doc,...}`)
+
+`sep`
+
+: separator (default: none) (Doc)
+
+Returns
+
+- concatenated doc (Doc)
+
+### double_quotes {#pandoc.layout.double_quotes}
+
+`double_quotes (doc)`
+
+Wraps a `Doc` in double quotes.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- `doc` enclosed by `"` chars (Doc)
+
+### flush {#pandoc.layout.flush}
+
+`flush (doc)`
+
+Makes a `Doc` flush against the left margin.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- flushed `doc` (Doc)
+
+### hang {#pandoc.layout.hang}
+
+`hang (doc, ind, start)`
+
+Creates a hanging indent.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`ind`
+
+: indentation width (integer)
+
+`start`
+
+: document (Doc)
+
+Returns
+
+- `doc` prefixed by `start` on the first line, subsequent lines
+ indented by `ind` spaces. (Doc)
+
+### inside {#pandoc.layout.inside}
+
+`inside (contents, start, end)`
+
+Encloses a `Doc` inside a start and end `Doc`.
+
+Parameters
+
+`contents`
+
+: document (Doc)
+
+`start`
+
+: document (Doc)
+
+`end`
+
+: document (Doc)
+
+Returns
+
+- enclosed contents (Doc)
+
+### lblock {#pandoc.layout.lblock}
+
+`lblock (doc, width)`
+
+Creates a block with the given width and content, aligned to the
+left.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`width`
+
+: block width in chars (integer)
+
+Returns
+
+- doc put into block with max `width` chars per line. (Doc)
+
+### literal {#pandoc.layout.literal}
+
+`literal (text)`
+
+Creates a `Doc` from a string.
+
+Parameters
+
+`text`
+
+: literal value (string)
+
+Returns
+
+- doc contatining just the literal string (Doc)
+
+### nest {#pandoc.layout.nest}
+
+`nest (doc, ind)`
+
+Indents a `Doc` by the specified number of spaces.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`ind`
+
+: indentation size (integer)
+
+Returns
+
+- `doc` indented by `ind` spaces (Doc)
+
+### nestle {#pandoc.layout.nestle}
+
+`nestle (doc)`
+
+Removes leading blank lines from a `Doc`.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- `doc` with leading blanks removed (Doc)
+
+### nowrap {#pandoc.layout.nowrap}
+
+`nowrap (doc)`
+
+Makes a `Doc` non-reflowable.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- same as input, but non-reflowable (Doc)
+
+### parens {#pandoc.layout.parens}
+
+`parens (doc)`
+
+Puts the `doc` in parentheses.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- doc enclosed by (). (Doc)
+
+### prefixed {#pandoc.layout.prefixed}
+
+`prefixed (doc, prefix)`
+
+Uses the specified string as a prefix for every line of the inside
+document (except the first, if not at the beginning of the line).
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`prefix`
+
+: prefix for each line (string)
+
+Returns
+
+- prefixed `doc` (Doc)
+
+### quotes {#pandoc.layout.quotes}
+
+`quotes (doc)`
+
+Wraps a `Doc` in single quotes.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- doc enclosed in `'`. (Doc)
+
+### rblock {#pandoc.layout.rblock}
+
+`rblock (doc, width)`
+
+Creates a block with the given width and content, aligned to the
+right.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`width`
+
+: block width in chars (integer)
+
+Returns
+
+- doc, right aligned in a block with max`width` chars per line.
+ (Doc)
+
+### vfill {#pandoc.layout.vfill}
+
+`vfill (border)`
+
+An expandable border that, when placed next to a box, expands to
+the height of the box. Strings cycle through the list provided.
+
+Parameters
+
+`border`
+
+: vertically expanded characters (string)
+
+Returns
+
+- automatically expanding border Doc (Doc)
+
+### render {#pandoc.layout.render}
+
+`render (doc[, colwidth])`
+
+Render a @\'Doc\'@. The text is reflowed on breakable spacesto
+match the given line length. Text is not reflowed if theline
+length parameter is omitted or nil.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`colwidth`
+
+: planned maximum line length (integer)
+
+Returns
+
+- rendered doc (Doc)
+
+### is_empty {#pandoc.layout.is_empty}
+
+`is_empty (doc)`
+
+Checks whether a doc is empty.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- `true` iff `doc` is the empty document, `false` otherwise.
+ (boolean)
+
+### height {#pandoc.layout.height}
+
+`height (doc)`
+
+Returns the height of a block or other Doc.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- doc height (integer\|string)
+
+### min_offset {#pandoc.layout.min_offset}
+
+`min_offset (doc)`
+
+Returns the minimal width of a `Doc` when reflowed at breakable
+spaces.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- minimal possible width (integer\|string)
+
+### offset {#pandoc.layout.offset}
+
+`offset (doc)`
+
+Returns the width of a `Doc` as number of characters.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+Returns
+
+- doc width (integer\|string)
+
+### real_length {#pandoc.layout.real_length}
+
+`real_length (str)`
+
+Returns the real length of a string in a monospace font: 0 for a
+combining chaeracter, 1 for a regular character, 2 for an East
+Asian wide character.
+
+Parameters
+
+`str`
+
+: UTF-8 string to measure (string)
+
+Returns
+
+- text length (integer\|string)
+
+### update_column {#pandoc.layout.update_column}
+
+`update_column (doc, i)`
+
+Returns the column that would be occupied by the last laid out
+character.
+
+Parameters
+
+`doc`
+
+: document (Doc)
+
+`i`
+
+: start column (integer)
+
+Returns
+
+- column number (integer\|string)
+
# Module pandoc.template
Handle pandoc templates.
diff --git a/pandoc.cabal b/pandoc.cabal
index 35cc543ca..43fb4648a 100644
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -484,6 +484,7 @@ library
hslua >= 2.1 && < 2.2,
hslua-aeson >= 2.1 && < 2.2,
hslua-marshalling >= 2.1 && < 2.2,
+ hslua-module-doclayout>= 1.0.2 && < 1.1,
hslua-module-path >= 1.0 && < 1.1,
hslua-module-system >= 1.0 && < 1.1,
hslua-module-text >= 1.0 && < 1.1,
diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs
index c3d792a37..1df3fa959 100644
--- a/src/Text/Pandoc/Lua/Init.hs
+++ b/src/Text/Pandoc/Lua/Init.hs
@@ -45,6 +45,7 @@ runLua luaOp = do
loadedModules :: [(Name, Name)]
loadedModules =
[ ("pandoc.List", "List")
+ , ("pandoc.layout", "layout")
, ("pandoc.mediabag", "mediabag")
, ("pandoc.path", "path")
, ("pandoc.system", "system")
diff --git a/src/Text/Pandoc/Lua/Packages.hs b/src/Text/Pandoc/Lua/Packages.hs
index 452d8e9eb..1a9cb23bb 100644
--- a/src/Text/Pandoc/Lua/Packages.hs
+++ b/src/Text/Pandoc/Lua/Packages.hs
@@ -22,6 +22,7 @@ import Text.Pandoc.Lua.Marshal.List (pushListModule)
import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua)
import qualified HsLua as Lua
+import qualified HsLua.Module.DocLayout as DocLayout
import qualified HsLua.Module.Path as Path
import qualified HsLua.Module.Text as Text
import qualified Text.Pandoc.Lua.Module.Pandoc as Pandoc
@@ -49,6 +50,7 @@ pandocPackageSearcher :: String -> PandocLua Lua.NumResults
pandocPackageSearcher pkgName =
case pkgName of
"pandoc" -> pushModuleLoader Pandoc.documentedModule
+ "pandoc.layout" -> pushModuleLoader DocLayout.documentedModule
"pandoc.mediabag" -> pushModuleLoader MediaBag.documentedModule
"pandoc.path" -> pushModuleLoader Path.documentedModule
"pandoc.system" -> pushModuleLoader System.documentedModule
diff --git a/stack.yaml b/stack.yaml
index 6c0bf4ce1..72be68094 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -18,6 +18,7 @@ extra-deps:
- hslua-classes-2.1.0
- hslua-core-2.1.0
- hslua-marshalling-2.1.0
+- hslua-module-doclayout-1.0.2
- hslua-module-path-1.0.1
- hslua-module-system-1.0.1
- hslua-module-text-1.0.1
diff --git a/tools/update-lua-module-docs.lua b/tools/update-lua-module-docs.lua
index 2e32d3ea7..8d21d958e 100644
--- a/tools/update-lua-module-docs.lua
+++ b/tools/update-lua-module-docs.lua
@@ -76,9 +76,9 @@ local function render_function (doc, level, modulename)
Header(level, name, {id}),
Plain{Code(string.format('%s (%s)', name, args))},
} .. read_blocks(doc.description)
- .. List(#doc.parameters > 0 and {Header(level+1, 'Parameters')} or {})
+ .. List(#doc.parameters > 0 and {Para 'Parameters'} or {})
.. List{paramlist}
- .. List(#doc.results > 0 and {Header(level + 1, 'Returns')} or {})
+ .. List(#doc.results > 0 and {Para 'Returns'} or {})
.. render_results(doc.results)
end
@@ -106,7 +106,7 @@ local function render_module (doc)
return Blocks{
Header(1, Inlines('Module ' .. doc.name), {'module-' .. doc.name})
- } .. fields .. functions
+ } .. read_blocks(doc.description) .. fields .. functions
end
--- Retrieves the documentation object for the given value.
@@ -119,7 +119,9 @@ local function get_module_name(header)
end
--- Set of modules for which documentation should be generated.
-local handled_modules = {}
+local handled_modules = {
+ layout = true
+}
return {{
Pandoc = function (doc)