186 lines
5.7 KiB
Lua
186 lines
5.7 KiB
Lua
--[[
|
|
|
|
This file defines an Acronym and the Acronyms table.
|
|
|
|
--]]
|
|
|
|
|
|
local Helpers = require("acronyms_helpers")
|
|
|
|
|
|
-- Define an Acronym with some default values
|
|
Acronym = {
|
|
-- The acronym's key, or label. Used to identify it. Must be unique.
|
|
key = nil,
|
|
-- The acronym's short form (i.e., the acronym itself).
|
|
shortname = nil,
|
|
-- The acronym's definition, or description.
|
|
longname = nil,
|
|
-- The number of times this acronym was used.
|
|
occurrences = 0,
|
|
-- The order in which acronyms are defined. 1=first, 2=second, etc.
|
|
definition_order = nil,
|
|
-- The order in which acronyms appear in the document. 1=first, nil=never.
|
|
usage_order = nil,
|
|
}
|
|
|
|
|
|
-- Create a new Acronym
|
|
function Acronym:new(object)
|
|
setmetatable(object, self)
|
|
self.__index = self
|
|
|
|
-- Check that important attributes are non-nil
|
|
assert(object.shortname ~= nil,
|
|
"An Acronym shortname should not be nil!")
|
|
assert(object.longname ~= nil,
|
|
"An Acronym longname should not be nil!")
|
|
|
|
-- If the key is not set, we want to use the shortname instead.
|
|
-- (Most of the time, the key is the shortname in lower case anyway...)
|
|
object.key = object.key or object.shortname
|
|
|
|
return object
|
|
end
|
|
|
|
|
|
-- Debug (helper) function
|
|
function Acronym.__tostring(acronym)
|
|
local str = "Acronym{"
|
|
str = str .. "key=" .. acronym.key .. ";"
|
|
str = str .. "short=" .. acronym.shortname .. ";"
|
|
str = str .. "long=" .. acronym.longname .. ";"
|
|
str = str .. "occurrences=" .. acronym.occurrences .. ";"
|
|
str = str .. "definition_order=" .. tostring(acronym.definition_order) .. ";"
|
|
str = str .. "usage_order=" .. tostring(acronym.usage_order)
|
|
str = str .. "}"
|
|
return str
|
|
end
|
|
|
|
|
|
-- Increment the count of occurrences
|
|
function Acronym:incrementOccurrences()
|
|
self.occurrences = self.occurrences + 1
|
|
end
|
|
|
|
|
|
-- Is this the acronym's first occurrence?
|
|
function Acronym:isFirstUse()
|
|
return self.occurrences <= 1
|
|
end
|
|
|
|
|
|
-- The Acronyms database.
|
|
Acronyms = {
|
|
-- The table that contains all acronyms, indexed by their key.
|
|
acronyms = {},
|
|
|
|
-- The current "definition_order" value.
|
|
-- Each time a new acronym is defined, we increment this value to keep
|
|
-- count of the order in which acronyms are defined.
|
|
current_definition_order = 0,
|
|
|
|
-- Access to the `Acronym` class, if necessary.
|
|
Acronym = Acronym,
|
|
}
|
|
|
|
|
|
-- Get the Acronym with the given key, or nil if not found.
|
|
function Acronyms:get(key)
|
|
return self.acronyms[key]
|
|
end
|
|
|
|
|
|
-- Does the table contains the given key?
|
|
function Acronyms:contains(key)
|
|
return self:get(key) ~= nil
|
|
end
|
|
|
|
|
|
-- Add a new acronym to the table. Also handles duplicates.
|
|
function Acronyms:add(acronym, on_duplicate)
|
|
assert(acronym.key ~= nil,
|
|
"The acronym key should not be nil!")
|
|
assert(on_duplicate ~= nil,
|
|
"on_duplicate should not be nil!")
|
|
|
|
-- Handling duplicate keys
|
|
if self:contains(acronym.key) then
|
|
if on_duplicate == "replace" then
|
|
-- Do nothing, let us replace the previous acronym.
|
|
elseif on_duplicate == "keep" then
|
|
-- Do nothing, but do not replace: we return here.
|
|
return
|
|
elseif on_duplicate == "warn" then
|
|
-- Warn, and do not replace.
|
|
warn("Duplicate key: ", acronym.key)
|
|
return
|
|
elseif on_duplicate == "error" then
|
|
-- Stop execution.
|
|
error("Duplicate key: " .. acronym.key)
|
|
else
|
|
error("Unrecognized option on_duplicate = " .. on_duplicate)
|
|
end
|
|
end
|
|
|
|
self.current_definition_order = self.current_definition_order + 1
|
|
acronym.definition_order = self.current_definition_order
|
|
self.acronyms[acronym.key] = acronym
|
|
end
|
|
|
|
|
|
-- Populate the Acronyms database from a YAML metadata
|
|
function Acronyms:parseFromMetadata(metadata, on_duplicate)
|
|
-- We expect the acronyms to be in the `metadata.acronyms.keys` field.
|
|
if not (metadata and metadata.acronyms and metadata.acronyms.keys) then
|
|
return
|
|
end
|
|
-- This field should be a Pandoc "MetaList" (so we can iter over it).
|
|
if not Helpers.isMetaList(metadata.acronyms.keys) then
|
|
error("The acronyms.keys should be a list!")
|
|
end
|
|
|
|
-- Iterate over the defined acronyms. We use `ipairs` since we want to
|
|
-- keep their original order (useful for the `definition_order`!).
|
|
for _, v in ipairs(metadata.acronyms.keys) do
|
|
-- Remember that each of these values can be nil!
|
|
-- By using `and`, we make sure that `stringify` is applied on non-nil.
|
|
local key = v.key and pandoc.utils.stringify(v.key)
|
|
local shortname = v.shortname and pandoc.utils.stringify(v.shortname)
|
|
local longname = v.longname and pandoc.utils.stringify(v.longname)
|
|
local acronym = Acronym:new{
|
|
key = key,
|
|
shortname = shortname,
|
|
longname = longname,
|
|
}
|
|
Acronyms:add(acronym, on_duplicate)
|
|
end
|
|
end
|
|
|
|
|
|
-- Populate the Acronyms database from a YAML file
|
|
-- Inspired from https://github.com/dsanson/pandoc-abbreviations.lua/
|
|
function Acronyms:parseFromYamlFile(filepath, on_duplicate)
|
|
assert(filepath ~= nil,
|
|
"filepath must not be nil!")
|
|
|
|
-- First, read the file's content.
|
|
local file = io.open(filepath, "r")
|
|
if file == nil then
|
|
warn("File ", filepath, " could not be read! (does not exist?)")
|
|
return
|
|
end
|
|
local content = file:read("*a")
|
|
file:close()
|
|
|
|
-- Secondly, use Pandoc's read ability to parse the content.
|
|
-- Pandoc does not know how to read YAML, so we'll trick it by
|
|
-- asking to parse Markdown instead (since the Markdown's metadata
|
|
-- is YAML anyway).
|
|
local metadata = pandoc.read(content, "markdown").meta
|
|
|
|
-- Finally, read the metadata as usual.
|
|
self:parseFromMetadata(metadata, on_duplicate)
|
|
end
|
|
|
|
return Acronyms
|