diff --git a/modules/lang/latex/+fontification.el b/modules/lang/latex/+fontification.el new file mode 100644 index 000000000..fa853e726 --- /dev/null +++ b/modules/lang/latex/+fontification.el @@ -0,0 +1,89 @@ +;;; lang/latex/+fontification.el -*- lexical-binding: t; -*- + +;; Fontification taken from https://tex.stackexchange.com/a/86119/81279 +(setq font-latex-match-reference-keywords + '( + ;; biblatex + ("printbibliography" "[{") + ("addbibresource" "[{") + ;; Standard commands + ("cite" "[{") + ("Cite" "[{") + ("parencite" "[{") + ("Parencite" "[{") + ("footcite" "[{") + ("footcitetext" "[{") + ;; Style-specific commands + ("textcite" "[{") + ("Textcite" "[{") + ("smartcite" "[{") + ("Smartcite" "[{") + ("cite*" "[{") + ("parencite*" "[{") + ("supercite" "[{") + ;; Qualified citation lists + ("cites" "[{") + ("Cites" "[{") + ("parencites" "[{") + ("Parencites" "[{") + ("footcites" "[{") + ("footcitetexts" "[{") + ("smartcites" "[{") + ("Smartcites" "[{") + ("textcites" "[{") + ("Textcites" "[{") + ("supercites" "[{") + ;; Style-independent commands + ("autocite" "[{") + ("Autocite" "[{") + ("autocite*" "[{") + ("Autocite*" "[{") + ("autocites" "[{") + ("Autocites" "[{") + ;; Text commands + ("citeauthor" "[{") + ("Citeauthor" "[{") + ("citetitle" "[{") + ("citetitle*" "[{") + ("citeyear" "[{") + ("citedate" "[{") + ("citeurl" "[{") + ;; Special commands + ("fullcite" "[{") + ;; cleveref + ("cref" "{") + ("Cref" "{") + ("cpageref" "{") + ("Cpageref" "{") + ("cpagerefrange" "{") + ("Cpagerefrange" "{") + ("crefrange" "{") + ("Crefrange" "{") + ("labelcref" "{"))) + +(setq font-latex-match-textual-keywords + '( + ;; biblatex brackets + ("parentext" "{") + ("brackettext" "{") + ("hybridblockquote" "[{") + ;; Auxiliary Commands + ("textelp" "{") + ("textelp*" "{") + ("textins" "{") + ("textins*" "{") + ;; subcaption + ("subcaption" "[{"))) + +(setq font-latex-match-variable-keywords + '( + ;; amsmath + ("numberwithin" "{") + ;; enumitem + ("setlist" "[{") + ("setlist*" "[{") + ("newlist" "{") + ("renewlist" "{") + ("setlistdepth" "{") + ("restartlist" "{") + ("crefname" "{"))) diff --git a/modules/lang/latex/README.org b/modules/lang/latex/README.org new file mode 100644 index 000000000..620669f40 --- /dev/null +++ b/modules/lang/latex/README.org @@ -0,0 +1,53 @@ +#+TITLE: :lang latex + +* Module Description +Provide a helping hand when working with LaTeX documents. + +** Feature: ++ Sane defaults ++ Fontification of many popular commands ++ Pretty indentation of wrapped lines using the ~adaptive-wrap~ package ++ Spell checking with ~flyschek~ ++ Change PDF viewer to Okular or ~latex-preview-pane~ ++ Bibtex editor ++ Autocompletion using ~company-mode~ ++ Ivy or Helm for selecting bibliography ++ Compile your .tex code only once using LatexMk + + +* Customization + +** Custom Variables +Two custom variables state where AUCTeX will search for bibliography files and their corresponding PDFs. +Set these variables in your private configuration with: +#+BEGIN_SRC emacs_lisp +(set! :latex-bibtex-file "./your/bib/file.bib") +(set! :latex-bibtex-pdfs-dir "./dir/with/bib/pdfs/") +#+END_SRC +If the variables are not set, they are ignored. + +** LatexMk +Use LatexMk instead of normal LaTeX to compile documents. LatexMk only needs to run once to get all references, bibliography and other things right. + +Activate with the flag '+latexmk' of the latex module in init.el. +#+BEGIN_SRC emacs_lisp +(latex +latexmk) +#+END_SRC + +** Okular +Use Okular as default PDF viewer. + +Activate with the flag '+okular' of the latex module in init.el. +#+BEGIN_SRC emacs_lisp +(latex +okular) +#+END_SRC + +** Preivew-Pane +Instead of using an external program to display rendered .tex files, use an emacs window to display the rendered file. + +This flag is incompatible with the ~+okular~ flag. + +Activate with the flag '+preview-pane' of the latex module in init.el. +#+BEGIN_SRC emacs_lisp +(latex +preview-pane) +#+END_SRC diff --git a/modules/lang/latex/autoload.el b/modules/lang/latex/autoload.el new file mode 100644 index 000000000..6e95a3ff6 --- /dev/null +++ b/modules/lang/latex/autoload.el @@ -0,0 +1,43 @@ +;;; lang/latex/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun +latex/LaTeX-indent-item () + "Provide proper indentation for LaTeX \"itemize\",\"enumerate\", and \"description\" environments. + + \"\\item\" is indented `LaTeX-indent-level' spaces relative to + the the beginning of the environment. + + Continuation lines are indented either twice + `LaTeX-indent-level', or `LaTeX-indent-level-item-continuation' + if the latter is bound." + (save-match-data + (let* ((offset LaTeX-indent-level) + (contin (or (and (boundp '+latex-indent-level-item-continuation) + +latex-indent-level-item-continuation) + (* 4 LaTeX-indent-level))) + (re-beg "\\\\begin{") + (re-end "\\\\end{") + (re-env "\\(itemize\\|\\enumerate\\|description\\)") + (indent (save-excursion + (when (looking-at (concat re-beg re-env "}")) + (end-of-line)) + (LaTeX-find-matching-begin) + (current-column)))) + (cond ((looking-at (concat re-beg re-env "}")) + (or (save-excursion + (beginning-of-line) + (ignore-errors + (LaTeX-find-matching-begin) + (+ (current-column) + (if (looking-at (concat re-beg re-env "}")) + contin + offset)))) + indent)) + ((looking-at (concat re-end re-env "}")) + indent) + ((looking-at "\\\\item") + (+ offset indent)) + (t + (+ contin indent)))))) + + diff --git a/modules/lang/latex/config.el b/modules/lang/latex/config.el index 1c1876086..2f6690c8b 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -1,96 +1,225 @@ ;;; lang/latex/config.el -*- lexical-binding: t; -*- -(defvar +latex-bibtex-dir "~/work/writing/biblio/" +(defvar +latex-bibtex-file "" + "File AUCTeX (specifically RefTeX) uses to search for citations.") + +(defvar +latex-bibtex-dir "" "Where bibtex files are kept.") -(defvar +latex-bibtex-default-file "default.bib" - "TODO") +(defvar +latex-indent-level-item-continuation 8 + "Custom indentation level for items in enumeration-type environments") -;; -;; AucTex/LaTeX bootstrap -;; +(def-setting! :latex-bibtex-file (file) + "Sets the default file RefTeX uses to search for citations." + `(setq +latex-bibtex-file ,file)) -;; Because tex-mode is built-in and AucTex has conflicting components, we need -;; to ensure that auctex gets loaded instead of tex-mode. -(load "auctex" nil t) -(load "auctex-autoloads" nil t) -(push '("\\.[tT]e[xX]\\'" . TeX-latex-mode) auto-mode-alist) +(def-setting! :latex-bibtex-dir (dir) + "Sets the directory where AUCTeX will search for PDFs associated to BibTeX references." + `(setq +latex-bibtex-dir ,dir)) -(add-hook! (latex-mode LaTeX-mode) #'turn-on-auto-fill) -(add-hook! 'LaTeX-mode-hook #'(LaTeX-math-mode TeX-source-correlate-mode)) -(add-transient-hook! 'LaTeX-mode-hook - (setq TeX-auto-save t +(def-package! tex-site + :init + ;; Manually load the AUCTEX autoloads. This is normally done by package-initialize, + ;; ... which we do not use. + (load "auctex.el" nil t t) + (load "auctex-autoloads.el" nil t t) + :config + ;; Set some varibles to fontify common LaTeX commands. + (load! +fontification) + (setq + ;; Enable parse on load. TeX-parse-self t + ;; When running TeX, just save, don't ask TeX-save-query nil + ;; Enable parse on save. + TeX-auto-save t + ;; Use hidden directories for AUCTeX files. + TeX-auto-local ".auctex-auto" + TeX-style-local ".auctex-style" + ;; When correlating sources to rendered PDFs, don't start the emacs server TeX-source-correlate-start-server nil - LaTeX-fill-break-at-separators nil - LaTeX-section-hook - '(LaTeX-section-heading - LaTeX-section-title - LaTeX-section-toc - LaTeX-section-section - LaTeX-section-label)) - + TeX-source-correlate-mode t + TeX-source-correlate-method 'synctex + ;; Fonts for section, subsection, etc + font-latex-fontify-sectioning 1.15) + (setq-default TeX-master nil) + ;; Display the output of the latex commands in a popup. (set! :popup " output\\*$" '((size . 15))) - (map! :map LaTeX-mode-map "C-j" nil)) + ;; TeX Font Styling + (def-package! tex-style + :defer t) -;; -;; Plugins -;; + ;; TeX Folding + (def-package! tex-fold + :defer t + :init + (add-hook! 'TeX-mode-hook 'TeX-fold-mode)) -(def-package! reftex ; built-in - :commands (turn-on-reftex reftex-mode) + (def-package! latex + :defer t + :init + (setq + ;; Add the toc entry to the sectioning hooks. + LaTeX-section-hook + '(LaTeX-section-heading + LaTeX-section-title + LaTeX-section-toc + LaTeX-section-section + LaTeX-section-label) + LaTeX-fill-break-at-separators nil + ;; Item indentation. + LaTeX-item-indent 0) + :config + (map! :map LaTeX-mode-map "C-j" nil) + ;; Do not prompt for Master files, this allows auto-insert to add templates to .tex files + (add-hook! '(LaTeX-mode TeX-mode) '(lambda () (remove-hook 'find-file-hooks (car find-file-hooks) 'local))) + ;; Adding useful things for latex + (add-hook! LaTeX-mode (LaTeX-math-mode) (TeX-source-correlate-mode)(TeX-global-PDF-mode t) + (TeX-PDF-mode t) (visual-line-mode +1)) + (when (featurep! :feature spellcheck) + (add-hook! LaTeX-mode (flyspell-mode t))) + ;; Default language setting. + (setq ispell-dictionary "english") + ;; Use chktex to search for errors in a latex file. + (setcar (cdr (assoc "Check" TeX-command-list)) "chktex -v6 %s") + ;; Set a custom item indentation + (setq LaTeX-indent-environment-list + (nconc '(("itemize" +latex/LaTeX-indent-item) + ("enumerate" +latex/LaTeX-indent-item) + ("description" +latex/LaTeX-indent-item)) + LaTeX-indent-environment-list)))) + +(after! latex + ;; Use Okular is the user says so. + (when (featurep! +okular) + ;; Configure Okular as viewer. Including a bug fix (https://bugs.kde.org/show_bug.cgi?id=373855) + (add-to-list 'TeX-view-program-list + '("Okular" ("okular --unique file:%o" (mode-io-correlate "#src:%n%a")))) + (add-to-list 'TeX-view-program-selection + '(output-pdf "Okular")))) + +(def-package! preview + ;; The preview package is currently broken with the latest AUCTeX version ("11.90.2.2017-07-25) + ;; ... and Ghostscript 9.22. It's now fixed in AUCTeX master, so we just have to wait. + :init + (progn + (setq-default preview-scale 1.4 + preview-scale-function '(lambda () (* (/ 10.0 (preview-document-pt)) preview-scale)))) + (add-hook! LaTeX-mode #'LaTeX-preview-setup)) + +(def-package! reftex + :commands turn-on-reftex :init (setq reftex-plug-into-AUCTeX t - reftex-default-bibliography (list +latex-bibtex-default-file) - reftex-toc-split-windows-fraction 0.2) - + reftex-toc-split-windows-fraction 0.3) + (unless (string-empty-p +latex-bibtex-file) + (setq reftex-default-bibliography (list (expand-file-name +latex-bibtex-file)))) + ; Get ReTeX working with biblatex + ; http://tex.stackexchange.com/questions/31966/setting-up-reftex-with-biblatex-citation-commands/31992#31992 + (setq reftex-cite-format + '((?t . "\\textcite[]{%l}") + (?a . "\\autocite[]{%l}") + (?c . "\\cite[]{%l}") + (?s . "\\smartcite[]{%l}") + (?f . "\\footcite[]{%l}") + (?n . "\\nocite{%l}") + (?b . "\\blockcquote[]{%l}{}"))) (add-hook! (latex-mode LaTeX-mode) #'turn-on-reftex) - :config (map! :map reftex-mode-map :localleader :n ";" 'reftex-toc) - (add-hook! 'reftex-toc-mode-hook (reftex-toc-rescan) (map! :local :e "j" #'next-line :e "k" #'previous-line :e "q" #'kill-buffer-and-window - :e "ESC" #'kill-buffer-and-window))) + :e "ESC" #'kill-buffer-and-window + "C-g" #'reftex-toc-quit))) - -(def-package! bibtex ; built-in +(def-package! bibtex :defer t + :mode ("\\.bib" . bibtex-mode) :config (setq bibtex-dialect 'biblatex bibtex-align-at-equal-sign t bibtex-text-indentation 20 - bibtex-completion-bibliography (list +latex-bibtex-default-file)) - + bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file))) (map! :map bibtex-mode-map "C-c \\" #'bibtex-fill-entry)) +(def-package! latex-preview-pane + :when (featurep! +preview-pane) + :commands latex-preview-pane-enable + :init + (setq latex-preview-pane-multifile-mode 'auctex) + (add-hook! (latex-mode LaTeX-mode) #'latex-preview-pane-enable) + (add-to-list 'TeX-view-program-list + '("preview-pane" + latex-preview-pane-mode)) + (add-to-list 'TeX-view-program-selection + '(output-pdf "preview-pane")) + :config + (map! :map doc-view-mode-map + "ESC" #'delete-window + "q" #'delete-window + "k" (λ! (quit-window) (delete-window)))) + +;; Enable latexmk only if the user explicitly says so with the module flag '+latexmk'. +(def-package! auctex-latexmk + :when (featurep! +latexmk) + :init + ;; Pass the -pdf flag when TeX-PDF-mode is active + (setq auctex-latexmk-inherit-TeX-PDF-mode t) + ;; Set LatexMk as the default + (add-hook 'LaTeX-mode-hook '(lambda () (setq TeX-command-default "LatexMk"))) + :config + ;; Add latexmk as a TeX target + (auctex-latexmk-setup)) (def-package! ivy-bibtex :when (featurep! :completion ivy) - :commands ivy-bibtex) - + :commands ivy-bibtex + :config + (setq ivy-bibtex-default-action 'ivy-bibtex-insert-key) + (unless (string-empty-p +latex-bibtex-file) + (setq bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file)))) + (unless (string-empty-p +latex-bibtex-dir) + (setq bibtex-completion-library-path (list +latex-bibtex-dir) + bibtex-completion-pdf-field "file" + bibtex-completion-notes-path (f-expand "notes.org" +latex-bibtex-dir) + bibtex-completion-pdf-open-function + (lambda (fpath) (async-start-process "open-pdf" "/usr/bin/xdg-open" nil fpath))))) (def-package! helm-bibtex :when (featurep! :completion helm) - :commands helm-bibtex) - + :commands helm-bibtex + :config + (unless (string-empty-p +latex-bibtex-file) + (setq bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file)))) + (unless (string-empty-p +latex-bibtex-dir) + (setq bibtex-completion-library-path (list +latex-bibtex-dir) + bibtex-completion-pdf-field "file" + bibtex-completion-notes-path (f-expand "notes.org" +latex-bibtex-dir) + bibtex-completion-pdf-open-function + (lambda (fpath) (async-start-process "open-pdf" "/usr/bin/xdg-open" nil fpath))))) (def-package! company-auctex :when (featurep! :completion company) - :commands company-auctex-init + :commands (company-auctex-init) :init ;; We can't use the (set! :company-backend ...) because Auctex reports its - ;; major-mode as `latex-mode', but uses LaTeX-mode-hook for its mode, which is - ;; :company-backend doesn't anticipate (and shouldn't have to!) + ;; major-mode as `latex-mode', but uses LaTeX-mode-hook for its mode, which + ;; is not anticipated by :company-backend (and shouldn't have to!) (add-hook! LaTeX-mode (make-variable-buffer-local 'company-backends) (company-auctex-init))) + +;; Nicely indent lines that have wrapped when visual line mode is activated +(def-package! adaptive-wrap + :commands (adaptive-wrap-prefix-mode) + :init + (add-hook! LaTeX-mode 'adaptive-wrap-prefix-mode) + (setq-default adaptive-wrap-extra-indent 0)) diff --git a/modules/lang/latex/packages.el b/modules/lang/latex/packages.el index ebf26c035..9939c2366 100644 --- a/modules/lang/latex/packages.el +++ b/modules/lang/latex/packages.el @@ -2,7 +2,18 @@ ;;; lang/latex/packages.el (package! auctex) -;; (package! auctex-latexmk) +(package! flyspell) +(package! adaptive-wrap) + +;; Optional module features: + +(when (featurep! +latexmk) + (package! auctex-latexmk)) + +(when (featurep! +preview-pane) + (package! latex-preview-pane)) + +;; Features according to other user selected options (when (featurep! :completion company) (package! company-auctex)) @@ -10,3 +21,4 @@ (package! ivy-bibtex)) (when (featurep! :completion helm) (package! helm-bibtex)) +