Skip to content

Instantly share code, notes, and snippets.

@dk949
Last active May 15, 2023 22:27
Show Gist options
  • Save dk949/380da9878c53be01ab2132310af84ba3 to your computer and use it in GitHub Desktop.
Save dk949/380da9878c53be01ab2132310af84ba3 to your computer and use it in GitHub Desktop.
Pandoc filter to insert todonotes todos without inline latex
--[[
See bottom of scrip for license
Usage:
---
header-includes: |
\usepackage{todonotes}
...
text text text [TODO: todo text goes here] text text.
[TODO:space after the colon is optional]
Here is another one, but with options [TODO: A green note; color=green!40]. Note that the
space after the semicolon is not optional.
This is the list of todos:
[LISTOFTODOS]
]]
local listOfTodosMarker = "[LISTOFTODOS]"
local beginSentinel = "[TODO:"
local optionSentinel = ";"
local endSentinel = "]"
local State = { BEGIN = 0, PARSING = 1, OPTIONS = 2 }
local function ends_with(str, val)
return str:sub(#str - #val + 1) == val
end
local function starts_with(str, val)
return str:sub(1, #val) == val
end
local function make_todo(text, options)
local str = "\\todo"
if options then
str = str .. "[" .. options .. "]"
end
str = str .. "{" .. text .. "}"
return pandoc.RawInline("latex", str)
end
local function make_list_of_todos()
return pandoc.RawInline("latex", "\\listoftodos")
end
local function run_todonotes(para)
local changed = false
local state = State.BEGIN
local currTodo = ""
local currOptions = ""
local currStart = 0
local currEnd = 0
local function reset()
currTodo = ""
currStart = 0
currEnd = 0
end
local function fill_with_space()
for i = currStart + 1, currEnd do
para.content[i] = pandoc.Space()
end
end
for idx, inline in pairs(para.content) do
local text = inline.text
currEnd = currEnd + 1
if text then
if state == State.BEGIN then
if starts_with(text, beginSentinel) then
changed = true
currTodo = currTodo .. text:sub(#beginSentinel + 1)
if currTodo ~= "" then currTodo = currTodo .. " " end
currStart = idx
currEnd = idx
state = State.PARSING
elseif text == listOfTodosMarker then
changed = true
para.content[idx] = make_list_of_todos()
end
elseif state == State.PARSING then
if ends_with(text, endSentinel) then
currTodo = currTodo .. text:sub(1, #text - #endSentinel)
fill_with_space()
para.content[currStart] = make_todo(currTodo)
reset()
state = State.BEGIN
elseif ends_with(text, optionSentinel) then
currTodo = currTodo .. text:sub(1, #text - #optionSentinel)
state = State.OPTIONS
else
currTodo = currTodo .. text .. " "
end
elseif state == State.OPTIONS then
if ends_with(text, endSentinel) then
currOptions = currOptions .. text:sub(1, #text - #endSentinel)
fill_with_space()
para.content[currStart] = make_todo(currTodo, currOptions)
reset()
state = State.BEGIN
else
currOptions = currOptions .. text .. " "
end
else
error("Unknwon state: " .. tostring(state))
end
end
end
if changed then return para end
end
return {
{ Para = run_todonotes }
}
--[[
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <https://unlicense.org>
]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment