From df6438e2277dd2b9d012d5a3de2fb43aede25237 Mon Sep 17 00:00:00 2001 From: Gerard Vermeulen Date: Mon, 7 Nov 2022 11:50:17 +0100 Subject: [PATCH] Preserve indentation in source blocks for Python (use the -i switch) --- README.org | 5266 ++++++++++++++++++++++++++-------------------------- 1 file changed, 2638 insertions(+), 2628 deletions(-) diff --git a/README.org b/README.org index 0795b1c..5a3fdcf 100644 --- a/README.org +++ b/README.org @@ -8,11 +8,11 @@ #+property: header-args:org :tangle include.org #+startup: showeverything #+begin_src latex :noweb yes :results raw - ,#+latex_header: <> - ,#+latex_header: <> - ,#+latex_header: <> - ,#+latex_header: <> - ,#+latex_header: <> +,#+latex_header: <> +,#+latex_header: <> +,#+latex_header: <> +,#+latex_header: <> +,#+latex_header: <> #+end_src * Quick start @@ -30,10 +30,10 @@ to install a selected set of packages. Quit Emacs and invoke Emacs again. #+caption: Clone and initialize the user-emacs-directory. #+name: lst:prepare-user-emacs-directory #+begin_src shell :noeval :tangle no - cd ~ - git clone ccdr@mercury.grenoble.cnrs.fr:SERVER/emacs.d.git .emacs.d - make --directory=.emacs.d init - emacs & +cd ~ +git clone ccdr@mercury.grenoble.cnrs.fr:SERVER/emacs.d.git .emacs.d +make --directory=.emacs.d init +emacs & #+end_src * Introduction @@ -127,20 +127,20 @@ Try to load [[https://github.com/emacscollective/no-littering][no-littering]] as #+caption: Tangle the early-init-file. #+name: lst:tangle-early-init-file #+begin_src emacs-lisp :tangle early-init.el - ;;; early-init.el --- user early-init file -*- lexical-binding: t -*- - ;;; Commentary: - ;;; Code: - (setq load-prefer-newer t) +;;; early-init.el --- user early-init file -*- lexical-binding: t -*- +;;; Commentary: +;;; Code: +(setq load-prefer-newer t) - (require 'no-littering nil 'noerror) +(require 'no-littering nil 'noerror) - (provide 'early-init) - ;; Emacs looks for "Local variables:" after the last "?\n?\f". - - ;; Local Variables: - ;; indent-tabs-mode: nil - ;; End: - ;;; earl-init.el ends here +(provide 'early-init) +;; Emacs looks for "Local variables:" after the last "?\n?\f". + +;; Local Variables: +;; indent-tabs-mode: nil +;; End: +;;; earl-init.el ends here #+end_src In order to get help in understanding the code block above in a buffer showing @@ -178,115 +178,115 @@ The [[info:emacs#Init File][init file (info)]] does not load the ~custom-file~ a #+caption: Customize the first set of Emacs variables. #+name: lst:1st-custom-set-variables-call #+begin_src emacs-lisp - ;;; init.el --- user init file -*- lexical-binding: t -*- - ;;; Commentary: - ;;; Code: - (require 'cl-lib) +;;; init.el --- user init file -*- lexical-binding: t -*- +;;; Commentary: +;;; Code: +(require 'cl-lib) - (custom-set-variables - '(after-save-hook #'executable-make-buffer-file-executable-if-script-p) - '(column-number-mode t) - '(cursor-type 'box) - `(custom-file ,(locate-user-emacs-file "custom.el")) - '(epg-pinentry-mode 'loopback) - '(global-hl-line-mode t) - '(global-hl-line-sticky-flag t) - '(history-delete-duplicates t) - '(history-length 500) - '(indent-tabs-mode nil) - '(inhibit-startup-buffer-menu t) - '(inhibit-startup-screen t) - '(initial-buffer-choice t) - '(initial-scratch-message "") - `(insert-directory-program ,(or (executable-find "gls") - (executable-find "ls"))) - '(kill-ring-max 300)) +(custom-set-variables + '(after-save-hook #'executable-make-buffer-file-executable-if-script-p) + '(column-number-mode t) + '(cursor-type 'box) + `(custom-file ,(locate-user-emacs-file "custom.el")) + '(epg-pinentry-mode 'loopback) + '(global-hl-line-mode t) + '(global-hl-line-sticky-flag t) + '(history-delete-duplicates t) + '(history-length 500) + '(indent-tabs-mode nil) + '(inhibit-startup-buffer-menu t) + '(inhibit-startup-screen t) + '(initial-buffer-choice t) + '(initial-scratch-message "") + `(insert-directory-program ,(or (executable-find "gls") + (executable-find "ls"))) + '(kill-ring-max 300)) #+end_src #+caption[Customize the second set of Emacs variables]: #+caption: Customize the second set of Emacs variables. #+name: lst:2nd-custom-set-variables-call #+begin_src emacs-lisp - (custom-set-variables - ;; See https://github.com/melpa/melpa#mirrors for official Melpa mirrors. - '(package-archives - '(("gnu" . "https://elpa.gnu.org/packages/") - ("gnu-devel" . "https://elpa.gnu.org/devel/") - ("melpa" . "https://melpa.org/packages/") - ;; ("melpa" . "https://www.mirrorservice.org/sites/melpa.org/packages/") - ("nongnu" . "https://elpa.nongnu.org/nongnu/"))) - ;; Pin packages to GNU ELPA for info or stability. - '(package-pinned-packages - `,(delq nil `((auctex . "gnu") - (compat . "gnu") - (consult . "gnu-devel") - ,(when (version< emacs-version "28.9.9") - '(eglot . "gnu-devel")) - (embark . "gnu-devel") - (embark-consult . "gnu-devel") - (engrave-faces . "gnu") - (marginalia . "gnu-devel") - (org . "gnu-devel") - ,(when (version< emacs-version "28.9.9") - '(python . "gnu-devel")) - (queue . "gnu") - (rainbow-mode . "gnu") - (spinner . "gnu") - (xr . "gnu") - (vertico . "gnu-devel"))))) +(custom-set-variables + ;; See https://github.com/melpa/melpa#mirrors for official Melpa mirrors. + '(package-archives + '(("gnu" . "https://elpa.gnu.org/packages/") + ("gnu-devel" . "https://elpa.gnu.org/devel/") + ("melpa" . "https://melpa.org/packages/") + ;; ("melpa" . "https://www.mirrorservice.org/sites/melpa.org/packages/") + ("nongnu" . "https://elpa.nongnu.org/nongnu/"))) + ;; Pin packages to GNU ELPA for info or stability. + '(package-pinned-packages + `,(delq nil `((auctex . "gnu") + (compat . "gnu") + (consult . "gnu-devel") + ,(when (version< emacs-version "28.9.9") + '(eglot . "gnu-devel")) + (embark . "gnu-devel") + (embark-consult . "gnu-devel") + (engrave-faces . "gnu") + (marginalia . "gnu-devel") + (org . "gnu-devel") + ,(when (version< emacs-version "28.9.9") + '(python . "gnu-devel")) + (queue . "gnu") + (rainbow-mode . "gnu") + (spinner . "gnu") + (xr . "gnu") + (vertico . "gnu-devel"))))) #+end_src #+caption[Customize the third set of Emacs variables]: #+caption: Customize the third set of Emacs variables. #+name: lst:3rd-custom-set-variables-call #+begin_src emacs-lisp - (custom-set-variables - '(package-selected-packages - `,(delq nil `(async ; asynchroneous processing - auctex ; Aalborg University Center TeX - company ; complete anything - engrave-faces ; convert font-lock to ANSI/HTML/LaTeX - magit ; Git Text-based User Interface - no-littering ; keep `user-emacs-directory' clean - org ; thought organizer - ,(when (version< emacs-version "28.9.9") - 'python) ; major mode to edit Python files - vertico ; VERTical Interactive Completion - wgrep ; open a writable grep buffer - xr)))) ; undo rx to grok regular expressions +(custom-set-variables + '(package-selected-packages + `,(delq nil `(async ; asynchroneous processing + auctex ; Aalborg University Center TeX + company ; complete anything + engrave-faces ; convert font-lock to ANSI/HTML/LaTeX + magit ; Git Text-based User Interface + no-littering ; keep `user-emacs-directory' clean + org ; thought organizer + ,(when (version< emacs-version "28.9.9") + 'python) ; major mode to edit Python files + vertico ; VERTical Interactive Completion + wgrep ; open a writable grep buffer + xr)))) ; undo rx to grok regular expressions #+end_src #+caption[Customize the fourth set of Emacs variables]: #+caption: Customize the fourth set of Emacs variables. #+name: lst:4th-custom-set-variables-call #+begin_src emacs-lisp +(custom-set-variables + '(recentf-mode t) + '(save-place-mode t) + '(scroll-bar-mode nil) + '(tab-always-indent 'complete) + '(tab-width 8) + '(tool-bar-mode nil) + '(url-cookie-trusted-urls nil) + '(url-cookie-untrusted-urls '(".*")) + '(use-dialog-box nil) + '(view-read-only t)) + +(when (version< "28.0" emacs-version) (custom-set-variables - '(recentf-mode t) - '(save-place-mode t) - '(scroll-bar-mode nil) - '(tab-always-indent 'complete) - '(tab-width 8) - '(tool-bar-mode nil) - '(url-cookie-trusted-urls nil) - '(url-cookie-untrusted-urls '(".*")) - '(use-dialog-box nil) - '(view-read-only t)) + '(mode-line-compact 'long) + '(next-error-message-highlight t) + '(use-short-answers t))) - (when (version< "28.0" emacs-version) - (custom-set-variables - '(mode-line-compact 'long) - '(next-error-message-highlight t) - '(use-short-answers t))) +(when (eq system-type 'darwin) + (custom-set-variables + '(ns-alternate-modifier nil) + '(ns-command-modifier 'meta) + '(ns-right-command-modifier 'super))) - (when (eq system-type 'darwin) - (custom-set-variables - '(ns-alternate-modifier nil) - '(ns-command-modifier 'meta) - '(ns-right-command-modifier 'super))) - - (when (eq window-system 'ns) - (add-to-list 'initial-frame-alist '(height . 51)) - (add-to-list 'initial-frame-alist '(width . 180))) +(when (eq window-system 'ns) + (add-to-list 'initial-frame-alist '(height . 51)) + (add-to-list 'initial-frame-alist '(width . 180))) #+end_src * [[info:emacs#Package Installation][Install the selected packages (info)]] @@ -320,41 +320,41 @@ the contents of packages and allows to update packages to the latest version. #+caption: Install the selected packages. #+name: lst:install-selected-packages #+begin_src emacs-lisp - (unless noninteractive - (unless (require 'no-littering nil 'noerror) - (unless (bound-and-true-p package-archive-contents) - (package-refresh-contents)) - ;; Install and require `no-littering'. - (package-install 'no-littering) - (require 'no-littering) - ;; https://emacs.stackexchange.com/a/45939 answers - ;; "How to shadow automatically a built-in package by installing it?" - (defun shadow-builtin-by-install (pkg) - (when-let ((desc (cadr (assq pkg package-archive-contents)))) - (package-install desc 'dont-select))) - ;; Shadow built-in `org' by installing `org'. - (shadow-builtin-by-install 'org) - ;; Shadow built-in `python' by installing `python'. - (when (version< emacs-version "28.9.9") - (shadow-builtin-by-install 'python)) - ;; Install the selected packages. - (package-install-selected-packages))) +(unless noninteractive + (unless (require 'no-littering nil 'noerror) + (unless (bound-and-true-p package-archive-contents) + (package-refresh-contents)) + ;; Install and require `no-littering'. + (package-install 'no-littering) + (require 'no-littering) + ;; https://emacs.stackexchange.com/a/45939 answers + ;; "How to shadow automatically a built-in package by installing it?" + (defun shadow-builtin-by-install (pkg) + (when-let ((desc (cadr (assq pkg package-archive-contents)))) + (package-install desc 'dont-select))) + ;; Shadow built-in `org' by installing `org'. + (shadow-builtin-by-install 'org) + ;; Shadow built-in `python' by installing `python'. + (when (version< emacs-version "28.9.9") + (shadow-builtin-by-install 'python)) + ;; Install the selected packages. + (package-install-selected-packages))) - (defun ensure-package-selection (package) - "Ensure selection of PACKAGE." - (when (and (package-installed-p package) - (bound-and-true-p package-selected-packages)) - (cl-pushnew package package-selected-packages))) +(defun ensure-package-selection (package) + "Ensure selection of PACKAGE." + (when (and (package-installed-p package) + (bound-and-true-p package-selected-packages)) + (cl-pushnew package package-selected-packages))) - (defun ensure-package-installation (&rest packages) - "Ensure installation of all packages in PACKAGES." - (let ((ok t)) - (dolist (package packages) - (unless (package-installed-p package) - (package-install package)) - (unless (ensure-package-selection package) - (setq ok nil))) - ok)) +(defun ensure-package-installation (&rest packages) + "Ensure installation of all packages in PACKAGES." + (let ((ok t)) + (dolist (package packages) + (unless (package-installed-p package) + (package-install package)) + (unless (ensure-package-selection package) + (setq ok nil))) + ok)) #+end_src * [[info:emacs#Faces][Text faces or styles (info)]] @@ -386,142 +386,142 @@ theming: #+caption: Configure =face-attributes=. #+name: lst:configure-face-attributes #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; Set face attributes. - (cond - ((eq system-type 'darwin) - (set-face-attribute 'default nil :family "Hack" :height 120) - (set-face-attribute 'fixed-pitch nil :family "Hack") - (set-face-attribute 'variable-pitch nil :family "FiraGo")) - ((eq system-type 'gnu/linux) - (set-face-attribute 'default nil :family "Hack" :height 110) - (set-face-attribute 'fixed-pitch nil :family "Hack") - (set-face-attribute 'variable-pitch nil :family "FiraGo")) - (t - (set-face-attribute 'default nil :family "Hack" :height 110) - (set-face-attribute 'fixed-pitch nil :family "Hack") - (set-face-attribute 'variable-pitch nil :family "DejaVu Sans")))) +(with-eval-after-load 'emacs + ;; Set face attributes. + (cond + ((eq system-type 'darwin) + (set-face-attribute 'default nil :family "Hack" :height 120) + (set-face-attribute 'fixed-pitch nil :family "Hack") + (set-face-attribute 'variable-pitch nil :family "FiraGo")) + ((eq system-type 'gnu/linux) + (set-face-attribute 'default nil :family "Hack" :height 110) + (set-face-attribute 'fixed-pitch nil :family "Hack") + (set-face-attribute 'variable-pitch nil :family "FiraGo")) + (t + (set-face-attribute 'default nil :family "Hack" :height 110) + (set-face-attribute 'fixed-pitch nil :family "Hack") + (set-face-attribute 'variable-pitch nil :family "DejaVu Sans")))) #+end_src #+caption[Implement =set-default-face-height=]: #+caption: Implement =set-default-face-height=. #+name: lst:set-default-face-height #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun set-default-face-height () - "Set the default face height in all current and future frames. +(with-eval-after-load 'emacs + (defun set-default-face-height () + "Set the default face height in all current and future frames. - Scale all other faces with a height that is a real number." - (interactive) - (let* ((prompt (format "face heigth (%s): " - (face-attribute 'default :height))) - (choices (mapcar #'number-to-string - (number-sequence 50 200 10))) - (height (string-to-number - (completing-read prompt choices nil 'require-match)))) - (message "Setting the height of the default face to %s" height) - (set-face-attribute 'default nil :height height)))) +Scale all other faces with a height that is a real number." + (interactive) + (let* ((prompt (format "face heigth (%s): " + (face-attribute 'default :height))) + (choices (mapcar #'number-to-string + (number-sequence 50 200 10))) + (height (string-to-number + (completing-read prompt choices nil 'require-match)))) + (message "Setting the height of the default face to %s" height) + (set-face-attribute 'default nil :height height)))) #+end_src #+caption[Use =buffer-face-mode= to set fixed or variable pitch face]: #+caption: Use =buffer-face-mode= to set fixed or variable pitch face. #+name: lst:use-buffer-face-mode-for-fixed-or-variable-pitch-face #+begin_src emacs-lisp - ;; Use proportional font faces in current buffer - (defun set-buffer-variable-pitch-face () - "Set a variable width (proportional) font in current buffer." - (interactive) - (setq buffer-face-mode-face 'variable-pitch) - (buffer-face-mode)) +;; Use proportional font faces in current buffer +(defun set-buffer-variable-pitch-face () + "Set a variable width (proportional) font in current buffer." + (interactive) + (setq buffer-face-mode-face 'variable-pitch) + (buffer-face-mode)) - ;; Use monospaced font faces in current buffer - (defun set-buffer-fixed-pitch-face () - "Set a fixed width (monospace) font in current buffer." - (interactive) - (setq buffer-face-mode-face 'fixed-pitch) - (buffer-face-mode)) +;; Use monospaced font faces in current buffer +(defun set-buffer-fixed-pitch-face () + "Set a fixed width (monospace) font in current buffer." + (interactive) + (setq buffer-face-mode-face 'fixed-pitch) + (buffer-face-mode)) - (add-hook 'magit-mode-hook #'set-buffer-fixed-pitch-face) - (add-hook 'prog-mode-hook #'set-buffer-fixed-pitch-face) +(add-hook 'magit-mode-hook #'set-buffer-fixed-pitch-face) +(add-hook 'prog-mode-hook #'set-buffer-fixed-pitch-face) #+end_src #+caption[Fix a `gtk' color and implement =invert-default-face=]: #+caption: Fix a `gtk' color and implement =invert-default-face=. #+name: lst:fix-gtk-color-for-invert-default-face #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun fix-gtk-region-face-background-color () - (when (featurep 'gtk) - (set-face-attribute - 'region nil - :background (cdr (assoc (face-attribute 'default :background) - '(("white" . "LightGoldenrod2") - ("black" . "blue3"))))))) - - (defun invert-default-face () - "Invert the default face." - (interactive) - (invert-face 'default) - (fix-gtk-region-face-background-color)) +(with-eval-after-load 'emacs + (defun fix-gtk-region-face-background-color () + (when (featurep 'gtk) + (set-face-attribute + 'region nil + :background (cdr (assoc (face-attribute 'default :background) + '(("white" . "LightGoldenrod2") + ("black" . "blue3"))))))) + (defun invert-default-face () + "Invert the default face." + (interactive) + (invert-face 'default) (fix-gtk-region-face-background-color)) + + (fix-gtk-region-face-background-color)) #+end_src #+caption[Shadow Org font-lock faces to improve the readability]: #+caption: Shadow Org font-lock faces to improve the readability. #+name: lst:shadow-org-font-lock-faces #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; Shadow two definitions in org-faces.el: - (defface org-block - ;; https://emacs.stackexchange.com/a/9604 answers: - ;; How to override a defined face for light and dark backgrounds? - `((((background dark)) - :inherit (fixed-pitch) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :background "#444444") - (t - :inherit (fixed-pitch) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :background "#FFFFD0")) - "My face used for text inside various blocks. +(with-eval-after-load 'emacs + ;; Shadow two definitions in org-faces.el: + (defface org-block + ;; https://emacs.stackexchange.com/a/9604 answers: + ;; How to override a defined face for light and dark backgrounds? + `((((background dark)) + :inherit (fixed-pitch) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#444444") + (t + :inherit (fixed-pitch) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#FFFFD0")) + "My face used for text inside various blocks. - It is always used for source blocks. You can refine what face - should be used depending on the source block language by setting, - `org-src-block-faces', which takes precedence. +It is always used for source blocks. You can refine what face +should be used depending on the source block language by setting, +`org-src-block-faces', which takes precedence. - When `org-fontify-quote-and-verse-blocks' is not nil, text inside - verse and quote blocks are fontified using the `org-verse' and - `org-quote' faces, which inherit from `org-block'.") +When `org-fontify-quote-and-verse-blocks' is not nil, text inside +verse and quote blocks are fontified using the `org-verse' and +`org-quote' faces, which inherit from `org-block'.") - (defface org-table - ;; https://emacs.stackexchange.com/a/9604 answers: - ;; How to override a defined face for light and dark backgrounds? - `((((background dark)) - :inherit (fixed-pitch) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :background "#444444") - (t - :inherit (fixed-pitch) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :background "#FFFFD0")) - "My face for tables.")) + (defface org-table + ;; https://emacs.stackexchange.com/a/9604 answers: + ;; How to override a defined face for light and dark backgrounds? + `((((background dark)) + :inherit (fixed-pitch) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#444444") + (t + :inherit (fixed-pitch) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#FFFFD0")) + "My face for tables.")) #+end_src #+caption[Shadow Emacs font-lock faces to improve the readability]: #+caption: Shadow Emacs font-lock faces to improve the readability. #+name: lst:shadow-emacs-font-lock-faces #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; Shadow one definition in sh-script.el: - (defface sh-heredoc - '((((class color) (background dark)) - (:foreground "yellow")) - (((class color) (background light)) - (:foreground "magenta")) - (t - (:weight bold))) - "My face to show a here-document.")) +(with-eval-after-load 'emacs + ;; Shadow one definition in sh-script.el: + (defface sh-heredoc + '((((class color) (background dark)) + (:foreground "yellow")) + (((class color) (background light)) + (:foreground "magenta")) + (t + (:weight bold))) + "My face to show a here-document.")) #+end_src * [[info:emacs#Windows][Window management (info)]] @@ -537,74 +537,74 @@ and [[lst:3rd-window-management]] implement a selection of his recommendations. #+caption: Window management functions and key bindings. #+name: lst:1st-window-management #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; https://www.masteringemacs.org/article/demystifying-emacs-window-manager - (defun split-root-below (arg) - "Split window below from the root or from the parent with ARG." - (interactive "P") - (split-window (if arg (window-parent (selected-window)) - (frame-root-window)) - nil 'below nil)) +(with-eval-after-load 'emacs + ;; https://www.masteringemacs.org/article/demystifying-emacs-window-manager + (defun split-root-below (arg) + "Split window below from the root or from the parent with ARG." + (interactive "P") + (split-window (if arg (window-parent (selected-window)) + (frame-root-window)) + nil 'below nil)) - (defun split-root-right (arg) - "Split window right from the root or from the parent with ARG." - (interactive "P") - (split-window (if arg (window-parent (selected-window)) - (frame-root-window)) - nil 'right nil)) + (defun split-root-right (arg) + "Split window right from the root or from the parent with ARG." + (interactive "P") + (split-window (if arg (window-parent (selected-window)) + (frame-root-window)) + nil 'right nil)) - (defun toggle-window-dedication () - "Toggles window dedication in the selected window." - (interactive) - (set-window-dedicated-p - (selected-window) (not (window-dedicated-p (selected-window))))) + (defun toggle-window-dedication () + "Toggles window dedication in the selected window." + (interactive) + (set-window-dedicated-p + (selected-window) (not (window-dedicated-p (selected-window))))) - (defun make-display-buffer-matcher-function (major-modes) - "Return a lambda function to match a list of MAJOR-MODES." - (lambda (buffer-name action) - (with-current-buffer buffer-name (apply #'derived-mode-p major-modes)))) + (defun make-display-buffer-matcher-function (major-modes) + "Return a lambda function to match a list of MAJOR-MODES." + (lambda (buffer-name action) + (with-current-buffer buffer-name (apply #'derived-mode-p major-modes)))) - (global-set-key (kbd "M-o") #'other-window)) + (global-set-key (kbd "M-o") #'other-window)) #+end_src #+caption[Window management modes]: #+caption: Window management modes. #+name: lst:2nd-window-management #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (winner-mode +1)) +(with-eval-after-load 'emacs + (winner-mode +1)) #+end_src #+caption[Window management variables]: #+caption: Window management variables. #+name: lst:3rd-window-management #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; https://www.masteringemacs.org/article/demystifying-emacs-window-manager - (custom-set-variables - '(switch-to-buffer-in-dedicated-window 'pop) - '(switch-to-buffer-obey-display-actions t)) +(with-eval-after-load 'emacs + ;; https://www.masteringemacs.org/article/demystifying-emacs-window-manager + (custom-set-variables + '(switch-to-buffer-in-dedicated-window 'pop) + '(switch-to-buffer-obey-display-actions t)) - (add-to-list 'display-buffer-alist - `(,(rx (or "*Apropos*" - "*Help*" - "*info")) - (display-buffer-reuse-window display-buffer-pop-up-window) - (inhibit-same-window . nil))) - (add-to-list 'display-buffer-alist - `(,(rx (or "*Occur*" - "*grep*" - "*xref*")) - display-buffer-reuse-window - (inhibit-same-window . nil))) - (add-to-list 'display-buffer-alist - '("\\*compilation\\*" - display-buffer-no-window - (allow-no-window . t))) - (add-to-list 'display-buffer-alist - '("^\\*Dictionary\\*" display-buffer-in-side-window - (side . left) - (window-width . 70)))) + (add-to-list 'display-buffer-alist + `(,(rx (or "*Apropos*" + "*Help*" + "*info")) + (display-buffer-reuse-window display-buffer-pop-up-window) + (inhibit-same-window . nil))) + (add-to-list 'display-buffer-alist + `(,(rx (or "*Occur*" + "*grep*" + "*xref*")) + display-buffer-reuse-window + (inhibit-same-window . nil))) + (add-to-list 'display-buffer-alist + '("\\*compilation\\*" + display-buffer-no-window + (allow-no-window . t))) + (add-to-list 'display-buffer-alist + '("^\\*Dictionary\\*" display-buffer-in-side-window + (side . left) + (window-width . 70)))) #+end_src * [[info:elisp#Advising Functions][Advising functions (info)]] @@ -616,56 +616,56 @@ and [[lst:3rd-window-management]] implement a selection of his recommendations. #+caption: Toggle any advice. #+name: lst:toggle-any-advice #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun advice-toggle (symbol where function &optional props) - "Toggle between states after `advice-remove' and `advice-add'." - (let ((how "%s `%s' advice `%s' %s `%s'")) - (if (advice-member-p function symbol) - (progn - (message how "Removal of" where function "from" symbol) - (advice-remove symbol function)) - (message how "Addition of" where function "to" symbol) - (advice-add symbol where function props))))) +(with-eval-after-load 'emacs + (defun advice-toggle (symbol where function &optional props) + "Toggle between states after `advice-remove' and `advice-add'." + (let ((how "%s `%s' advice `%s' %s `%s'")) + (if (advice-member-p function symbol) + (progn + (message how "Removal of" where function "from" symbol) + (advice-remove symbol function)) + (message how "Addition of" where function "to" symbol) + (advice-add symbol where function props))))) #+end_src #+caption[Toggle specific advice]: #+caption: Toggle specific advice. #+name: lst:toggle-specific-advice #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun toggle-engrave-faces-latex-face-apply-override () - "Toggle `engrave-faces-latex-face-apply' advice." - (interactive) - (advice-toggle 'engrave-faces-latex-face-apply - :override #'engrave-faces-latex-face-apply-override)) +(with-eval-after-load 'emacs + (defun toggle-engrave-faces-latex-face-apply-override () + "Toggle `engrave-faces-latex-face-apply' advice." + (interactive) + (advice-toggle 'engrave-faces-latex-face-apply + :override #'engrave-faces-latex-face-apply-override)) - (defun toggle-engrave-faces-latex-face-mapper-override () - "Toggle `engrave-faces-latex-face-mapper' advice." - (interactive) - (advice-toggle 'engrave-faces-latex-face-mapper - :override #'engrave-faces-latex-face-mapper-override)) + (defun toggle-engrave-faces-latex-face-mapper-override () + "Toggle `engrave-faces-latex-face-mapper' advice." + (interactive) + (advice-toggle 'engrave-faces-latex-face-mapper + :override #'engrave-faces-latex-face-mapper-override)) - (defun toggle-eww-display-pdf-around () - "Toggle `eww-display-advice' advice." - (interactive) - (advice-toggle 'eww-display-pdf :around #'eww-display-pdf-as-binary)) + (defun toggle-eww-display-pdf-around () + "Toggle `eww-display-advice' advice." + (interactive) + (advice-toggle 'eww-display-pdf :around #'eww-display-pdf-as-binary)) - (defun toggle-ilog-timer-function-after () - "Toggle `ilog-timer-function' advice." - (interactive) - (advice-toggle 'ilog-timer-function :after #'ilog-ensure-ilog-buffer-window)) + (defun toggle-ilog-timer-function-after () + "Toggle `ilog-timer-function' advice." + (interactive) + (advice-toggle 'ilog-timer-function :after #'ilog-ensure-ilog-buffer-window)) - (defun toggle-keycast-log-update-buffer-override () - "Toggle `keycast-log-update-buffer' advice." - (interactive) - (advice-toggle 'keycast-log-update-buffer - :override #'keycast-log-update-buffer-plain)) + (defun toggle-keycast-log-update-buffer-override () + "Toggle `keycast-log-update-buffer' advice." + (interactive) + (advice-toggle 'keycast-log-update-buffer + :override #'keycast-log-update-buffer-plain)) - (defun toggle-org-babel-python-format-session-value-override () - "Toggle `org-babel-python-format-session-value' advice." - (interactive) - (advice-toggle 'org-babel-python-format-session-value - :override #'org-babel-python-format-session-value-override))) + (defun toggle-org-babel-python-format-session-value-override () + "Toggle `org-babel-python-format-session-value' advice." + (interactive) + (advice-toggle 'org-babel-python-format-session-value + :override #'org-babel-python-format-session-value-override))) #+end_src * [[info:emacs#Dired][Dired: directory editor as file manager (info)]] @@ -705,29 +705,29 @@ extension. #+caption: Customize =dired=. #+name: lst:customize-dired #+begin_src emacs-lisp - (with-eval-after-load 'dired - (custom-set-variables - '(dired-dwim-target t) - ;; | switch | action | - ;; |--------+----------------------------------------| - ;; | -a | also list hidden entries | - ;; | -l | use a long listing format | - ;; | -X | sort alphabetically by entry extension | - ;; | -G | skip long listing format group names | - ;; | -1 | list one entry per line | - '(dired-listing-switches "-alGX1 --group-directories-first") - '(dired-recursive-copies 'always) - '(dired-recursive-deletes 'always))) +(with-eval-after-load 'dired + (custom-set-variables + '(dired-dwim-target t) + ;; | switch | action | + ;; |--------+----------------------------------------| + ;; | -a | also list hidden entries | + ;; | -l | use a long listing format | + ;; | -X | sort alphabetically by entry extension | + ;; | -G | skip long listing format group names | + ;; | -1 | list one entry per line | + '(dired-listing-switches "-alGX1 --group-directories-first") + '(dired-recursive-copies 'always) + '(dired-recursive-deletes 'always))) - (with-eval-after-load 'files - (custom-set-variables - ;; Ensure the use of `GNU-ls' from `coreutils' on darwin. - '(insert-directory-program (or (executable-find "gls") - (executable-find "ls"))))) +(with-eval-after-load 'files + (custom-set-variables + ;; Ensure the use of `GNU-ls' from `coreutils' on darwin. + '(insert-directory-program (or (executable-find "gls") + (executable-find "ls"))))) - (with-eval-after-load 'wdired - (custom-set-variables - '(wdired-allow-to-change-permissions t))) +(with-eval-after-load 'wdired + (custom-set-variables + '(wdired-allow-to-change-permissions t))) #+end_src Listing [[lst:extra-dired-key-bindings]] adds new key bindings to =dired-mode-map= to: @@ -742,45 +742,45 @@ by experienced Emacs users. #+caption: Extra =dired= key bindings. #+name: lst:extra-dired-key-bindings #+begin_src emacs-lisp - (with-eval-after-load 'dired - (defun dired-eww-open-file () - "In Dired, open the regular file named on this line with eww" - (interactive) - (let ((file (dired-get-file-for-visit))) - (if (file-regular-p file) - (eww-open-file file) - (error "Eww rejects `%s', since it is not a regular file" file)))) +(with-eval-after-load 'dired + (defun dired-eww-open-file () + "In Dired, open the regular file named on this line with eww" + (interactive) + (let ((file (dired-get-file-for-visit))) + (if (file-regular-p file) + (eww-open-file file) + (error "Eww rejects `%s', since it is not a regular file" file)))) - ;; https://truongtx.me/tmtxt-dired-async.html - (defun dired-rsync (target) - "Copy marked files with `rsync' to TARGET directory." - (interactive - (list (expand-file-name - (read-file-name "Rsync to:" (dired-dwim-target-directory))))) - ;; Store all marked files into the `files' list and intialize - ;; the `rsync-command'. - (let ((files (dired-get-marked-files nil current-prefix-arg)) - (rsync-command "rsync -av --progress ")) - ;; Add all marked files as arguments to the `rsync-command'. - (dolist (file files) - (setq rsync-command - (concat rsync-command - (if (string-match "^/ssh:\\(.*\\)$" file) - (format " -e ssh %s" (match-string 1 file)) - (shell-quote-argument file)) " "))) - ;; Append the destination directory to the `rsync-command'. + ;; https://truongtx.me/tmtxt-dired-async.html + (defun dired-rsync (target) + "Copy marked files with `rsync' to TARGET directory." + (interactive + (list (expand-file-name + (read-file-name "Rsync to:" (dired-dwim-target-directory))))) + ;; Store all marked files into the `files' list and intialize + ;; the `rsync-command'. + (let ((files (dired-get-marked-files nil current-prefix-arg)) + (rsync-command "rsync -av --progress ")) + ;; Add all marked files as arguments to the `rsync-command'. + (dolist (file files) (setq rsync-command (concat rsync-command - (if (string-match "^/ssh:\\(.*\\)$" target) - (format " -e ssh %s" (match-string 1 target)) - (shell-quote-argument target)))) - ;; Run the async shell command. - (async-shell-command rsync-command) - ;; Finally, switch to that window. - (other-window 1))) + (if (string-match "^/ssh:\\(.*\\)$" file) + (format " -e ssh %s" (match-string 1 file)) + (shell-quote-argument file)) " "))) + ;; Append the destination directory to the `rsync-command'. + (setq rsync-command + (concat rsync-command + (if (string-match "^/ssh:\\(.*\\)$" target) + (format " -e ssh %s" (match-string 1 target)) + (shell-quote-argument target)))) + ;; Run the async shell command. + (async-shell-command rsync-command) + ;; Finally, switch to that window. + (other-window 1))) - (define-key dired-mode-map (kbd "E") #'dired-eww-open-file) - (define-key dired-mode-map (kbd "Y") #'dired-rsync)) + (define-key dired-mode-map (kbd "E") #'dired-eww-open-file) + (define-key dired-mode-map (kbd "Y") #'dired-rsync)) #+end_src * [[info:elisp#Processes][Processes (info)]] @@ -796,12 +796,12 @@ output to =stdout=. #+caption: Process utilities. #+name: lst:process-utilities #+begin_src emacs-lisp - ;; https://gitlab.com/howardabrams/spacemacs.d/blob/master/layers/ha-org/funcs.el#L418 - (defun shell-command-with-exit-code (program &rest args) - "Run PROGRAM with ARGS and return exit-code and output in a list." - (with-temp-buffer - (list (apply 'call-process program nil (current-buffer) nil args) - (buffer-string)))) +;; https://gitlab.com/howardabrams/spacemacs.d/blob/master/layers/ha-org/funcs.el#L418 +(defun shell-command-with-exit-code (program &rest args) + "Run PROGRAM with ARGS and return exit-code and output in a list." + (with-temp-buffer + (list (apply 'call-process program nil (current-buffer) nil args) + (buffer-string)))) #+end_src * [[info:emacs#Help][Help (info)]] @@ -842,45 +842,45 @@ defined in this Org file. #+caption: Configure =shortdoc=. #+name: lst:configure-shortdoc #+begin_src emacs-lisp - (when (fboundp 'shortdoc-display-group) - (define-key help-map (kbd "y") #'shortdoc-display-group) - (with-eval-after-load 'shortdoc - ;; Ensure defining the functions before documenting them. - (define-short-documentation-group init - "Advice" - (advice-toggle :no-manual t) - (toggle-engrave-faces-latex-face-apply-override :no-manual t) - (toggle-engrave-faces-latex-face-mapper-override :no-manual t) - (toggle-eww-display-pdf-around :no-manual t) - (toggle-ilog-timer-function-after :no-manual t) - (toggle-keycast-log-update-buffer-override :no-manual t) - (toggle-org-babel-python-format-session-value-override :no-manual t) - "Face" - (invert-default-face :no-manual t) - (set-default-face-height :no-manual t) - "Interaction" - (enable-this-command :no-manual t) - (narrow-or-widen-dwim :no-manual t) - (org-narrow-to-table :no-manual t) - "LaTeX" - (biber-delete-cache :no-manual t) - (update-lualatex-opentype-font-name-database :no-manual t) - "Org" - (by-backend :no-manual t) - (by-backend-kbd-org-macro :no-manual t) - (org-active-current-time-stamp :nomanual t) - (org-babel-execute:latex-extra-header :no-manual t) - (org-babel-execute:latex-header :no-manual t) - (org-electric-dollar :no-manual t) - (org-eval-emacs-lisp-setup-blocks :no-manual t) - (org-eval-python-setup-blocks :no-manual t) - (org-eval-infixed-blocks :no-manual t) - (org-latex-engraved-source-block-filter :no-manual t) - (org-inactive-current-time-stamp :nomanual t) - (org-syntax-convert-keyword-case-to-lower :no-manual t) - (smart-latex-engrave-org-source-blocks :no-manual t) - "Python" - (choose-common-python-interpreter :no-manual t)))) +(when (fboundp 'shortdoc-display-group) + (define-key help-map (kbd "y") #'shortdoc-display-group) + (with-eval-after-load 'shortdoc + ;; Ensure defining the functions before documenting them. + (define-short-documentation-group init + "Advice" + (advice-toggle :no-manual t) + (toggle-engrave-faces-latex-face-apply-override :no-manual t) + (toggle-engrave-faces-latex-face-mapper-override :no-manual t) + (toggle-eww-display-pdf-around :no-manual t) + (toggle-ilog-timer-function-after :no-manual t) + (toggle-keycast-log-update-buffer-override :no-manual t) + (toggle-org-babel-python-format-session-value-override :no-manual t) + "Face" + (invert-default-face :no-manual t) + (set-default-face-height :no-manual t) + "Interaction" + (enable-this-command :no-manual t) + (narrow-or-widen-dwim :no-manual t) + (org-narrow-to-table :no-manual t) + "LaTeX" + (biber-delete-cache :no-manual t) + (update-lualatex-opentype-font-name-database :no-manual t) + "Org" + (by-backend :no-manual t) + (by-backend-kbd-org-macro :no-manual t) + (org-active-current-time-stamp :nomanual t) + (org-babel-execute:latex-extra-header :no-manual t) + (org-babel-execute:latex-header :no-manual t) + (org-electric-dollar :no-manual t) + (org-eval-emacs-lisp-setup-blocks :no-manual t) + (org-eval-python-setup-blocks :no-manual t) + (org-eval-infixed-blocks :no-manual t) + (org-latex-engraved-source-block-filter :no-manual t) + (org-inactive-current-time-stamp :nomanual t) + (org-syntax-convert-keyword-case-to-lower :no-manual t) + (smart-latex-engrave-org-source-blocks :no-manual t) + "Python" + (choose-common-python-interpreter :no-manual t)))) #+end_src ** [[info:info#Top][Info (info)]] @@ -895,19 +895,19 @@ looks for files. #+caption: Configure =info=. #+name: lst:configure-info #+begin_src emacs-lisp - (with-eval-after-load 'info - ;; Make Emacs find the "*.info" files in `package-user-dir' on Gentoo Linux. - (when (eq system-type 'gnu/linux) - (dolist (path - (nreverse - (mapcar - (lambda (name) - (expand-file-name (file-name-directory name))) - (directory-files-recursively package-user-dir "\\.info\\'")))) - (add-to-list 'Info-directory-list path nil #'file-equal-p))) - ;; Make Emacs find my "python.info" file. - (add-to-list 'Info-directory-list - (expand-file-name "~/.local/share/info"))) +(with-eval-after-load 'info + ;; Make Emacs find the "*.info" files in `package-user-dir' on Gentoo Linux. + (when (eq system-type 'gnu/linux) + (dolist (path + (nreverse + (mapcar + (lambda (name) + (expand-file-name (file-name-directory name))) + (directory-files-recursively package-user-dir "\\.info\\'")))) + (add-to-list 'Info-directory-list path nil #'file-equal-p))) + ;; Make Emacs find my "python.info" file. + (add-to-list 'Info-directory-list + (expand-file-name "~/.local/share/info"))) #+end_src * [[info:emacs#Key Bindings][Key bindings (info)]] @@ -945,16 +945,16 @@ users from shooting themselves in the feet. Listing #+caption: Configure the =disabled-command-function=. #+name: lst:configure-disabled-command-function #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (setq disabled-command-function - (defun enable-this-command (&rest _args) - "Called when a disabled command is executed. - Enable it and re-execute it." - (put this-command 'disabled nil) - (message "You typed %s. %s was disabled until now." - (key-description (this-command-keys)) this-command) - (sit-for 0) - (call-interactively this-command)))) +(with-eval-after-load 'emacs + (setq disabled-command-function + (defun enable-this-command (&rest _args) + "Called when a disabled command is executed. +Enable it and re-execute it." + (put this-command 'disabled nil) + (message "You typed %s. %s was disabled until now." + (key-description (this-command-keys)) this-command) + (sit-for 0) + (call-interactively this-command)))) #+end_src ** [[https://github.com/michael-heerdegen/interaction-log.el#readme][Interaction-log]] @@ -966,18 +966,18 @@ users from shooting themselves in the feet. Listing #+caption: Configure =interaction-log=. #+name: lst:configure-interaction-log #+begin_src emacs-lisp - (when (and (ensure-package-installation 'interaction-log) - (require 'interaction-log nil 'noerror)) +(when (and (ensure-package-installation 'interaction-log) + (require 'interaction-log nil 'noerror)) - ;; https://www.skybert.net/emacs/show-shortcuts-when-giving-presentations/ - (defun ilog-ensure-ilog-buffer-window () - "Ensure the visibility of the `ilog' buffer, when it exists." - (when (and (get-buffer ilog-buffer-name) - (not (get-buffer-window ilog-buffer-name))) - (display-buffer (get-buffer ilog-buffer-name)))) + ;; https://www.skybert.net/emacs/show-shortcuts-when-giving-presentations/ + (defun ilog-ensure-ilog-buffer-window () + "Ensure the visibility of the `ilog' buffer, when it exists." + (when (and (get-buffer ilog-buffer-name) + (not (get-buffer-window ilog-buffer-name))) + (display-buffer (get-buffer ilog-buffer-name)))) - (define-key help-map (kbd "C-l") #'interaction-log-mode) - (advice-add 'ilog-timer-function :after #'ilog-ensure-ilog-buffer-window)) + (define-key help-map (kbd "C-l") #'interaction-log-mode) + (advice-add 'ilog-timer-function :after #'ilog-ensure-ilog-buffer-window)) #+end_src @@ -993,39 +993,39 @@ Listing [[lst:configure-keycast]] configures =keycast=. #+caption: Configure =keycast=. #+name: lst:configure-keycast #+begin_src emacs-lisp - ;; Make `keycast-log-update-buffer' use a buffer similar to the - ;; control buffer `ediff-setup-windows-plain' returns. - (when (and (ensure-package-installation 'keycast) - (require 'keycast nil 'noerror)) - (custom-set-variables - '(keycast-mode-line-window-predicate 'keycast-bottom-right-window-p)) +;; Make `keycast-log-update-buffer' use a buffer similar to the +;; control buffer `ediff-setup-windows-plain' returns. +(when (and (ensure-package-installation 'keycast) + (require 'keycast nil 'noerror)) + (custom-set-variables + '(keycast-mode-line-window-predicate 'keycast-bottom-right-window-p)) - (defun keycast-log-update-buffer-plain () - (let ((buffer (get-buffer keycast-log-buffer-name))) - (unless (buffer-live-p buffer) - (setq buffer (get-buffer-create keycast-log-buffer-name)) - (with-current-buffer buffer - (setq buffer-read-only t))) - (unless (get-buffer-window buffer) - (display-buffer buffer '(display-buffer-at-bottom - (dedicated . t) - (window-height . 10)))) - (when-let ((output (keycast--format keycast-log-format))) - (with-current-buffer buffer - (goto-char (if keycast-log-newest-first (point-min) (point-max))) - (let ((inhibit-read-only t)) - (when (and (> keycast--command-repetitions 0) - (string-match-p "%[rR]" keycast-log-format)) - (unless keycast-log-newest-first - (backward-char)) - (ignore-errors - (delete-region (line-beginning-position) - (1+ (line-end-position))))) - (insert output)) - (goto-char (if keycast-log-newest-first (point-min) (point-max))))))) + (defun keycast-log-update-buffer-plain () + (let ((buffer (get-buffer keycast-log-buffer-name))) + (unless (buffer-live-p buffer) + (setq buffer (get-buffer-create keycast-log-buffer-name)) + (with-current-buffer buffer + (setq buffer-read-only t))) + (unless (get-buffer-window buffer) + (display-buffer buffer '(display-buffer-at-bottom + (dedicated . t) + (window-height . 10)))) + (when-let ((output (keycast--format keycast-log-format))) + (with-current-buffer buffer + (goto-char (if keycast-log-newest-first (point-min) (point-max))) + (let ((inhibit-read-only t)) + (when (and (> keycast--command-repetitions 0) + (string-match-p "%[rR]" keycast-log-format)) + (unless keycast-log-newest-first + (backward-char)) + (ignore-errors + (delete-region (line-beginning-position) + (1+ (line-end-position))))) + (insert output)) + (goto-char (if keycast-log-newest-first (point-min) (point-max))))))) - (advice-add 'keycast-log-update-buffer - :override #'keycast-log-update-buffer-plain)) + (advice-add 'keycast-log-update-buffer + :override #'keycast-log-update-buffer-plain)) #+end_src * [[info:emacs#Emacs Server][Using Emacs as a server (info)]] @@ -1046,9 +1046,9 @@ The code in listing [[lst:start-emacs-server]] starts the Emacs server. #+caption: Start the Emacs server. #+name: lst:start-emacs-server #+begin_src emacs-lisp - (when window-system - (unless (or noninteractive (daemonp)) - (add-hook 'after-init-hook #'server-start))) +(when window-system + (unless (or noninteractive (daemonp)) + (add-hook 'after-init-hook #'server-start))) #+end_src ** Latexmk save-compile-display loop @@ -1068,27 +1068,27 @@ variable in section are compatible. The local variable ~compile-command~ in the #+caption: Tangle the =Latexmk= resource file. #+name: lst:latexmkrc #+begin_src perl :tangle latexmkrc :comments no - # pdf creator - $pdf_mode = 4; # 4 means lualatex - # pdf previewer and update pdf previewer - $pdf_previewer = "emacsclient -e '(find-file-other-window %S)'"; - $pdf_update_method = 4; # 4 runs $pdf_update_command to force the update - $pdf_update_command = "emacsclient -e '(with-current-buffer (find-buffer-visiting %S) (pdf-view-revert-buffer nil t))'"; - # see for instance glossary.latexmkrc - add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' ); - add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' ); - # use ".=" to append to $clean_ext - $clean_ext .= " acr acn alg bbl dvi glo gls glg ist lol lst"; - $clean_ext .= " nav run.xml snm synctex.gz"; - sub makeglossaries { - my ($name, $path) = fileparse( $$Psource ); - return system "makeglossaries -d '$path' '$name'"; - } - # Emacs looks for "Local variables:" after the last "newline-formfeed". - - # Local Variables: - # mode: perl - # End: +# pdf creator +$pdf_mode = 4; # 4 means lualatex +# pdf previewer and update pdf previewer +$pdf_previewer = "emacsclient -e '(find-file-other-window %S)'"; +$pdf_update_method = 4; # 4 runs $pdf_update_command to force the update +$pdf_update_command = "emacsclient -e '(with-current-buffer (find-buffer-visiting %S) (pdf-view-revert-buffer nil t))'"; +# see for instance glossary.latexmkrc +add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' ); +add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' ); +# use ".=" to append to $clean_ext +$clean_ext .= " acr acn alg bbl dvi glo gls glg ist lol lst"; +$clean_ext .= " nav run.xml snm synctex.gz"; +sub makeglossaries { + my ($name, $path) = fileparse( $$Psource ); + return system "makeglossaries -d '$path' '$name'"; +} +# Emacs looks for "Local variables:" after the last "newline-formfeed". + +# Local Variables: +# mode: perl +# End: #+end_src ** [[https://qutebrowser.org/doc/userscripts.html][Qutebrowser userscript]] @@ -1114,15 +1114,15 @@ may hang or die. #+header: :tangle-mode (identity #o755) #+name: lst:qutebrowser-userscript #+begin_src python :noeval :tangle org-store-link - #!/usr/bin/env python - from urllib.parse import urlencode - from os import environ, execvp +#!/usr/bin/env python +from urllib.parse import urlencode +from os import environ, execvp - url = environ.get("QUTE_URL", "https://orgmode.org") - title = environ.get("QUTE_TITLE", "Org Mode") - parameters = urlencode({"url": url, "title": title}) - print(payload := f"org-protocol://store-link?{parameters}") - execvp("emacsclient", ("-n", payload)) +url = environ.get("QUTE_URL", "https://orgmode.org") +title = environ.get("QUTE_TITLE", "Org Mode") +parameters = urlencode({"url": url, "title": title}) +print(payload := f"org-protocol://store-link?{parameters}") +execvp("emacsclient", ("-n", payload)) #+end_src ** TODO Look into: org-protocol handling with other browser on Darwin @@ -1144,32 +1144,32 @@ may hang or die. #+caption: Ensure =applescript-mode= installation. #+name: lst:ensure-applescript-mode-installation #+begin_src emacs-lisp - (when (ensure-package-installation 'applescript-mode)) +(when (ensure-package-installation 'applescript-mode)) #+end_src #+caption[Applescript code to register =org-protocol= on Darwin]: #+caption: Applescript code to register =org-protocol= on Darwin. #+name: lst:applescript-org-protocol #+begin_src applescript :tangle no - on emacsclient(input) - do shell script "/usr/local/bin/emacsclient -n -c '" & input & "'" - tell application "Emacs" to activate - end emacsclient +on emacsclient(input) + do shell script "/usr/local/bin/emacsclient -n -c '" & input & "'" + tell application "Emacs" to activate +end emacsclient - on open location input +on open location input + emacsclient(input) +end open location + +on open inputs + repeat with raw_input in inputs + set input to POSIX path of raw_input emacsclient(input) - end open location + end repeat +end open - on open inputs - repeat with raw_input in inputs - set input to POSIX path of raw_input - emacsclient(input) - end repeat - end open - - on run - do shell script emacsclient("") - end run +on run + do shell script emacsclient("") +end run #+end_src * Completion @@ -1206,21 +1206,21 @@ file. #+caption: Enable =savehist-mode= and =vertico-mode=. #+name: lst:enable-vertico-mode #+begin_src emacs-lisp - (when (fboundp 'savehist-mode) - (savehist-mode +1) - (custom-set-variables - '(savehist-additional-variables - '(eww-history - kill-ring - regexp-search-string - search-ring - search-string)))) - (when (fboundp 'vertico-mode) - (vertico-mode +1)) - (with-eval-after-load 'vertico - (define-key vertico-map (kbd "RET") #'vertico-directory-enter) - (define-key vertico-map (kbd "DEL") #'vertico-directory-delete-char) - (define-key vertico-map (kbd "M-DEL") #'vertico-directory-delete-word)) +(when (fboundp 'savehist-mode) + (savehist-mode +1) + (custom-set-variables + '(savehist-additional-variables + '(eww-history + kill-ring + regexp-search-string + search-ring + search-string)))) +(when (fboundp 'vertico-mode) + (vertico-mode +1)) +(with-eval-after-load 'vertico + (define-key vertico-map (kbd "RET") #'vertico-directory-enter) + (define-key vertico-map (kbd "DEL") #'vertico-directory-delete-char) + (define-key vertico-map (kbd "M-DEL") #'vertico-directory-delete-word)) #+end_src #+attr_latex: :booktabs yes :float table @@ -1263,16 +1263,16 @@ file. #+caption: Configure =orderless=. #+name: lst:configure-orderless #+begin_src emacs-lisp - (when (ensure-package-installation 'marginalia) - (with-eval-after-load 'orderless - (custom-set-variables - '(orderless-component-separator " +")) +(when (ensure-package-installation 'marginalia) + (with-eval-after-load 'orderless + (custom-set-variables + '(orderless-component-separator " +")) - (defun just-one-face (fn &rest args) - (let ((orderless-match-faces [completions-common-part])) - (apply fn args))) + (defun just-one-face (fn &rest args) + (let ((orderless-match-faces [completions-common-part])) + (apply fn args))) - (advice-add 'company-capf--candidates :around #'just-one-face))) + (advice-add 'company-capf--candidates :around #'just-one-face))) #+end_src ** [[info:embark#Top][Embark (info)]] @@ -1299,15 +1299,15 @@ Listing [[lst:configure-embark]] configures =embark= key bindings: #+caption: Configure =embark=. #+name: lst:configure-embark #+begin_src emacs-lisp - (when (ensure-package-installation 'embark) - (when (fboundp 'embark-act) - (global-set-key (kbd "C-,") #'embark-act)) - (when (fboundp 'embark-dwim) - (global-set-key (kbd "C-:") #'embark-dwim)) - (when (fboundp 'embark-bindings) - (global-set-key (kbd "C-h B") #'embark-bindings)) - (when (fboundp 'embark-prefix-help-command) - (setq prefix-help-command #'embark-prefix-help-command))) +(when (ensure-package-installation 'embark) + (when (fboundp 'embark-act) + (global-set-key (kbd "C-,") #'embark-act)) + (when (fboundp 'embark-dwim) + (global-set-key (kbd "C-:") #'embark-dwim)) + (when (fboundp 'embark-bindings) + (global-set-key (kbd "C-h B") #'embark-bindings)) + (when (fboundp 'embark-prefix-help-command) + (setq prefix-help-command #'embark-prefix-help-command))) #+end_src ** [[info:marginalia#Top][Marginalia (info)]] @@ -1321,9 +1321,9 @@ Listing [[lst:enable-marginalia-mode]] enables =marginalia-mode=. #+caption: Enable =marginalia-mode=. #+name: lst:enable-marginalia-mode #+begin_src emacs-lisp - (when (and (ensure-package-installation 'marginalia) - (fboundp 'marginalia-mode)) - (marginalia-mode +1)) +(when (and (ensure-package-installation 'marginalia) + (fboundp 'marginalia-mode)) + (marginalia-mode +1)) #+end_src ** [[info:consult#Top][Consult (info)]] @@ -1386,38 +1386,38 @@ function [[info:elisp#Minibuffer Completion][completing-read]]. Listing [[lst:c #+caption: Configure =consult=. #+name: lst:configure-consult #+begin_src emacs-lisp - (when (ensure-package-installation 'consult) - (custom-set-variables - '(consult-project-function #'(lambda (_) (vc-root-dir)))) - ;; C-c bindings (current-global-map) - (global-set-key (kbd "C-c h") #'consult-history) - (global-set-key (kbd "C-c m") #'consult-mode-command) - ;; C-h bindings (help-map) - (define-key help-map (kbd "a") #'consult-apropos) - ;; C-x bindings (ctl-x-map) - (define-key ctl-x-map (kbd "M-:") #'consult-complex-command) - (define-key ctl-x-map (kbd "b") #'consult-buffer) - (define-key ctl-x-4-map (kbd "b") #'consult-buffer-other-window) - (define-key ctl-x-5-map (kbd "b") #'consult-buffer-other-frame) - (define-key ctl-x-r-map (kbd "x") #'consult-register) - (define-key ctl-x-r-map (kbd "b") #'consult-bookmark) - ;; M-g bindings (goto-map) - (define-key goto-map (kbd "g") #'consult-goto-line) - (define-key goto-map (kbd "M-g") #'consult-goto-line) - (define-key goto-map (kbd "o") #'consult-outline) - (define-key goto-map (kbd "m") #'consult-mark) - (define-key goto-map (kbd "k") #'consult-global-mark) - (define-key goto-map (kbd "i") #'consult-imenu) - (define-key goto-map (kbd "e") #'consult-compile-error) - ;; M-s bindings (search-map) - (define-key search-map (kbd "g") #'consult-git-grep) - (define-key search-map (kbd "f") #'consult-find) - (define-key search-map (kbd "k") #'consult-keep-lines) - (define-key search-map (kbd "l") #'consult-line) - (define-key search-map (kbd "m") #'consult-multi-occur) - (define-key search-map (kbd "u") #'consult-focus-lines) - ;; Other bindings (current-global-map) - (global-set-key (kbd "M-y") #'consult-yank-pop)) +(when (ensure-package-installation 'consult) + (custom-set-variables + '(consult-project-function #'(lambda (_) (vc-root-dir)))) + ;; C-c bindings (current-global-map) + (global-set-key (kbd "C-c h") #'consult-history) + (global-set-key (kbd "C-c m") #'consult-mode-command) + ;; C-h bindings (help-map) + (define-key help-map (kbd "a") #'consult-apropos) + ;; C-x bindings (ctl-x-map) + (define-key ctl-x-map (kbd "M-:") #'consult-complex-command) + (define-key ctl-x-map (kbd "b") #'consult-buffer) + (define-key ctl-x-4-map (kbd "b") #'consult-buffer-other-window) + (define-key ctl-x-5-map (kbd "b") #'consult-buffer-other-frame) + (define-key ctl-x-r-map (kbd "x") #'consult-register) + (define-key ctl-x-r-map (kbd "b") #'consult-bookmark) + ;; M-g bindings (goto-map) + (define-key goto-map (kbd "g") #'consult-goto-line) + (define-key goto-map (kbd "M-g") #'consult-goto-line) + (define-key goto-map (kbd "o") #'consult-outline) + (define-key goto-map (kbd "m") #'consult-mark) + (define-key goto-map (kbd "k") #'consult-global-mark) + (define-key goto-map (kbd "i") #'consult-imenu) + (define-key goto-map (kbd "e") #'consult-compile-error) + ;; M-s bindings (search-map) + (define-key search-map (kbd "g") #'consult-git-grep) + (define-key search-map (kbd "f") #'consult-find) + (define-key search-map (kbd "k") #'consult-keep-lines) + (define-key search-map (kbd "l") #'consult-line) + (define-key search-map (kbd "m") #'consult-multi-occur) + (define-key search-map (kbd "u") #'consult-focus-lines) + ;; Other bindings (current-global-map) + (global-set-key (kbd "M-y") #'consult-yank-pop)) #+end_src ** [[https://company-mode.github.io/][Company: a modular complete anything framework for Emacs]] @@ -1431,19 +1431,19 @@ Listing [[lst:configure-company]] configures =company=. #+caption: Configure =company=. #+name: lst:configure-company #+begin_src emacs-lisp - (when (fboundp 'company-mode) - (custom-set-variables - ;; https://github.com/purcell/emacs.d/issues/778 - '(company-transformers '(company-sort-by-occurrence))) - (dolist (hook '(LaTeX-mode-hook - org-mode-hook - emacs-lisp-mode-hook - lisp-interaction-mode-hook - lisp-mode-hook - python-mode-hook - ielm-mode-hook - sly-mrepl-mode-hook)) - (add-hook hook #'company-mode))) +(when (fboundp 'company-mode) + (custom-set-variables + ;; https://github.com/purcell/emacs.d/issues/778 + '(company-transformers '(company-sort-by-occurrence))) + (dolist (hook '(LaTeX-mode-hook + org-mode-hook + emacs-lisp-mode-hook + lisp-interaction-mode-hook + lisp-mode-hook + python-mode-hook + ielm-mode-hook + sly-mrepl-mode-hook)) + (add-hook hook #'company-mode))) #+end_src ** [[https://lists.gnu.org/archive/html/emacs-devel/2021-12/msg00802.html][Minibuffer history completion]] @@ -1459,29 +1459,29 @@ previous input in the minibuffer. Listing #+caption: Enable =minibuffer-history-completion=. #+name: lst:enable-minibuffer-history-completion #+begin_src emacs-lisp - (when (require 'minibuffer nil 'noerror) - ;; https://www.masteringemacs.org/article/understanding-minibuffer-completion - (custom-set-variables - '(completion-category-overrides '((file (styles basic substring)))) - '(completion-ignore-case nil) - '(completion-styles '(flex partial-completion substring))) +(when (require 'minibuffer nil 'noerror) + ;; https://www.masteringemacs.org/article/understanding-minibuffer-completion + (custom-set-variables + '(completion-category-overrides '((file (styles basic substring)))) + '(completion-ignore-case nil) + '(completion-styles '(flex partial-completion substring))) - (defun minibuffer-setup-history-completions () - (unless (or minibuffer-completion-table minibuffer-completion-predicate) - (setq-local minibuffer-completion-table - (symbol-value minibuffer-history-variable)))) + (defun minibuffer-setup-history-completions () + (unless (or minibuffer-completion-table minibuffer-completion-predicate) + (setq-local minibuffer-completion-table + (symbol-value minibuffer-history-variable)))) - (add-hook 'minibuffer-setup-hook 'minibuffer-setup-history-completions) + (add-hook 'minibuffer-setup-hook 'minibuffer-setup-history-completions) - ;; Adapted from ‘minibuffer-complete’: - (defun minibuffer-complete-history () - "Allow minibuffer completion on previous input." - (interactive) - (completion-in-region (minibuffer--completion-prompt-end) (point-max) - (symbol-value minibuffer-history-variable) - nil)) + ;; Adapted from ‘minibuffer-complete’: + (defun minibuffer-complete-history () + "Allow minibuffer completion on previous input." + (interactive) + (completion-in-region (minibuffer--completion-prompt-end) (point-max) + (symbol-value minibuffer-history-variable) + nil)) - (define-key minibuffer-local-map (kbd "C-") #'minibuffer-complete-history)) + (define-key minibuffer-local-map (kbd "C-") #'minibuffer-complete-history)) #+end_src * [[info:emacs#Search][Search and replace (info)]] @@ -1532,11 +1532,11 @@ to {{{kbd(M-s d)}}} and =deadgrep-edit-mode= to {{{kbd(C-c C-w)}}}. #+caption: Configure =deadgrep=. #+name: lst:configure-deadgrep #+begin_src emacs-lisp - (when (and (ensure-package-installation 'deadgrep) - (fboundp 'deadgrep)) - (define-key search-map (kbd "d") #'deadgrep) - (with-eval-after-load 'deadgrep - (define-key deadgrep-mode-map (kbd "C-c C-w") #'deadgrep-edit-mode))) +(when (and (ensure-package-installation 'deadgrep) + (fboundp 'deadgrep)) + (define-key search-map (kbd "d") #'deadgrep) + (with-eval-after-load 'deadgrep + (define-key deadgrep-mode-map (kbd "C-c C-w") #'deadgrep-edit-mode))) #+end_src ** [[https://www.genivia.com/get-ugrep.html][Ugrep]] @@ -1553,30 +1553,30 @@ suggestions on those pages. #+caption: Use =ugrep= when available. #+name: lst:use-ugrep #+begin_src emacs-lisp - (when (executable-find "ugrep") - (with-eval-after-load 'grep - (custom-set-variables - `(grep-template ,(string-join '("ugrep" - "--color=always" - "--decompress" - "--ignore-binary" - "--ignore-case" - "--include=\"\"" - "--line-number" - "--null" - "--recursive" - "--regexp=") - " ")))) - (with-eval-after-load 'xref - (custom-set-variables - '(xref-search-program-alist - '((grep - . "xargs -0 grep --null -snHE -e ") - (ripgrep - . "xargs -0 rg --null -nH --no-heading --no-messages -g '!*/' -e ") - (ugrep - . "xargs -0 ugrep --null -ns -e "))) - '(xref-search-program 'ugrep)))) +(when (executable-find "ugrep") + (with-eval-after-load 'grep + (custom-set-variables + `(grep-template ,(string-join '("ugrep" + "--color=always" + "--decompress" + "--ignore-binary" + "--ignore-case" + "--include=\"\"" + "--line-number" + "--null" + "--recursive" + "--regexp=") + " ")))) + (with-eval-after-load 'xref + (custom-set-variables + '(xref-search-program-alist + '((grep + . "xargs -0 grep --null -snHE -e ") + (ripgrep + . "xargs -0 rg --null -nH --no-heading --no-messages -g '!*/' -e ") + (ugrep + . "xargs -0 ugrep --null -ns -e "))) + '(xref-search-program 'ugrep)))) #+end_src * [[info:emacs#Version Control][Version Control (info)]] @@ -1599,17 +1599,17 @@ single frame and to make all text visible prior to ediffing Org buffers. #+caption: Configure =ediff=. #+name: lst:configure-ediff #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (custom-set-variables - '(ediff-merge-split-window-function #'split-window-horizontally) - '(ediff-split-window-function #'split-window-horizontally) - '(ediff-window-setup-function #'ediff-setup-windows-plain))) - (with-eval-after-load 'org - ;; https://github.com/oantolin/emacs-config#readme - (defun ediff-with-org-show-all () - "Expand all headings prior to ediffing org buffers." - (add-hook 'ediff-prepare-buffer-hook #'org-show-all nil t)) - (add-hook 'org-mode-hook #'ediff-with-org-show-all)) +(with-eval-after-load 'emacs + (custom-set-variables + '(ediff-merge-split-window-function #'split-window-horizontally) + '(ediff-split-window-function #'split-window-horizontally) + '(ediff-window-setup-function #'ediff-setup-windows-plain))) +(with-eval-after-load 'org + ;; https://github.com/oantolin/emacs-config#readme + (defun ediff-with-org-show-all () + "Expand all headings prior to ediffing org buffers." + (add-hook 'ediff-prepare-buffer-hook #'org-show-all nil t)) + (add-hook 'org-mode-hook #'ediff-with-org-show-all)) #+end_src ** [[https://git-scm.com/book/en/v2][Git]] @@ -1629,35 +1629,35 @@ or src_emacs-lisp{(magit-push-current-to-upstream)}. #+caption: Forking and branching on Github or Gitlab. #+name: lst:forking-and-branching-remote-repositories #+begin_src shell :noeval - # Clone the repository - git clone git@github.com:gav451/engrave-faces engrave-faces-fork - cd engrave-face-fork - # Handle 1st branch: - # - Create and switch to a new branch with either: - git switch -c latex-engrave-symbolic-color-names - # or: git checkout -b latex-engrave-symbolic-color-names - # - Use "--set-upstream origin" as a 1st-time branch push: - git push --set-upstream origin latex-engrave-symbolic-color-names - # - Create, add, and commit, and push changes in this branch: - nano engrave-faces-latex.el - git add engrave-faces-latex.el - git commit -m 'Commit latex-engrave-dont-symbolic-color-names changes' - git push - # - Switch to master branch: - git checkout master - # Handle 2nd branch: - # - Create and switch to a new branch with either: - git switch -c latex-engrave-dont-wrap-white-space - # - or: git checkout -b latex-engrave-dont-wrap-white-space - # - Use "--set-upstream origin" as a 1st-time branch push: - git push --set-upstream origin latex-engrave-dont-wrap-white-space - # - Create, add, commit, and push changes in this branch: - nano engrave-faces-latex.el - git add engrave-faces-latex.el - git commit -m 'Commit latex-engrave-dont-wrap-white-space changes' - git push - # - Switch to master branch: - git checkout master +# Clone the repository +git clone git@github.com:gav451/engrave-faces engrave-faces-fork +cd engrave-face-fork +# Handle 1st branch: +# - Create and switch to a new branch with either: +git switch -c latex-engrave-symbolic-color-names +# or: git checkout -b latex-engrave-symbolic-color-names +# - Use "--set-upstream origin" as a 1st-time branch push: +git push --set-upstream origin latex-engrave-symbolic-color-names +# - Create, add, and commit, and push changes in this branch: +nano engrave-faces-latex.el +git add engrave-faces-latex.el +git commit -m 'Commit latex-engrave-dont-symbolic-color-names changes' +git push +# - Switch to master branch: +git checkout master +# Handle 2nd branch: +# - Create and switch to a new branch with either: +git switch -c latex-engrave-dont-wrap-white-space +# - or: git checkout -b latex-engrave-dont-wrap-white-space +# - Use "--set-upstream origin" as a 1st-time branch push: +git push --set-upstream origin latex-engrave-dont-wrap-white-space +# - Create, add, commit, and push changes in this branch: +nano engrave-faces-latex.el +git add engrave-faces-latex.el +git commit -m 'Commit latex-engrave-dont-wrap-white-space changes' +git push +# - Switch to master branch: +git checkout master #+end_src *** [[https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/git-push-new-branch-remote-github-gitlab-upstream-example][List all Git branches]] @@ -1669,7 +1669,7 @@ or src_emacs-lisp{(magit-push-current-to-upstream)}. #+caption: List all =git= branches. #+name: lst:list-all-git-branches #+begin_src shell :exports both :results verbatim - git -C ~/VCS/engrave-faces-fork branch -a +git -C ~/VCS/engrave-faces-fork branch -a #+end_src #+RESULTS: lst:list-all-git-branches @@ -1710,9 +1710,9 @@ Listing [[lst:configure-nov]] configures [[https://depp.brause.cc/nov.el/][nov.e #+caption: Configure =nov=. #+name: lst:configure-nov #+begin_src emacs-lisp - (when (and (ensure-package-installation 'nov) - (fboundp 'nov-mode)) - (add-to-list 'auto-mode-alist `(,(rx ".epub" eos) . nov-mode))) +(when (and (ensure-package-installation 'nov) + (fboundp 'nov-mode)) + (add-to-list 'auto-mode-alist `(,(rx ".epub" eos) . nov-mode))) #+end_src ** Reading PDF files @@ -1733,23 +1733,23 @@ rebuild the =epdfinfo= executable that serves the [[https://en.wikipedia.org/wik #+caption: Configure =pdf-tools=. #+name: lst:configure-pdf-tools #+begin_src emacs-lisp - (when (and (ensure-package-installation 'pdf-tools 'saveplace-pdf-view) - (fboundp 'pdf-loader-install)) - ;; `pdf-loader-install' is the lazy equivalent of `pdf-tools-install': - ;; see the README file. - (pdf-loader-install) +(when (and (ensure-package-installation 'pdf-tools 'saveplace-pdf-view) + (fboundp 'pdf-loader-install)) + ;; `pdf-loader-install' is the lazy equivalent of `pdf-tools-install': + ;; see the README file. + (pdf-loader-install) - (with-eval-after-load 'pdf-outline - ;; Unmask the `image-save' key binding in `pdf-view-mode-map' and - ;; in `image-mode-map' (by parenthood). - (define-key pdf-outline-minor-mode-map (kbd "o") nil) - (define-key pdf-outline-minor-mode-map (kbd "O") #'pdf-outline)) + (with-eval-after-load 'pdf-outline + ;; Unmask the `image-save' key binding in `pdf-view-mode-map' and + ;; in `image-mode-map' (by parenthood). + (define-key pdf-outline-minor-mode-map (kbd "o") nil) + (define-key pdf-outline-minor-mode-map (kbd "O") #'pdf-outline)) - (with-eval-after-load 'pdf-view - (custom-set-variables - '(pdf-view-display-size 'fit-page) - `(pdf-view-use-scaling ,(eq system-type 'darwin))) - (require 'saveplace-pdf-view nil 'noerror))) + (with-eval-after-load 'pdf-view + (custom-set-variables + '(pdf-view-display-size 'fit-page) + `(pdf-view-use-scaling ,(eq system-type 'darwin))) + (require 'saveplace-pdf-view nil 'noerror))) #+end_src * Writing @@ -1785,64 +1785,64 @@ configuration objectives: #+caption: Require and configure =TeX=. #+name: lst:require-tex #+begin_src emacs-lisp - ;; Use `require' to make `TeX-master' a safe local variable. - (when (require 'tex nil 'noerror) - (custom-set-variables - '(TeX-auto-save t) - '(TeX-engine 'luatex) - '(TeX-indent-close-delimiters "]") - '(TeX-indent-open-delimiters "[") - '(TeX-install-font-lock #'font-latex-setup) - '(TeX-parse-self t) - ;; Disable `TeX-electric-math' to prevent collisions with `smartparens'. - '(TeX-electric-math nil))) +;; Use `require' to make `TeX-master' a safe local variable. +(when (require 'tex nil 'noerror) + (custom-set-variables + '(TeX-auto-save t) + '(TeX-engine 'luatex) + '(TeX-indent-close-delimiters "]") + '(TeX-indent-open-delimiters "[") + '(TeX-install-font-lock #'font-latex-setup) + '(TeX-parse-self t) + ;; Disable `TeX-electric-math' to prevent collisions with `smartparens'. + '(TeX-electric-math nil))) #+end_src #+caption[Update the =LuaLaTeX OpenType Font= name database]: #+caption: Update the =LuaLaTeX= =OpenType Font= name database. #+name: lst:update-lualatex-opentype-font-name-database #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun update-lualatex-opentype-font-name-database () - "Update the \"OpenType Font\" name database for \"LuaLaTeX\"." - (interactive) - (cl-destructuring-bind (exit-code output) - (shell-command-with-exit-code - "luaotfload-tool" "-vv" "--update" "--force") - (if (= 0 exit-code) - (message "%s" (string-trim output)) - (error "%s" (string-trim output)))))) +(with-eval-after-load 'emacs + (defun update-lualatex-opentype-font-name-database () + "Update the \"OpenType Font\" name database for \"LuaLaTeX\"." + (interactive) + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code + "luaotfload-tool" "-vv" "--update" "--force") + (if (= 0 exit-code) + (message "%s" (string-trim output)) + (error "%s" (string-trim output)))))) #+end_src #+caption[Configure =bibtex=]: #+caption: Configure =bibtex=. #+name: lst:configure-bibtex #+begin_src emacs-lisp - (with-eval-after-load 'bibtex - (custom-set-variables '(bibtex-dialect 'BibTeX))) +(with-eval-after-load 'bibtex + (custom-set-variables '(bibtex-dialect 'BibTeX))) #+end_src #+caption[Configure =font-latex=]: #+caption: Configure =font-latex=. #+name: lst:configure-font-latex #+begin_src emacs-lisp - (with-eval-after-load 'font-latex - (custom-set-variables - '(font-latex-fontify-sectioning 1.0))) +(with-eval-after-load 'font-latex + (custom-set-variables + '(font-latex-fontify-sectioning 1.0))) #+end_src #+caption[Configure =latex=]: #+caption: Configure =latex=. #+name: lst:configure-latex #+begin_src emacs-lisp - (with-eval-after-load 'latex - (custom-set-variables - '(LaTeX-electric-left-right-brace t) - '(LaTeX-section-hook '(LaTeX-section-heading - LaTeX-section-title - LaTeX-section-toc - LaTeX-section-section - LaTeX-section-label)))) +(with-eval-after-load 'latex + (custom-set-variables + '(LaTeX-electric-left-right-brace t) + '(LaTeX-section-hook '(LaTeX-section-heading + LaTeX-section-title + LaTeX-section-toc + LaTeX-section-section + LaTeX-section-label)))) #+end_src *** [[https://gitlab.com/matsievskiysv/math-preview/-/blob/master/README.md][Math-preview]] @@ -1857,53 +1857,53 @@ buffers with help of an external [[https://nodejs.org][node.js]] program. #+caption: Configure =math-preview=. #+name: lst:configure-math-preview #+begin_src emacs-lisp - (when (ensure-package-installation 'math-preview) - (with-eval-after-load 'math-preview - ;; https://docs.mathjax.org/en/latest/input/tex/extensions/physics.html - (let ((physics (split-string " - abs absolutevalue acomm acos acosecant acosine acot acotangent - acsc admat anticommutator antidiagonalmatrix arccos arccosecant - arccosine arccot arccotangent arccsc arcsec arcsecant arcsin - arcsine arctan arctangent asec asecant asin asine atan atangent - bmqty bqty Bqty bra braket comm commutator cos cosecant cosh - cosine cot cotangent coth cp cross crossproduct csc csch curl dd - derivative det determinant diagonalmatrix diffd differential div - divergence dmat dotproduct dv dyad erf ev eval evaluated exp - expectationvalue exponential expval fderivative fdv flatfrac - functionalderivative grad gradient gradientnabla hypcosecant - hypcosine hypcotangent hypsecant hypsine hyptangent - identitymatrix Im imaginary imat innerproduct ip ket ketbra - laplacian ln log logarithm matrixdeterminant matrixel - matrixelement matrixquantity mdet mel mqty naturallogarithm norm - op order outerproduct partialderivative paulimatrix pb - pderivative pdv pmat pmqty Pmqty poissonbracket pqty Pr - principalvalue Probability pv PV qall qand qas qassume qc qcc - qcomma qelse qeven qfor qgiven qif qin qinteger qlet qodd qor - qotherwise qq qqtext qsince qthen qty quantity qunless qusing - rank Re real Res Residue sbmqty sec secant sech sin sine sinh - smallmatrixquantity smdet smqty spmqty sPmqty svmqty tan tangent - tanh tr Tr trace Trace va var variation vb vdot vectorarrow - vectorbold vectorunit vmqty vnabla vqty vu xmat xmatrix - zeromatrix zmat"))) - (cl-pushnew `("physics" . ,physics) - math-preview-tex-packages-autoload-packages)) - (setq math-preview-raise 0.5 - math-preview-scale 1 - math-preview-tex-default-packages '("autoload" "ams" "physics")) - (let ((command (executable-find "~/node_modules/.bin/math-preview"))) - (if command - (setq math-preview-command command) - ;; https://stackoverflow.com/a/17509764 answers: - ;; How to install an npm package from github directly? - (unless (file-directory-p "~/node_modules") - (make-directory "~/node_modules")) - (cl-destructuring-bind (exit-code output) - (shell-command-with-exit-code - "npm" "install" - "git+https://gitlab.com/matsievskiysv/math-preview.git") - (if (= 0 exit-code) - (message "%s" (string-trim output)) - (error "%s" (string-trim output)))))))) +(when (ensure-package-installation 'math-preview) + (with-eval-after-load 'math-preview + ;; https://docs.mathjax.org/en/latest/input/tex/extensions/physics.html + (let ((physics (split-string " +abs absolutevalue acomm acos acosecant acosine acot acotangent +acsc admat anticommutator antidiagonalmatrix arccos arccosecant +arccosine arccot arccotangent arccsc arcsec arcsecant arcsin +arcsine arctan arctangent asec asecant asin asine atan atangent +bmqty bqty Bqty bra braket comm commutator cos cosecant cosh +cosine cot cotangent coth cp cross crossproduct csc csch curl dd +derivative det determinant diagonalmatrix diffd differential div +divergence dmat dotproduct dv dyad erf ev eval evaluated exp +expectationvalue exponential expval fderivative fdv flatfrac +functionalderivative grad gradient gradientnabla hypcosecant +hypcosine hypcotangent hypsecant hypsine hyptangent +identitymatrix Im imaginary imat innerproduct ip ket ketbra +laplacian ln log logarithm matrixdeterminant matrixel +matrixelement matrixquantity mdet mel mqty naturallogarithm norm +op order outerproduct partialderivative paulimatrix pb +pderivative pdv pmat pmqty Pmqty poissonbracket pqty Pr +principalvalue Probability pv PV qall qand qas qassume qc qcc +qcomma qelse qeven qfor qgiven qif qin qinteger qlet qodd qor +qotherwise qq qqtext qsince qthen qty quantity qunless qusing +rank Re real Res Residue sbmqty sec secant sech sin sine sinh +smallmatrixquantity smdet smqty spmqty sPmqty svmqty tan tangent +tanh tr Tr trace Trace va var variation vb vdot vectorarrow +vectorbold vectorunit vmqty vnabla vqty vu xmat xmatrix +zeromatrix zmat"))) + (cl-pushnew `("physics" . ,physics) + math-preview-tex-packages-autoload-packages)) + (setq math-preview-raise 0.5 + math-preview-scale 1 + math-preview-tex-default-packages '("autoload" "ams" "physics")) + (let ((command (executable-find "~/node_modules/.bin/math-preview"))) + (if command + (setq math-preview-command command) + ;; https://stackoverflow.com/a/17509764 answers: + ;; How to install an npm package from github directly? + (unless (file-directory-p "~/node_modules") + (make-directory "~/node_modules")) + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code + "npm" "install" + "git+https://gitlab.com/matsievskiysv/math-preview.git") + (if (= 0 exit-code) + (message "%s" (string-trim output)) + (error "%s" (string-trim output)))))))) #+end_src *** TODO Improve the AUCTeX configuration slowly @@ -1922,7 +1922,7 @@ buffers with help of an external [[https://nodejs.org][node.js]] program. #+caption: Configure =markdown-mode=. #+name: lst:configure-markdown-mode #+begin_src emacs-lisp - (when (ensure-package-installation 'markdown-mode)) +(when (ensure-package-installation 'markdown-mode)) #+end_src ** Writing Org files @@ -1939,12 +1939,12 @@ buffers with help of an external [[https://nodejs.org][node.js]] program. #+caption: Activate =Org=. #+name: lst:activate-org #+begin_src emacs-lisp - (when (cl-every #'fboundp '(org-agenda org-capture)) - (global-set-key (kbd "C-c a") #'org-agenda) - (global-set-key (kbd "C-c c") #'org-capture) - (with-eval-after-load 'ol - (global-set-key (kbd "C-c l") #'org-store-link) - (global-set-key (kbd "C-c C-l") #'org-insert-link-global))) +(when (cl-every #'fboundp '(org-agenda org-capture)) + (global-set-key (kbd "C-c a") #'org-agenda) + (global-set-key (kbd "C-c c") #'org-capture) + (with-eval-after-load 'ol + (global-set-key (kbd "C-c l") #'org-store-link) + (global-set-key (kbd "C-c C-l") #'org-insert-link-global))) #+end_src *** Org customization @@ -1983,311 +1983,321 @@ backward compatibility. See table [[tab:org-latex-class-tag-placeholder]] and ty #+caption: Customize =org-babel=. #+name: lst:customize-org-babel #+begin_src emacs-lisp - (with-eval-after-load 'ob-core +(with-eval-after-load 'ob-core + (custom-set-variables + '(org-confirm-babel-evaluate nil))) + +(with-eval-after-load 'ob-latex + (custom-set-variables + '(org-babel-latex-preamble + (lambda (_) + "\\documentclass[preview]{standalone}\n")) + '(org-babel-latex-begin-env + (lambda (_) + "\\begin{document}\n")) + '(org-babel-latex-end-env + (lambda (_) + "\\end{document}\n")))) + +(with-eval-after-load 'ob-lisp + (with-eval-after-load 'sly (custom-set-variables - '(org-confirm-babel-evaluate nil))) + '(org-babel-lisp-eval-fn #'sly-eval)))) - (with-eval-after-load 'ob-latex - (custom-set-variables - '(org-babel-latex-preamble - (lambda (_) - "\\documentclass[preview]{standalone}\n")) - '(org-babel-latex-begin-env - (lambda (_) - "\\begin{document}\n")) - '(org-babel-latex-end-env - (lambda (_) - "\\end{document}\n")))) - - (with-eval-after-load 'ob-lisp - (with-eval-after-load 'sly - (custom-set-variables - '(org-babel-lisp-eval-fn #'sly-eval)))) - - (with-eval-after-load 'ob-python - (choose-common-python-interpreter 'python)) +(with-eval-after-load 'ob-python + (choose-common-python-interpreter 'python)) #+end_src #+caption[Customize =ob-python=]: #+caption: Customize =ob-python=. #+name: lst:customize-ob-python #+begin_src emacs-lisp - (with-eval-after-load 'ob-python - (defun org-babel-python-format-session-value-override - (src-file result-file result-params) - "Return Python code to evaluate SRC-FILE and write result to RESULT-FILE. - Use `black' instead of `pprint' when \"pp\" is a member of RESULT-PARAMS." - (format "\ - import ast - with open('%s') as __org_babel_python_tmpfile: - __org_babel_python_ast = ast.parse(__org_babel_python_tmpfile.read()) - __org_babel_python_final = __org_babel_python_ast.body[-1] - if isinstance(__org_babel_python_final, ast.Expr): - __org_babel_python_ast.body = __org_babel_python_ast.body[:-1] - exec(compile(__org_babel_python_ast, '', 'exec')) - __org_babel_python_final = eval( - compile(ast.Expression(__org_babel_python_final.value), '', 'eval') - ) - with open('%s', 'w') as __org_babel_python_tmpfile: - if %s: - import black - __org_babel_python_tmpfile.write( - black.format_str(repr(__org_babel_python_final), mode=black.Mode()) - ) - else: - __org_babel_python_tmpfile.write(str(__org_babel_python_final)) - else: - exec(compile(__org_babel_python_ast, '', 'exec')) - __org_babel_python_final = None" - (org-babel-process-file-name src-file 'noquote) - (org-babel-process-file-name result-file 'noquote) - (if (member "pp" result-params) "True" "False"))) +(with-eval-after-load 'ob-python + (defun org-babel-python-format-session-value-override + (src-file result-file result-params) + "Return Python code to evaluate SRC-FILE and write result to RESULT-FILE. +Use `black' instead of `pprint' when \"pp\" is a member of RESULT-PARAMS." + (format "\ +import ast +with open('%s') as __org_babel_python_tmpfile: + __org_babel_python_ast = ast.parse(__org_babel_python_tmpfile.read()) +__org_babel_python_final = __org_babel_python_ast.body[-1] +if isinstance(__org_babel_python_final, ast.Expr): + __org_babel_python_ast.body = __org_babel_python_ast.body[:-1] + exec(compile(__org_babel_python_ast, '', 'exec')) + __org_babel_python_final = eval( + compile(ast.Expression(__org_babel_python_final.value), '', 'eval') + ) + with open('%s', 'w') as __org_babel_python_tmpfile: + if %s: + import black + __org_babel_python_tmpfile.write( + black.format_str(repr(__org_babel_python_final), mode=black.Mode()) + ) + else: + __org_babel_python_tmpfile.write(str(__org_babel_python_final)) +else: + exec(compile(__org_babel_python_ast, '', 'exec')) + __org_babel_python_final = None" + (org-babel-process-file-name src-file 'noquote) + (org-babel-process-file-name result-file 'noquote) + (if (member "pp" result-params) "True" "False"))) - (advice-add 'org-babel-python-format-session-value - :override #'org-babel-python-format-session-value-override)) + (advice-add 'org-babel-python-format-session-value + :override #'org-babel-python-format-session-value-override)) #+end_src #+caption[Customize =Org=]: #+caption: Customize =Org=. #+name: lst:customize-org #+begin_src emacs-lisp - (with-eval-after-load 'org - (custom-set-variables - `(org-babel-load-languages - (delq nil '((C . t) - (calc . t) - ,(when (fboundp 'grapviz-dot-mode) '(dot . t)) - (emacs-lisp . t) - (eshell . t) - ,(when (fboundp 'fennel-mode) '(fennel . t)) - (fortran . t) - ,(when (fboundp 'gnuplot-mode) '(gnuplot . t)) - (js . t) - (latex . t) - (lisp . t) - ,(when (fboundp 'lua-mode) '(lua . t)) - ,(when (fboundp 'maxima-mode) '(maxima . t)) - (org . t) - (perl . t) - (python . t) - (shell . t)))) - '(org-export-backends '(ascii beamer html icalendar latex odt texinfo)) - '(org-file-apps '((auto-mode . emacs) - (directory . emacs) - ("\\.mm\\'" . default) - ("\\.x?html?\\'" . default) - ("\\.pdf\\'" . emacs))) - '(org-modules '(ol-bibtex - ol-doi - ol-eww - ol-info - org-id - org-protocol - org-tempo)) - '(org-structure-template-alist '(("a" . "export ascii") - ("c" . "center") - ("C" . "comment") - ("e" . "example") - ("E" . "export") - ("h" . "export html") - ("l" . "export latex") - ("q" . "quote") - ("s" . "src") - ("p" . "src python :session") - ("v" . "verse"))))) +(with-eval-after-load 'org + (custom-set-variables + `(org-babel-load-languages + (delq nil '((C . t) + (calc . t) + ,(when (fboundp 'grapviz-dot-mode) '(dot . t)) + (emacs-lisp . t) + (eshell . t) + ,(when (fboundp 'fennel-mode) '(fennel . t)) + (fortran . t) + ,(when (fboundp 'gnuplot-mode) '(gnuplot . t)) + (js . t) + (latex . t) + (lisp . t) + ,(when (fboundp 'lua-mode) '(lua . t)) + ,(when (fboundp 'maxima-mode) '(maxima . t)) + (org . t) + (perl . t) + (python . t) + (shell . t)))) + '(org-export-backends '(ascii beamer html icalendar latex odt texinfo)) + '(org-file-apps '((auto-mode . emacs) + (directory . emacs) + ("\\.mm\\'" . default) + ("\\.x?html?\\'" . default) + ("\\.pdf\\'" . emacs))) + '(org-modules '(ol-bibtex + ol-doi + ol-eww + ol-info + org-id + org-protocol + org-tempo)) + '(org-structure-template-alist '(("a" . "export ascii") + ("c" . "center") + ("C" . "comment") + ("e" . "example") + ("E" . "export") + ("h" . "export html") + ("l" . "export latex") + ("q" . "quote") + ("s" . "src") + ("p" . "src python :session") + ("v" . "verse"))))) +#+end_src + + +#+caption[Configure =org-src=]: +#+caption: Configure =org-src=. +#+name: lst:configure-org-src +#+begin_src emacs-lisp +(with-eval-after-load 'org-src + (custom-set-variables + '(org-src-preserve-indentation t))) #+end_src #+caption[Configure =org-mode-map=]: #+caption: Configure =org-mode-map=. #+name: lst:configure-org-mode-map #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; From: "Nicolas Richard" - ;; Date: Fri, 08 Mar 2013 16:23:02 +0100 [thread overview] - ;; Message-ID: <87vc913oh5.fsf@yahoo.fr> (raw) - (defun org-electric-dollar () - "When called once, insert \\(\\) and leave point in between. - When called twice, replace the previously inserted \\(\\) by one $." - (interactive) - (if (and (looking-at "\\\\)") (looking-back "\\\\(" (- (point) 2))) - (progn (delete-char 2) - (delete-char -2) - (insert "$")) - (insert "\\(\\)") - (backward-char 2))) +(with-eval-after-load 'emacs + ;; From: "Nicolas Richard" + ;; Date: Fri, 08 Mar 2013 16:23:02 +0100 [thread overview] + ;; Message-ID: <87vc913oh5.fsf@yahoo.fr> (raw) + (defun org-electric-dollar () + "When called once, insert \\(\\) and leave point in between. +When called twice, replace the previously inserted \\(\\) by one $." + (interactive) + (if (and (looking-at "\\\\)") (looking-back "\\\\(" (- (point) 2))) + (progn (delete-char 2) + (delete-char -2) + (insert "$")) + (insert "\\(\\)") + (backward-char 2))) - (defun org-active-current-time-stamp () - "Insert an active date-time stamp of the current time." - (interactive) - (if (fboundp 'org-insert-time-stamp) - (org-insert-time-stamp (current-time) 'with-hm) - (let ((stamp (format-time-string "<%Y-%m-%d %a %H:%M>" (current-time)))) - (insert stamp) - stamp))) + (defun org-active-current-time-stamp () + "Insert an active date-time stamp of the current time." + (interactive) + (if (fboundp 'org-insert-time-stamp) + (org-insert-time-stamp (current-time) 'with-hm) + (let ((stamp (format-time-string "<%Y-%m-%d %a %H:%M>" (current-time)))) + (insert stamp) + stamp))) - (defun org-inactive-current-time-stamp () - "Insert an inactive date-time stamp of the current time." - (interactive) - (if (fboundp 'org-insert-time-stamp) - (org-insert-time-stamp (current-time) 'with-hm 'inactive) - (let ((stamp (format-time-string "[%Y-%m-%d %a %H:%M]" (current-time)))) - (insert stamp) - stamp))) + (defun org-inactive-current-time-stamp () + "Insert an inactive date-time stamp of the current time." + (interactive) + (if (fboundp 'org-insert-time-stamp) + (org-insert-time-stamp (current-time) 'with-hm 'inactive) + (let ((stamp (format-time-string "[%Y-%m-%d %a %H:%M]" (current-time)))) + (insert stamp) + stamp))) - (with-eval-after-load 'org - (define-key org-mode-map - (kbd "C-c ") #'org-inactive-current-time-stamp) - (define-key org-mode-map - (kbd "C-c C-") #'org-active-current-time-stamp) - (define-key org-mode-map (kbd "$") #'org-electric-dollar) - (define-key org-mode-map (kbd "M-q") #'org-fill-paragraph))) + (with-eval-after-load 'org + (define-key org-mode-map + (kbd "C-c ") #'org-inactive-current-time-stamp) + (define-key org-mode-map + (kbd "C-c C-") #'org-active-current-time-stamp) + (define-key org-mode-map (kbd "$") #'org-electric-dollar) + (define-key org-mode-map (kbd "M-q") #'org-fill-paragraph))) #+end_src #+caption[Customize =org-link=]: #+caption: Customize =org-link=. #+name: lst:customize-org-link #+begin_src emacs-lisp - (with-eval-after-load 'ol - (custom-set-variables - '(org-link-file-path-type 'relative))) +(with-eval-after-load 'ol + (custom-set-variables + '(org-link-file-path-type 'relative))) #+end_src #+caption[Customize =org-export=]: #+caption: Customize =org-export=. #+name: lst:customize-org-export #+begin_src emacs-lisp - (with-eval-after-load 'ox - (custom-set-variables - '(org-export-dispatch-use-expert-ui t))) +(with-eval-after-load 'ox + (custom-set-variables + '(org-export-dispatch-use-expert-ui t))) #+end_src #+caption[Customize =org= for export to LuaLaTeX]: #+caption: Customize =org= for export to LuaLaTeX. #+name: lst:customize-org-for-lualatex-export #+begin_src emacs-lisp - (with-eval-after-load 'org - ;; https://list.orgmode.org/87o84fd4oi.fsf@posteo.net/ - (add-to-list - 'org-preview-latex-process-alist - '(luamagick - :programs ("lualatex" "convert") - :description "pdf > png" - :message "you need to install lualatex and imagemagick." - :image-input-type "pdf" - :image-output-type "png" - :image-size-adjust (1.0 . 1.0) - :post-clean nil - :latex-header nil - :latex-compiler ("lualatex -interaction nonstopmode -output-directory %o %f") - :image-converter ("convert -density %D -trim -antialias %f -quality 100 %O"))) - (custom-set-variables - '(org-preview-latex-default-process 'luamagick) - '(org-latex-default-packages-alist '(("" "fontspec" t ("lualatex")) - ("AUTO" "inputenc" t ("pdflatex")) - ("T1" "fontenc" t ("pdflatex")) - ("" "graphicx" t) - ("" "longtable" nil) - ("" "wrapfig" nil) - ("" "rotating" nil) - ("normalem" "ulem" t) - ("" "amsmath" t) - ("" "amssymb" t) - ("" "capt-of" nil) - ("" "hyperref" nil))))) +(with-eval-after-load 'org + ;; https://list.orgmode.org/87o84fd4oi.fsf@posteo.net/ + (add-to-list + 'org-preview-latex-process-alist + '(luamagick + :programs ("lualatex" "convert") + :description "pdf > png" + :message "you need to install lualatex and imagemagick." + :image-input-type "pdf" + :image-output-type "png" + :image-size-adjust (1.0 . 1.0) + :post-clean nil + :latex-header nil + :latex-compiler ("lualatex -interaction nonstopmode -output-directory %o %f") + :image-converter ("convert -density %D -trim -antialias %f -quality 100 %O"))) + (custom-set-variables + '(org-preview-latex-default-process 'luamagick) + '(org-latex-default-packages-alist '(("" "fontspec" t ("lualatex")) + ("AUTO" "inputenc" t ("pdflatex")) + ("T1" "fontenc" t ("pdflatex")) + ("" "graphicx" t) + ("" "longtable" nil) + ("" "wrapfig" nil) + ("" "rotating" nil) + ("normalem" "ulem" t) + ("" "amsmath" t) + ("" "amssymb" t) + ("" "capt-of" nil) + ("" "hyperref" nil))))) #+end_src #+caption[Customize =ox-latex= for export to LuaLaTeX]: #+caption: Customize =ox-latex= for export to LuaLaTeX. #+name: lst:customize-ox-latex-for-lualatex-export #+begin_src emacs-lisp - (with-eval-after-load 'ox-latex - (custom-set-variables - '(org-latex-pdf-process - ;; https://tecosaur.github.io/emacs-config/#compiling - `(,(concat "latexmk -f -pdf -%latex" - " -interaction=nonstopmode -shell-escape -outdir=%o %f"))) - '(org-latex-compiler "lualatex") - '(org-latex-hyperref-template "\\hypersetup{ - pdfauthor={%a}, - pdftitle={%t}, - pdfkeywords={%k}, - pdfsubject={%d}, - pdfcreator={%c}, - pdflang={%L}, - citecolor=blue, - colorlinks=true, - filecolor=blue, - hyperfootnotes=false, - linkcolor=blue, - unicode=true, - urlcolor=blue, - }\n") - `,(if (version< emacs-version "28.9.9") - '(org-latex-listings 'minted) - '(org-latex-src-block-backend 'minted)) - '(org-latex-minted-langs '((cc "c++") - (conf "text") - (cperl "perl") - (diff "diff") - (shell-script "bash") - (json "json") - (org "text") - (toml "toml"))) - '(org-latex-minted-options '(("bgcolor" "LightGoldenrodYellow"))) - `(org-latex-logfiles-extensions - ',(cl-union '("lof" "lot") org-latex-logfiles-extensions :test #'equal)) - '(org-latex-prefer-user-labels t) - '(org-latex-subtitle-separate t))) +(with-eval-after-load 'ox-latex + (custom-set-variables + '(org-latex-pdf-process + ;; https://tecosaur.github.io/emacs-config/#compiling + `(,(concat "latexmk -f -pdf -%latex" + " -interaction=nonstopmode -shell-escape -outdir=%o %f"))) + '(org-latex-compiler "lualatex") + '(org-latex-hyperref-template "\\hypersetup{ + pdfauthor={%a}, + pdftitle={%t}, + pdfkeywords={%k}, + pdfsubject={%d}, + pdfcreator={%c}, + pdflang={%L}, + citecolor=blue, + colorlinks=true, + filecolor=blue, + hyperfootnotes=false, + linkcolor=blue, + unicode=true, + urlcolor=blue, +}\n") + `,(if (version< emacs-version "28.9.9") + '(org-latex-listings 'minted) + '(org-latex-src-block-backend 'minted)) + '(org-latex-minted-langs '((cc "c++") + (conf "text") + (cperl "perl") + (diff "diff") + (shell-script "bash") + (json "json") + (org "text") + (toml "toml"))) + '(org-latex-minted-options '(("bgcolor" "LightGoldenrodYellow"))) + `(org-latex-logfiles-extensions + ',(cl-union '("lof" "lot") org-latex-logfiles-extensions :test #'equal)) + '(org-latex-prefer-user-labels t) + '(org-latex-subtitle-separate t))) #+end_src #+caption[Customize =org-latex-classes= for backwards compatibility]: #+caption: Customize =org-latex-classes= for backwards compatibility. #+name: lst:customize-org-latex-classes #+begin_src emacs-lisp - (with-eval-after-load 'ox-latex - (mapc (function (lambda (element) - (add-to-list 'org-latex-classes element))) - (nreverse - (quote (("elsarticle-1+2+3" ; Elsevier journals - "\\documentclass{elsarticle} - [NO-DEFAULT-PACKAGES] - [PACKAGES] - [EXTRA]" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) - ("article-1+2+3" - "\\documentclass{article} - [NO-DEFAULT-PACKAGES] - [PACKAGES] - [EXTRA]" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) - ("report-1+2+3" - "\\documentclass[11pt]{report} - [NO-DEFAULT-PACKAGES] - [PACKAGES] - [EXTRA]" - ("\\part{%s}" . "\\part*{%s}") - ("\\chapter{%s}" . "\\chapter*{%s}") - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) - ("book-1+2+3" - "\\documentclass[11pt]{book} - [NO-DEFAULT-PACKAGES] - [PACKAGES] - [EXTRA]" - ("\\part{%s}" . "\\part*{%s}") - ("\\chapter{%s}" . "\\chapter*{%s}") - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))))) +(with-eval-after-load 'ox-latex + (mapc (function (lambda (element) + (add-to-list 'org-latex-classes element))) + (nreverse + (quote (("elsarticle-1+2+3" ; Elsevier journals + "\\documentclass{elsarticle} +[NO-DEFAULT-PACKAGES] +[PACKAGES] +[EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) + ("article-1+2+3" + "\\documentclass{article} +[NO-DEFAULT-PACKAGES] +[PACKAGES] +[EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) + ("report-1+2+3" + "\\documentclass[11pt]{report} +[NO-DEFAULT-PACKAGES] +[PACKAGES] +[EXTRA]" + ("\\part{%s}" . "\\part*{%s}") + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) + ("book-1+2+3" + "\\documentclass[11pt]{book} +[NO-DEFAULT-PACKAGES] +[PACKAGES] +[EXTRA]" + ("\\part{%s}" . "\\part*{%s}") + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))))) #+end_src *** [[https://github.com/bdarcus/citar][Citar: citing bibliography]] with [[https://orgmode.org/][Org Mode]] @@ -2310,38 +2320,38 @@ configuration. #+caption: Configure =oc-cite= with =citar=. #+name: lst:configure-oc-cite+citar #+begin_src emacs-lisp +(with-eval-after-load 'oc + ;; Org-9.5 needs the requirements, but Org-9.6 does not. + (when (version< (org-version) "9.5.99") + (require 'oc-biblatex) + (require 'oc-csl))) + +(with-eval-after-load 'org + (define-key org-mode-map (kbd "C-c b") #'org-cite-insert)) + +(when (ensure-package-installation 'citar 'citar-embark) + (with-eval-after-load 'embark + (when (fboundp 'citar-embark-mode) + (citar-embark-mode +1))) + (with-eval-after-load 'oc - ;; Org-9.5 needs the requirements, but Org-9.6 does not. - (when (version< (org-version) "9.5.99") - (require 'oc-biblatex) - (require 'oc-csl))) + (custom-set-variables + '(org-cite-export-processors '((latex biblatex) + (t csl))) + '(org-cite-global-bibliography '("~/VCS/research/refs.bib"))) + + (when (require 'citar nil 'noerror) + (custom-set-variables + '(org-cite-activate-processor 'citar) + '(org-cite-follow-processor 'citar) + '(org-cite-insert-processor 'citar)))) (with-eval-after-load 'org - (define-key org-mode-map (kbd "C-c b") #'org-cite-insert)) - - (when (ensure-package-installation 'citar 'citar-embark) - (with-eval-after-load 'embark - (when (fboundp 'citar-embark-mode) - (citar-embark-mode +1))) - - (with-eval-after-load 'oc + (when (require 'citar nil 'noerror) (custom-set-variables - '(org-cite-export-processors '((latex biblatex) - (t csl))) - '(org-cite-global-bibliography '("~/VCS/research/refs.bib"))) - - (when (require 'citar nil 'noerror) - (custom-set-variables - '(org-cite-activate-processor 'citar) - '(org-cite-follow-processor 'citar) - '(org-cite-insert-processor 'citar)))) - - (with-eval-after-load 'org - (when (require 'citar nil 'noerror) - (custom-set-variables - '(citar-bibliography '("~/VCS/research/refs.bib")) - '(citar-library-file-extensions '("djvu" "pdf")) - '(citar-library-paths '("~/VCS/research/papers/")))))) + '(citar-bibliography '("~/VCS/research/refs.bib")) + '(citar-library-file-extensions '("djvu" "pdf")) + '(citar-library-paths '("~/VCS/research/papers/")))))) #+end_src Ref. [cite:@Schulte.MCSE.2011.41] shows that [[https://orgmode.org/][Org-mode]] is a simple, plain-text @@ -2375,17 +2385,17 @@ valid directories and files. In an [[https://orgmode.org/][Org-mode]] buffer th #+caption: Delete =Biber= cache when =Biber= fails to make a bibliography. #+name: lst:delete-biber-cache #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; https://tex.stackexchange.com/a/579356 answers - ;; "How to solve Biber exiting with error code 2 but no error messages?" - (defun biber-delete-cache () - "Delete the `Biber' cache to get rid of `Biber' exit code 2." - (interactive) - (cl-destructuring-bind (exit-code output) - (shell-command-with-exit-code "rm" "-rf" "$(biber --cache)") - (if (= 0 exit-code) - (message "%s" (string-trim output)) - (error "%s" (string-trim output)))))) +(with-eval-after-load 'emacs + ;; https://tex.stackexchange.com/a/579356 answers + ;; "How to solve Biber exiting with error code 2 but no error messages?" + (defun biber-delete-cache () + "Delete the `Biber' cache to get rid of `Biber' exit code 2." + (interactive) + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code "rm" "-rf" "$(biber --cache)") + (if (= 0 exit-code) + (message "%s" (string-trim output)) + (error "%s" (string-trim output)))))) #+end_src *** [[https://github.com/tecosaur/engrave-faces#readme][Engrave Faces]] @@ -2436,115 +2446,115 @@ listings below make* [[https://github.com/tecosaur/engrave-faces#readme][Engrave #+caption: breakable LaTeX environments. #+name: lst:org-latex-engraved-source-block-filter #+begin_src emacs-lisp :results silent - (defun org-latex-engraved-source-block-filter (data _backend _info) - "Replace \"Code\" with \"Breakable\" in non-floating environments. +(defun org-latex-engraved-source-block-filter (data _backend _info) + "Replace \"Code\" with \"Breakable\" in non-floating environments. - Customize `org-latex-engraved-preamble' to define a Breakable (non-floating) - environment and an unbreakable Code (floating) environment." - (unless (string-match "^\\\\DeclareTColorBox\\[\\]{Breakable}" - org-latex-engraved-preamble) - (user-error "`org-latex-engraved-preamble' defines no `Breakable' environment")) - (when (eq org-latex-src-block-backend 'engraved) - (let ((enter "^\\\\begin{Code}\n\\\\begin{Verbatim}") - (leave "^\\\\end{Verbatim}\n\\\\end{Code}")) - ;; Transform only blocks matching the enter regexp at position 0. - ;; Do not transform blocks that are listing environments. - (when (and (string-match enter data) (eql 0 (match-beginning 0))) +Customize `org-latex-engraved-preamble' to define a Breakable (non-floating) +environment and an unbreakable Code (floating) environment." + (unless (string-match "^\\\\DeclareTColorBox\\[\\]{Breakable}" + org-latex-engraved-preamble) + (user-error "`org-latex-engraved-preamble' defines no `Breakable' environment")) + (when (eq org-latex-src-block-backend 'engraved) + (let ((enter "^\\\\begin{Code}\n\\\\begin{Verbatim}") + (leave "^\\\\end{Verbatim}\n\\\\end{Code}")) + ;; Transform only blocks matching the enter regexp at position 0. + ;; Do not transform blocks that are listing environments. + (when (and (string-match enter data) (eql 0 (match-beginning 0))) + (setq data (replace-match + "\\begin{Breakable}\n\\begin{Verbatim}" t t data)) + (when (string-match leave data (match-end 0)) (setq data (replace-match - "\\begin{Breakable}\n\\begin{Verbatim}" t t data)) - (when (string-match leave data (match-end 0)) - (setq data (replace-match - "\\end{Verbatim}\n\\end{Breakable}" t t data)) - (when (string-match enter data) - (user-error "The `enter' regexp `%s' should not match" enter)) - (when (string-match leave data) - (user-error "The `leave' regexp `%s' should not match" leave)) - data))))) + "\\end{Verbatim}\n\\end{Breakable}" t t data)) + (when (string-match enter data) + (user-error "The `enter' regexp `%s' should not match" enter)) + (when (string-match leave data) + (user-error "The `leave' regexp `%s' should not match" leave)) + data))))) #+end_src #+caption[Smart LaTeX engraving of =org-src-mode= blocks]: #+caption: Smart LaTeX engraving of =org-src-mode= blocks. #+name: lst:smart-latex-engrave-org-source-blocks #+begin_src emacs-lisp - (defun smart-latex-engrave-org-source-blocks () - "Enable smart LaTeX engraving of `org-src-mode' blocks. +(defun smart-latex-engrave-org-source-blocks () + "Enable smart LaTeX engraving of `org-src-mode' blocks. - Sets backend and preamble locally to support floating unbreakable LaTeX - environments and non-floating breakable LaTeX environments by means of - `org-latex-engraved-source-block-filter'." - (interactive) - (when (require 'ox-latex nil 'noerror) - (setq-local org-latex-src-block-backend 'engraved - org-latex-engraved-preamble "\\usepackage{fvextra} - [FVEXTRA-SETUP] +Sets backend and preamble locally to support floating unbreakable LaTeX +environments and non-floating breakable LaTeX environments by means of +`org-latex-engraved-source-block-filter'." + (interactive) + (when (require 'ox-latex nil 'noerror) + (setq-local org-latex-src-block-backend 'engraved + org-latex-engraved-preamble "\\usepackage{fvextra} +[FVEXTRA-SETUP] - % Make code and line numbers normalsize. Make line numbers grey. - \\renewcommand\\theFancyVerbLine{ - \\normalsize\\color{black!40!white}\\arabic{FancyVerbLine}} - % In case engrave-faces-latex-gen-preamble has not been run. - \\providecolor{EfD}{HTML}{f7f7f7} - \\providecolor{EFD}{HTML}{28292e} - % To use \\DeclareTColorBox from the tcolorbox package: - \\usepackage[breakable,xparse]{tcolorbox} - % Define a Breakable environment to fontify code outside floats. - \\DeclareTColorBox[]{Breakable}{o}{ - colback=EfD, colframe=EFD, colupper=EFD, - fontupper=\\normalsize\\setlength{\\fboxsep}{0pt}, - IfNoValueTF={#1}{ - boxsep=1pt, arc=1pt, outer arc=1pt, boxrule=0.5pt, - }{ - boxsep=1pt, arc=0pt, outer arc=0pt, boxrule=0pt, leftrule=1pt - }, - left=2pt, right=2pt, top=1pt, bottom=1pt, breakable - } - % Define an unbreakable Code environment to fontify code inside floats. - \\DeclareTColorBox[]{Code}{o}{ - colback=EfD, colframe=EFD, colupper=EFD, - fontupper=\\normalsize\\setlength{\\fboxsep}{0pt}, - IfNoValueTF={#1}{ - boxsep=1pt, arc=1pt, outer arc=1pt, boxrule=0.5pt - }{ - boxsep=1pt, arc=0pt, outer arc=0pt, boxrule=0pt, leftrule=1pt - }, - left=2pt, right=2pt, top=1pt, bottom=1pt, - } +% Make code and line numbers normalsize. Make line numbers grey. +\\renewcommand\\theFancyVerbLine{ + \\normalsize\\color{black!40!white}\\arabic{FancyVerbLine}} +% In case engrave-faces-latex-gen-preamble has not been run. +\\providecolor{EfD}{HTML}{f7f7f7} +\\providecolor{EFD}{HTML}{28292e} +% To use \\DeclareTColorBox from the tcolorbox package: +\\usepackage[breakable,xparse]{tcolorbox} +% Define a Breakable environment to fontify code outside floats. +\\DeclareTColorBox[]{Breakable}{o}{ + colback=EfD, colframe=EFD, colupper=EFD, + fontupper=\\normalsize\\setlength{\\fboxsep}{0pt}, + IfNoValueTF={#1}{ + boxsep=1pt, arc=1pt, outer arc=1pt, boxrule=0.5pt, + }{ + boxsep=1pt, arc=0pt, outer arc=0pt, boxrule=0pt, leftrule=1pt + }, + left=2pt, right=2pt, top=1pt, bottom=1pt, breakable +} +% Define an unbreakable Code environment to fontify code inside floats. +\\DeclareTColorBox[]{Code}{o}{ + colback=EfD, colframe=EFD, colupper=EFD, + fontupper=\\normalsize\\setlength{\\fboxsep}{0pt}, + IfNoValueTF={#1}{ + boxsep=1pt, arc=1pt, outer arc=1pt, boxrule=0.5pt + }{ + boxsep=1pt, arc=0pt, outer arc=0pt, boxrule=0pt, leftrule=1pt + }, + left=2pt, right=2pt, top=1pt, bottom=1pt, +} - [LISTINGS-SETUP]"))) +[LISTINGS-SETUP]"))) #+end_src #+caption[Fix engraving of symbolic color names]: #+caption: Fix engraving of symbolic colors names. #+name: lst:ensure-engrave-faces-with-latex-face-apply-fix #+begin_src emacs-lisp :tangle no - (when (and (ensure-package-installation 'engrave-faces) - (require 'engrave-faces-latex nil t)) - (defun engrave-faces-latex--color (color) - "Convert COLOR loosely to a string of six hexadecimal digits." - (if (char-equal ?# (aref color 0)) - (substring color 1 7) - (apply 'format "%02x%02x%02x" - (mapcar (lambda (c) (ash c -8)) - (color-values color))))) +(when (and (ensure-package-installation 'engrave-faces) + (require 'engrave-faces-latex nil t)) + (defun engrave-faces-latex--color (color) + "Convert COLOR loosely to a string of six hexadecimal digits." + (if (char-equal ?# (aref color 0)) + (substring color 1 7) + (apply 'format "%02x%02x%02x" + (mapcar (lambda (c) (ash c -8)) + (color-values color))))) - (defun engrave-faces-latex-face-apply-override (faces content) - "Convert attributes of FACES to LaTeX commands applied to CONTENT." - (let ((attrs (engrave-faces-merge-attributes faces))) - (let ((bg (plist-get attrs :background)) - (fg (plist-get attrs :foreground)) - (it (eql (plist-get attrs :slant) 'italic)) - (bl (member (plist-get attrs :weight) '(bold extra-bold))) - (st (plist-get attrs :strike-through))) - (concat - (when bg (concat "\\colorbox[HTML]{" - (engrave-faces-latex--color bg) "}{")) - (when fg (concat "\\textcolor[HTML]{" - (engrave-faces-latex--color fg) "}{")) - (when st "\\sout{") (when bl "\\textbf{") (when it "\\textit{") - content - (when bg "}") (when fg "}") (when st "}") (when bl "}") (when it "}"))))) + (defun engrave-faces-latex-face-apply-override (faces content) + "Convert attributes of FACES to LaTeX commands applied to CONTENT." + (let ((attrs (engrave-faces-merge-attributes faces))) + (let ((bg (plist-get attrs :background)) + (fg (plist-get attrs :foreground)) + (it (eql (plist-get attrs :slant) 'italic)) + (bl (member (plist-get attrs :weight) '(bold extra-bold))) + (st (plist-get attrs :strike-through))) + (concat + (when bg (concat "\\colorbox[HTML]{" + (engrave-faces-latex--color bg) "}{")) + (when fg (concat "\\textcolor[HTML]{" + (engrave-faces-latex--color fg) "}{")) + (when st "\\sout{") (when bl "\\textbf{") (when it "\\textit{") + content + (when bg "}") (when fg "}") (when st "}") (when bl "}") (when it "}"))))) - (advice-add 'engrave-faces-latex-face-apply - :override #'engrave-faces-latex-face-apply-override)) + (advice-add 'engrave-faces-latex-face-apply + :override #'engrave-faces-latex-face-apply-override)) #+end_src #+caption[Fix engraving of horizontal/vertical spacing in multiline docstrings]: @@ -2552,49 +2562,49 @@ listings below make* [[https://github.com/tecosaur/engrave-faces#readme][Engrave #+caption: documentation strings. #+name: lst:ensure-engrave-faces-with-latex-face-mapper-fix #+begin_src emacs-lisp :tangle no - (when (require 'engrave-faces-latex nil t) - (defun engrave-faces-latex-face-mapper-override (faces content) - "Create a LaTeX representation of CONTENT with FACES applied." - (let* ((style (engrave-faces-preset-style faces)) - (protected-content - (funcall - (if (and engrave-faces-latex-mathescape - (eq 'font-lock-comment-face (car style))) - #'engrave-faces-latex--protect-content-mathescape - #'engrave-faces-latex--protect-content) - content))) - ;; Wrap groups of "words joined by blank characters" in LaTeX commands. - ;; Do not wrap newlines and other whitespace between those groups. - (let ((regexp (rx (or (group-n 1 (+ graph ) (* (+ blank) (+ graph))) - (group-n 2 (+ (any "\n" space)))))) - (slug (when (and style - (eq engrave-faces-latex-output-style 'preset)) - (plist-get (cdr style) :slug))) - (start 0) (stack)) - (while (string-match regexp protected-content start) - (setq start (match-end 0)) - (when-let ((pc (match-string 1 protected-content))) - (if (stringp slug) - (push (concat "\\EF" slug "{" pc "}") stack) - (push (engrave-faces-latex-face-apply faces pc) stack))) - (when-let ((pc (match-string 2 protected-content))) - (push pc stack))) - (apply #'concat (nreverse stack))))) +(when (require 'engrave-faces-latex nil t) + (defun engrave-faces-latex-face-mapper-override (faces content) + "Create a LaTeX representation of CONTENT with FACES applied." + (let* ((style (engrave-faces-preset-style faces)) + (protected-content + (funcall + (if (and engrave-faces-latex-mathescape + (eq 'font-lock-comment-face (car style))) + #'engrave-faces-latex--protect-content-mathescape + #'engrave-faces-latex--protect-content) + content))) + ;; Wrap groups of "words joined by blank characters" in LaTeX commands. + ;; Do not wrap newlines and other whitespace between those groups. + (let ((regexp (rx (or (group-n 1 (+ graph ) (* (+ blank) (+ graph))) + (group-n 2 (+ (any "\n" space)))))) + (slug (when (and style + (eq engrave-faces-latex-output-style 'preset)) + (plist-get (cdr style) :slug))) + (start 0) (stack)) + (while (string-match regexp protected-content start) + (setq start (match-end 0)) + (when-let ((pc (match-string 1 protected-content))) + (if (stringp slug) + (push (concat "\\EF" slug "{" pc "}") stack) + (push (engrave-faces-latex-face-apply faces pc) stack))) + (when-let ((pc (match-string 2 protected-content))) + (push pc stack))) + (apply #'concat (nreverse stack))))) - (advice-add 'engrave-faces-latex-face-mapper - :override #'engrave-faces-latex-face-mapper-override)) + (advice-add 'engrave-faces-latex-face-mapper + :override #'engrave-faces-latex-face-mapper-override)) #+end_src #+caption[Emacs setup to use =engrave-faces-latex= in =org-mode= smartly]: #+caption: Emacs setup to use =engrave-faces-latex= in =org-mode= smartly. #+name: lst:ox-engraved-emacs-lisp-setup #+begin_src emacs-lisp :tangle no - (with-eval-after-load 'ox - (make-variable-buffer-local 'org-export-filter-src-block-functions) - (add-to-list 'org-export-filter-src-block-functions - 'org-latex-engraved-source-block-filter) - (when (fboundp 'smart-latex-engrave-org-source-blocks) - (smart-latex-engrave-org-source-blocks))) +(with-eval-after-load 'ox + (make-variable-buffer-local 'org-export-filter-src-block-functions) + (add-to-list 'org-export-filter-src-block-functions + 'org-latex-engraved-source-block-filter) + (when (fboundp 'smart-latex-engrave-org-source-blocks) + (smart-latex-engrave-org-source-blocks))) #+end_src *** [[info:org#Adding Hyperlink Types][Making Org hyperlink types (info)]] @@ -2621,167 +2631,167 @@ The listings below implement four groups of =org-link= types: #+caption: Define =org-link= types for backwards compatibility with =org-ref=. #+name: lst:org-ref-like-org-link-types #+begin_src emacs-lisp - (with-eval-after-load 'ol - (org-link-set-parameters "ac*" :export #'org-ref-ac*-export) - (org-link-set-parameters "cite" :export #'org-ref-cite-export) - (org-link-set-parameters "eqref" :export #'org-ref-eqref-export) - (org-link-set-parameters "hyperlink" :export #'org-ref-hyperlink-export) - (org-link-set-parameters "label" :export #'org-ref-label-export) - (org-link-set-parameters "ref" :export #'org-ref-ref-export) +(with-eval-after-load 'ol + (org-link-set-parameters "ac*" :export #'org-ref-ac*-export) + (org-link-set-parameters "cite" :export #'org-ref-cite-export) + (org-link-set-parameters "eqref" :export #'org-ref-eqref-export) + (org-link-set-parameters "hyperlink" :export #'org-ref-hyperlink-export) + (org-link-set-parameters "label" :export #'org-ref-label-export) + (org-link-set-parameters "ref" :export #'org-ref-ref-export) - (defun org-ref-ac*-export (path _desc backend _info) - (pcase backend - (`latex (format "\\gls*{%s}" path)) - (_ path))) + (defun org-ref-ac*-export (path _desc backend _info) + (pcase backend + (`latex (format "\\gls*{%s}" path)) + (_ path))) - (defun org-ref-cite-export (path _desc backend _info) - (pcase backend - (`latex (format "\\cite{%s}" path)) - (_ path))) + (defun org-ref-cite-export (path _desc backend _info) + (pcase backend + (`latex (format "\\cite{%s}" path)) + (_ path))) - (defun org-ref-eqref-export (path _desc backend _info) - (pcase backend - (`latex (format "\\eqref{%s}" path)) - (_ path))) + (defun org-ref-eqref-export (path _desc backend _info) + (pcase backend + (`latex (format "\\eqref{%s}" path)) + (_ path))) - (defun org-ref-hyperlink-export (path desc backend _info) - (pcase backend - (`latex (format "\\hyperlink{%s}{%s}" path desc)) - (_ path))) + (defun org-ref-hyperlink-export (path desc backend _info) + (pcase backend + (`latex (format "\\hyperlink{%s}{%s}" path desc)) + (_ path))) - (defun org-ref-label-export (path _desc backend _info) - (pcase backend - (`latex (format "\\label{%s}" path)) - (_ path))) + (defun org-ref-label-export (path _desc backend _info) + (pcase backend + (`latex (format "\\label{%s}" path)) + (_ path))) - (defun org-ref-ref-export (path _desc backend _info) - (pcase backend - (`latex (format "\\ref{%s}" path)) - (_ path)))) + (defun org-ref-ref-export (path _desc backend _info) + (pcase backend + (`latex (format "\\ref{%s}" path)) + (_ path)))) #+end_src #+caption[Define an =org-link= type for =pdf-tools=]: #+caption: Define an =org-link= type for =pdf-tools=. #+name: lst:define-org-pdfview-link-type #+begin_src emacs-lisp - (with-eval-after-load 'ol - (autoload 'pdf-view-goto-page "pdf-view" nil t) - (org-link-set-parameters "pdfview" - :follow #'org-pdfview-open - :export #'org-pdfview-export - :store #'org-pdfview-store-link) +(with-eval-after-load 'ol + (autoload 'pdf-view-goto-page "pdf-view" nil t) + (org-link-set-parameters "pdfview" + :follow #'org-pdfview-open + :export #'org-pdfview-export + :store #'org-pdfview-store-link) - (defun org-pdfview-export (link description backend _) - "Export a \"pdfview\" type link. - The paths of the links export as file relative paths in order to - facilate moving single directories or whole directory trees." - (let ((path (if (string-match "\\(.+\\)::.+" link) - (match-string 1 link) - link)) - (desc (or description link))) - (when (stringp path) - (setq path (file-relative-name path)) - (pcase backend - (`html (format "%s" path desc)) - (`latex (format "\\href{%s}{%s}" path desc)) - (`ascii (format "%s (%s)" desc path)) - (_ path))))) + (defun org-pdfview-export (link description backend _) + "Export a \"pdfview\" type link. +The paths of the links export as file relative paths in order to +facilate moving single directories or whole directory trees." + (let ((path (if (string-match "\\(.+\\)::.+" link) + (match-string 1 link) + link)) + (desc (or description link))) + (when (stringp path) + (setq path (file-relative-name path)) + (pcase backend + (`html (format "%s" path desc)) + (`latex (format "\\href{%s}{%s}" path desc)) + (`ascii (format "%s (%s)" desc path)) + (_ path))))) - (defun org-pdfview-open (link _) - "Open a \"pdfview\" type link." - (string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link) - (let ((path (match-string 1 link)) - (page (and (match-beginning 2) - (string-to-number (match-string 2 link))))) - ;; Let Org mode open the file (in-emacs = 1) to ensure - ;; org-link-frame-setup is respected. - (org-open-file path 1) - (when page (pdf-view-goto-page page)))) + (defun org-pdfview-open (link _) + "Open a \"pdfview\" type link." + (string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link) + (let ((path (match-string 1 link)) + (page (and (match-beginning 2) + (string-to-number (match-string 2 link))))) + ;; Let Org mode open the file (in-emacs = 1) to ensure + ;; org-link-frame-setup is respected. + (org-open-file path 1) + (when page (pdf-view-goto-page page)))) - (defun org-pdfview-store-link () - "Store a \"pdfview\" type link." - (when (eq major-mode 'pdf-view-mode) - (let* ((path buffer-file-name) - (page (pdf-view-current-page)) - (link (concat "pdfview:" path "::" (number-to-string page)))) - (org-link-store-props - :type "pdfview" - :link link - :description path))))) + (defun org-pdfview-store-link () + "Store a \"pdfview\" type link." + (when (eq major-mode 'pdf-view-mode) + (let* ((path buffer-file-name) + (page (pdf-view-current-page)) + (link (concat "pdfview:" path "::" (number-to-string page)))) + (org-link-store-props + :type "pdfview" + :link link + :description path))))) #+end_src #+caption[Define an =org-link= type for =YouTube=]: #+caption: Define an =org-link= type for =YouTube=. #+name: lst:define-org-yt-link-type #+begin_src emacs-lisp - (with-eval-after-load 'ol - ;; https://bitspook.in/blog/extending-org-mode-to-handle-youtube-links/ - (org-link-set-parameters "yt" - :follow #'org-yt-open - :export #'org-yt-export) +(with-eval-after-load 'ol + ;; https://bitspook.in/blog/extending-org-mode-to-handle-youtube-links/ + (org-link-set-parameters "yt" + :follow #'org-yt-open + :export #'org-yt-export) - (defun org-yt-open (path prefix) - "Open PATH with \"emms\", \"mpv\", or `browse-url' (when PREFIX)." - (let ((url (format "https:%s" path))) - (cond - (prefix - (browse-url url)) - ((require 'emms nil 'noerror) - (emms-add-url url) - (with-current-emms-playlist - (save-excursion - (emms-playlist-last) - (emms-playlist-mode-play-current-track))) ) - ((executable-find "mpv") - (let ((display-buffer-alist - `((,shell-command-buffer-name-async . (display-buffer-no-window))))) - (async-shell-command (format "\"%s\" \"%s\"" url))) - (message "Launched mpv with \"%s\"" url)) - (t - (user-error "Can't open `%s': install `emms' and/or `mpv'" url))))) + (defun org-yt-open (path prefix) + "Open PATH with \"emms\", \"mpv\", or `browse-url' (when PREFIX)." + (let ((url (format "https:%s" path))) + (cond + (prefix + (browse-url url)) + ((require 'emms nil 'noerror) + (emms-add-url url) + (with-current-emms-playlist + (save-excursion + (emms-playlist-last) + (emms-playlist-mode-play-current-track))) ) + ((executable-find "mpv") + (let ((display-buffer-alist + `((,shell-command-buffer-name-async . (display-buffer-no-window))))) + (async-shell-command (format "\"%s\" \"%s\"" url))) + (message "Launched mpv with \"%s\"" url)) + (t + (user-error "Can't open `%s': install `emms' and/or `mpv'" url))))) - (defun org-yt-export (path desc backend _) - "Export an \"yt\" link." - (pcase backend - (`html - (let* ((video-id (cadar (url-parse-query-string path))) - (url (if (string-empty-p video-id) - path - (format "//youtube.com/embed/%s" video-id)))) - (format - (concat "") - url desc))) - (`latex (format "\\href{https:%s}{%s}" path desc)) - (_ path)))) + (defun org-yt-export (path desc backend _) + "Export an \"yt\" link." + (pcase backend + (`html + (let* ((video-id (cadar (url-parse-query-string path))) + (url (if (string-empty-p video-id) + path + (format "//youtube.com/embed/%s" video-id)))) + (format + (concat "") + url desc))) + (`latex (format "\\href{https:%s}{%s}" path desc)) + (_ path)))) #+end_src #+caption[Patch =ol-info=]: #+caption: Patch =ol-info=. #+name: lst:patch-org-info-link-type #+begin_src emacs-lisp :exports code :results silent - (with-eval-after-load 'ol-info - (defun org-info-export (path desc format) - "Export an info link. - See `org-link-parameters' for details about PATH, DESC and FORMAT." - (let* ((parts (split-string path "#\\|::")) - (manual (car parts)) - (node (or (nth 1 parts) "Top"))) - (pcase format - (`html - (format "%s" - (org-info-map-html-url manual) - (org-info--expand-node-name node) - (or desc path))) - (`latex - (format "\\href{%s\\#%s}{%s}" - (org-info-map-html-url manual) - (org-info--expand-node-name node) - (or desc path))) - (`texinfo - (let ((title (or desc ""))) - (format "@ref{%s,%s,,%s,}" node title manual))) - (_ nil))))) +(with-eval-after-load 'ol-info + (defun org-info-export (path desc format) + "Export an info link. +See `org-link-parameters' for details about PATH, DESC and FORMAT." + (let* ((parts (split-string path "#\\|::")) + (manual (car parts)) + (node (or (nth 1 parts) "Top"))) + (pcase format + (`html + (format "%s" + (org-info-map-html-url manual) + (org-info--expand-node-name node) + (or desc path))) + (`latex + (format "\\href{%s\\#%s}{%s}" + (org-info-map-html-url manual) + (org-info--expand-node-name node) + (or desc path))) + (`texinfo + (let ((title (or desc ""))) + (format "@ref{%s,%s,,%s,}" node title manual))) + (_ nil))))) #+end_src #+attr_latex: :options breaklines @@ -2789,23 +2799,23 @@ The listings below implement four groups of =org-link= types: #+caption: Patch buffer local =ol-info=. #+name: lst:emacs-lisp-setup-buffer-local-ol-info #+begin_src emacs-lisp :exports code :results silent :tangle no - (with-eval-after-load 'ol-info - (make-variable-buffer-local 'org-info-emacs-documents) - (setq org-info-emacs-documents (delete "org" org-info-emacs-documents)) - (make-variable-buffer-local 'org-info-other-documents) - (setq org-info-other-documents - (cl-union - '(("consult" . "https://github.com/minad/consult") - ("embark" . "https://github.com/oantolin/embark") - ("magit" . "https://magit.vc/manual/magit.html") - ("marginalia" . "https://github.com/minad/marginalia") - ("maxima" . - "https://maxima.sourceforge.io/docs/manual/maxima_singlepage.html") - ("org" . "https://orgmode.org/org.html") - ("orderless" . "https://github.com/oantolin/orderless") - ("sly" . "https://joaotavora.github.io/sly/") - ("vertico" . "https://github.com/minad/vertico")) - org-info-other-documents :test #'equal))) +(with-eval-after-load 'ol-info + (make-variable-buffer-local 'org-info-emacs-documents) + (setq org-info-emacs-documents (delete "org" org-info-emacs-documents)) + (make-variable-buffer-local 'org-info-other-documents) + (setq org-info-other-documents + (cl-union + '(("consult" . "https://github.com/minad/consult") + ("embark" . "https://github.com/oantolin/embark") + ("magit" . "https://magit.vc/manual/magit.html") + ("marginalia" . "https://github.com/minad/marginalia") + ("maxima" . + "https://maxima.sourceforge.io/docs/manual/maxima_singlepage.html") + ("org" . "https://orgmode.org/org.html") + ("orderless" . "https://github.com/oantolin/orderless") + ("sly" . "https://joaotavora.github.io/sly/") + ("vertico" . "https://github.com/minad/vertico")) + org-info-other-documents :test #'equal))) #+end_src *** [[https://tecosaur.github.io/emacs-config/#translate-capital-keywords][Translate capital keywords (old) to lower case (new)]] @@ -2817,21 +2827,21 @@ The listings below implement four groups of =org-link= types: #+caption: Convert upper to lower case keywords. #+name: lst:convert-upper-to-lower-case-keywords #+begin_src emacs-lisp - (with-eval-after-load 'emacs - ;; https://tecosaur.github.io/emacs-config/#translate-capital-keywords - (defun org-syntax-convert-keyword-case-to-lower () - "Convert all #+KEYWORDS to #+keywords." - (interactive) - (when (derived-mode-p 'org-mode) - (save-excursion - (goto-char (point-min)) - (let ((count 0) - (case-fold-search nil)) - (while (re-search-forward "^[ \t]*#\\+[A-Z_]+" nil t) - (unless (s-matches-p "RESULTS" (match-string 0)) - (replace-match (downcase (match-string 0)) t) - (setq count (1+ count)))) - (message "Replaced %d keywords" count)))))) +(with-eval-after-load 'emacs + ;; https://tecosaur.github.io/emacs-config/#translate-capital-keywords + (defun org-syntax-convert-keyword-case-to-lower () + "Convert all #+KEYWORDS to #+keywords." + (interactive) + (when (derived-mode-p 'org-mode) + (save-excursion + (goto-char (point-min)) + (let ((count 0) + (case-fold-search nil)) + (while (re-search-forward "^[ \t]*#\\+[A-Z_]+" nil t) + (unless (s-matches-p "RESULTS" (match-string 0)) + (replace-match (downcase (match-string 0)) t) + (setq count (1+ count)))) + (message "Replaced %d keywords" count)))))) #+end_src *** [[https://lists.gnu.org/archive/html/emacs-orgmode/2016-07/msg00394.html][Evaluate specific source blocks at load-time]] @@ -2845,33 +2855,33 @@ The listings below implement four groups of =org-link= types: #+caption: Evaluate specific source blocks at load-time. #+name: lst:load-time-specific-source-block-evaluation #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun org-eval-named-blocks-with-infix (infix) - "Evaluate all source blocks having INFIX in their name." - (when (eq major-mode 'org-mode) - (let ((blocks - (org-element-map - (org-element-parse-buffer 'greater-element nil) 'src-block - (lambda (block) - (when-let ((name (org-element-property :name block))) - (when (string-match-p infix name) block)))))) - (dolist (block blocks) - (goto-char (org-element-property :begin block)) - (org-babel-execute-src-block))))) +(with-eval-after-load 'emacs + (defun org-eval-named-blocks-with-infix (infix) + "Evaluate all source blocks having INFIX in their name." + (when (eq major-mode 'org-mode) + (let ((blocks + (org-element-map + (org-element-parse-buffer 'greater-element nil) 'src-block + (lambda (block) + (when-let ((name (org-element-property :name block))) + (when (string-match-p infix name) block)))))) + (dolist (block blocks) + (goto-char (org-element-property :begin block)) + (org-babel-execute-src-block))))) - (defun org-eval-emacs-lisp-setup-blocks () - "Evaluate all source blocks having \"emacs-lisp-setup\" in their name." - (interactive) - (org-eval-named-blocks-with-infix "emacs-lisp-setup")) + (defun org-eval-emacs-lisp-setup-blocks () + "Evaluate all source blocks having \"emacs-lisp-setup\" in their name." + (interactive) + (org-eval-named-blocks-with-infix "emacs-lisp-setup")) - (defun org-eval-python-setup-blocks () - "Evaluate all source blocks having \"python-setup\" in their name." - (interactive) - (org-eval-named-blocks-with-infix "python-setup")) + (defun org-eval-python-setup-blocks () + "Evaluate all source blocks having \"python-setup\" in their name." + (interactive) + (org-eval-named-blocks-with-infix "python-setup")) - ;; Emacs looks for "Local variables:" after the last "newline-formfeed". - (add-to-list 'safe-local-eval-forms '(org-eval-emacs-lisp-setup-blocks)) - (add-to-list 'safe-local-eval-forms '(org-eval-python-setup-blocks))) + ;; Emacs looks for "Local variables:" after the last "newline-formfeed". + (add-to-list 'safe-local-eval-forms '(org-eval-emacs-lisp-setup-blocks)) + (add-to-list 'safe-local-eval-forms '(org-eval-python-setup-blocks))) #+end_src *** [[info:org#LaTeX header and sectioning][Easy LaTeX preamble editing]] @@ -2900,38 +2910,38 @@ new [[info:org#Editing Source Code][-modes]]: =latex-header= and =late #+caption: easily. #+name: lst:org-babel-latex-header-blocks #+begin_src emacs-lisp :exports code :results silent - (with-eval-after-load 'emacs - (defun prefix-all-lines (prefix body) - (with-temp-buffer - (insert body) - (string-insert-rectangle (point-min) (point-max) prefix) - (buffer-string))) +(with-eval-after-load 'emacs + (defun prefix-all-lines (prefix body) + (with-temp-buffer + (insert body) + (string-insert-rectangle (point-min) (point-max) prefix) + (buffer-string))) - (defun org-babel-execute:latex-extra-header (body _params) - "Execute a block of LaTeX extra header lines with org-babel. - This function is called by `org-babel-execute-src-block' and - prefixes all lines with \"#+latex_extra_header: \"." - (prefix-all-lines "#+latex_extra_header: " body)) + (defun org-babel-execute:latex-extra-header (body _params) + "Execute a block of LaTeX extra header lines with org-babel. +This function is called by `org-babel-execute-src-block' and +prefixes all lines with \"#+latex_extra_header: \"." + (prefix-all-lines "#+latex_extra_header: " body)) - (defun org-babel-execute:latex-header (body _params) - "Execute a block of LaTeX header lines with org-babel. - This function is called by `org-babel-execute-src-block' and - prefixes all lines with \"#+latex_header: \"." - (prefix-all-lines "#+latex_header: " body)) + (defun org-babel-execute:latex-header (body _params) + "Execute a block of LaTeX header lines with org-babel. +This function is called by `org-babel-execute-src-block' and +prefixes all lines with \"#+latex_header: \"." + (prefix-all-lines "#+latex_header: " body)) - (defvar org-babel-default-header-args:latex-extra-header - '((:exports . "results") (:results . "raw"))) + (defvar org-babel-default-header-args:latex-extra-header + '((:exports . "results") (:results . "raw"))) - (defvar org-babel-default-header-args:latex-header - '((:exports . "results") (:results . "raw"))) + (defvar org-babel-default-header-args:latex-header + '((:exports . "results") (:results . "raw"))) - (with-eval-after-load 'org-src - (custom-set-variables - '(org-src-window-setup 'current-window)) + (with-eval-after-load 'org-src + (custom-set-variables + '(org-src-window-setup 'current-window)) - (add-to-list 'org-src-lang-modes '("toml" . conf-toml)) - (add-to-list 'org-src-lang-modes '("latex-header" . latex)) - (add-to-list 'org-src-lang-modes '("latex-extra-header" . latex)))) + (add-to-list 'org-src-lang-modes '("toml" . conf-toml)) + (add-to-list 'org-src-lang-modes '("latex-header" . latex)) + (add-to-list 'org-src-lang-modes '("latex-extra-header" . latex)))) #+end_src The old way is to use a special export attribute as in the function @@ -2944,50 +2954,50 @@ this broken function (broken, since it relies on support only in org-mode before #+caption: Convert marked LaTeX export blocks to LaTeX header lines. #+name: lst:org-latex-header-blocks-filter #+begin_src emacs-lisp - (with-eval-after-load 'ox - (defun org-latex-header-blocks-filter (backend) - "Convert marked LaTeX export blocks to \"#+latex_header: \" lines. - The marker is a line \"#+header: :header yes\" preceding the block. +(with-eval-after-load 'ox + (defun org-latex-header-blocks-filter (backend) + "Convert marked LaTeX export blocks to \"#+latex_header: \" lines. +The marker is a line \"#+header: :header yes\" preceding the block. - For instance, the LaTeX export block +For instance, the LaTeX export block - ,#+header: :header yes - ,#+begin_export latex - % This line converts to a LaTeX header line. - ,#+end_export +,#+header: :header yes +,#+begin_export latex +% This line converts to a LaTeX header line. +,#+end_export - converts to +converts to - \"#+latex_header: % This line converts to a LaTeX header line.\"." - (when (org-export-derived-backend-p backend 'latex) - (let ((blocks - (org-element-map - (org-element-parse-buffer 'greater-element nil) 'export-block - (lambda (block) - (let ((type (org-element-property :type block)) - (header (org-export-read-attribute :header block :header))) - (when (and (string= type "LATEX") (string= header "yes")) - block)))))) - (mapc (lambda (block) - ;; Set point to where to insert LaTeX header lines - ;; after deleting the block. - (goto-char (org-element-property :post-affiliated block)) - (let ((lines - (split-string (org-element-property :value block) "\n"))) - (delete-region (org-element-property :begin block) - (org-element-property :end block)) - (dolist (line lines) - (insert (concat "#+latex_header: " - (replace-regexp-in-string "\\` *" "" line) - "\n"))))) - ;; Reverse to go upwards to avoid wrecking the list of - ;; block positions in the file that would occur in case - ;; of going downwards. - (reverse blocks))))) +\"#+latex_header: % This line converts to a LaTeX header line.\"." + (when (org-export-derived-backend-p backend 'latex) + (let ((blocks + (org-element-map + (org-element-parse-buffer 'greater-element nil) 'export-block + (lambda (block) + (let ((type (org-element-property :type block)) + (header (org-export-read-attribute :header block :header))) + (when (and (string= type "LATEX") (string= header "yes")) + block)))))) + (mapc (lambda (block) + ;; Set point to where to insert LaTeX header lines + ;; after deleting the block. + (goto-char (org-element-property :post-affiliated block)) + (let ((lines + (split-string (org-element-property :value block) "\n"))) + (delete-region (org-element-property :begin block) + (org-element-property :end block)) + (dolist (line lines) + (insert (concat "#+latex_header: " + (replace-regexp-in-string "\\` *" "" line) + "\n"))))) + ;; Reverse to go upwards to avoid wrecking the list of + ;; block positions in the file that would occur in case + ;; of going downwards. + (reverse blocks))))) - ;; Push the filter on the hook. - (cl-pushnew #'org-latex-header-blocks-filter - org-export-before-parsing-hook)) + ;; Push the filter on the hook. + (cl-pushnew #'org-latex-header-blocks-filter + org-export-before-parsing-hook)) #+end_src This file uses the new way, while keeping the old way for backwards @@ -3009,20 +3019,20 @@ define the [[https://orgmode.org/][Org mode]] =kbd= macro in listing #+caption: Define Emacs Lisp utilities to define the =Org-mode= =kbd= macro. #+name: lst:by-backend-kbd-org-macro #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (when (ensure-package-installation 'htmlize) - (autoload 'htmlize-protect-string "htmlize" nil t)) +(with-eval-after-load 'emacs + (when (ensure-package-installation 'htmlize) + (autoload 'htmlize-protect-string "htmlize" nil t)) - ;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-LaTeX.html - (defmacro by-backend (&rest body) - "Help for org-export backend dependent execution." - `(cl-case ',(bound-and-true-p org-export-current-backend) ,@body)) + ;; https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-LaTeX.html + (defmacro by-backend (&rest body) + "Help for org-export backend dependent execution." + `(cl-case ',(bound-and-true-p org-export-current-backend) ,@body)) - (defun by-backend-kbd-org-macro (keys) - "Help for an org-export backend dependent \"#+macro: kbd\"." - (by-backend - (html (format "@@html:%s@@" (htmlize-protect-string keys))) - (latex (format "@@latex:\\colorbox{PowderBlue}{\\texttt{%s}}@@" keys))))) + (defun by-backend-kbd-org-macro (keys) + "Help for an org-export backend dependent \"#+macro: kbd\"." + (by-backend + (html (format "@@html:%s@@" (htmlize-protect-string keys))) + (latex (format "@@latex:\\colorbox{PowderBlue}{\\texttt{%s}}@@" keys))))) #+end_src *** [[info:org#Export Settings][File inclusion (info)]] and [[info:org#Noweb Reference Syntax][Noweb (info)]] trickery @@ -3047,195 +3057,195 @@ inclusion (info)]] and [[info:org#Noweb Reference Syntax][noweb (info)]] tricker #+name: latex-header-1 #+begin_src latex :exports none - % Begin of the LaTeX preamble: - % See: https://list.orgmode.org/87o807r7fr.fsf@posteo.net/ - % From: "Juan Manuel Macías" - % To: orgmode - % Subject: [tip] Insert arbitrary LaTeX code at the beginning of any float environment - % Date: Sun, 08 May 2022 22:22:16 +0000 - % Message-ID: <87o807r7fr.fsf@posteo.net> - % LuaLaTeX-, PdfLaTeX-, or XeTeX-COMPILER COMPATIBILITY: - % Prevent collisions by using font packages before compiler specific packages. - \usepackage{ifthen,ifluatex,ifxetex} - \ifthenelse{\boolean{luatex}}{ - \usepackage{fontspec} % lualatex - }{\ifthenelse{\boolean{xetex}}{ - \usepackage{mathspec} % xetex - }{ - \usepackage[T1]{fontenc} % pdflatex - \usepackage[utf8]{inputenc} % pdflatex - } +% Begin of the LaTeX preamble: +% See: https://list.orgmode.org/87o807r7fr.fsf@posteo.net/ +% From: "Juan Manuel Macías" +% To: orgmode +% Subject: [tip] Insert arbitrary LaTeX code at the beginning of any float environment +% Date: Sun, 08 May 2022 22:22:16 +0000 +% Message-ID: <87o807r7fr.fsf@posteo.net> +% LuaLaTeX-, PdfLaTeX-, or XeTeX-COMPILER COMPATIBILITY: +% Prevent collisions by using font packages before compiler specific packages. +\usepackage{ifthen,ifluatex,ifxetex} +\ifthenelse{\boolean{luatex}}{ + \usepackage{fontspec} % lualatex +}{\ifthenelse{\boolean{xetex}}{ + \usepackage{mathspec} % xetex + }{ + \usepackage[T1]{fontenc} % pdflatex + \usepackage[utf8]{inputenc} % pdflatex } - \usepackage{amsmath} - \usepackage{amssymb} - \usepackage{pifont} % check mark (\ding{52}) and cross mark (\ding{56}) - \usepackage{textcomp} % \texttimes - \usepackage{wasysym} % \diameter +} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{pifont} % check mark (\ding{52}) and cross mark (\ding{56}) +\usepackage{textcomp} % \texttimes +\usepackage{wasysym} % \diameter - % Org-mode REQUIREMENTS: - \usepackage{graphicx} - \usepackage{longtable} - \usepackage{wrapfig} - \usepackage{rotating} - \usepackage[normalem]{ulem} - \usepackage{capt-of} - \usepackage{hyperref} - % End of the 1st LaTeX header block. +% Org-mode REQUIREMENTS: +\usepackage{graphicx} +\usepackage{longtable} +\usepackage{wrapfig} +\usepackage{rotating} +\usepackage[normalem]{ulem} +\usepackage{capt-of} +\usepackage{hyperref} +% End of the 1st LaTeX header block. #+end_src #+caption[LaTeX preamble: replacing the =Org-mode= default packages]: #+caption: LaTeX preamble: replacing the =Org-mode= default packages. #+name: lst:latex-header-1 #+begin_src latex :exports code :noweb yes - <> +<> #+end_src #+name: latex-header-2 #+begin_src latex :exports none - % LANGUAGE: - \usepackage{babel} - \usepackage{fvextra} - \usepackage{csquotes} +% LANGUAGE: +\usepackage{babel} +\usepackage{fvextra} +\usepackage{csquotes} - % LISTS: - \usepackage{enumitem} - \setlist{noitemsep} +% LISTS: +\usepackage{enumitem} +\setlist{noitemsep} - % LISTINGS: - % Section 2.6 of caption-eng.pdf (texdoc caption) explains that the sign - % of "skip" depends on the assumption "position=above" or "position=below". - % The assumption should match the real caption position in the LaTeX code. - \usepackage{caption} - \usepackage[newfloat]{minted} - \captionsetup[listing]{position=below,skip=0em} - \usemintedstyle{xcode} +% LISTINGS: +% Section 2.6 of caption-eng.pdf (texdoc caption) explains that the sign +% of "skip" depends on the assumption "position=above" or "position=below". +% The assumption should match the real caption position in the LaTeX code. +\usepackage{caption} +\usepackage[newfloat]{minted} +\captionsetup[listing]{position=below,skip=0em} +\usemintedstyle{xcode} - % TABLES: - % https://tex.stackexchange.com/questions/341205/ - % what-is-the-difference-between-tabular-tabular-and-tabularx-environments - % https://emacs.stackexchange.com/questions/26179/ - % change-org-mode-table-style-just-for-latex-export - % https://tex.stackexchange.com/questions/468585/ - % table-formatting-using-siunitx - \usepackage{booktabs} - \usepackage{colortbl} - \usepackage{tabularx} % DANGER: beware of Org table :width and :align options! - % End of the 2nd LaTeX header block. +% TABLES: +% https://tex.stackexchange.com/questions/341205/ +% what-is-the-difference-between-tabular-tabular-and-tabularx-environments +% https://emacs.stackexchange.com/questions/26179/ +% change-org-mode-table-style-just-for-latex-export +% https://tex.stackexchange.com/questions/468585/ +% table-formatting-using-siunitx +\usepackage{booktabs} +\usepackage{colortbl} +\usepackage{tabularx} % DANGER: beware of Org table :width and :align options! +% End of the 2nd LaTeX header block. #+end_src #+caption[LaTeX preamble: language, lists and floats]: #+caption: LaTeX preamble: language, lists and floats. #+name: lst:latex-header-2 #+begin_src latex :exports code :noweb yes - <> +<> #+end_src #+name: latex-header-3 #+begin_src latex :exports none - % PAGE LAYOUT: - \usepackage{fancyhdr} - \usepackage{lastpage} - \usepackage[ - headheight=20mm, - top=40mm, - bottom=20mm, - left=0.1\paperwidth, - right=0.1\paperwidth, - heightrounded, - verbose, - ]{geometry} +% PAGE LAYOUT: +\usepackage{fancyhdr} +\usepackage{lastpage} +\usepackage[ + headheight=20mm, + top=40mm, + bottom=20mm, + left=0.1\paperwidth, + right=0.1\paperwidth, + heightrounded, + verbose, +]{geometry} - % TECHNICS: - \usepackage{siunitx} - \usepackage{tikz} - % End of the 3rd LaTeX header block. +% TECHNICS: +\usepackage{siunitx} +\usepackage{tikz} +% End of the 3rd LaTeX header block. #+end_src #+caption[LaTeX preamble: page layout and technics]: #+caption: LaTeX preamble: page layout. #+name: lst:latex-header-3 #+begin_src latex :exports code :noweb yes - <> +<> #+end_src #+name: latex-header-4 #+begin_src latex :exports none - % FLOAT BARRIERS: - % https://tex.stackexchange.com/questions/118662/use-placeins-for-subsections - % Make section an implicit float barrier: - \usepackage[section]{placeins} - % Make subsection an implicit float barrier: - \makeatletter - \AtBeginDocument{% - \expandafter\renewcommand\expandafter\subsection\expandafter{% - \expandafter\@fb@secFB\subsection - }% - } - \makeatother - % Make subsubsection an implicit float barrier: - \makeatletter - \AtBeginDocument{% - \expandafter\renewcommand\expandafter\subsubsection\expandafter{% - \expandafter\@fb@secFB\subsubsection - }% - } - % End of the 4th LaTeX header block. +% FLOAT BARRIERS: +% https://tex.stackexchange.com/questions/118662/use-placeins-for-subsections +% Make section an implicit float barrier: +\usepackage[section]{placeins} +% Make subsection an implicit float barrier: +\makeatletter +\AtBeginDocument{% + \expandafter\renewcommand\expandafter\subsection\expandafter{% + \expandafter\@fb@secFB\subsection + }% +} +\makeatother +% Make subsubsection an implicit float barrier: +\makeatletter +\AtBeginDocument{% + \expandafter\renewcommand\expandafter\subsubsection\expandafter{% + \expandafter\@fb@secFB\subsubsection + }% +} +% End of the 4th LaTeX header block. #+end_src #+caption[LaTeX preamble: float barriers]: #+caption: LaTeX preamble: float barriers. #+name: lst:latex-header-4 #+begin_src latex :exports code :noweb yes - <> +<> #+end_src #+name: latex-header-5 #+begin_src latex :exports none - % FANCY HEADERS AND FOOTERS: - % Add fancy headers and footers to normal pages. - \pagestyle{fancy} +% FANCY HEADERS AND FOOTERS: +% Add fancy headers and footers to normal pages. +\pagestyle{fancy} +\fancyhf{} +\renewcommand{\footrulewidth}{0.4pt} +\fancyfoot[C]{\emph{ + Emacs setup for use with \LaTeX{}, Org, and Python -- Gerard Vermeulen + } +} +\renewcommand{\headrulewidth}{0.4pt} +\fancyhead[L]{\includegraphics[height=1.8cm]{Org-mode-unicorn.png}} +\fancyhead[C]{ + Page: \thepage/\pageref{LastPage} \\ + \text{ } \\ + \text{ } \\ + DRAFT +} +\fancyhead[R]{\includegraphics[height=1.8cm]{Emacs-logo.png}} + +% Add fancy header and footer to custom titlepage. +% https://tex.stackexchange.com/questions/506102/ +% adding-header-and-footer-to-custom-titlepage +\fancypagestyle{titlepage}{% \fancyhf{} \renewcommand{\footrulewidth}{0.4pt} \fancyfoot[C]{\emph{ - Emacs setup for use with \LaTeX{}, Org, and Python -- Gerard Vermeulen - } - } + Emacs setup for use with \LaTeX{}, Org, and Python -- Gerard Vermeulen}} \renewcommand{\headrulewidth}{0.4pt} \fancyhead[L]{\includegraphics[height=1.8cm]{Org-mode-unicorn.png}} \fancyhead[C]{ - Page: \thepage/\pageref{LastPage} \\ + \pageref{LastPage} pages \\ \text{ } \\ \text{ } \\ DRAFT } \fancyhead[R]{\includegraphics[height=1.8cm]{Emacs-logo.png}} - - % Add fancy header and footer to custom titlepage. - % https://tex.stackexchange.com/questions/506102/ - % adding-header-and-footer-to-custom-titlepage - \fancypagestyle{titlepage}{% - \fancyhf{} - \renewcommand{\footrulewidth}{0.4pt} - \fancyfoot[C]{\emph{ - Emacs setup for use with \LaTeX{}, Org, and Python -- Gerard Vermeulen}} - \renewcommand{\headrulewidth}{0.4pt} - \fancyhead[L]{\includegraphics[height=1.8cm]{Org-mode-unicorn.png}} - \fancyhead[C]{ - \pageref{LastPage} pages \\ - \text{ } \\ - \text{ } \\ - DRAFT - } - \fancyhead[R]{\includegraphics[height=1.8cm]{Emacs-logo.png}} - } - % End of the 5th and last LaTeX header block. +} +% End of the 5th and last LaTeX header block. #+end_src #+caption[LaTeX preamble: fancy headers and footers]: #+caption: LaTeX preamble: fancy headers and footers. #+name: lst:latex-header-5 #+begin_src latex :exports code :noweb yes - <> +<> #+end_src *** [[info:org#LaTeX specific export settings][Advanced LaTeX export settings]] @@ -3256,58 +3266,58 @@ exporting from Org-mode to LaTeX. #+header: :var title-page=lst/title-page #+name: lst:ox-latex-emacs-lisp-setup #+begin_src emacs-lisp :results silent :tangle no - (when (require 'ox-latex nil 'noerror) - ;; https://emacs.stackexchange.com/questions/47347/ - ;; customizing-org-latex-title-command-to-edit-title-page - (make-variable-buffer-local 'org-latex-classes) - (cl-pushnew '("article-local" - "\\documentclass[11pt]{article} - [NO-DEFAULT-PACKAGES] - [PACKAGES] - [EXTRA]" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) - org-latex-classes :key #'car :test #'equal) +(when (require 'ox-latex nil 'noerror) + ;; https://emacs.stackexchange.com/questions/47347/ + ;; customizing-org-latex-title-command-to-edit-title-page + (make-variable-buffer-local 'org-latex-classes) + (cl-pushnew '("article-local" + "\\documentclass[11pt]{article} +[NO-DEFAULT-PACKAGES] +[PACKAGES] +[EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")) + org-latex-classes :key #'car :test #'equal) - (make-variable-buffer-local 'org-latex-title-command) - (setq org-latex-title-command (concat title-page)) + (make-variable-buffer-local 'org-latex-title-command) + (setq org-latex-title-command (concat title-page)) - (make-variable-buffer-local 'org-latex-toc-command) - (setq org-latex-toc-command " - \\tableofcontents\\label{toc} - \\listoflistings - \\listoftables - \\newpage - ") + (make-variable-buffer-local 'org-latex-toc-command) + (setq org-latex-toc-command " +\\tableofcontents\\label{toc} +\\listoflistings +\\listoftables +\\newpage +") - (make-variable-buffer-local 'org-latex-subtitle-format) - (setq org-latex-subtitle-format "")) + (make-variable-buffer-local 'org-latex-subtitle-format) + (setq org-latex-subtitle-format "")) #+end_src #+caption[Show a title-page example for =org-latex-title-command=]: #+caption: Show a title-page example for =org-latex-title-command=. #+name: lst/title-page #+begin_src latex :exports code :results silent :tangle no - \begin{titlepage} - %% https://tex.stackexchange.com/questions/506102/ - %% adding-header-and-footer-to-custom-titlepage - \thispagestyle{titlepage} - \begin{center} - %% Title - \begin{Huge} - {\bf %t} \\ - \vspace{1em} - \end{Huge} - %% Author - \begin{Large} - {\bf %a} \\ - \vspace{1em} - \end{Large} - \end{center} - \end{titlepage} +\begin{titlepage} + %% https://tex.stackexchange.com/questions/506102/ + %% adding-header-and-footer-to-custom-titlepage + \thispagestyle{titlepage} + \begin{center} + %% Title + \begin{Huge} + {\bf %t} \\ + \vspace{1em} + \end{Huge} + %% Author + \begin{Large} + {\bf %a} \\ + \vspace{1em} + \end{Large} + \end{center} +\end{titlepage} #+end_src *** [[https://orgmode.org/worg/dev/org-syntax-edited.html][Org Syntax]] @@ -3331,35 +3341,35 @@ non-interactive =org-element= functions to an =Emacs-lisp= buffer. #+caption: Grok how =org-element= parses your document. #+name: lst:grok-org-element-tree #+begin_src emacs-lisp - (with-eval-after-load 'org-element - (when (require 'pp nil 'noerror) - (defconst grok-org-output - "*Grok Org Element Output*" - "Grok Org output buffer name.") +(with-eval-after-load 'org-element + (when (require 'pp nil 'noerror) + (defconst grok-org-output + "*Grok Org Element Output*" + "Grok Org output buffer name.") - (defun grok-org-element-at-point () - (interactive) + (defun grok-org-element-at-point () + (interactive) + (pp-display-expression + (org-element-at-point) grok-org-output)) + + (defun grok-org-element-context () + (interactive) + (pp-display-expression + (org-element-context) grok-org-output)) + + (defun grok-org-element-parse-buffer () + (interactive) + (let ((what (completing-read + "granularity: " + '(headline element greater-element object) + nil 'require-match))) (pp-display-expression - (org-element-at-point) grok-org-output)) + (org-element-parse-buffer what) grok-org-output))) - (defun grok-org-element-context () - (interactive) - (pp-display-expression - (org-element-context) grok-org-output)) - - (defun grok-org-element-parse-buffer () - (interactive) - (let ((what (completing-read - "granularity: " - '(headline element greater-element object) - nil 'require-match))) - (pp-display-expression - (org-element-parse-buffer what) grok-org-output))) - - (defun grok-org-heading-components () - (interactive) - (pp-display-expression - (org-heading-components) grok-org-output)))) + (defun grok-org-heading-components () + (interactive) + (pp-display-expression + (org-heading-components) grok-org-output)))) #+end_src ** Grammar, spelling, and style tools @@ -3390,13 +3400,13 @@ abbreviation definitions in this file by means of: #+caption: Definition of the =misspellings-abbrev= keyboard macro. #+name: lst:misspellings-abbrev #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (fset 'misspellings-abbrev - (kmacro-lambda-form - [?\C-s ?- ?> return backspace backspace ?\C-k ?\C-x ?a ?i ?g ?\C-y return] - 0 "%d")) +(with-eval-after-load 'emacs + (fset 'misspellings-abbrev + (kmacro-lambda-form + [?\C-s ?- ?> return backspace backspace ?\C-k ?\C-x ?a ?i ?g ?\C-y return] + 0 "%d")) - (setq-default abbrev-mode t)) + (setq-default abbrev-mode t)) #+end_src Listing [[lst:word-games]] defines the =anagram-p= function that migth be used for a @@ -3407,68 +3417,68 @@ the future. #+caption: Better parsing of the common misspellings list. #+name: lst:better-misspellings #+begin_src emacs-lisp - (with-eval-after-load 'emacs - (defun browse-common-misspellings () - "Open the Wikipedia page of common misspellings for machines in EWW." - (interactive) - (eww (concat "https://en.wikipedia.org/wiki/Wikipedia" - ":Lists_of_common_misspellings/For_machines"))) +(with-eval-after-load 'emacs + (defun browse-common-misspellings () + "Open the Wikipedia page of common misspellings for machines in EWW." + (interactive) + (eww (concat "https://en.wikipedia.org/wiki/Wikipedia" + ":Lists_of_common_misspellings/For_machines"))) - (defun wordnet-check (word) - "Check whether WORD occurs in the wordnet lexical database." - (cl-destructuring-bind (exit-code output) - (shell-command-with-exit-code "wn" word "-grepn" "-grepv" "-grepa" "-grepr") - (if (= 0 exit-code) - (< 0 (length (string-trim output))) - (error "%s" (string-trim output))))) + (defun wordnet-check (word) + "Check whether WORD occurs in the wordnet lexical database." + (cl-destructuring-bind (exit-code output) + (shell-command-with-exit-code "wn" word "-grepn" "-grepv" "-grepa" "-grepr") + (if (= 0 exit-code) + (< 0 (length (string-trim output))) + (error "%s" (string-trim output))))) - (defun better-misspellings () - "Pick the best from each common misspelling multiple choice of corrections." - (interactive) - (let (start end lines) - (save-excursion - (if (re-search-forward (rx bol "abandon")) - (setq start (match-beginning 0)) - (user-error "Failed to find beginning of misspellings")) - (if (re-search-forward (rx bol "Retrieved from")) - (setq end (match-beginning 0)) - (user-error "Failed to find end of misspellings"))) - (dolist (line (split-string - (buffer-substring-no-properties start end) "\n")) - (pcase-let ((`(,lhs . (,rhs . ,rest)) (split-string line "->"))) - (when (and (stringp rhs) - (string-match ", " rhs)) - (message "%s -> %s" lhs rhs) - (let ((words (split-string rhs ", ")) - (stack)) - (dolist (word words) - (when (wordnet-check word) - (message "wordnet finds: %s" word) - (push word stack)))))))))) + (defun better-misspellings () + "Pick the best from each common misspelling multiple choice of corrections." + (interactive) + (let (start end lines) + (save-excursion + (if (re-search-forward (rx bol "abandon")) + (setq start (match-beginning 0)) + (user-error "Failed to find beginning of misspellings")) + (if (re-search-forward (rx bol "Retrieved from")) + (setq end (match-beginning 0)) + (user-error "Failed to find end of misspellings"))) + (dolist (line (split-string + (buffer-substring-no-properties start end) "\n")) + (pcase-let ((`(,lhs . (,rhs . ,rest)) (split-string line "->"))) + (when (and (stringp rhs) + (string-match ", " rhs)) + (message "%s -> %s" lhs rhs) + (let ((words (split-string rhs ", ")) + (stack)) + (dolist (word words) + (when (wordnet-check word) + (message "wordnet finds: %s" word) + (push word stack)))))))))) #+end_src #+caption[Word games]: #+caption: Word games. #+name: lst:word-games #+begin_src emacs-lisp - ;; https://funcall.blogspot.com/2022/07/lets-play-wordle.html - ;; https://github.com/tabatkins/wordle-list +;; https://funcall.blogspot.com/2022/07/lets-play-wordle.html +;; https://github.com/tabatkins/wordle-list - (defun anagram-p (evil vile) - "Check whether strings EVIL and VILE are anagrams of each other." - (if (string= evil vile) - nil - (string= (cl-sort evil #'<) (cl-sort vile #'<)))) +(defun anagram-p (evil vile) + "Check whether strings EVIL and VILE are anagrams of each other." + (if (string= evil vile) + nil + (string= (cl-sort evil #'<) (cl-sort vile #'<)))) - ;; https://funcall.blogspot.com/2020/01/palindromes-redux-and-sufficiently.html - ;; https://irreal.org/blog/?p=8570 - (defun palindrome-p (word) - "Check whether the string WORD is a palindrome." - (cl-do ((head 0 (1+ head)) - (tail (1- (length word)) (1- tail)) - (ok t)) - ((or (not ok) (>= head tail) ok) - (setq ok (= (aref word head) (aref word tail)))))) +;; https://funcall.blogspot.com/2020/01/palindromes-redux-and-sufficiently.html +;; https://irreal.org/blog/?p=8570 +(defun palindrome-p (word) + "Check whether the string WORD is a palindrome." + (cl-do ((head 0 (1+ head)) + (tail (1- (length word)) (1- tail)) + (ok t)) + ((or (not ok) (>= head tail) ok) + (setq ok (= (aref word head) (aref word tail)))))) #+end_src *** [[https://dict.org/bin/Dict][DICT.org]] @@ -3495,58 +3505,58 @@ I am using the following Debian Bullseye dictionaries on Darwin and Gentoo: #+name: lst:darwin-dict-resource-file #+header: :tangle (if (eq 'darwin system-type) "~/.dictrc" "no") #+begin_src conf - # https://jpmens.net/2020/03/08/looking-up-words-with-dict/ - server 127.0.0.1 { - port 2628 - } - # Local Variables: - # mode: conf-unix - # End: +# https://jpmens.net/2020/03/08/looking-up-words-with-dict/ +server 127.0.0.1 { + port 2628 +} +# Local Variables: +# mode: conf-unix +# End: #+end_src #+caption[Make a configuration file for =dictd= on =Darwin=]: #+caption: Make a configuration file for =dictd= on =Darwin=. #+name: lst:dictd-configuration-file #+begin_src shell :eval (if (eq 'darwin system-type) "yes" "never") :results silent - cat > ~/.dictd.conf < ~/.dictd.conf <