From e91cb1124391541f7b6b62d2fa67ce78d3a24a66 Mon Sep 17 00:00:00 2001 From: Undead Kernel Date: Mon, 1 Jan 2018 20:48:23 +0100 Subject: [PATCH 1/2] Latex module revamped Latex language module with previews, latexmk, reftex, bibtex and others. Completion with company mode. Selection of bibliography using Ivy or Helm. Later preview panel or okular as viewers. LatexMk for compiling code. Prettified indentation with adaptive-wrap along with good indentation of environments. Additional fontification of common commands. --- modules/lang/latex/+fontification.el | 89 +++++++++++ modules/lang/latex/README.org | 53 +++++++ modules/lang/latex/autoload.el | 43 ++++++ modules/lang/latex/config.el | 220 +++++++++++++++++++++------ modules/lang/latex/packages.el | 14 +- 5 files changed, 372 insertions(+), 47 deletions(-) create mode 100644 modules/lang/latex/+fontification.el create mode 100644 modules/lang/latex/README.org create mode 100644 modules/lang/latex/autoload.el 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..7b483be15 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -1,96 +1,224 @@ ;;; 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-pdfs-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-pdfs dir + "Sets the default file AUXTeX uses to search for PDF files associated to citations.." + (setq +latex-bibtex-pdfs-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 (s-blank? +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 + (unless (s-blank? +latex-bibtex-file) + (setq bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file)))) + (unless (s-blank? +latex-bibtex-pdfs-dir) + (setq bibtex-completion-library-path (list +latex-bibtex-pdfs-dir) + bibtex-completion-pdf-field "file" + bibtex-completion-notes-path (f-expand "notes.org" +latex-bibtex-pdfs-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 (s-blank? +latex-bibtex-file) + (setq bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file)))) + (unless (s-blank? +latex-bibtex-pdfs-dir) + (setq bibtex-completion-library-path (list +latex-bibtex-pdfs-dir) + bibtex-completion-pdf-field "file" + bibtex-completion-notes-path (f-expand "notes.org" +latex-bibtex-pdfs-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)) + From 56a3c817789f1438aaac4a492c8c3ef551728d61 Mon Sep 17 00:00:00 2001 From: UndeadKernel Date: Tue, 9 Jan 2018 14:19:02 +0100 Subject: [PATCH 2/2] Correct def-setting and use string-empty-p. Change default ivy-bibtex behavior to insert bibliography. --- modules/lang/latex/config.el | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/modules/lang/latex/config.el b/modules/lang/latex/config.el index 7b483be15..2f6690c8b 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -3,20 +3,20 @@ (defvar +latex-bibtex-file "" "File AUCTeX (specifically RefTeX) uses to search for citations.") -(defvar +latex-bibtex-pdfs-dir "" +(defvar +latex-bibtex-dir "" "Where bibtex files are kept.") (defvar +latex-indent-level-item-continuation 8 "Custom indentation level for items in enumeration-type environments") -(def-setting! :latex-bibtex-file file +(def-setting! :latex-bibtex-file (file) "Sets the default file RefTeX uses to search for citations." - (setq +latex-bibtex-file file)) + `(setq +latex-bibtex-file ,file)) -(def-setting! :latex-bibtex-pdfs dir - "Sets the default file AUXTeX uses to search for PDF files associated to citations.." - (setq +latex-bibtex-pdfs-dir dir)) +(def-setting! :latex-bibtex-dir (dir) + "Sets the directory where AUCTeX will search for PDFs associated to BibTeX references." + `(setq +latex-bibtex-dir ,dir)) (def-package! tex-site @@ -115,7 +115,7 @@ :init (setq reftex-plug-into-AUCTeX t reftex-toc-split-windows-fraction 0.3) - (unless (s-blank? +latex-bibtex-file) + (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 @@ -183,12 +183,13 @@ :when (featurep! :completion ivy) :commands ivy-bibtex :config - (unless (s-blank? +latex-bibtex-file) + (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 (s-blank? +latex-bibtex-pdfs-dir) - (setq bibtex-completion-library-path (list +latex-bibtex-pdfs-dir) + (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-pdfs-dir) + 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))))) @@ -196,12 +197,12 @@ :when (featurep! :completion helm) :commands helm-bibtex :config - (unless (s-blank? +latex-bibtex-file) + (unless (string-empty-p +latex-bibtex-file) (setq bibtex-completion-bibliography (list (expand-file-name +latex-bibtex-file)))) - (unless (s-blank? +latex-bibtex-pdfs-dir) - (setq bibtex-completion-library-path (list +latex-bibtex-pdfs-dir) + (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-pdfs-dir) + 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)))))