Ajout inner-parens-to-brackets

This commit is contained in:
Bastien Dumont 2024-05-24 15:45:18 +02:00
parent 2506617bc1
commit ebf03f204f
3 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright © 2024 Bastien Dumont
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,4 @@
This filter converts nested parentheses to brackets (and conversely).
I use it mostly to post-process citeproc output.

View File

@ -0,0 +1,91 @@
-- 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