Last active
September 18, 2018 15:02
-
-
Save bpj/5513fc3fc4e33fc6330b693bcd9e4198 to your computer and use it in GitHub Desktop.
Pandoc filter to add anchors to option descriptions in CLI program documentation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
pandoc options-anchors.lua | |
Pandoc filter which walks all definition lists in all divs with a class | |
`options-list` (or `optionslist` or `option-list` or `optionlist`) and | |
wraps all DL terms whose stringification starts with what looks like a | |
CLI option name[^1] in a span with an id `option-LONG-OPTION-NAME`, | |
where `LONG-OPTION-NAME` is the first long option name[^2] in the | |
stringified term. e.g. | |
```markdown_pandoc | |
:::options-list | |
`-C`, `--change`, `-m`, `--mogrify` | |
: Change things. | |
`--thing=`*STRING* | |
: Specify something | |
::: | |
``` | |
becomes | |
```markdown_pandoc | |
:::options-list | |
[`-C`, `--change`, `-m`, `--mogrify`]{#option-change} | |
: Change things. | |
[`--thing=`*STRING*]{#option-thing} | |
: Specify something | |
::: | |
``` | |
This is primarily intended for the Pandoc manual, but may be used for any | |
CLI program documentation document with similar layout. | |
[^1]: 'option-like' is defined as one or two hyphens followed by a | |
letter followed by zero or more hyphens or word characters. | |
[^2]: 'long-option-like' is defined as two hyphens followed by a letter | |
followed by one or more hyphens or word characters. | |
Author: Benct Philip Jonsson <[email protected]> | |
]] | |
local p = pandoc | |
local u = pandoc.utils | |
-- from bpj's bag of tricks a perlism for sure... | |
local function first_idx (array, pattern) | |
for i,v in ipairs(array) do | |
local s = string.find(tostring(v), pattern) | |
if s ~= nil then return i end | |
end | |
return nil | |
end | |
local function get_option_id (term) | |
term = u.stringify(p.Emph(term)) | |
local s = string.find(term, '^%-%-?%a[%-%w]*') | |
if s ~= nil then | |
local name = string.match(term, '%-%-(%a[%-%w]+)') | |
if name ~= nil then return 'option-' .. name end | |
end | |
return nil | |
end | |
local function is_element (value, t) | |
if type(value) ~= 'table' then return false end | |
if value.t and t == value.t then return true end | |
return false | |
end | |
local function span_with_id (inlines, id) | |
if #inlines < 1 then return {} end | |
if #inlines == 1 then | |
if is_element(inlines[1], 'Span') then | |
local span = inlines[1] | |
local old_id = span.identifier or "" | |
if old_id == id then return span end | |
if string.len(old_id) == 0 then | |
span.identifier = id | |
return { span } | |
end | |
end | |
end | |
return { p.Span(inlines, p.Attr(id)) } | |
end | |
local function option_anchors (div) | |
local is_opt_list = first_idx(div.classes, '^options?%-?list$') | |
if is_opt_list == nil then return end | |
return p.walk_block( div, { | |
DefinitionList = function (dl) | |
for _,pair in ipairs(dl.content) do | |
local id = get_option_id(pair[1]) | |
if id ~= nil then | |
pair[1] = span_with_id(pair[1], id) | |
end | |
end | |
return dl | |
end | |
}) | |
end | |
return { { Div = option_anchors } } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment