From 10cf3cd6ed7312ab63e8615eb93b7814bf4b24a2 Mon Sep 17 00:00:00 2001 From: TEC Date: Fri, 26 Mar 2021 02:39:13 +0800 Subject: [PATCH] Org: LaTeX, separate font choice from templates Now typefaces an be set with new #+options: fontset:?, which has default value given by org-latex-default-fontset. --- config.org | 267 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 182 insertions(+), 85 deletions(-) diff --git a/config.org b/config.org index 8232032..637525b 100644 --- a/config.org +++ b/config.org @@ -7010,38 +7010,51 @@ commands below are defined. #+end_src **** Class templates -We'll be setting up an nice preamble to use in a new default export class. -#+name: latex-fancy-preamble -#+begin_src LaTeX -\\usepackage[osf]{Alegreya} -\\usepackage{AlegreyaSans} -\\usepackage[scale=0.88]{sourcecodepro} +#+begin_src emacs-lisp :noweb no-export +(after! ox-latex + (add-to-list 'org-latex-classes + '("scr-article" + "\\documentclass{scrartcl}" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + (add-to-list 'org-latex-classes + '("blank" + "[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n[EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + (add-to-list 'org-latex-classes + '("bmc-article" + "\\documentclass[article,code,maths]{bmc}\n[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n[EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + (add-to-list 'org-latex-classes + '("bmc" + "\\documentclass[code,maths]{bmc}\n[NO-DEFAULT-PACKAGES]\n[NO-PACKAGES]\n[EXTRA]" + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))) -\\makeatletter -% Kerning around the A needs adjusting -\\DeclareRobustCommand{\\LaTeX}{L\\kern-.24em% - {\\sbox\\z@ T% - \\vbox to\\ht\\z@{\\hbox{\\check@mathfonts - \\fontsize\\sf@size\\z@ - \\math@fontsfalse\\selectfont - A}% - \\vss}% - }% - \\kern-.10em% - \\TeX} -% tabular lining figures in tables -\\renewcommand{\\tabular}{\\AlegreyaTLF\\let\\@halignto\\@empty\\@tabular} -\\makeatother - -\\usepackage[activate={true,nocompatibility},final,tracking=true,kerning=true,spacing=true,factor=2000]{microtype} - -\\setlength{\\parskip}{\\baselineskip} -\\setlength{\\parindent}{0pt} - -\\renewcommand{\\quote}{\\list{}{\\rightmargin\\leftmargin}\\item\\relax\\em} +(setq org-latex-default-class "scr-article" + org-latex-tables-booktabs t + org-latex-hyperref-template " +<> +") #+end_src + The =hyperref= setup needs to be handled separately however. #+name: latex-fancy-hyperref #+begin_src LaTeX @@ -7064,62 +7077,6 @@ The =hyperref= setup needs to be handled separately however. \\urlstyle{same} #+end_src -#+begin_src emacs-lisp :noweb no-export -(after! ox-latex - (add-to-list 'org-latex-classes - '("fancy-article" - "\\documentclass{scrartcl}\n -[DEFAULT-PACKAGES] -[PACKAGES] - -<> -" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) - (add-to-list 'org-latex-classes - '("blank" - "[NO-DEFAULT-PACKAGES] - [NO-PACKAGES] - [EXTRA]" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) - (add-to-list 'org-latex-classes - '("bmc-article" - "\\documentclass[article,code,maths]{bmc} - [NO-DEFAULT-PACKAGES] - [NO-PACKAGES] - [EXTRA]" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) - (add-to-list 'org-latex-classes - '("bmc" - "\\documentclass[code,maths]{bmc} - [NO-DEFAULT-PACKAGES] - [NO-PACKAGES] - [EXTRA]" - ("\\chapter{%s}" . "\\chapter*{%s}") - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))) - -(setq org-latex-default-class "fancy-article" - org-latex-tables-booktabs t - org-latex-hyperref-template " -<> -") -#+end_src - **** A cleverer preamble ***** Use case We often want particular snippets of LaTeX in our documents preambles. @@ -7269,6 +7226,7 @@ exists. #+end_src ***** Content-feature-preamble association + Initially this idea was implemented with an alist that associated a construct that would search the current Org file for an indication that some feature was needed, with a LaTeX snippet to be inserted in the preamble which would provide @@ -7548,6 +7506,145 @@ There are also some obsolete entries in the default value, specifically ("" "xcolor" nil) ; Generally useful ("" "hyperref" nil))) #+end_src +**** Font collections + +Using the lovely conditional preamble, I'll define a number of font collections +that can be used for LaTeX exports. Who knows, maybe I'll use it with other +export formats too at some point. + +To start with I'll create a default state variable and register =fontset= as part +of =#+options=. + +#+begin_src emacs-lisp +(defvar org-latex-default-fontset 'alegreya + "Fontset from `org-latex-fontsets' to use by default. +As cm (computer modern) is TeX's default, that causes nothing +to be added to the document. + +If \"nil\" no custom fonts will ever be used.") + +(eval '(cl-pushnew '(:latex-font-set nil "fontset" org-latex-default-fontset) + (org-export-backend-options (org-export-get-backend 'latex)))) +#+end_src + +Then a function is needed to generate a LaTeX snippet which applies the fontset. It +would be nice if this could be done for individual styles and use different +styles as the main document font. If the individual typefaces for a fontset are +defined individually as (=:serif=, =:sans=, =:mono=, and =:maths=). I can use those to +generate LaTeX for subsets of the full fontset. Then, if I don't let any fontset +names have =-= in them, I can use =-sans= and =-mono= as suffixes that specify the +document font to use. + +#+begin_src emacs-lisp +(defun org-latex-fontset-entry () + "Get the fontset spec of the current file. +Has format \"name\" or \"name-style\" where 'name' is one of +the cars in `org-latex-fontsets'." + (let ((fontset-spec + (symbol-name + (or (car (delq nil + (mapcar + (lambda (opt-line) + (plist-get (org-export--parse-option-keyword opt-line 'latex) + :latex-font-set)) + (cdar (org-collect-keywords '("OPTIONS")))))) + org-latex-default-fontset)))) + (cons (intern (car (split-string fontset-spec "-"))) + (when (cadr (split-string fontset-spec "-")) + (intern (concat ":" (cadr (split-string fontset-spec "-")))))))) + +(defun org-latex-fontset (&rest desired-styles) + "Generate a LaTeX preamble snippet which applies the current fontset for DESIRED-STYLES." + (let* ((fontset-spec (org-latex-fontset-entry)) + (fontset (alist-get (car fontset-spec) org-latex-fontsets))) + (if fontset + (concat + (mapconcat + (lambda (style) + (when (plist-get fontset style) + (concat (plist-get fontset style) "\n"))) + desired-styles + "") + (when (memq (cdr fontset-spec) desired-styles) + (pcase (cdr fontset-spec) + (:serif nil) + (:sans "\\renewcommand{\\familydefault}{\\sfdefault}\n") + (:mono "\\renewcommand{\\familydefault}{\\ttdefault}\n")))) + (error "Font-set %s is not provided in org-latex-fontsets" (car fontset-spec))))) +#+end_src + +Now that all the functionality has been implemented, we should hook it into our +preamble generation. + +#+begin_src emacs-lisp +(add-to-list 'org-latex-conditional-features '(org-latex-default-fontset . custom-font) t) +(add-to-list 'org-latex-feature-implementations '(custom-font :snippet (org-latex-fontset :serif :sans :mono)) t) +(add-to-list 'org-latex-feature-implementations '(!custom-maths-font :when (custom-font maths) :snippet (org-latex-fontset :maths)) t) +#+end_src + +Finally, we just need to add some fonts. + +#+begin_src emacs-lisp +(defvar org-latex-fontsets + '((cm nil) ; computer modern + (ibm + :serif "\\usepackage{plex-serif}" + :sans "\\usepackage{plex-sans}" + :mono "\\usepackage{plex-mono}" + :maths "% maths TBD") + (newpx + :serif "\\usepackage{newpxtext}" + :sans "\\usepackage{gillius}" + :mono "\\usepackage[scale=0.9]{sourcecodepro}" + :maths "\\usepackage[varbb]{newpxmath}") + (kp + :serif "\\usepackage{kpfonts}") + (alegreya + :serif "\\usepackage[osf]{Alegreya}" + :sans "\\usepackage{AlegreyaSans}" + :mono "\\usepackage[scale=0.88]{sourcecodepro}" + :maths "\\usepackage[varbb]{newpxmath}")) + "Alist of fontset specifications. +Each car is the name of the fontset (which cannot include \"-\"). + +Each cdr is a plist with (optional) keys :serif, :sans, :mono, and :maths. +A key's value is a LaTeX snippet which loads such a font.") +#+end_src + +When we're using Alegreya we can apply a lovely little tweak to =tabular= which +(locally) changes the figures used to lining fixed-width. + +#+begin_src emacs-lisp +(add-to-list 'org-latex-conditional-features '((string= (car (org-latex-fontset-entry)) "alegreya") . alegreya-typeface)) +(add-to-list 'org-latex-feature-implementations '(alegreya-typeface) t) +(add-to-list 'org-latex-feature-implementations '(!alegreya-tabular-figures :when (alegreya-typeface table) :snippet " +\\makeatletter +% tabular lining figures in tables +\\renewcommand{\\tabular}{\\AlegreyaTLF\\let\\@halignto\\@empty\\@tabular} +\\makeatother\n") t) +#+end_src + +Due to the Alegreya's metrics, the =\LaTeX= symbol doesn't quite look right. We +can correct for this by redefining it with subtlety shifted kerning. + +#+begin_src emacs-lisp +(add-to-list 'org-latex-conditional-features '("LaTeX" . latex-symbol)) +(add-to-list 'org-latex-feature-implementations '(latex-symbol :when alegreya-typeface :snippet " +\\makeatletter +% Kerning around the A needs adjusting +\\DeclareRobustCommand{\\LaTeX}{L\\kern-.24em% + {\\sbox\\z@ T% + \\vbox to\\ht\\z@{\\hbox{\\check@mathfonts + \\fontsize\\sf@size\\z@ + \\math@fontsfalse\\selectfont + A}% + \\vss}% + }% + \\kern-.10em% + \\TeX} +\\makeatother\n") t) +#+end_src + **** Cover page To make a nice cover page, a simple method that comes to mind is just redefining @@ -7986,7 +8083,7 @@ Once the idea of having the look of the LaTeX document produced match the current Emacs theme, I was enraptured. The result is the pseudo-class ~chameleon~. #+begin_src emacs-lisp (after! ox - (defvar ox-chameleon-base-class "fancy-article" + (defvar ox-chameleon-base-class "scr-article" "The base class that chameleon builds on") (defvar ox-chameleon--p nil