From 6d0cd7eaf3ed9435a0d45354f7b8cdb7c40e4fca Mon Sep 17 00:00:00 2001 From: Alex Povel Date: Thu, 29 Oct 2020 18:28:21 +0100 Subject: [PATCH] Switch to Lua implementation --- .gitlab-ci.yml | 55 ------------------------------- chapters/frontmatter/colophon.tex | 19 ++--------- cookbook.cls | 13 +++++--- lua/envvar_newcommands.lua | 47 ++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 77 deletions(-) create mode 100644 lua/envvar_newcommands.lua diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ea55de7..8ff6ba8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,53 +19,6 @@ default: # only: # - tags -# Define some stages so to get rid of 'Test' as default: -stages: - - prepare - - build - -insert_git_metadata: - stage: prepare - script: - # Declare associative (-A) array with predefined GitLab CI variables. - # The keys correspond to the command names found in the LaTeX code: - - | - declare -A GITINFO=( - [GitRefName]=$CI_COMMIT_REF_NAME - [GitShortSHA]=$CI_COMMIT_SHORT_SHA - ) - - # Iterate over array and replace the LaTeX commands, - # e.g. \newcommand*{\GitRefName}{n.a.}, - # with - # e.g. \newcommand*{\GitRefName}{v1.00}. - # Use double quotes to enable variable expansion. - # Employ and use capture group \1 to replace current LaTeX command - # (given by key in array) by corresponding value for that key. - # Run on all class files (cls) found. Only do it once (no global option to sed), - # for safety: the relevant \newcommand should only occur once. - # Checking with `grep` is simpler/clearer than using sed's `q` option. - - | - for k in "${!GITINFO[@]}" - do - grep --silent "${k}" *.cls || \ - { \ - echo "Failed to find (and therefore replace) '${k}'." && \ - exit 1; \ - }; - sed --in-place "s~\(newcommand\*{\\\\$k}\){.*}~\1{${GITINFO[$k]}}~" *.cls - done - # Hand the processed *.cls file(s) to the next stage: - artifacts: - # Overrides default - paths: - # Hand over the modified file, otherwise the depending stage only gets the - # default non-modified one. - - "*.cls" - needs: [] - # This *shouldn't* fail, but failure is not catastrophic: - allow_failure: true - build_latex: stage: build script: @@ -77,10 +30,6 @@ build_latex: # Configure latexmk tool using '.latexmkrc' in project root. # After the run, display the relevant rules (for debugging). - latexmk --rules - needs: - - job: insert_git_metadata - # Also get that job's artifacts (like what `dependencies` used to do): - artifacts: true build_pandoc: stage: build @@ -95,7 +44,3 @@ build_pandoc: --metadata=date:$(date --iso-8601) \ --output=${README_BASENAME}.pdf \ ${README_BASENAME}.md - # Despite being in a later stage, specifying that this particular jobs 'needs' - # no other job allows it run immediately, leading to concurrent running of stages - # which would otherwise run serially, speeding up the pipeline - needs: [] diff --git a/chapters/frontmatter/colophon.tex b/chapters/frontmatter/colophon.tex index c823c8d..10030f1 100644 --- a/chapters/frontmatter/colophon.tex +++ b/chapters/frontmatter/colophon.tex @@ -4,11 +4,6 @@ \thispagestyle{empty} \vspace*{\fill} -% Use URL as wrapper to escape special chars in tags, mainly underscores like "Fix_It" -% \urlstyle takes rm, tt etc. -% https://tex.stackexchange.com/a/20891/120853 -\DeclareUrlCommand{\EscWrapper}{\urlstyle{tt}} - \begingroup% Keep changes local to this group \hypersetup{hidelinks} \color{g2} @@ -35,18 +30,8 @@ \\ \TransCompiledOn{} & \textbf{\DTMnow{}}\\ \addlinespace - % Expand Argument first, else we print \GitRefName etc. literally. - % Then wrap into special command to escape chars (like underscores): - Git Ref.\ Name & - \texttt{\textbf{% - \expandafter\EscWrapper\expandafter{\GitRefName}% - }} - \\ - Git Short SHA & - \texttt{% - \expandafter\EscWrapper\expandafter{\GitShortSHA}% - } - \\ + Git Version & \texttt{\textbf{\GitRefName{}}} \\ + Git Hash & \texttt{\GitShortSHA{}} \\ \addlinespace Engine & \prettybanner{}\\ \LaTeX{} Version & \hologo{\fmtname} (\fmtversion)\\ diff --git a/cookbook.cls b/cookbook.cls index a072578..7c5e120 100644 --- a/cookbook.cls +++ b/cookbook.cls @@ -351,11 +351,14 @@ % https://tex.stackexchange.com/a/350583/120853 \StrSubstitute{\shortbanner}{\detokenize{LuaTeX}}{\hologo{LuaTeX}}[\prettybanner] -% These are inserted into the PDF metadata. -% In the build process, the defaults should be replaced by the respective, -% current values (see gitlab-ci.yml / your CI script for this) -\newcommand*{\GitRefName}{n.a.} -\newcommand*{\GitShortSHA}{n.a.} +% Generate some control sequences which contain metadata, which can be inserted e.g. +% into the PDF metadata (e.g. to have the exact git commit SHA of a build). +% Do not use Lua code in `\directlua`, way too annoying with all the escaping (see: +% https://www.overleaf.com/learn/latex/Articles/An_Introduction_to_LuaTeX_(Part_2):_Understanding_%5Cdirectlua +% ). Just execute an outside, proper file. +\directlua{% + dofile("lua/envvar_newcommands.lua") +} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lua/envvar_newcommands.lua b/lua/envvar_newcommands.lua new file mode 100644 index 0000000..25bb246 --- /dev/null +++ b/lua/envvar_newcommands.lua @@ -0,0 +1,47 @@ +--[[ + The following import is not required since in LuaTeX's `\directlua` environment, + `token` is already available. However, this is nice to keep linters from complaining + about an undefined variable. +--]] +local token = require("token") + +--[[ + Trying to incorporate dynamic values into certain newcommand macros. Their + contents are set at build-time according to environment variables. This is useful + for automatic workflows in CI environments. See also: + https://tex.stackexchange.com/a/1739/120853. + An alternative to using environment variables are command line arguments: + https://tex.stackexchange.com/a/18813/120853 + However, this seems more error-prone and requires more steps, e.g. piping arguments + to `lualatex` through `latexmk` first, etc. + The previous approach was to `sed` for certain `newcommand` definitions in an + additional CI job. This was much more error-prone (bash scripting) and less + easily expanded than the below approach. + LuaTeX provides excellent access to TeX, making this implementation much easier. +--]] + +local missing = "n.a." + +-- Environment variables as used e.g. in GitLab CI: +local macros_to_envvars = { + GitRefName = "CI_COMMIT_REF_NAME", + GitShortSHA = "CI_COMMIT_SHORT_SHA", +} + +for macro_name, env_var in pairs(macros_to_envvars) do + local content = os.getenv(env_var) + if content == nil then + content = missing + end + --[[ + The `content` can contain unprintable characters, like underscores in git branch + names. Towards this end, use detokenize in the macro itself, which will make all + characters printable (assigns category code 12). Use `\string` to escape the + backslashes so they make it into the Lua interpreter intact. See also: + https://www.overleaf.com/learn/latex/Articles/An_Introduction_to_LuaTeX_(Part_2):_Understanding_%5Cdirectlua + --]] + local escaped_content = "\\detokenize{"..content.."}" + + -- Set a macro, like `\newcommand`, see also: https://tex.stackexchange.com/a/450892/120853 + token.set_macro(macro_name, escaped_content) +end