PAaSO/Midterm assesment/_extensions/acronyms/acronyms.lua

186 lines
5.7 KiB
Lua
Raw Normal View History

2026-08-19 09:27:27 +02:00
--[[
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