272 lines
7.7 KiB
TeX
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
|
|
% }
|
|
}
|