pandoc-lua-filters/inner-parens-to-brackets/inner-parens-to-brackets.lua

92 lines
3.1 KiB
Lua
Raw Permalink Normal View History

2024-05-24 14:45:18 +01:00
-- inner-parens-to-brackets.lua
-- A Pandoc Lua filter that converts nested parentheses to brackets (and conversely).
-- Copyright 2024 Bastien Dumont (bastien.dumont [at] posteo.net)
-- This file is under the MIT License: see LICENSE for more details.
local previously_signalled = {}
local function signal_if_new(id, msg)
if not previously_signalled[id] then
io.stdout:write('INFO: ' .. msg .. '\n')
previously_signalled[id] = true
end
end
function Para(para)
local whole_para = pandoc.utils.stringify(para)
local parens_trace = {}
local i_str = 0
local isolate_parens = {
-- In case there are several level of parentheses in the same Str object
-- (could theoretically happen due to non-breaking spaces).
-- Also simplifies check_and_replace() below.
Str = function(str)
local text = str.text
if string.match(text, '[][()]') then
local substrings = {}
for a, b, c in string.gmatch(text, '([^][()]*)([][()]?)([^][()]*)') do
for _, sub in ipairs({ a, b, c }) do
if sub ~= '' then table.insert(substrings, pandoc.Str(sub)) end
end
end
return substrings
end
end
}
local check_and_replace = {
traverse = 'topdown',
Str = function(str)
i_str = i_str + 1
local text = str.text
if text == '(' then
if #parens_trace > 0 then
if parens_trace[#parens_trace] == '(' then
str.text = '['
signal_if_new(whole_para .. i_str,
'Replacing a left parenthesis with a bracket ' ..
'in the following item: ' .. whole_para)
end
end
table.insert(parens_trace, str.text)
elseif text == ')' then
if #parens_trace > 0 then
if parens_trace[#parens_trace] == '[' then
str.text = ']'
signal_if_new(whole_para .. i_str,
'Replacing a right parenthesis with a bracket ' ..
'in the following item: ' .. whole_para)
end
end
table.remove(parens_trace)
elseif text == '[' then
if #parens_trace > 0 then
if parens_trace[#parens_trace] == '[' then
str.text = '('
signal_if_new(whole_para .. i_str,
'Replacing a left bracket with a parenthesis ' ..
'in the following item: ' .. whole_para)
end
end
table.insert(parens_trace, str.text)
elseif text == ']' then
if #parens_trace > 0 then
if parens_trace[#parens_trace] == '(' then
str.text = ')'
signal_if_new(whole_para .. i_str,
'Replacing a right bracket with a parenthesis ' ..
'in the following item: ' .. whole_para)
end
end
table.remove(parens_trace)
end
return str
end
}
local processed_para = para:walk(isolate_parens):walk(check_and_replace)
if #parens_trace > 0 then
io.stdout:write('WARNING: Unbalanced parentheses or brackets found in ' .. whole_para .. '\n')
end
return processed_para
end