92 lines
3.1 KiB
Lua
92 lines
3.1 KiB
Lua
|
-- 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
|