‘The half minute which we daily devote to the winding-up of our watches is an exertion of labour almost insensible; yet, by the aid of a few wheels, its effect is spread over the whole twenty-four hours.’

Auto-generate "creator" PDF metadata in AUCTeX using yasnippet

Benjamin Slade

After struggling with some poorly-handled, apparently “reset” proofs introducing heaps of errors (despite my providing a .tex source) for the past few days,1 I thought about providing automated pdf-tags indicating creation tools used for my TeX-produced documents. Real, professionally-typeset documents deserve to have the tools used to produce them properly recognised in their metadata. So here’s a yasnippet which generates auto-populated hyperref options to generate a pdf-creator tag indicating the version of Emacs, AUCTeX, and distro used:

# -*- mode: snippet -*-
# name: version-hyperref
# key: hyperv
# --
\usepackage[pdfusetitle,
 pdfcreator={`(replace-regexp-in-string "_" "-"
  (concat (replace-regexp-in-string "\n" "" (substring (emacs-version) 0 (1- (cl-search "(" (emacs-version))) ))
     " with AUCTeX " (pkg-info-version-info 'auctex)
   (if (shell-command-to-string "type -p lsb_release > /dev/null")
      (concat
        " on "
      (substring (shell-command-to-string "lsb_release -sd") 1 (- (length (shell-command-to-string "lsb_release -sd")) 2))
        " ("
      (substring (shell-command-to-string "lsb_release -sr") 0 (- (length (shell-command-to-string "lsb_release -sr")) 1))
        " '"
      (substring (shell-command-to-string "lsb_release -sc") 0 (- (length (shell-command-to-string "lsb_release -sc")) 1))
         "'" " release, using the "
      (replace-regexp-in-string "\n$" "" (shell-command-to-string "uname -r")) " kernel)")
     (if (shell-command-to-string "type -p guix > /dev/null")
       (concat
         "on Guix System "
       (shell-command-to-string "guix system -V | awk 'NR==1{printf $5}'")
         " (using the "
       (replace-regexp-in-string "\n$" "" (shell-command-to-string "uname -r")) " kernel)")))))`}]{hyperref}

Snippets can execute elisp code placed between `...`. The version of Emacs (with some of the additional less-relevant information removed via substring combined with cl-search (for “(”, the beginning of the additional information)), and AUCTeX can easily be done using Emacs-internal functions, (emacs-version) and (pkg-info-version-info 'auctex), respectively.

For the operating-system information, we rely on external calls to the shell via Emacs’s shell-command-to-string function. Many distros will have lsb_release application (from the Linux Standard Base project) available (and presumably usually part of the base-install). Running lsb_release --help reveals a helpful set of options:

SYNOPSIS
        lsb_release [OPTION]...
OPTIONS
        −v, −−version
        Display the version of the LSB specification against which the distribution is compliant.

        −i, −−id
        Display the string id of the distributor.

        −d, −−description
        Display the single line text description of the distribution.

        −r, −−release
        Display the release number of the distribution.

        −c, −−codename
        Display the codename according to the distribution release.

        −a, −−all
        Display all of the above information.

        −s, −−short
        Display all of the above information in short output format.

        −h, −−help
        Display this message.
LSB Version:	1.0

And we can get various bits of information about the distribution out via passing different flags to lsb_release (combined with the -s “short description” flag).

Some distros don’t use the lsb_release, and looking at various methods neofetch employs to manage to suss out the distro was instructive. I added a method to allow for detecting the version of Guix System distribution, and it could be easily extended (in neofetch-style) to employ other methods for additional distros. (But the lsb_release method should handle the majority of distros.)

Finally, we get can the kernel version out via the ubiquitous uname application, via uname -r.

Thus calling this snippet on Void Linux results in a TeX block like this:

\usepackage[pdfusetitle,
pdfcreator={GNU Emacs 26.2 with AUCTeX 12.1.2 on Void Linux
(rolling 'void' release, using the 5.1.5-1 kernel)}]{hyperref}

(The hyperref option pdfusetitle will make use of the values of the TeX-defined \author{...} and \title={...} commands to populate the author and title pdf metadata. If you do anything funky with these fields (like adding a \thanks{...} command to your title), you may need to take out the pdfusetitle option and manually specify these tags via pdfauthor={...} etc.)

On Guix System (née GuixSD) the result will be something like:

\usepackage[pdfusetitle,
pdfcreator={GNU Emacs 26.2 with AUCTeX 12.1.2
on Guix System 1.0.1-1.8204295 (using the 5.1.2-gnu kernel)}]{hyperref}

An amusing side-discovery of putting this snippet together is that Arch Linux multiply – and insistently – reminds the uname caller of the distro the kernel belongs to. I.e., using this snippet on my Arch machine resulted in:

 \usepackage[pdfusetitle,
pdfcreator={GNU Emacs 26.2 with AUCTeX 12.1.2 on
Arch Linux (rolling 'n/a' release, using the 5.1.5-arch1-2-ARCH kernel)}]{hyperref}

  1. The horrifying reality of “professional” desktop publishing software stands in contrast to real professional documents produced in (La)TeX; and any resulting professionalism in the output of the former results from squeezing additional unpaid labour from researchers who have to correct the errors of “professional” typesetters. [return]