mirror of
https://github.com/davatorium/rofi.git
synced 2024-11-25 13:55:34 -05:00
238 lines
5.7 KiB
Lua
238 lines
5.7 KiB
Lua
|
local Def = {}
|
||
|
|
||
|
function Def:new(d)
|
||
|
-- init with empty def
|
||
|
if d == nil then
|
||
|
d = {
|
||
|
start_idx = nil,
|
||
|
end_idx = nil,
|
||
|
def_par = nil,
|
||
|
content = {},
|
||
|
}
|
||
|
end
|
||
|
setmetatable(d, self)
|
||
|
self.__index = self
|
||
|
return d
|
||
|
end
|
||
|
|
||
|
function Def:init(start_idx, el)
|
||
|
self.start_idx = start_idx
|
||
|
self.def_par = el
|
||
|
end
|
||
|
|
||
|
function Def:append(el)
|
||
|
if self.start_idx ~= nil then
|
||
|
table.insert(self.content, el)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function Def:stop(end_idx)
|
||
|
if self.start_idx == nil then
|
||
|
return nil
|
||
|
end
|
||
|
local out = self:new({
|
||
|
start_idx = self.start_idx,
|
||
|
end_idx = end_idx,
|
||
|
def_par = self.def_par,
|
||
|
content = self.content,
|
||
|
})
|
||
|
self.start_idx = nil
|
||
|
self.end_idx = nil
|
||
|
self.def_par = nil
|
||
|
self.content = {}
|
||
|
return out
|
||
|
end
|
||
|
|
||
|
function Def:to_string()
|
||
|
return string.format("start: %d, end: %d, def_par: %s", self.start_idx, self.end_idx, self.def_par)
|
||
|
end
|
||
|
|
||
|
function find_defs(doc)
|
||
|
local defs = {}
|
||
|
local idx = 0
|
||
|
local def = Def:new()
|
||
|
|
||
|
-- find defintions:
|
||
|
-- * start at paragraphs with `word` ...
|
||
|
-- * stop at next definition or next header
|
||
|
local filter = {
|
||
|
traverse = "topdown",
|
||
|
Para = function(el)
|
||
|
idx = idx + 1
|
||
|
|
||
|
local new_def_start = #el.content >= 1 and el.content[1].tag == "Code"
|
||
|
|
||
|
if new_def_start then
|
||
|
local newd = def:stop(idx - 1)
|
||
|
table.insert(defs, newd)
|
||
|
|
||
|
def:init(idx, el.content)
|
||
|
else
|
||
|
def:append(el)
|
||
|
end
|
||
|
return nil, false
|
||
|
end,
|
||
|
Block = function(el)
|
||
|
idx = idx + 1
|
||
|
def:append(el)
|
||
|
-- stop exploring after one nesting level
|
||
|
return nil, false
|
||
|
end,
|
||
|
Header = function(el)
|
||
|
idx = idx + 1
|
||
|
local newd = def:stop(idx - 1)
|
||
|
table.insert(defs, newd)
|
||
|
return nil, false
|
||
|
end,
|
||
|
}
|
||
|
|
||
|
doc:walk(filter)
|
||
|
local newd = def:stop(idx - 1)
|
||
|
table.insert(defs, newd)
|
||
|
|
||
|
return defs
|
||
|
end
|
||
|
|
||
|
function convert_defs(doc, defs)
|
||
|
local idx = 0
|
||
|
local out_blocks = {}
|
||
|
|
||
|
local convert_defs = {
|
||
|
traverse = "topdown",
|
||
|
Block = function(el)
|
||
|
idx = idx + 1
|
||
|
for _, d in ipairs(defs) do
|
||
|
if idx == d.end_idx then
|
||
|
local dl = pandoc.DefinitionList({ { d.def_par, { d.content } } })
|
||
|
table.insert(out_blocks, dl:walk())
|
||
|
return {}, false
|
||
|
end
|
||
|
if idx >= d.start_idx and idx < d.end_idx then
|
||
|
-- drop
|
||
|
return {}, false
|
||
|
end
|
||
|
end
|
||
|
table.insert(out_blocks, el:walk())
|
||
|
return nil, false
|
||
|
end,
|
||
|
}
|
||
|
|
||
|
doc:walk(convert_defs)
|
||
|
|
||
|
return pandoc.Pandoc(out_blocks, doc.meta)
|
||
|
end
|
||
|
|
||
|
-- for <2.17 compatibility
|
||
|
-- equivalent to `doc:walk(filter)`
|
||
|
local function walk_doc(doc, filter)
|
||
|
local div = pandoc.Div(doc.blocks)
|
||
|
local blocks = pandoc.walk_block(div, filter).content
|
||
|
return pandoc.Pandoc(blocks, doc.meta)
|
||
|
end
|
||
|
|
||
|
local function extract_title(doc)
|
||
|
local title = {}
|
||
|
local section
|
||
|
local filter = {
|
||
|
Header = function(el)
|
||
|
local f = {
|
||
|
Str = function(el)
|
||
|
if el.text:find("%(1%)") ~= nil then
|
||
|
section = "General Commands Manual"
|
||
|
elseif el.text:find("%(5%)") ~= nil then
|
||
|
section = "File Formats Manual"
|
||
|
end
|
||
|
table.insert(title, el)
|
||
|
end,
|
||
|
Inline = function(el)
|
||
|
table.insert(title, el)
|
||
|
end,
|
||
|
}
|
||
|
if el.level == 1 then
|
||
|
pandoc.walk_block(el, f)
|
||
|
return {} -- drop
|
||
|
end
|
||
|
return nil
|
||
|
end,
|
||
|
}
|
||
|
|
||
|
doc = walk_doc(doc, filter)
|
||
|
|
||
|
local to_inline = function(s)
|
||
|
local r = {}
|
||
|
for w in s:gmatch("%S+") do
|
||
|
table.insert(r, pandoc.Str(w))
|
||
|
table.insert(r, pandoc.Space())
|
||
|
end
|
||
|
table.remove(r, #r)
|
||
|
return r
|
||
|
end
|
||
|
|
||
|
if section ~= nil then
|
||
|
for _, e in ipairs({
|
||
|
pandoc.Space(),
|
||
|
pandoc.Str("rofi"),
|
||
|
pandoc.Space(),
|
||
|
pandoc.Str("|"),
|
||
|
table.unpack(to_inline(section)),
|
||
|
}) do
|
||
|
table.insert(title, e)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
doc.meta = pandoc.Meta({
|
||
|
title = pandoc.MetaInlines(title),
|
||
|
})
|
||
|
|
||
|
return doc
|
||
|
end
|
||
|
|
||
|
local function decrement_heading(doc)
|
||
|
local filter = {
|
||
|
Header = function(el)
|
||
|
if el.level > 1 then
|
||
|
el.level = el.level - 1
|
||
|
return el
|
||
|
end
|
||
|
return nil
|
||
|
end,
|
||
|
}
|
||
|
|
||
|
doc = walk_doc(doc, filter)
|
||
|
return doc
|
||
|
end
|
||
|
|
||
|
local function code_in_strong(doc)
|
||
|
local filter = {
|
||
|
Code = function(el)
|
||
|
return pandoc.Strong(el.text)
|
||
|
end,
|
||
|
}
|
||
|
|
||
|
doc = walk_doc(doc, filter)
|
||
|
return doc
|
||
|
end
|
||
|
|
||
|
--- Run filtering function through whole document
|
||
|
--
|
||
|
-- * find argument definitions: paragraph starting with inline code (`-arg`)
|
||
|
-- * replace the paragraphs until the end of the definition with a DefinitionList
|
||
|
-- * extract metadata title from main heading
|
||
|
-- * decrement heading from 1 for better display
|
||
|
-- * convert inline code text to Strong as usual in man pages
|
||
|
function Pandoc(doc)
|
||
|
if PANDOC_VERSION >= pandoc.types.Version("2.17.0") then
|
||
|
-- 2.17 is required for topdown traversal
|
||
|
local defs = find_defs(doc)
|
||
|
doc = convert_defs(doc, defs)
|
||
|
end
|
||
|
|
||
|
doc = extract_title(doc)
|
||
|
|
||
|
doc = decrement_heading(doc)
|
||
|
|
||
|
doc = code_in_strong(doc)
|
||
|
|
||
|
return doc
|
||
|
end
|