Module pancake

Toolkit for writing Lua filters for Pandoc.

Synopsis:

pancake = require 'pancake'

Pancake aims to work with Pandoc ≥ v2.0.4. However, it has only been tested with v2.9–v2.18, and only on Linux and macOS.

Tip:

Pancake automatically loads Pandoc’s modules (e.g., pandoc.system) into the global namespace; this is useful when you are using older versions of Pandoc, which do not do this automatically. So, you may want to load it before setting up a per-function or per-module environment.

Info:

  • Copyright: 2022 Odin Kroeger
  • Release: 1.0.0b18
  • License: MIT
  • Author: Odin Kroeger

Metadata

VERSION Pancake’s version.

System

PATH_SEP The path segment separator used by the operating system.
EOL The end of line sequence typically used on the given operating system.

Type-checking

type_match (val, decl) Check whether a value is of a type.
type_check (...) Decorator that adds type checks to a function.

Errors

asserter ([fin[, msgh]]) Create a custom assertion function.
protect (func) Decorator that runs a function in protected mode.
unprotect (func) Decorator that raises an error if a function returns a fail value.

Tables

copy (val) Make a deep copy of a value.
keys (tab) Get the indices and number of items in a table.
order (values) Derive a sorting function from a list of values.
sorted (tab[, func[, raw]]) Iterate over the key-value pairs of a table in a given order.
tabulate (iter[, tab[, idx=1]]) Tabulate the values that an iterator returns.
walk (val, func) Apply a function to each node of a tree.

Strings

split (str, pattern[, max[, opts]]) Iterate over substrings of a string.

Variables

vars_get ([level=2]) Get a copy of a function’s variables.
vars_sub (str, vars) Substitute variables in strings.
env_sub (str) Substitute environment variables in strings.

Metatables

no_case Metatable that makes indices case-insensitive.
no_case.__index (tab, key) Look up an item.
no_case.__newindex (tab, key, val) Store a new item.

Prototypes

Object Base prototype.
Object:clone ([tab[, mt]]) Delegate to an object.
Object:new (...) Initialise an Object.
getterify (tab) Add getters to a table.

File I/O

file_exists (fname) Check whether a file exists.
file_locate (fname) Locate a file in Pandoc’s resource path.
file_read (fname) Read a file.
file_write (fname, ...) Write data to a file.
tmp_fname ([dir[, templ='tmp-XXXXXX']]) Generate a name for a temporary file.
with_tmp_file (func[, dir[, templ]]) Run a function with a temporary file.

Paths

path_join (...) Join path segments.
path_normalise (path) Normalise a path.
path_prettify (path) Prettify a path.
path_split (path) Split a path into a directory and a filename.
project_dir () Guess the project directory.

Warnings

xwarn (...) Print a message to STDERR.

Elements

elem_clone (elem) Make a shallow copy of a Pandoc AST element.
elem_type (elem) Get the type of a Pandoc AST element.
elem_walk (elem, filter) Walk an AST element and apply a filter to matching elements.

Options

Options An option list.
Options:new (...) Create a new option list.
Options:add (...) Add an option to the list.
Options:parse (meta) Parse options from a metadata block (OO-interface).
opts_parse (meta, ...) Parse options from a metadata block (function interface).


Metadata

VERSION
Pancake’s version.

System

PATH_SEP
The path segment separator used by the operating system.
EOL
The end of line sequence typically used on the given operating system.

Type-checking

type_match (val, decl)
Check whether a value is of a type.

Type Declaration Grammar:

Give one or more Lua type names separated by a pipe symbol (‘|’) to check whether a value is of one of the given types (e.g., ‘string|table’ checks whether the value is a string or a table). ‘’ is short for the list of all types save for nil. ‘?T’ is short for ‘T*|nil’ (e.g., ‘?table’ is short for ‘table|nil’).

In Extended Backus-Naur Form:

Type = ‘boolean’ | ‘function’ | ‘nil’ | ‘number’ | ‘string’ | ‘table’ | ‘thread’ | ‘userdata’

Type list = [ ‘?’ ], type, { ‘|’, type }

Wildcard = [ ‘?’ ], ‘*’

Type declaration = type list | wildcard

Complex Types:

You can check types of table or userdata fields by declarding a table that maps indices to declarations.

  > type_check({1, '2'}, {'number', 'number'})
  nil    index 2: expected number, got string.
  > type_check({foo = 'bar'}, {foo = '?table'})
  nil    index foo: expected table or nil, got string.
  > type_check('foo', {foo = '?table'})
  nil    expected table or userdata, got string.

Caveats:

Wrong type names (e.g., ‘int’) do not throw an error, but will always return one.

Parameters:

  • val A value.
  • decl string or table A type declaration.

Returns:

    bool true if the value matches the declaration.

Or

  1. nil nil otherwise.
  2. string An error message.
type_check (...)
Decorator that adds type checks to a function.

Only adds type checks if the global CHECK_TYPES evaluates as true.

Type declaration grammar:

The type declaration syntax is that of type_match, save for that you can use ‘…’ to declare that the remaining arguments are of the same type as the previous one.

Caveats:

    • Wrong type names (e.g., ‘int’) do not throw an error.
    • Sometimes the strack trace is wrong.

Tip:

    Obscure Lua errors may indicate that the quotes around ‘…’ are missing.

Parameters:

  • ... string or table One type declaration per argument.

Returns:

    func A function that adds type checks to another function.

Usage:

    store = type_check('*', 'table', '?number', '...')(
        function (val, tab, ...)
             local indices = table.pack(...)
             for i = 1, indices.n do tab[indices[i]] = val end
        end
    )

Errors

asserter ([fin[, msgh]])
Create a custom assertion function.

See http://lua-users.org/wiki/FinalizedExceptions.

Parameters:

  • fin func Called before an error is thrown. (optional)
  • msgh func Given the error and the caller’s variables, should return a new error. (optional)

Returns:

    func An assertion function.

Usage:

    > local assert = asserter(nil, vars_sub)
    > function foo ()
    >    local bar = 'The bar'
    >    assert(false, '${bar} is to blame!')
    > end
    > foo()
    The bar is to blame!
    stack traceback:
            [C]: in function 'error'
            stdin:3: in function 'foo'
            (...tail calls...)
            [C]: in ?
protect (func)
Decorator that runs a function in protected mode.

See http://lua-users.org/wiki/FinalizedExceptions.

Parameters:

  • func func A function.

Returns:

    func A function running in protected mode.

See also:

Usage:

    > foo = protect(function () return 'foo' end)
    > foo()
    foo
    > boo = protect(function () error 'bar!' end)
    > boo()
    nil    bar!
unprotect (func)
Decorator that raises an error if a function returns a fail value.

Parameters:

  • func func A function.

Returns:

    func A function that throws an error on failures.

See also:

Usage:

    > foo = unprotect(function () return 'foo' end)
    > foo()
    foo
    > boo = unprotect(function () return nil, 'boo.' end)
    > boo()
    boo.
    stack traceback:
            [C]: in function 'error'
            stdin:4: in function 'boo'
            (...tail calls...)
            [C]: in ?

Tables

copy (val)

Make a deep copy of a value.

  • Copies metatables.
  • Handles cyclic data.
  • Bypasses __pairs and __newindex.

Parameters:

  • val A value.

Returns:

    A deep copy.

Usage:

    > foo = {1, 2, 3}
    > bar = {foo, 4}
    > baz = copy(bar)
    > foo[#foo + 1] = 4
    > table.unpack(baz, 1)
    1    2    3
keys (tab)
Get the indices and number of items in a table.

Tip:

    select(2, keys(t)) == #t checks whether a table is a list.

Parameters:

  • tab tab A table.

Returns:

  1. tab The indices.
  2. int The number of items.
order (values)
Derive a sorting function from a list of values.

Values that are not in the list are sorted lexically.

Parameters:

  • values tab Values.

Returns:

    func A sorting function.

Usage:

    > tab = {a = 3, b = 4, c = 2, d = 1}
    > for k, v in sorted(tab, order{'d', 'c'}) do
    >     print(k, v)
    > end
    d    1
    c    2
    a    3
    b    4
sorted (tab[, func[, raw]])
Iterate over the key-value pairs of a table in a given order.

Parameters:

  • tab tab A table.
  • func func A sorting function. Defaults to the sort metamethod or sorting lexically. (optional)
  • raw bool Bypass __pairs metamethod? Done by default if __pairs is set to sorted. (optional)

Returns:

    func A stateful iterator.

Usage:

    > -- Iterating over keys in lexical order.
    > tab = {c = 3, b = 2, a = 1}
    > for k, v in sorted(tab) do
    >     print(k, v)
    > end
    a    1
    b    2
    c    3
    -- Supplying a sorting function.
    > for k, v in sorted(tab, order{'c', 'b', 'a'}) do
    >     print(k, v)
    > end
    c    3
    b    2
    a    1
    > -- Setting the `sort` metamethod.
    > mt = {sort = order{'c', 'b', 'a'}}
    > setmetatable(tab, mt)
    > for k, v in sorted(tab) do
    >     print(k, v)
    > end
    c    3
    b    2
    a    1
    > -- Using `sorted` as `__pairs` metamethod.
    > mt.__pairs = sorted
    > for k, v in pairs(tab) do
    >     print(k, v)
    > end
    c    3
    b    2
    a    1
tabulate (iter[, tab[, idx=1]])
Tabulate the values that an iterator returns.

Parameters:

  • iter func An iterator. Must accept, though not honour, the same arguments as next.
  • tab tab A table to iterate over. (optional)
  • idx An index to start at. (default 1)

Returns:

    {...,n=number} The values returned by the iterator.

Usage:

    > tab = {a = true, b = true, c = true}
    > unpack(tabulate(next, tab))
    a    b    c
walk (val, func)

Apply a function to each node of a tree.

  • Nodes are only changed if the function returns a non-nil value.
  • The tree is walked bottom-up.
  • Handles cyclic data structures.

Parameters:

  • val A value.
  • func func A function.

Returns:

    A changed value.

Strings

split (str, pattern[, max[, opts]])
Iterate over substrings of a string.

Options:

split accepts a string of option characters:

  • ‘P’: Disable pattern matching.
  • ‘E’: Skip empty substrings.
  • ‘l’: Add seperator to left of substring; implies ‘E’.
  • ‘r’: Add seperator to right; implies ‘E’.

An empty string of options is ignored silently.

Caveats:

    Does not support multi-byte characters.

Parameters:

  • str string A string.
  • pattern string Where to split the string.
  • max int Split the string into at most that many substrings. (optional)
  • opts string Option string. (optional)

Returns:

    func A stateful iterator.

Usage:

    > for s in split('CamelCase', '%f[%u]') do
    >     print(s)
    > end
    
    Camel
    Case
    > for s in split('CamelCase', '%f[%u]', nil, 'E') do
    >     print(s)
    > end
    Camel
    Case
    > for s in split('foobar', '[fb]', nil, 'l') do
    >     print(s)
    > end
    foo
    bar

Variables

vars_get ([level=2])
Get a copy of a function’s variables.

Caveats:

    If a global variable is shadowed by a variable that is neither one of the function’s local variables nor one of its upvalues, then that variable is looked up in _ENV and the shadowing variable is ignored.

Parameters:

  • level int A stack level > 0, where vars_get is at level 1, its caller is at level 2, etc. (default 2)

Returns:

    table A mapping of variable names to values.

Usage:

    > function bar ()
    >     print(vars_get(3).foo)
    > end
    > function foo ()
    >     foo = 'foo'
    >     bar()
    > end
    > foo()
    foo
vars_sub (str, vars)

Substitute variables in strings.

If a string of characters is placed within braces (‘{…}’) and the opening brace (‘{’) immediately follows a single dollar (‘$’) sign, then that string is interpreted as a variable name and the whole expression is replaced with the value of that variable. Variable names must only consist of letters, numbers, and underscores (‘_’) and must start with a letter or an underscore.

> vars_sub(
>     '${v1} is ${v2}.',
>     {v1 = 'foo', v2 = 'bar'}
> )
foo is bar.

If a braced string is preceded by two or more dollar signs, it is not interpreted as a variable name and the expression is not replaced with the value of a variable. Moreover, any series of n dollar signs that precedes a pair of braces (e.g., $${...}) is replaced with n – 1 dollar signs.

> vars_sub(
>     '$${var} costs $1.',
>     {var = 'foo'}
> )
${var} costs $1.

You can lookup values in tables by joining table indices with dots (‘.’).

> vars_sub(
>     '${foo.bar} is baz.', {
>         foo = { bar = 'baz' }
>     }
> )
baz is baz.

If a variable name is followed by a pipe symbol (‘|’), then the string between that pipe symbol and the next pipe symbol/closing brace is interpreted as a function name, this function is then given the value of that variable, and the whole expression is replaced with the first value the function returns.

> vars_sub(
>     '${var|barify} is bar!', {
>         var = 'foo',
>         barify = function (s)
>             return s:gsub('foo', 'bar')
>         end
>     }
> )
bar is bar!

Variables are substituted recursively.

> vars_sub(
>     '${foo|barify} is bar.', {
>         foo = '${bar}',
>         bar = 'baz',
>         barify = function (s) return s:gsub('baz', 'bar') end
>     }
> )
bar is bar.

The expression as a whole must evaluate either to a string or a number.

Variables can also be looked up by a function. The function is run in protected mode. If it throws an error, vars_sub will return nil and the error object thrown by the function. This mode does not support multi-dimensional lookups (${foo.bar}), pipes (${foo|bar}), or recursive substitution.

> vars_sub(
>     '${foo} is bar.',
>     function (key)
>         if key == 'foo' then return 'bar' end
>     end
> )
bar is bar.

Parameters:

  • str string A string.
  • vars func or tab A mapping of variable names to values.

Returns:

    string A transformed string.

Or

  1. nil nil if an error occurred.
  2. string An error message.
env_sub (str)
Substitute environment variables in strings.

Uses the same syntax as vars_sub, but without pipes or recursive substitution.

Side-effects:

    Prints a warning to STDERR if a variable is empty.

Parameters:

Returns:

    string A transformed string.

Or

  1. nil nil if an error occurred.
  2. string An error message.

Metatables

no_case
Metatable that makes indices case-insensitive.

Usage:

    > tab = setmetatable({}, no_case)
    > tab.FOO = 'bar'
    > tab.foo
    bar
no_case.__index (tab, key)
Look up an item.

Parameters:

  • tab tab A table.
  • key A key.

Returns:

    The item.
no_case.__newindex (tab, key, val)
Store a new item.

Parameters:

  • tab tab A table.
  • key A key.
  • val A value.

Prototypes

Object
Base prototype.

Tip:

    Object(...) is equivalent to Object:new(...).
Object:clone ([tab[, mt]])

Delegate to an object.

Set a table’s metatable to a copy of the objects’s metatable, then set the table’s __index metavalue to the object. If no table is given, create one. If a metatable is given, override the table’s new metatable with that table. In other words,

 Object:clone(tab, mt)

is equivalent to

 do
     local mt = update({}, getmetatable(Object), {__index = Object}, mt)
     setmetatable(tab or {}, mt)
 end

Caveats:

    The given table is changed in-place.

Parameters:

  • tab tab A table. (optional)
  • mt tab A metatable. (optional)

Returns:

    tab The table.

Usage:

    > Foo = Object:clone({}, {__tostring = function (t) return t.bar end})
    > Foo.bar = 'baz'
    > tostring(Foo)
    baz
    > bar = Foo()
    > tostring(bar)
    baz
    > bar.bar = 'bar'
    > tostring(bar)
    bar
Object:new (...)
Initialise an Object.

Object:new(...) is equivalent to update(Object:clone(), ...).

Parameters:

  • ... tab Properties.

Returns:

    Object An object.

Usage:

    > foo = Object:new{foo = 'foo'}
    > foo.foo
    foo
    > bar = foo:new{bar = 'bar'}
    > bar.foo
    foo
    > bar.bar
    bar
getterify (tab)
Add getters to a table.

Getter protocol:

If an index is not present in a the table, look for a function of the same name in the table’s getters metavalue, which must be a table that maps indices to functions. If getters contains a function of the give name, that function is called with the table as its only argument and whatever it returns is returned as the value of the given index. If getters does not contain a function of that name, the name is looked up using the table’s old __index metavalue.

Caveats:

    • Tables are modified in-place.
    • Getters are not inherited.

Parameters:

  • tab tab A table.

Returns:

    tab The table.

Usage:

    > -- Enable getters for an object:
    > Foo = getterify(Object:clone())
    > Foo.foo = 'bar'
    > mt = getmetatable(Foo)
    > mt.getters = {bar = function (obj) return obj.foo end}
    > Foo.bar
    bar
    > -- Getters are *not* inherited.
    > baz = Foo()
    > baz.foo = 'bam!'
    > -- The getter is reached via the prototype chain,
    > -- so it sees Foo.foo, not bar.foo:
    > baz.bar
    bar
    > -- But you can make getters quasi-inheritable:
    > Foo.clone = function (...) return getterify(Object.clone(...)) end
    > baz = Foo()
    > baz.foo = 'bam!'
    > baz.bar
    bam!
    > -- Now every object down the prototype chain is getterified.
    > bam = baz()
    > bam.foo = 'BAM!'
    > bam.bar
    BAM!

File I/O

file_exists (fname)
Check whether a file exists.

Caveats:

    Another process may create a file of the given name between the time file_exists tries to access that file and the time it returns.

Parameters:

Returns:

    boolean true if the file exists.

Or

  1. nil nil if the file does not exist.
  2. string An error message.
  3. int The error number 2.

Raises:

An error if the file cannot be closed again.
file_locate (fname)
Locate a file in Pandoc’s resource path.

Caveats:

    Absolute filenames are returned as they are.

Parameters:

Returns:

    string A filename in Pandoc’s resource path.

Or

  1. nil nil if the file could not be found.
  2. string An error message.
file_read (fname)
Read a file.

Parameters:

Returns:

    string The contents of the file.

Or

  1. nil nil if an error occurred.
  2. string An error message.
  3. int An error number.
file_write (fname, ...)
Write data to a file.

If a file of that name exists already, it is overwritten.

Caveats:

    Data is first written to a temporary file, that file is then renamed to the given filename. This is safe and secure starting with Pandoc v2.8. If you are using an older version of Pandoc, the caveats of with_tmp_file apply.

    Moreover, if Pandoc exits because it catches a signal (e.g., because the user presses Ctrl-c), this file will not be deleted. This is a bug in Pandoc.

Side-effects:

    • Creates and deletes a temporary file.
    • Prints warnings to STDERR.

Parameters:

Returns:

    bool true if the data was written to the given file.

Or

  1. nil nil if an error occurred.
  2. string An error message.
  3. int An error number.

Raises:

An error if no unused temporary filename could be generated in Pandoc < v2.8 or if the temporary directory could not be created in Pandoc ≥ v2.8; the latter error cannot be caught.
tmp_fname ([dir[, templ='tmp-XXXXXX']])
Generate a name for a temporary file.

Caveats:

    Another process may create a file of the same name between the time tmp_fname checks whether that name is in use and the time it returns.

Parameters:

  • dir string A directory to prefix the filename with. (optional)
  • templ string A template for the filename. ‘X’s are replaced with random alphanumeric characters. (default 'tmp-XXXXXX')

Returns:

    string A filename.

Or

  1. nil nil if the generated filename is in use.
  2. string An error message.
with_tmp_file (func[, dir[, templ]])
Run a function with a temporary file.

Generates a temporary filename. Does not create that file. If the function raises an error or returns nil or false, the file of that name is deleted.

Caveats:

    The temporary file may have been created by another process. If that file is located within a directory that other users have write access to (e.g., /tmp), this is a security issue!

    Moreover, if Pandoc exits because it catches a signal (e.g., because the user presses Ctrl-c), the file will not be deleted. This is a bug in Pandoc.

Side-effects:

    May print error messages to STDERR.

Parameters:

  • func func Given the name of the temporary file. Must not change the working directory!
  • dir string A directory to prefix the name of the temporary file with. See tmp_fname. (optional)
  • templ string A template for the name of the temporary file. See tmp_fname. (optional)

Returns:

    The values returned by the function.

Raises:

An error if no unused temporary filename could be generated.

Paths

path_join (...)
Join path segments.

Parameters:

Returns:

    string A path.

Usage:

    > path_join('foo', 'bar')
    foo/bar
path_normalise (path)
Normalise a path.

Parameters:

Returns:

    string A normalised path.

Usage:

    > path_normalise './foo/./bar//'
    foo/bar
path_prettify (path)

Prettify a path.

Steps:

  1. The path is normalised.
  2. The current working directory is removed from its beginning.
  3. The user’s home directory is replaced with ‘~’, but only on POSIX systems.

Requires:

    Pandoc ≥ v2.12 to remove the working directory from a path; in earlier versions, this step is skipped.

Parameters:

Returns:

    string A prettier path.

Usage:

    > path_prettify(env_sub '${HOME}/foo/./bar//')
    ~/foo/bar
path_split (path)
Split a path into a directory and a filename.

Parameters:

Returns:

  1. string The directory the file is in.
  2. string The file’s name.

Usage:

    > path_split 'foo/bar'
    foo    bar
project_dir ()
Guess the project directory.

The project directory is the directory of the first input file not named ‘-’ (i.e., of the first actual input file). If there is no such file, the project directory is the current working directory.

Requires:

    The working directory is represented by ‘.’ in Pandoc < v2.8.

Returns:

    string A directory.

Warnings

xwarn (...)
Print a message to STDERR.

Printout:

Prefixed with the filename of the script and ‘: ’, terminated with EOL. Non-strings are coerced to strings.

Message priority:

Messages are only printed if their priority is greater or equal to PANDOC_STATE.verbosity.

Variable substitution:

If string values contain variable names, they are replaced with the values of the local variables, of the upvalues of the calling function, or, if there are no local variables or upvalues of the given names, of _ENV. See vars_sub for the syntax and vars_get for limitations.

Options:

String values starting with an ‘@’ are interpreted as options:

  • ‘@error’, ‘@warning’, ‘@info’: Set the message’s priority. (default ‘warning’)
  • ‘@noopts’: Turn option processing off. (default on)
  • ‘@novars’: Turn variable substitution off. (default on)
  • ‘@plain’: Turn variable substitution and option processing off.
  • ‘@vars’: Turn variable substitution on.

Options are case-sensitive. Unknown options are ignored silently.

Requires:

    Pandoc ≥ v2.4 to respect --quiet and --verbose; in earlier versions, those options are ignored.

Parameters:

  • ... Messages. At least one must be given.

Elements

elem_clone (elem)
Make a shallow copy of a Pandoc AST element.

Parameters:

  • elem pandoc.AstElement A Pandoc AST element.

Returns:

    pandoc.AstElement The clone.
elem_type (elem)
Get the type of a Pandoc AST element.

Parameters:

  • elem pandoc.AstElement A Pandoc AST element.

Returns:

  1. string A type (e.g., ‘Str’).
  2. string or nil A super-type (e.g., ‘Block’ or ‘Meta’).
  3. string or nil ⋮.

Or

  1. nil nil if the given value is not a Pandoc AST element.
  2. string An error message.
elem_walk (elem, filter)
Walk an AST element and apply a filter to matching elements.

Differences to Pandoc’s Walkers:

  • The filter is applied to the given element itself.
  • The AST is traversed bottom-up or top-down, but not typewise, and matching elements are traversed, too.
  • Support for the filter keywords ‘Block’, ‘Inline’, and ‘AstElement’, which match any block, any inline, or any element respectively.
  • Metadata fields and documents as a whole are traversed, too.

Direction of Traversal:

Depends on the filter’s traverse field:

  • bottomup: Traverse the AST bottom-up.
  • topdown: Traverse the AST top-down. (default)

The AST is traversed left-to-right either way.

Caveats:

    This function needs more testing.

Parameters:

Returns:

    Typically, but not necessarily, a new Pandoc AST element.

Options

Options
An option list.

Prototype:

See also:

Options:new (...)

Create a new option list.

opts = Options:new{name = 'foo'}

is equivalent to:

opts = Options()
opts:add{name = 'foo'}

Parameters:

  • ... tab Option definitions.

See also:

Options:add (...)
Add an option to the list.

Parameters:

  • ... tab Option definitions.

See also:

Usage:

    opts = Options()
    opts:add{
        name = 'bar',
        type = 'number',
        parse = function (x)
            if x < 1 then return nil, 'not a positive number.' end
            return x
        end
    }
Options:parse (meta)
Parse options from a metadata block (OO-interface).

Parameters:

  • meta pandoc.MetaMap A metadata block.

Returns:

    tab A mapping of option names to values.

Or

  1. nil nil if an error occurred.
  2. string An error message.

See also:

Usage:

    > meta = pandoc.MetaMap{
    >     ['foo-bar'] = pandoc.MetaInlines(pandoc.List{
    >         pandoc.Str "0123"
    >     })
    > parser = Options()
    > parser:add{
    >     name = 'bar',
    >     prefix = 'foo',
    >     type = 'number',
    >     parse = function (x)
    >         if x < 1 then return nil, 'not a positive number.' end
    >         return x
    >     end
    > }
    > opts = parser:parse(meta)
    > opts.bar
    123
    > type(opts.bar)
    number
opts_parse (meta, ...)
Parse options from a metadata block (function interface).

Option Definition Syntax:

An option definition is a table with the following keys:

  • name: (string) An option name.
  • type: (string) An option type. (default ‘string’)
  • parse: (func) A parser. (optional)
  • prefix: (string) A prefix. (optional)

Mapping of Option Names to Metadata Fieldnames:

The name of the metadata field is the name of the option with underscores replaced by dashes. If the option has a prefix, then the fieldname is prefixed with that prefix and a dash after underscores have been replaced with dashes.

In Lua:

fieldname = name:gsub('_', '-')
if prefix then fieldname = prefix .. '-' .. fieldname end

Type Declaration Grammar:

Configuration values can be of any of four types:

  • ‘boolean’
  • ‘number’
  • ‘string’
  • ‘array’

If an option is declared to be of one of the scalar types ‘boolean’, ‘number’, or ‘string’, then its value is required to be of the Lua type of the same name or convertible to that type; if an option is declared as ‘boolean’, the strings ‘true’, ’t', ‘yes’ and ‘y’ are converted to true, and ‘false’, ‘f’, ‘no’ and ‘n’ to false (case is ignored).

If an option is declared to be an ‘array’, its value is required to be of the Pandoc type pandoc.List or convertible to that type. However, if a scalar value is encountered where an array is expected, the value is wrapped in a single-item list automatically.

Items in an array must all be of the same type. That type is declared by appending ‘<T>’ to ‘array’, where T is either the name of a scalar type or another array declaration (e.g., ‘array’); T defaults to ‘string’.

An option can be declared to be of any of a list of types by listing multiple type names separated by a pipe symbol (‘|’), for example, ‘string|list’. The first type that matches ‘wins’, even if winning requires a type conversion (e.g., ‘string|number’ is, effectively, equivalent to ‘string’).

In Extended Backus-Naur Form:

Scalar = ‘boolean’ | ‘number’ | ‘string’

Array = ‘array’, [ ‘<’, ( scalar | array ), ‘>’ ]

Type = scalar | array

Type list = type, { ‘|’, type }

No type checks or conversions are performed for nil.

Parse Protocol:

Parsers are given the converted value and should return either a new value or nil and an error message.

Parsers are not invoked for nil.

Caveats:

    Options:add throws an error if it is given a wrong option type (e.g., ‘int’ or ‘array[number]’). opts_parse accepts wrong option types and only throws an error if it encounters an option that is supposed to be of that type.

Parameters:

  • meta pandoc.MetaMap A metadata block.
  • ... Option Option definitions.

Returns:

    tab A mapping of option names to values.

See also:

Usage:

    > meta = pandoc.MetaMap{
    >     ['foo-bar'] = pandoc.MetaInlines(pandoc.List{
    >         pandoc.Str "0123"
    >     })
    > opts = opts_parse(meta, {
    >     name = 'bar',
    >     prefix = 'foo',
    >     type = 'number',
    >     parse = function (x)
    >         if x < 1 then return nil, 'not a positive number.' end
    >         return x
    >     end
    > })
    > opts.bar
    123
    > type(opts.bar)
    number
generated by LDoc 1.4.6 Last updated 2022-04-15 19:08:25