formelsammlung/src/pkg/mqref.sty
2025-03-02 00:32:49 +01:00

272 lines
7.7 KiB
TeX

\ProvidesPackage{mqref}
\RequirePackage{mqlua}
\RequirePackage{mqfqname}
\RequirePackage{mqquantity}
\newcommand\luaDoubleFieldValue[3]{%
\directlua{
if #1 \string~= nil and #1[#2] \string~= nil and #1[#2][#3] \string~= nil then
tex.sprint(#1[#2][#3])
return
end
luatexbase.module_warning('luaDoubleFieldValue', 'Invalid indices to `#1`: `#2` and `#3`');
tex.sprint("???")
}%
}
% LABELS
\begin{luacode}
-- Contains <label>: <true> for defined labels
-- This could later be extended to contain a list of all fqnames that
-- reference the label to make a network of references or sth like that
labels = labels or {}
-- Table of all labels that dont exist but were referenced
-- <label>: <fqname where it was referenced>
missingLabels = {}
-- aux file with labels for completion in vim
labelsFilepath = OUTDIR .. "/labels.txt" or "/tmp/labels.txt"
labelsLuaFilepath = OUTDIR .. "/labels.lua.txt" or "/tmp/labels.lua.txt"
-- aux file for debugging
missingLabelsFilepath = OUTDIR .. "/missing-labels.txt" or "/tmp/missing-labels.txt"
function labelExists(label)
if labels[label] == nil then return false else return true end
end
function labelSet(label)
labels[label] = true
end
if fileExists(labelsLuaFilepath) then
labels = dofile(labelsLuaFilepath) or {}
end
\end{luacode}
\begin{luacode*}
function serializeKeyValues(tbl)
local result = {}
-- sort by keys making a new table with keys as values and sorting that
for k, v in pairs(tbl) do
table.insert(result, k)
end
table.sort(result)
s = ""
for i, k in ipairs(result) do
s = s .. k .. "\tin\t" .. tbl[k] .. "\n"
end
return s
end
function dumpTableKeyValues(tableobj, filepath)
table.sort(tableobj)
local file = io.open(filepath, "w")
file:write(serializeKeyValues(tableobj))
file:close()
end
function serializeKeys(tbl)
local result = {}
-- sort by keys making a new table with keys as values and sorting that
for k, v in pairs(tbl) do
table.insert(result, k)
end
table.sort(result)
return table.concat(result, "\n")
end
function dumpTableKeys(tableobj, filepath)
table.sort(tableobj)
local file = io.open(filepath, "w")
file:write(serializeKeys(tableobj))
file:close()
end
\end{luacode*}
\AtEndDocument{\directlua{dumpTableKeys(labels, labelsFilepath)}}
\AtEndDocument{\directlua{dumpTable(labels, labelsLuaFilepath)}}
\AtEndDocument{\directlua{dumpTableKeyValues(missingLabels, missingLabelsFilepath)}}
% Set a label and write the label to the aux file
% [1]
\newcommand\mqfqname@label[1][\fqname]{
\label{#1}
\directlua{labelSet(\luastring{#1})}
}
% REFERENCES
% All xyzRef commands link to the key using the translated name
% Uppercase (XyzRef) commands have different link texts, but the same link target
% 1: key/fully qualified name (without qty/eq/sec/const/el... prefix)
\begin{luacode*}
function hyperref(target, text)
local s = ""
if labelExists(target) then
s = "\\hyperref[" .. target .. "]"
else -- mark as missing and referenced in current section
missingLabels[target] = fqnameGet()
end
if text == nil or text == "" then
tex.sprint(s .. "{" .. tlGetFallbackCurrent(target) .. "}")
else
tex.sprint(s .. "{" .. text .. "}")
end
end
\end{luacode*}
% Equations/Formulas
% \newrobustcmd{\fqEqRef}[1]{%
\newrobustcmd{\fAbsRef}[2][]{%
\directlua{hyperref(\luastring{#2}, \luastring{#1})}%
}
\newcommand{\fRef}[2][]{
\directlua{hyperref(translateRelativeFqname(\luastring{#2}), \luastring{#1})}
}
% [1]: link text
% 2: number of steps to take up
% 3: link target relative to the previous fqname section
\newcommand{\mqfqname@fRelRef}[3][1]{
\directlua{
local N = fqnameGetDepth()
luatexbase.module_warning('fRelRef', '(N=' .. N .. ') #2');
if N > #2 then
local upfqname = fqnameGetN(N-#2)
hyperref(upfqname .. \luastring{:#3}, \luastring{#1})
else
luatexbase.module_warning('fUpRef', 'fqname depth (N=' .. N .. ') too low for fUpRef if #1');
end
}
}
\newcommand{\fThisRef}[2][]{\mqfqname@fRelRef[#1]{0}{#2}}
\newcommand{\fUpRef}[2][]{\mqfqname@fRelRef[#1]{1}{#2}}
\newcommand{\fUppRef}[2][]{\mqfqname@fRelRef[#1]{2}{#2}}
% Quantities
% <symbol>
\newrobustcmd{\qtyRef}[2][]{%
% \edef\tempname{\luaDoubleFieldValue{quantities}{"#1"}{"fqname"}}%
% \hyperref[qty:#1]{\GT{\tempname}}%
\directlua{hyperref(quantityGetFqname(\luastring{#2}), \luastring{#1})}
}
% <symbol> <name>
\newrobustcmd{\QtyRef}[2][]{%
$\quantity@getSymbol{#2}$ \qtyRef{#2}{}%
}
% Constants
% <name>
\newrobustcmd{\constRef}[2][]{%
% \edef\tempname{\luaDoubleFieldValue{constants}{"#1"}{"linkto"}}%
% \hyperref[const:#1]{\GT{\tempname}}%
\directlua{hyperref(constantGetFqname(\luastring{#2}), \luastring{#1})}
}
% <symbol> <name>
\newrobustcmd{\ConstRef}[2][]{%
$\constant@getSymbol{#2}$ \constRef{#2}%
}
% Element from periodic table
% <symbol>
\newrobustcmd{\elRef}[1]{%
\hyperref[el:#1]{{\color{fg0}#1}}%
}
% <name>
\newrobustcmd{\ElRef}[1]{%
\hyperref[el:#1]{\GT{el:#1}}%
}
% "LABELS"
% These currently do not place a label,
% instead they provide an alternative way to reference an existing label
\begin{luacode}
absLabels = absLabels or {}
abbrLabels = abbrLabels or {}
function absLabelAdd(key, target, translationKey)
absLabels[key] = {
fqname = (target == "") and fqnameGet() or target,
translation = translationKey or ""
}
end
function absLabelGetTarget(key)
if absLabels[key] then
return absLabels[key].fqname or "abs:" .. key
else
return "abs:" .. key
end
end
function absLabelGetTranslationKey(key)
if absLabels[key] then
return absLabels[key].translation or ""
else
return ""
end
end
function abbrLabelAdd(key, target, label)
abbrLabels[key] = {
abbr = label,
fqname = (target == "") and fqnameGet() or target
}
end
function abbrLabelGetTarget(key)
if abbrLabels[key] then
return abbrLabels[key].fqname or "abbr:" .. key
else
return "abbr:" .. key
end
end
function abbrLabelGetAbbr(key)
if abbrLabels[key] then
return abbrLabels[key].abbr or ""
else
return ""
end
end
\end{luacode}
% [1]: translation key, if different from target
% 2: target (fqname to point to), if left empty will use current fqname
% 3: key
\newcommand{\absLink}[3][]{
\directLuaAuxExpand{
absLabelAdd(\luastring{#3}, \luastring{#2}, \luastring{#1})
}
}
% [1]: target (fqname to point to)
% 2: key
% 3: label (abbreviation)
\newcommand{\abbrLink}[3][]{
\directLuaAuxExpand{
abbrLabelAdd(\luastring{#2}, \luastring{#1}, \luastring{#3})
}
}
% [1]: text
% 2: key
\newcommand{\absRef}[2][]{%
\directlua{
local text = (\luastring{#1} == "") and absLabelGetTranslationKey(\luastring{#2}) or \luastring{#1}
if text \string~= "" then
text = tlGetFallbackCurrent(text)
end
hyperref(absLabelGetTarget(\luastring{#2}, text))
}%
}
\newrobustcmd{\abbrRef}[1]{%
\directlua{hyperref(abbrLabelGetTarget(\luastring{#1}), abbrLabelGetAbbr(\luastring{#1}))}
% if abbrLabels["#1"] == nil then
% tex.sprint(string.sanitize(\luastring{#1}) .. "???")
% else
% tex.sprint("\\hyperref[" .. abbrLabels["#1"]["fqname"] .. "]{" .. abbrLabels["#1"]["abbr"] .. "}")
% end
% }
}