LaTeX

AuCTeX is the best LaTeX editing suite of all time.

Load Packages

(use-package tex
  :ensure auctex
  :demand
  :bind
  <<do.latex/keys>>
  :init
  (require 'texmathp)
  (require 'preview)
  <<do.latex/settings>>
  <<do.latex/fontification>>
  <<do.latex/linebreaks>>
  <<do.latex/synctex>>
  <<do.latex/xelatex>>
  <<do.latex/custom>>
  :config
  <<do.latex/hooks>>)

General settings

We generally want to autosave and output to PDF. Last line autosaves on compilation with C-c C-c.

(setq-default TeX-master nil)
(setq-default TeX-command-extra-options "--shell-escape")
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq TeX-PDF-mode t)
(setq reftex-plug-into-AUCTeX t)
(setq TeX-save-query nil)
(setq TeX-error-overview-open-after-TeX-run t)
(setq TeX-electric-math '("$" . "$"))
(setq TeX-electric-sub-and-superscript t)

The section headers should be rendered using the Computer Modern font

(require 'font-latex)
(set-face-attribute 'font-latex-sectioning-5-face nil :family "Fira Sans")
(setq font-latex-fontify-sectioning 1.2)
(font-latex-update-sectioning-faces)

When we insert $, want to insert LaTeX Math \(\LaTeX\) symbols instead.

(defun do.latex/insert-math ()
  (interactive)
  (insert "\\(\\)")
  (backward-char 2))

Finally, fix some collisions with the company completion engine and add other keybindings

(:map TeX-mode-map (("<tab>" . do.completion/tab-indent-or-complete)
                    ("$" . do.latex/insert-math)))

Fix auto-fill with inline math

More info here.

(setq-default LaTeX-fill-break-at-separators (quote (\\\( \\\[ \\\])))

LSP

This is currently unused.

(require 'lsp-mode)

(defun do.latex.lsp/texlab-cmd ()
  (list (concat (file-name-as-directory initel-directory) "random/texlab")))

(lsp-register-client
   (make-lsp-client :new-connection
                    (lsp-stdio-connection
                     #'do.latex.lsp/texlab-cmd)
                    :major-modes '(tex-mode yatex-mode latex-mode LaTeX-mode)
                    :server-id 'texlab
                    :notification-handlers
                    (lsp-ht
                     ("window/progress"
                      'lsp-latex-window-progress))))


;;(add-hook 'LaTeX-mode-hook #'lsp)

SyncTeX and view programs

(setq TeX-source-correlate-method 'synctex)
(setq TeX-source-correlate-start-server t)
(add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode)
;; if we want to use okular, enable it as View program
(when (and (boundp 'do.minimal/pdf-reader)
           (string= "okular" do.minimal/pdf-reader))
  (setq TeX-view-program-selection
        '(((output-dvi has-no-display-manager)
           "dvi2tty")
          ((output-dvi style-pstricks)
           "Okular")
          (output-dvi "Okular")
          (output-pdf "Okular")
          (output-html "xdg-open"))))

Hooks

First line adds hook from previous section. The last hook we add sets the default face for prose to a serif font.

(add-hook 'LaTeX-mode-hook 'toggle-serif)
(add-hook 'LaTeX-mode-hook 'flyspell-mode)
(add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
(add-hook 'LaTeX-mode-hook 'visual-line-mode)

;; set up company completions (i.e., disable dabbrev)

(defun do.latex/setup-completion ()
  "Enable auctex-specific completion functions exclusively."
  (make-variable-buffer-local 'company-backends)
  (setq company-backends '(company-auctex-labels
                           company-auctex-bibs
                           (company-auctex-macros company-auctex-symbols company-auctex-environments)
                           (company-math-symbols-latex company-math-symbols-unicode)
                           company-yasnippet)))

(add-hook 'LaTeX-mode-hook #'do.latex/setup-completion)

XeLaTeX

(add-to-list 'TeX-command-list '("XeLaTeX" "%`xelatex %(extraopts)%(mode)%' %t" TeX-run-TeX nil t))

Latexmk

(use-package auctex-latexmk
  :ensure t
  :demand
  :init
  (auctex-latexmk-setup))

Spell checking

(use-package ispell
  :demand
  :init
  (setq-default ispell-program-name "hunspell")
  (setq ispell-really-hunspell t)
  <<do.latex.spelling/dicts>>
  <<do.latex.spelling/dict-en>>)

Dictionaries

(setq ispell-dictionary-base-alist
      '(("en_US"
         "[a-zA-Z]" "[^a-zA-Z]" "[']" nil
         ("-d" "en_US" "-i" "iso-8859-1") nil iso-8859-1)
        ("en_GB"
         "[a-zA-Z]" "[^a-zA-Z]" "[']" nil
         ("-d" "en_GB" "-i" "iso-8859-1") nil iso-8859-1)
        ("de_DE"
         "[a-zäöüßA-ZÄÖÜ]" "[^a-zäöüßA-ZÄÖÜ]" "[']" nil
         ("-d" "de_DE" "-i" "iso-8859-1") nil iso-8859-1)))

Activate a specific Dictionary after loading

(eval-after-load "ispell"
  (progn
    (setq ispell-dictionary "en_US")
    (setq ispell-silently-savep t)))

Emacs and IEEEeqnarray

We want emacs to play nice with the IEEEtran and IEEEtrantools packages. We also define some keyboard shortcuts. Stefan Moser's typeset_equations comes with a few keyboard bindings, but rather than using the recommended fset... commands to insert a new IEEEeqnarray, I want to insert them using snippets.

Snippets

The two snippets I defined are ieq.yasnippet to insert a regular IEEEeqnarray with argument {rCl} and ieqs.yasnippet to insert the starred version. The recommended keybindings are also defined within the snippet: I'm binding C-c i to insert the regular array nad C-c o to insert the starred array.

The ieq snippet looks like this:

# -*- mode: snippet -*-
# contributor: Dennis Ogbe <[email protected]>
# key: ieq
# group: math
# name: \begin{IEEEeqnarray}{rCl} ... \end{IEEEeqnarray}
# binding: C-c i
# --
\begin{IEEEeqnarray}{${1:rCl}}
\label{${2:"waiting for reftex-label call..."$(unless yas/modified-p (reftex-label nil 'dont-insert))}}
$0
\end{IEEEeqnarray}

LaTeX environments

Make AuCTeX aware of the IEEEeqnarray as a math environment.

(TeX-add-style-hook "latex"
                    (lambda ()
                      (LaTeX-add-environments
                       '("IEEEeqnarray" LaTex-env-label)
                       '("IEEEeqnarray*"))))
(add-hook 'LaTeX-mode-hook
          '(lambda ()
             (add-to-list 'font-latex-math-environments "IEEEeqnarray")
             (add-to-list 'font-latex-math-environments "IEEEeqnarray*")
             ;; need this  for electric subscripts
             (setq texmathp-tex-commands
                   '(("IEEEeqnarray" env-on)
                     ("IEEEeqnarray*" env-on)))
             (texmathp-compile)))

ispell and reftex

We also want to make ispell and reftex aware of IEEEeqnarray. The variable ispell-tex-skip-alists contains two lists with patterns for ispell to skip. Since Moser's proposed list is longer than the default emacs one, we'll just copy the whole list.

(setq ispell-tex-skip-alists
      '((("%\\[" . "%\\]")
         ;; All the standard LaTeX keywords from L. Lamport's guide:
         ;; \cite, \hspace, \hspace*, \hyphenation, \include, \includeonly, \input,
         ;; \label, \nocite, \rule (in ispell - rest included here)
         ("\\\\addcontentsline"              ispell-tex-arg-end 2)
         ("\\\\psfrag"                       ispell-tex-arg-end-psfrag 0)
         ("\\\\add\\(tocontents\\|vspace\\)" ispell-tex-arg-end)
         ("\\\\\\([aA]lph\\|arabic\\)"       ispell-tex-arg-end)
         ("\\\\author"                       ispell-tex-arg-end)
         ("\\\\bibliographystyle"            ispell-tex-arg-end)
         ("\\\\bibliography"                 ispell-tex-arg-end)
         ("\\\\bstctlcite"                   ispell-tex-arg-end)
         ("\\\\eqref"                        ispell-tex-arg-end)
         ("\\\\thref"                        ispell-tex-arg-end)
         ("\\\\label"                        ispell-tex-arg-end)
         ("\\\\makebox"                      ispell-tex-arg-end 0)
         ("\\\\document\\(class\\|style\\)" .
          "\\\\begin[ \t\n]*{[ \t\n]*document[ \t\n]*}"))
        (;; delimited with \begin.  In ispell: displaymath, eqnarray, eqnarray*,
         ;; equation, minipage, picture, tabular, tabular* (ispell)
         ("\\(figure\\|table\\)\\*?"  ispell-tex-arg-end 0)
         ("list"                      ispell-tex-arg-end 2)
         ("IEEEeqnarray\\*?". "\\\\end[ \t\n]*{[ \t\n]*IEEEeqnarray\\*?[ \t\n]*}")
         ("IEEEeqnarraybox[tm]?\\*?". "\\\\end[ \t\n]*{[ \t\n]*IEEEeqnarraybox[tm]?\\*?[ \t\n]*}")
         ("program"         . "\\\\end[ \t\n]*{[ \t\n]*program[ \t\n]*}")
         ("verbatim\\*?"    . "\\\\end[ \t\n]*{[ \t\n]*verbatim\\*?[ \t\n]*}")
         ("gather\\*?"      . "\\\\end[ \t\n]*{[ \t\n]*gather\\*?[ \t\n]*}"))))

The variable reftex-label-alist is also empty by default, so let's use the one from typeset_equations:

(setq reftex-label-alist
      '((nil              ?e "eq:"   "~\\eqref{%s}" nil nil)
        ("IEEEeqnarray"   ?e "eq:"   "~\\eqref{%s}" t   nil)
        ("IEEEeqnarray*"  ?e "eq:"   "~\\eqref{%s}" t   nil)
        ("lemma"          ?l "lem:"  "~\\ref{%s}"   t   ("lemma" "lem."))
        ("theorem"        ?h "thm:"  "~\\ref{%s}"   t   ("theorem" "th." "thm."))
        ("corollary"      ?c "cor:"  "~\\ref{%s}"   t   ("corollary" "cor."))
        ("conjecture"     ?j "conj:" "~\\ref{%s}"   t   ("conjecture" "conj."))
        ("proposition"    ?p "prop:" "~\\ref{%s}"   t   ("proposition" "prop."))
        ("claim"          ?m "clm:"  "~\\ref{%s}"   t   ("claim" "cl."))
        ("definition"     ?d "def:"  "~\\ref{%s}"   t   ("definition" "def."))
        ("remark"         ?r "rem:"  "~\\ref{%s}"   t   ("remark" "rem."))
        ("example"        ?x "ex:"   "~\\ref{%s}"   t   ("example" "ex."))
        ("exercise"       ?x "ex:"   "~\\ref{%s}"   t   ("exercise" "exer." "exerc." "ex."))
        ("enumerate"      ?i "item:" "~\\ref{%s}"   t   ("part"))))