diff --git a/.gitignore b/.gitignore index 33d1649..6f02458 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,10 @@ *.fdb_latexmk *.fls *.html +*.lof *.log +*.lol +*.lot *.out *.pdf *.py diff --git a/Emacs-logo.png b/Emacs-logo.png new file mode 100644 index 0000000..08051c8 Binary files /dev/null and b/Emacs-logo.png differ diff --git a/Org-mode-unicorn.png b/Org-mode-unicorn.png new file mode 100644 index 0000000..17a5f5f Binary files /dev/null and b/Org-mode-unicorn.png differ diff --git a/README.org b/README.org index 5b3145b..b1b50a1 100644 --- a/README.org +++ b/README.org @@ -3,9 +3,19 @@ #+author: Gerard Vermeulen #+babel: :cache no #+property: header-args :tangle init.el :comments link -#+property: header-args:emacs-lisp :results silent +#+property: header-args:emacs-lisp :exports code :results silent +# #+latex_class: article #+latex_class_options: [11pt,a4paper,svgnames] +#+latex_header: \usepackage[AUTO]{babel} +#+latex_header: \usepackage{fvextra} +#+latex_header: \usepackage{csquotes} +# +#+latex_header: \usepackage{caption} +#+latex_header: \usepackage[newfloat]{minted} +#+latex_header: \captionsetup[listing]{position=below,skip=0em} +#+latex_header: \usemintedstyle{xcode} +# #+latex_header: \hypersetup{ #+latex_header: citecolor=blue, #+latex_header: colorlinks=true, @@ -15,35 +25,59 @@ #+latex_header: unicode=true, #+latex_header: urlcolor=blue #+latex_header: } -#+latex_header: \usepackage{minted} -#+latex_header: \usemintedstyle{xcode} +# +#+latex_header: \usepackage{fancyhdr} +#+latex_header: \usepackage{lastpage} +# #+latex_header: \usepackage[ #+latex_header: headheight=20mm, #+latex_header: top=40mm, #+latex_header: bottom=20mm, -#+latex_header: left=0.1\paperwidth, -#+latex_header: right=0.1\paperwidth, +#+latex_header: left=60pt, +#+latex_header: right=60pt, #+latex_header: heightrounded, #+latex_header: verbose, #+latex_header: ]{geometry} +# +#+latex_header: % Make section an implicit float barrier: +#+latex_header: \usepackage[section]{placeins} +#+latex_header: % Make subsection an implicit float barrier: +#+latex_header: \makeatletter +#+latex_header: \AtBeginDocument{% +#+latex_header: \expandafter\renewcommand\expandafter\subsection\expandafter{% +#+latex_header: \expandafter\@fb@secFB\subsection +#+latex_header: }% +#+latex_header: } +#+latex_header: \makeatother +#+latex_header: % Make subsubsection an implicit float barrier: +#+latex_header: \makeatletter +#+latex_header: \AtBeginDocument{% +#+latex_header: \expandafter\renewcommand\expandafter\subsubsection\expandafter{% +#+latex_header: \expandafter\@fb@secFB\subsubsection +#+latex_header: }% +#+latex_header: } +#+latex_header: \makeatother * Quick start :PROPERTIES: :CUSTOM_ID: sec:quick-start :END: -Backup your =~/.emacs.d= directory to execute the following commands: +Backup your =user-emacs-directory= (defaults often to =~/.emacs.d= on =Linux=, +=Unix=, or =Darwin=) directory and execute the commands in listing +[[lst:prepare-user-emacs-directory]]. After normal (interactive mode, no batch +mode, neither server mode), Emacs will ask you to install a selected set of +packages. Quit Emacs and invoke Emacs again. +#+caption[Prepare the user-emacs-directory]: +#+caption: Clone and initialize the user-emacs-directory. +#+label: lst:prepare-user-emacs-directory #+begin_src shell :noeval :tangle no cd ~ - git clone ccdr@mercury.grenoble.cnrs.fr:SERVER/.emacs.d + git clone ccdr@mercury.grenoble.cnrs.fr:SERVER/emacs.d.git .emacs.d make --directory=.emacs.d init + emacs & #+end_src -After its invokation, Emacs will install a minimal set of packages. Now, you -have the option to install all optional packages using the command -=my-install-optional-packages=, but you can do this any time, or you can install -any package using the command =package-install= whenever you like. Quit Emacs -and invoke Emacs again. * Introduction :PROPERTIES: @@ -56,9 +90,9 @@ the reports is [[https://orgmode.org/][Org Mode]] plain text with [[https://www. format of the presentations is [[https://www.latex-project.org/][LaTeX]]. This [[info:org#Top][org]] file (more precisely the original [[info:org#Top][org]] source file of this file) -illustrates my work-flow by showing: +illustrates three methods in my work-flow: 1. How to tangle (or export) source blocks from [[info:org#Top][org]] files. This file contains - source blocks to produce the files =early-init.el=, =init.el=, =latexmkrc=, + source blocks to produce the files =early-init.el=, =init.el=, =latexmkrc=, =org-store-link=, and =example.py= by tangling. 2. How to export [[info:org#Top][org]] files to other formats such as [[https://en.wikipedia.org/wiki/HTML][HTML]], [[https://www.latex-project.org/][LaTeX]], and [[https://en.wikipedia.org/wiki/PDF][PDF]]. 3. How [[info:org#Hyperlinks][org hyperlinks (info)]] allow to link inside and outside [[info:org#Top][Org Mode]]: hover @@ -115,6 +149,9 @@ Here follows a list of interesting Emacs configurations: Try to load [[https://github.com/emacscollective/no-littering][no-littering]] as early as possible, since it helps to keep =~/.emacs.d= clean. +#+caption[Tangle the early-init-file]: +#+caption: Tangle the early-init-file. +#+label: lst:tangle-early-init-file #+begin_src emacs-lisp :tangle early-init.el ;;; early-init.el --- user early-init file -*- lexical-binding: t -*- ;;; Commentary: @@ -135,9 +172,9 @@ Try to load [[https://github.com/emacscollective/no-littering][no-littering]] as In order to get help in understanding the code block above in a buffer showing the original [[info:org#Top][Org]] source file, move point (or cursor) to one of the items of the list the and type =C-c C-c=: -1. src_emacs-lisp[:exports code]{(describe-variable #'load-prefer-newer t)} -2. src_emacs-lisp[:exports code]{(apropos-library "no-littering")} -3. src_emacs-lisp[:exports code]{(find-function #'hack-local-variables)} +1. src_emacs-lisp{(describe-variable #'load-prefer-newer t)} +2. src_emacs-lisp{(apropos-library "no-littering")} +3. src_emacs-lisp{(find-function #'hack-local-variables)} to execute the code between the curly braces for access to help. This shows why *Emacs is a self-documenting editor.* @@ -147,14 +184,22 @@ This shows why *Emacs is a self-documenting editor.* :CUSTOM_ID: sec:init-file-header :END: -The [[info:elisp#Quoting][quoting (info)]] and the [[info:elisp#Backquote][backquote (info)]] pages explain how to understand the -reader macros ~'~ (quote), ~`~ (backquote), ~,~ (substitute) and ~@,~ (splice) -in the ~custom-set-variable~ function call below. A tutorial of how to use those -reader macros is the [[https://mullikine.github.io/posts/macro-tutorial/][didactic emacs-lisp macro example]]. - -Because of the ~custom-set-variables~ function call, the [[info:emacs#Init File][init file (info)]] does -not load the ~custom-file~ as [[info:emacs#Saving Customizations][saving customizations (info)]] recommends. +The =user-init-file= header requires =cl-lib= and customizes Emacs variables. +It consists of three parts in listing [[lst:1st-custom-set-variables-call]], +[[lst:2nd-custom-set-variables-call]], and [[lst:3rd-custom-set-variables-call]] in +order to limit the length of the listings for exporting to LaTeX. The [[info:elisp#Quoting][quoting +(info)]] and the [[info:elisp#Backquote][backquote (info)]] pages explain how to understand the reader +macros ~'~ (quote), ~`~ (backquote), ~,~ (substitute) and ~@,~ (splice) in the +~custom-set-variables~ function calls in listing +[[lst:1st-custom-set-variables-call]], [[lst:2nd-custom-set-variables-call]], and +[[lst:3rd-custom-set-variables-call]]. A tutorial of how to use those reader macros +is the [[https://mullikine.github.io/posts/macro-tutorial/][didactic emacs-lisp macro example]]. The [[info:emacs#Init File][init file (info)]] does not load +the ~custom-file~ as [[info:emacs#Saving Customizations][saving customizations (info)]] recommends because of the +~custom-set-variables~ function calls. +#+caption[Customize the first set of Emacs variables]: +#+caption: Customize the first set of Emacs variables. +#+label: lst:1st-custom-set-variables-call #+begin_src emacs-lisp ;;; init.el --- user init file -*- lexical-binding: t -*- ;;; Commentary: @@ -165,13 +210,10 @@ not load the ~custom-file~ as [[info:emacs#Saving Customizations][saving customi '(after-save-hook #'executable-make-buffer-file-executable-if-script-p) '(column-number-mode t) '(cursor-type 'box) - ;; `(custom-file ,(make-temp-file "emacs-custom-")) `(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) @@ -182,14 +224,17 @@ not load the ~custom-file~ as [[info:emacs#Saving Customizations][saving customi '(kill-ring-max 300) '(package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ("nongnu" . "https://elpa.nongnu.org/nongnu/") - ("melpa" . "https://melpa.org/packages/"))) + ("melpa" . "https://melpa.org/packages/")))) +#+end_src + +#+caption[Customize the second set of Emacs variables]: +#+caption: Customize the second set of Emacs variables. +#+label: lst:2nd-custom-set-variables-call +#+begin_src emacs-lisp + (custom-set-variables `(package-selected-packages - `( - ,@(when (version< emacs-version "28.0") - '( - org ; plain text thought organizer - modus-themes ; high foreground/background contrast themes - )) + `(,@(when (version< emacs-version "28.0") + '(org)) ; plain text thought organizer anaconda-mode ; strangles python-mode async ; asynchroneous processing auctex ; Aalborg University Center TeX @@ -228,17 +273,16 @@ not load the ~custom-file~ as [[info:emacs#Saving Customizations][saving customi writegood-mode ; bullshit and weasel-word detector ws-butler ; remove trailing whitespace xr ; undo rx to grok regular expressions - yasnippet ; code or text template expansion - )) - '(python-indent-guess-indent-offset nil) + yasnippet))) ; code or text template expansion +#+end_src + +#+caption[Customize the third set of Emacs variables]: +#+caption: Customize the third set of Emacs variables. +#+label: lst:3rd-custom-set-variables-call +#+begin_src emacs-lisp + (custom-set-variables '(recentf-mode t) '(save-place-mode t) - '(savehist-additional-variables - '(eww-history - kill-ring - regexp-search-string - search-ring - search-string)) '(scroll-bar-mode nil) '(tab-always-indent 'complete) '(tab-width 8) @@ -260,9 +304,9 @@ not load the ~custom-file~ as [[info:emacs#Saving Customizations][saving customi (add-to-list 'initial-frame-alist '(width . 180))) #+end_src -* Package bootstrapping +* Install the selected packages :PROPERTIES: -:CUSTOM_ID: sec:package-bootstrapping +:CUSTOM_ID: sec:install-selected-packages :END: [[info:emacs#Package Installation][Emacs installs packages]] from archives on the internet. This setup uses three @@ -273,21 +317,21 @@ archives: Finally, the [[https://github.com/quelpa/quelpa][quelpa]] tool allows to fetch code from any source and build a package on your computer before installation. -The code assumes that the package system is in a *virgin* state in case the -package [[https://github.com/emacscollective/no-littering][no-littering]] is not present. Refreshing the contents of available -packages at least once is a requirement in order to be able to install and load -any packages, hence also [[https://github.com/emacscollective/no-littering][no-littering]]. +The code in listing [[lst:install-selected-packages]] assumes that the package +system is in a *virgin* state in case the package [[https://github.com/emacscollective/no-littering][no-littering]] is not present. +Refreshing the contents of available packages at least once is a requirement in +order to be able to install and load any packages, hence also [[https://github.com/emacscollective/no-littering][no-littering]]. -The call src_emacs-lisp[:exports code]{(package-install-selected-packages)} -checks the installation status of all packages in -src_emacs-lisp[:exports code]{package-selected-packages} and installs the -missing packages after the user has agreed to its prompt. - -After package bootstrapping, you have to refresh the list of available packages -yourself before updating the installed packages. +The call src_emacs-lisp{(package-install-selected-packages)} checks the +installation status of all packages in src_emacs-lisp{package-selected-packages} +and installs the missing packages after the user has agreed to its prompt. In +case of normal Emacs usage, src_emacs-lisp{(package-list-packages)} refreshes +the contents of packages and allows to update packages to the latest version. +#+caption[Install the selected packages]: +#+caption: Install the selected packages. +#+label: lst:install-selected-packages #+begin_src emacs-lisp - ;; The is the 1st package bootstrapping block. (unless (require 'no-littering nil 'noerror) (package-refresh-contents) (package-install 'no-littering) @@ -304,22 +348,25 @@ yourself before updating the installed packages. Emacs can act as a server that listens to a socket to share its state (for instance buffers and command history) with other programs by means of a shell -command =emacsclient=. +command =emacsclient=. Section [[#sec:latexmk-save-compile-display-loop]] and +[[#sec:qutebrowser-userscript]] show how to use ~emacsclient~ to: +1. Install an asynchronous (or background) loop of saving a LaTeX file, + compiling it, and redisplaying the output in Emacs. +2. Make [[https://qutebrowser.org][qutebrowser]] send html links with document titles to Emacs. +The code in listing [[lst:start-emacs-server]] starts the Emacs server. +#+caption[Start the Emacs server]: +#+caption: Start the Emacs server. +#+label: lst:start-emacs-server #+begin_src emacs-lisp (when window-system (unless (or noninteractive (daemonp)) (add-hook 'after-init-hook #'server-start))) #+end_src -The next two configuration blocks show how to use ~emacsclient~ to: -1. Install an asynchronous (or background) loop of saving a LaTeX file, - compiling it, and redisplaying the output in Emacs. -2. Make [[https://qutebrowser.org][qutebrowser]] send html links with document titles to Emacs. - -** LaTeX save-compile-display loop +** Latexmk save-compile-display loop :PROPERTIES: -:CUSTOM_ID: sec:latex-save-compile-display-loop +:CUSTOM_ID: sec:latexmk-save-compile-display-loop :END: The =latexmk= resource file in the next source code block shows how to use @@ -327,8 +374,11 @@ The =latexmk= resource file in the next source code block shows how to use (re)compilation on condition that the settings of the ~compile-command~ local variable in section are compatible. The local variable ~compile-command~ in the [[#sec:local-variables][local variables]] section (only visible in =org= files, but not in =html= and -=pdf= files) shows how to use the =latexmkrc= file.. +=pdf= files) shows how to use the =latexmkrc= file. +#+caption[Tangle the Latexmk resource file]: +#+caption: Tangle the Latexmk resource file. +#+label: lst:latexmkrc #+begin_src perl :tangle latexmkrc :comments none # pdf previewer and update pdf previewer $pdf_previewer = "emacsclient -e '(find-file-other-window %S)'"; @@ -337,7 +387,7 @@ variable in section are compatible. The local variable ~compile-command~ in the # see for instance glossary.latexmkrc add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' ); add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' ); - $clean_ext .= " acr acn alg bbl glo gls glg ist run.xml"; + $clean_ext .= " acr acn alg bbl glo gls glg ist lol run.xml"; sub makeglossaries { my ($name, $path) = fileparse( $$Psource ); return system "makeglossaries -d '$path' '$name'"; @@ -366,8 +416,11 @@ On a [[https://en.wikipedia.org/wiki/POSIX][POSIX]] system, you can run the user terminal to see whether it works. In case you try to run it from Emacs, Emacs may hang or die. +#+caption[Tangle a qutebrowser userscript]: +#+caption: Tangle a qutebrowser userscript. #+header: :comments none #+header: :tangle-mode (identity #o755) +#+label: lst:qutebrowser-userscript #+begin_src python :noeval :tangle org-store-link #!/usr/bin/env python from urllib.parse import urlencode @@ -402,19 +455,37 @@ packages to enrich the completion UI: where the order is that of [[https://github.com/bdarcus/citar#installation][enhancing citar's experience]] and the configuration steps below. -Finally, [[https://company-mode.github.io/][company: a modular complete-anything framework for Emacs]] fills another -niche than the five packages above. +Finally, [[https://company-mode.github.io/][company: a modular complete-anything framework for Emacs]] provides +completion in any buffer and [[#sec:minibuffer-history-completion][minibuffer-history-completion]] provides completion +on previous input in the minibuffer. ** [[info:vertico#Top][Vertico (info)]] :PROPERTIES: :CUSTOM_ID: sec:vertico-configuration :END: +Listing [[lst:enable-vertico-mode]] configures and enables =savehist-mode= and +enables =vertico-mode=. The documentation src_emacs-lisp{(describe-function +'savehist-mode)} why it is best to turn on =savehist-mode= in the Emacs init +file. + +#+caption[Enable =savehist-mode= and =vertico-mode=]: +#+caption: Enable =savehist-mode= and =vertico-mode=. +#+label: lst:enable-vertico-mode #+begin_src emacs-lisp (unless noninteractive + (custom-set-variables + '(history-delete-duplicates t) + '(history-length 500) + '(savehist-additional-variables + '(eww-history + kill-ring + regexp-search-string + search-ring + search-string))) + (savehist-mode +1) (when (fboundp 'vertico-mode) - (vertico-mode +1)) - (savehist-mode +1)) + (vertico-mode +1))) #+end_src ** [[info:orderless#Top][Orderless (info)]] @@ -422,7 +493,11 @@ niche than the five packages above. :CUSTOM_ID: sec:orderless-configuration :END: -#+attr_latex: :options bgcolor=LightGoldenrodYellow +Listing [[lst:configure-orderless]] enables =orderless=. + +#+caption[Configure =orderless=]: +#+caption: Configure =orderless=. +#+label: lst:configure-orderless #+begin_src emacs-lisp (unless noninteractive (when (fboundp 'orderless-filter) @@ -442,6 +517,11 @@ niche than the five packages above. :CUSTOM_ID: sec:embark-configuration :END: +Listing [[lst:configure-embark]] configures =embark=. + +#+caption[Configure =embark=]: +#+caption: Configure =embark=. +#+label: lst:configure-embark #+begin_src emacs-lisp (unless noninteractive (when (cl-every #'fboundp '(embark-act embark-bindings embark-dwim)) @@ -455,6 +535,11 @@ niche than the five packages above. :CUSTOM_ID: sec:marginalia-configuration :END: +Listing [[lst:enable-marginalia-mode]] enables =marginalia-mode=. + +#+caption[Enable =marginalia-mode=]: +#+caption: Enable =marginalia-mode=. +#+label: lst:enable-marginalia-mode #+begin_src emacs-lisp (unless noninteractive (when (fboundp 'marginalia-mode) @@ -466,6 +551,11 @@ niche than the five packages above. :CUSTOM_ID: sec:consult-configuration :END: +Listing [[lst:configure-consult]] configures =consult=. + +#+caption[Configure =consult=]: +#+caption: Configure =consult=. +#+label: lst:configure-consult #+begin_src emacs-lisp (unless noninteractive (when (fboundp 'consult-apropos) @@ -510,6 +600,11 @@ niche than the five packages above. :CUSTOM_ID: sec:company-configuration :END: +Listing [[lst:configure-company]] configures =company=. + +#+caption[Configure =company=]: +#+caption: Configure =company=. +#+label: lst:configure-company #+begin_src emacs-lisp (unless noninteractive (when (fboundp 'company-mode) @@ -526,10 +621,17 @@ niche than the five packages above. #+end_src ** Minibuffer history completion +:PROPERTIES: +:CUSTOM_ID: sec:minibuffer-history-completion +:END: See [[https://lists.gnu.org/archive/html/emacs-devel/2021-12/msg00802.html][Juri Linkov (Emacs Developer mailing list)]] for how to allow completion on -previous input in the minibuffer. +previous input in the minibuffer. Listing +[[lst:enable-minibuffer-history-completion]] enables minibuffer history completion. +#+caption[Enable =minibuffer-history-completion=]: +#+caption: Enable =minibuffer-history-completion=. +#+label: lst:enable-minibuffer-history-completion #+begin_src emacs-lisp (defun minibuffer-setup-history-completions () (unless (or minibuffer-completion-table minibuffer-completion-predicate) @@ -558,10 +660,17 @@ previous input in the minibuffer. #+end_src ** Prefix key-binding help +:PROPERTIES: +:CUSTOM_ID: sec:prefix-key-binding-help +:END: Configure ~which-key-mode~ so that typing =C-h= after a prefix key displays all -keys available after the prefix key. +keys available after the prefix key. Listing [[lst:enable-which-key-mode]] enables +=which-key-mode=. +#+caption[Enable =which-key-mode=]: +#+caption: Enable =which-key-mode=. +#+label: lst:enable-which-key-mode #+begin_src emacs-lisp (when (fboundp 'which-key-mode) (custom-set-variables @@ -572,15 +681,29 @@ keys available after the prefix key. #+end_src * Reading +:PROPERTIES: +:CUSTOM_ID: sec:reading +:END: -** EPUB files +** Reading EPUB files +:PROPERTIES: +:CUSTOM_ID: sec:reading-epub-files +:END: +Listing [[lst:enable-nov-mode]] enables =nov-mode=. + +#+caption[Enable =nov-mode=]: +#+caption: Enable =nov-mode=. +#+label: lst:enable-nov-mode #+begin_src emacs-lisp (when (fboundp 'nov-mode) (add-to-list 'auto-mode-alist `(,(rx ".epub" eos) . nov-mode))) #+end_src -** PDF files +** Reading PDF files +:PROPERTIES: +:CUSTOM_ID: sec:reading-pdf-files +:END: The [[https://github.com/vedang/pdf-tools][pdf-tools]] package exploits the [[https://github.com/freedesktop/poppler][poppler]] library to render and to let you annotate [[https://en.wikipedia.org/wiki/PDF][PDF]] files. It also exploits the [[https://wiki.contextgarden.net/SyncTeX][SyncTeX]] library to link anchors in [[https://en.wikipedia.org/wiki/PDF][PDF]] @@ -590,6 +713,9 @@ In order to use [[https://github.com/vedang/pdf-tools][pdf-tools]], you have to installation of [[https://github.com/vedang/pdf-tools][pdf-tools]] from [[https://melpa.org/][MELPA]] or after each update of [[https://github.com/freedesktop/poppler][poppler]] to build or rebuild the =epdfinfo= executable that serves the [[https://en.wikipedia.org/wiki/PDF][PDF]] files to Emacs. +#+caption[Enable =pdf-tools=]: +#+caption: Enable =pdf-tools=. +#+label: lst:enable-pdf-tools #+begin_src emacs-lisp ;; 'pdf-loader-install' is the lazy equivalent of 'pdf-tools-install': ;; see the README file. @@ -602,8 +728,14 @@ rebuild the =epdfinfo= executable that serves the [[https://en.wikipedia.org/wik #+end_src * Writing +:PROPERTIES: +:CUSTOM_ID: sec:writing +:END: -** LaTeX +** Writing LaTeX files +:PROPERTIES: +:CUSTOM_ID: sec:writing-latex-files +:END: Loading =tex.el= immediately instead of lazily ensures proper initialization of the [[https://en.wikipedia.org/wiki/AUCTeX][AUCTeX]]. For instance, the ~TeX-master~ safe local variable in the =tex.el= @@ -611,23 +743,59 @@ elisp library file has no autoload cookie. Without prior loading of =tex.el=, Emacs will complain that ~TeX-master~ is no safe local variable in case it reads a LaTeX file that sets ~TeX-master~. -Out of the box, [[https://en.wikipedia.org/wiki/AUCTeX][AUCTeX]] does not indent text between square brackets. The code -below corrects this by advising to override ~TeX-brace-count-line~ with -~my-TeX-brace-count-line~. - +#+caption[Require =AUCTeX=]: +#+caption: Require =AUCTeX=. +#+label: lst:require-auctex #+begin_src emacs-lisp ;; Try to get the `safe-local-variable' predicate for `TeX-master' (when (require 'tex nil 'noerror) + (custom-set-variables + '(TeX-auto-save t) + '(TeX-parse-self t))) +#+end_src + +#+caption[Configure =bibtex=]: +#+caption: Configure =bibtex=. +#+label: lst:configure-bibtex +#+begin_src emacs-lisp + (with-eval-after-load 'bibtex + (custom-set-variables + '(bibtex-dialect 'BibTeX))) +#+end_src + +#+caption[Configure =font-latex=]: +#+caption: Configure =font-latex=. +#+label: lst:configure-font-latex +#+begin_src emacs-lisp + (with-eval-after-load 'font-latex + (custom-set-variables + '(font-latex-fontify-sectioning 1.0))) +#+end_src + +#+caption[Configure =latex=]: +#+caption: Configure =latex=. +#+label: lst:configure-latex +#+begin_src emacs-lisp + (with-eval-after-load 'latex (custom-set-variables '(LaTeX-section-hook '(LaTeX-section-heading LaTeX-section-title LaTeX-section-toc LaTeX-section-section - LaTeX-section-label)) - '(TeX-auto-save t) - '(TeX-parse-self t) - '(font-latex-fontify-sectioning 1.0)) - ;; https://emacs.stackexchange.com/questions/17396/indentation-in-square-brackets + LaTeX-section-label)))) +#+end_src + +Out of the box, [[https://en.wikipedia.org/wiki/AUCTeX][AUCTeX]] does not indent text between square brackets. The code +in listing [[lst:configure-tex]] corrects this by advising to override +~TeX-brace-count-line~ with ~my-TeX-brace-count-line~. + +#+caption[Configure =TeX=]: +#+caption: Configure =TeX=. +#+label: lst:configure-tex +#+begin_src emacs-lisp + (with-eval-after-load 'tex + ;; https://emacs.stackexchange.com/questions/17396/ + ;; indentation-in-square-brackets (defun my-TeX-brace-count-line () "Count number of open/closed braces." (save-excursion @@ -650,19 +818,24 @@ below corrects this by advising to override ~TeX-brace-count-line~ with (forward-char) t)))))) count))) (advice-add 'TeX-brace-count-line :override #'my-TeX-brace-count-line)) - - (with-eval-after-load 'bibtex - (custom-set-variables - '(bibtex-dialect 'BibTeX))) #+end_src *** TODO Improve the AUCTeX configuration slowly [[https://github.com/thisirs/dotemacs/blob/master/lisp/init-auctex.el][AUCTeX setup of an experienced user]] -** Org-mode +** Writing Org files +:PROPERTIES: +:CUSTOM_ID: sec:writing-org-files +:END: -*** [[info:org#Activation][Activation (info)]] +*** [[info:org#Activation][Org activation (info)]] +:PROPERTIES: +:CUSTOM_ID: sec:activate-org +:END: +#+caption[Activate =Org=]: +#+caption: Activate =Org=. +#+label: lst:activate-org #+begin_src emacs-lisp ;; Inspect: ;; function with "C-h f" @@ -675,127 +848,230 @@ below corrects this by advising to override ~TeX-brace-count-line~ with (global-set-key (kbd "C-c C-l") #'org-insert-link-global) #+end_src -*** Customization - -#+begin_src emacs-lisp - (custom-set-variables - '(org-babel-python-command "python -E") - '(org-babel-load-languages '((C . t) - (calc . t) - (dot . t) - (emacs-lisp . t) - (eshell . t) - (fortran . t) - (gnuplot . t) - (latex . t) - (lisp . t) - (maxima . t) - (org . t) - (perl . t) - (python . t) - (scheme . t) - (shell . t))) - '(org-cite-export-processors '((latex biblatex) - (t csl))) - '(org-file-apps '((auto-mode . emacs) - (directory . emacs) - ("\\.mm\\'" . default) - ("\\.x?html?\\'" . default) - ("\\.pdf\\'" . emacs))) - '(org-confirm-babel-evaluate nil) - '(org-latex-compiler "lualatex") - '(org-latex-hyperref-template nil) - '(org-latex-listings 'minted) - '(org-latex-minted-options '(("bgcolor" "LightGoldenrodYellow"))) - '(org-latex-logfiles-extensions '("blg" "lof" "log" "lot" "out" "toc")) - '(org-latex-prefer-user-labels t) - '(org-modules '(ol-bibtex - ol-doi - ol-eww - ol-info - org-id - org-protocol - org-tempo)) - '(org-src-fontify-natively t) - '(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 :async") - ("v" . "verse")))) -#+end_src - -*** [[info:org#External Links][Export external links (info)]] +*** Org customization :PROPERTIES: -:CUSTOM_ID: sec:export-external-links +:CUSTOM_ID: sec:customize-org :END: +The code in listing [[lst:customize-org-babel]], [[lst:customize-org]], and +[[lst:customize-org-export]] does basic customization of [[https://orgmode.org/][Org Mode]] variables. + +#+caption[Customize =org-babel=]: +#+caption: Customize =org-babel=. +#+label: lst:customize-org-babel +#+begin_src emacs-lisp + (with-eval-after-load 'ob-core + (custom-set-variables + '(org-confirm-babel-evaluate nil))) + + (with-eval-after-load 'ob-python + (custom-set-variables + '(org-babel-python-command "python -E"))) +#+end_src + +#+caption[Customize =Org=]: +#+caption: Customize =Org=. +#+label: lst:customize-org +#+begin_src emacs-lisp + (with-eval-after-load 'org + (custom-set-variables + '(org-babel-load-languages '((C . t) + (calc . t) + (dot . t) + (emacs-lisp . t) + (eshell . t) + (fortran . t) + (gnuplot . t) + (latex . t) + (lisp . t) + (maxima . t) + (org . t) + (perl . t) + (python . t) + (scheme . t) + (shell . t))) + '(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 :async") + ("v" . "verse"))))) +#+end_src + +#+caption[Customize =org-export=]: +#+caption: Customize =org-export=. +#+label: lst:customize-org-export +#+begin_src emacs-lisp + (with-eval-after-load 'ox-latex + (custom-set-variables + '(org-latex-compiler "lualatex") + '(org-latex-hyperref-template nil) + '(org-latex-listings 'minted) + '(org-latex-minted-options '(("bgcolor" "LightGoldenrodYellow"))) + '(org-latex-logfiles-extensions '("blg" "lof" "log" "lot" "out" "toc")) + '(org-latex-prefer-user-labels t))) +#+end_src + +*** [[https://github.com/bdarcus/citar][Citar: citing bibliography]] with [[https://orgmode.org/][Org Mode]] +:PROPERTIES: +:CUSTOM_ID: sec:citing-bibliography +:END: + +[[https://github.com/bdarcus/citar][Citar]] is a completing-read front-end to browse and act on BibTeX, BibLaTeX, as +well as CSL JSON bibliographic data with LaTeX, markdown, and org-cite editing +support. In combination with vertico, orderless, embark, marginalia, and +consult, [[https://github.com/bdarcus/citar][Citar]] provides quick filtering and selecting of bibliographic entries +from the minibuffer, as well as the option to run different commands on those +selections. Listing [[lst:configure-oc-cite+citar]] configures =org-cite=, =citar=, +and =org=. + +#+caption[Configure =org-cite= with =citar=]: +#+caption: Configure =oc-cite= with =citar=. +#+label: lst:configure-oc-cite+citar +#+begin_src emacs-lisp + (with-eval-after-load 'oc + (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 + (when (require 'citar nil 'noerror) + (custom-set-variables + '(citar-bibliography '("~/VCS/research/refs.bib")) + '(citar-file-extensions '("djvu" "pdf")) + '(citar-library-paths '("~/VCS/research/papers/")))) + + (define-key org-mode-map (kbd "C-c b") 'org-cite-insert)) +#+end_src + +*** TODO Compare bibtex and biblatex +1. [[https://www.economics.utoronto.ca/osborne/latex/BIBTEX.HTM][Using bibtex: a short guide]] +2. [[https://www.tug.org/texlive//devsrc/Master/texmf-dist/doc/latex/biblatex/biblatex.pdf][The biblatex package]] +3. [[https://github.com/yuchenlin/rebiber][Rebiber: A tool for normalizing bibtex with official info]] +4. [[https://github.com/josephwright/biblatex-phys][A biblatex implementation of the AIP and APS bibliography style]] + +*** [[info:org#Adding Hyperlink Types][Making Org hyperlink types (info)]] +:PROPERTIES: +:CUSTOM_ID: sec:making-org-hyperlink-types +:END: + +The code in listing [[lst:define-org-link-types]] defines =org-link= types for +backwards compatibility with [[https://github.com/jkitchin/org-ref][org-ref]]. + +#+caption[Define =org-link= types]: +#+caption: Define =org-link= types. +#+label: lst:define-org-link-types #+begin_src emacs-lisp (with-eval-after-load 'ol (org-link-set-parameters "ac*" :export (lambda (path _desc backend _info) (pcase backend - (`latex - (format "\\gls*{%s}" path)) + (`latex (format "\\gls*{%s}" path)) (_ path)))) (org-link-set-parameters "cite" :export (lambda (path _desc backend _info) (pcase backend - (`latex - (format "\\cite{%s}" path)) + (`latex (format "\\cite{%s}" path)) (_ path)))) (org-link-set-parameters "eqref" :export (lambda (path _desc backend _info) (pcase backend - (`latex - (format "\\eqref{%s}" path)) + (`latex (format "\\eqref{%s}" path)) (_ path)))) (org-link-set-parameters "hyperlink" :export (lambda (path desc backend _info) - (pcase backend - (`latex - (format "\\hyperlink{%s}{%s}" path desc)) - (_ path)))) + (pcase backend + (`latex (format "\\hyperlink{%s}{%s}" path desc)) + (_ path)))) (org-link-set-parameters "label" :export (lambda (path _desc backend _info) (pcase backend - (`latex - (format "\\label{%s}" path)) + (`latex (format "\\label{%s}" path)) (_ path)))) (org-link-set-parameters "ref" :export (lambda (path _desc backend _info) (pcase backend - (`latex - (format "\\ref{%s}" path)) + (`latex (format "\\ref{%s}" path)) (_ path))))) #+end_src -In order to export the [[info:org#External Links][info links (info)]] in this document to =html= correctly, -modify the constant ~org-info-other-documents~ defined in =ol-info.el=. - -Note: how to make it work without tangling? +Listing [[lst:emacs-lisp-setup-patch-ol-info]] patches the function =org-info-export= +and the constant ~org-info-other-documents~, to export the [[info:org#External Links][info: links (info)]] in +this document to =html= and LaTeX correctly. +#+caption[Patch =ol-info=]: +#+caption: Patch =ol-info=. +#+name: lst:emacs-lisp-setup-patch-ol-info #+begin_src emacs-lisp - (add-hook - 'org-mode-hook - (lambda () - (when (boundp 'org-info-other-documents) - (dolist (recipe '(("consult" . "https://github.com/minad/consult") - ("embark" . "https://github.com/oantolin/embark") - ("marginalia" . "https://github.com/minad/marginalia") - ("orderless" . "https://github.com/oantolin/orderless") - ("vertico" . "https://github.com/minad/vertico"))) - (cl-pushnew recipe org-info-other-documents :test #'equal))))) + (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)))) + + (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") + ("marginalia" . "https://github.com/minad/marginalia") + ("orderless" . "https://github.com/oantolin/orderless") + ("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)]] +:PROPERTIES: +:CUSTOM_ID: sec:convert-upper-to-lower-case-keywords +:END: +#+caption[Convert upper to lower case keywords]: +#+caption: Convert upper to lower case keywords. +#+label: lst:convert-upper-to-lower-case-keywords #+begin_src emacs-lisp (with-eval-after-load 'org (defun org-syntax-convert-keyword-case-to-lower () @@ -812,60 +1088,46 @@ Note: how to make it work without tangling? (message "Replaced %d keywords" count))))) #+end_src +*** Evaluate specific source blocks at load-time +:PROPERTIES: +:CUSTOM_ID: sec:load-time-specific-source-block-evaluation +:END: + +#+caption[Evaluate specific source blocks at load-time]: +#+caption: Evaluate specific source blocks at load-time. +#+label: lst:load-time-specific-source-block-evaluation +#+begin_src emacs-lisp + (defun my-org-eval-blocks-named (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) + (message "%s" (org-element-property :name block)) + (when (string-match-p infix (org-element-property :name block)) + block))))) + (dolist (block blocks) + (goto-char (org-element-property :begin block)) + (org-babel-execute-src-block))))) + + ;; Emacs looks for "Local variables:" after the last "?\n?\f". + (add-to-list 'safe-local-eval-forms + '(apply 'my-org-eval-blocks-named '("emacs-lisp-setup"))) + (add-to-list 'safe-local-eval-forms + '(apply 'my-org-eval-blocks-named '("python-setup"))) +#+end_src + *** [[info:org#Advanced Export Configuration][Advanced Export Configuration (info)]] +:PROPERTIES: +:CUSTOM_ID: sec:org-document-export-hacks +:END: Stolen from [[https://git.sr.ht/~bzg/org-contrib/tree/master/item/lisp/ox-extra.el][ox-extra.el]] -#+begin_src emacs-lisp - (with-eval-after-load 'ox - (defun org-export-ignore-headlines (data backend info) - "Remove headlines tagged \"ignore\" retaining contents and promoting children. - Each headline tagged \"ignore\" will be removed retaining its - contents and promoting any children headlines to the level of the - parent." - (org-element-map data 'headline - (lambda (object) - (when (member "ignore" (org-element-property :tags object)) - (let ((level-top (org-element-property :level object)) - level-diff) - (mapc (lambda (el) - ;; recursively promote all nested headlines - (org-element-map el 'headline - (lambda (el) - (when (equal 'headline (org-element-type el)) - (unless level-diff - (setq level-diff (- (org-element-property :level el) - level-top))) - (org-element-put-property - el :level (- (org-element-property :level el) - level-diff))))) - ;; insert back into parse tree - (org-element-insert-before el object)) - (org-element-contents object))) - (org-element-extract-element object))) - info nil) - (org-extra--merge-sections data backend info) - data) - - (defun org-extra--merge-sections (data _backend info) - (org-element-map data 'headline - (lambda (hl) - (let ((sections - (cl-loop - for el in (org-element-map (org-element-contents hl) - '(headline section) #'identity info) - until (eq (org-element-type el) 'headline) - collect el))) - (when (and sections - (> (length sections) 1)) - (apply #'org-element-adopt-elements - (car sections) - (cl-mapcan (lambda (s) (org-element-contents s)) - (cdr sections))) - (mapc #'org-element-extract-element (cdr sections))))) - info))) -#+end_src - +#+caption[Convert marked LaTeX export blocks to LaTeX header lines]: +#+caption: Convert marked LaTeX export blocks to LaTeX header lines. +#+label: lst:org-latex-header-blocks-filter #+begin_src emacs-lisp (with-eval-after-load 'ox (defun org-latex-header-blocks-filter (backend) @@ -909,146 +1171,160 @@ Stolen from [[https://git.sr.ht/~bzg/org-contrib/tree/master/item/lisp/ox-extra. (reverse blocks)))))) #+end_src -#+begin_src emacs-lisp +[[https://emacs.stackexchange.com/questions/47347/customizing-org-latex-title-command-to-edit-title-page][How to customize =org-latex-title-command= only in this buffer]] + +#+caption[Hack LaTeX export buffer local variables]: +#+caption: Hack LaTeX export buffer local variables. +#+header: :var title-page=title-page +#+name: lst:emacs-lisp-setup-hack +#+begin_src emacs-lisp :exports code :results silent :tangle no (with-eval-after-load 'ox - (defun my-activate-buffer-local-org-export-filters () - "Activate my export filters locally in the current buffer." - (interactive) - (set (make-local-variable 'org-export-filter-parse-tree-functions) - (cl-pushnew #'org-export-ignore-headlines - org-export-filter-parse-tree-functions)) - (set (make-local-variable 'org-export-before-parsing-hook) - (cl-pushnew #'org-latex-header-blocks-filter - org-export-before-parsing-hook)))) -#+end_src - -#+name: emacs-lisp-setup -#+begin_src emacs-lisp :tangle no - (with-eval-after-load 'ox - (my-activate-buffer-local-org-export-filters)) -#+end_src - -#+begin_src emacs-lisp - (with-eval-after-load 'ox-latex - (mapc (lambda (item) - (add-to-list 'org-latex-classes item)) - '(;; The postfixes +1, +2, +3, -1, -2, and -3 denote: - ;; +1 => [DEFAULT-PACKAGES] - ;; +2 => [PACKAGES] - ;; +3 => [EXTRA] - ;; -1 => [NO-DEFAULT-PACKAGES] - ;; -2 => [NO-PACKAGES] - ;; -3 => [NO-EXTRA] - ("elsarticle-1+2+3" ; Elsevier journals - "\\documentclass{elsarticle} + (make-variable-buffer-local 'org-export-before-parsing-hook) + (cl-pushnew #'org-latex-header-blocks-filter + org-export-before-parsing-hook)) + (when (require 'ox-latex nil 'noerror) + (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}")) - ("article-1+2+3" - "\\documentclass{article} + ("\\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-toc-command) + (setq org-latex-toc-command + (mapconcat 'identity '("" + "\\tableofcontents\\label{toc}" + "\\listoffigures" + "\\listoflistings" + "\\listoftables" + "\\newpage" + "") "\n")) + + (make-variable-buffer-local 'org-latex-subtitle-format) + (setq org-latex-subtitle-format "")) +#+end_src + +#+caption[Define =my-ox-latex-export-buffer-local-variables=]: +#+caption: Define =my-ox-latex-export-buffer-local-variables=. +#+name: lst:emacs-lisp-setup-defun +#+begin_src emacs-lisp + (defun my-ox-latex-export-buffer-local-variables (title-page) + (with-eval-after-load 'ox + (make-variable-buffer-local 'org-export-before-parsing-hook) + (cl-pushnew #'org-latex-header-blocks-filter + org-export-before-parsing-hook)) + (when (require 'ox-latex nil 'noerror) + (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}")) - ("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}"))))) + ("\\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-toc-command) + (setq org-latex-toc-command + (mapconcat 'identity '("" + "\\tableofcontents\\label{toc}" + "\\listoffigures" + "\\listoflistings" + "\\listoftables" + "\\newpage" + "") "\n")) + + (make-variable-buffer-local 'org-latex-subtitle-format) + (setq org-latex-subtitle-format "") + org-latex-title-command)) #+end_src -*** Evaluate source blocks on loading +#+header: :header yes +#+begin_export latex +% 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}} -#+begin_src emacs-lisp - (defun my-org-eval-blocks-named (name) - "Evaluate all source blocks named NAME." - (when (eq major-mode 'org-mode) - (let ((blocks - (org-element-map - (org-element-parse-buffer 'greater-element nil) 'src-block - (lambda (block) - (when (string= name (org-element-property :name block)) - block))))) - (dolist (block blocks) - (goto-char (org-element-property :begin block)) - (org-babel-execute-src-block))))) +% 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_export - ;; Emacs looks for "Local variables:" after the last "?\n?\f". - (add-to-list 'safe-local-eval-forms - '(apply 'my-org-eval-blocks-named '("emacs-lisp-setup"))) - (add-to-list 'safe-local-eval-forms - '(apply 'my-org-eval-blocks-named '("python-setup"))) +[[lst:emacs-lisp-setup-call]] + +#+caption[Call =my-ox-latex-export-local-variables=]: +#+caption: Use the setup macro for =ox-latex=. +#+name: lst:emacs-lisp-setup-call +#+header: :var title-page=title-page +#+begin_src emacs-lisp :exports code :results silent :tangle no + (my-ox-latex-export-buffer-local-variables title-page) #+end_src -*** [[info:org#Citation export processors][Citation export processors (info)]] -:PROPERTIES: -:CUSTOM_ID: sec:citation-export-processors -:END: - -#+begin_src emacs-lisp - (with-eval-after-load 'oc - (require 'oc-biblatex) - (require 'oc-csl) - (custom-set-variables - '(org-cite-activate-processor 'citar) - '(org-cite-follow-processor 'citar) - '(org-cite-global-bibliography '("~/VCS/research/refs.bib")) - '(org-cite-insert-processor 'citar))) +#+caption[Show a title-page example for =org-latex-title-command=]: +#+caption: Show a title-page example for =org-latex-title-command=. +#+label: lst:title-page +#+name: 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} #+end_src -*** [[https://github.com/bdarcus/citar][Citar: citing bibliography]] -:PROPERTIES: -:CUSTOM_ID: sec:citing-bibliography -:END: - -[[https://github.com/bdarcus/citar][Citar]] provides a completing-read front-end to browse and act on BibTeX, -BibLaTeX, as well as CSL JSON bibliographic data with LaTeX, markdown, and -org-cite editing support. - -[[https://github.com/bdarcus/citar][Citar]] (in combination with vertico, orderless, embark, marginalia, and consult) -provides quick filtering and selecting of bibliographic entries from the -minibuffer, as well as the option to run different commands on those selections. - -#+begin_src emacs-lisp - (with-eval-after-load 'org - (when (require 'citar nil 'noerror) - (custom-set-variables - '(citar-bibliography '("~/VCS/research/refs.bib")) - '(citar-file-extensions '("djvu" "pdf")) - '(citar-library-paths '("~/VCS/research/papers/")))) - (define-key org-mode-map (kbd "C-c b") 'org-cite-insert)) -#+end_src - -*** TODO Compare bibtex and biblatex -1. [[https://www.economics.utoronto.ca/osborne/latex/BIBTEX.HTM][Using bibtex: a short guide]] -2. [[https://www.tug.org/texlive//devsrc/Master/texmf-dist/doc/latex/biblatex/biblatex.pdf][The biblatex package]] -3. [[https://github.com/yuchenlin/rebiber][Rebiber: A tool for normalizing bibtex with official info]] -4. [[https://github.com/josephwright/biblatex-phys][A biblatex implementation of the AIP and APS bibliography style]] - * Editing ** [[https://www.emacswiki.org/emacs/DisabledCommands][Enable disabled commands and inform]] @@ -1056,9 +1332,12 @@ minibuffer, as well as the option to run different commands on those selections. :CUSTOM_ID: sec:enable-disabled-commands :END: -Execute src_emacs-lisp[:exports code]{(find-library "novice")} to see how -Emacs prevents new users from shooting themselves in the feet. +Execute src_emacs-lisp{(find-library "novice")} to see how Emacs prevents new +users from shooting themselves in the feet. +#+caption[Configure the =disabled-command-function=]: +#+caption: Configure the =disabled-command-function=. +#+label: lst:configure-disabled-command-function #+begin_src emacs-lisp (setq disabled-command-function (defun my-enable-this-command (&rest _args) @@ -1082,6 +1361,9 @@ for instance a particular function or paragraph by removing clutter. The "Do What I Mean" [[https://endlessparentheses.com/emacs-narrow-or-widen-dwim.html][narrow-or-widen-dwim]] function allows to toggle between narrowed and widened buffer states. +#+caption[Configure =narrow-or-widen-dwim=]: +#+caption: Configure =narrow-or-widen-dwim=. +#+label: lst:configure-narrow-or-widen-dwim #+begin_src emacs-lisp (defun narrow-or-widen-dwim (p) "Widen if buffer is narrowed, narrow-dwim otherwise. @@ -1112,6 +1394,9 @@ widened buffer states. ** Synchronal multiple-region editing +#+caption[Enable =iedit=]: +#+caption: Enable =iedit=. +#+label: lst:enable-iedit #+begin_src emacs-lisp (unless noninteractive (require 'iedit nil 'noerror)) @@ -1119,6 +1404,9 @@ widened buffer states. ** Extraneous whitespace trimming +#+caption[Configure =ws-butler=]: +#+caption: Configure =ws-butler=. +#+label: lst:configure-ws-butler #+begin_src emacs-lisp (unless noninteractive (when (require 'ws-butler nil 'noerror) @@ -1159,8 +1447,12 @@ following links show how to put the documentation to practical use: how the machinery after the first and after later usages of =eval-expression= differ and discusses options how to handle those differences. -The next block aims to configure [[https://github.com/Fuco1/smartparens][smartparens]] for Elisp, LaTeX, Org, and Python. +Listing [[lst:configure-smartparens]] aims to configure [[https://github.com/Fuco1/smartparens][smartparens]] for Elisp, +LaTeX, Org, and Python. +#+caption[Configure =smartparens=]: +#+caption: Configure =smartparens=. +#+label: lst:configure-smartparens #+begin_src emacs-lisp (unless noninteractive ;; To disables pairing of the quote character for lisp modes, @@ -1209,6 +1501,9 @@ The next block aims to configure [[https://github.com/Fuco1/smartparens][smartpa :CUSTOM_ID: sec:electric-operators :END: +#+caption[Configure =electric-operator-mode=]: +#+caption: Configure =electric-operator-mode=. +#+label: lst:configure-electric-operator-mode #+begin_src emacs-lisp (when (fboundp 'electric-operator-mode) (add-hook 'c-mode-common #'electric-operator-mode) @@ -1216,7 +1511,13 @@ The next block aims to configure [[https://github.com/Fuco1/smartparens][smartpa #+end_src ** Smart snippets +:PROPERTIES: +:CUSTOM_ID: sec:smart-snippets +:END: +#+caption[Enable =yas-global-mode=]: +#+caption: Enable =yas-global-mode=. +#+label: lst:enable-yas-global-mode #+begin_src emacs-lisp (when (require 'yasnippet nil 'noerror) (custom-set-variables @@ -1225,7 +1526,33 @@ The next block aims to configure [[https://github.com/Fuco1/smartparens][smartpa #+end_src * Coding +:PROPERTIES: +:CUSTOM_ID: sec:coding +:END: +** Emacs-lisp coding +:PROPERTIES: +:CUSTOM_ID: sec:emacs-lisp-coding +:END: + +** Python coding +:PROPERTIES: +:CUSTOM_ID: sec:python-coding +:END: + +The [[https://www.emacswiki.org/emacs/PythonProgrammingInEmacs][Python Programming in Emacs]] wiki page lists options to enhance Emacs's +built-in ~python-mode~. Here, the focus is on two packages: +1. [[https://github.com/joaotavora/eglot][Eglot - Emacs polyGLOT: an Emacs LSP client that stays out of your way]]. The + maintainer also contributes to Emacs itself and has a deep understanding of + [[https://sheer.tj/the_way_of_emacs.html][the Way of Emacs]]. He refuses to add new features without seeing how they fit + into [[https://sheer.tj/the_way_of_emacs.html][the Way of Emacs]] as this discussion on [[https://github.com/joaotavora/eglot/issues/523][org-mode source code blocks]] + shows. +2. [[https://github.com/pythonic-emacs/anaconda-mode][Anaconda - code navigation, documentation lookup, and completion for Python]]. + + +#+caption[Configure =eglot= for Python]: +#+caption: Configure =eglot= for Python. +#+label: lst:configure-eglot-for-python #+begin_src emacs-lisp (with-eval-after-load 'eglot (add-to-list 'eglot-server-programs '(python-mode "pylsp")) @@ -1237,43 +1564,35 @@ The next block aims to configure [[https://github.com/Fuco1/smartparens][smartpa "scipy"))))))))) #+end_src -** Python coding - -The [[https://www.emacswiki.org/emacs/PythonProgrammingInEmacs][Python Programming in Emacs]] wiki page lists options to enhance Emacs's -built-in ~python-mode~. Here, the focus is on two packages: -1. [[https://github.com/pythonic-emacs/anaconda-mode][Anaconda - code navigation, documentation lookup, and completion for Python]]. -2. [[https://github.com/joaotavora/eglot][Eglot - Emacs polyGLOT: an Emacs LSP client that stays out of your way]]. The - maintainer also contributes to Emacs itself and has a deep understanding of - [[https://sheer.tj/the_way_of_emacs.html][the Way of Emacs]]. He refuses to add new features without seeing how they fit - into [[https://sheer.tj/the_way_of_emacs.html][the Way of Emacs]] as this discussion on [[https://github.com/joaotavora/eglot/issues/523][org-mode source code blocks]] - shows. - The snippet below initializes [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]]. See [[https://github.com/jorgenschaefer/elpy/blob/8d0de310d41ebf06b22321a8534546447456870c/elpy.el#L2775][elpy-module-company]] for how to handle ~company-backends~ as a local variable and the call to [[info:elisp#Advising Functions][advice-add]] opens Python org-mode edit-buffers in ~anaconda-mode~. +#+caption[Configure =anaconda= for Python]: +#+caption: Configure =anaconda= for Python. +#+label: lst:configure-anaconda-for-python #+begin_src emacs-lisp (with-eval-after-load 'python - (with-eval-after-load 'company (when (and (fboundp 'anaconda-mode) (fboundp 'company-anaconda)) (defun my-disable-anaconda-mode () (when (derived-mode-p 'python-mode) (anaconda-mode -1) - (set (make-local-variable 'company-backends) - (delq 'company-anaconda - (mapcar #'identity company-backends))) + (make-variable-buffer-local 'company-backends) + (setq company-backends + (delq 'company-anaconda + (mapcar #'identity company-backends))) (anaconda-eldoc-mode -1))) - (defun my-enable-anaconda-mode () (when (derived-mode-p 'python-mode) (anaconda-mode +1) - (set (make-local-variable 'company-backends) - (cons 'company-anaconda - (delq 'company-semantic - (delq 'company-capf - (mapcar #'identity company-backends))))) + (make-variable-buffer-local 'company-backends) + (setq company-backends + (cons 'company-anaconda + (delq 'company-semantic + (delq 'company-capf + (mapcar #'identity company-backends))))) (anaconda-eldoc-mode (if (file-remote-p default-directory) -1 1)))))) @@ -1284,7 +1603,6 @@ Python org-mode edit-buffers in ~anaconda-mode~. (when (derived-mode-p 'python-mode) (anaconda-mode -1) (anaconda-eldoc-mode -1))) - (defun my-enable-anaconda-mode () (when (derived-mode-p 'python-mode) (anaconda-mode +1) @@ -1293,7 +1611,6 @@ Python org-mode edit-buffers in ~anaconda-mode~. (when (fboundp 'my-enable-anaconda-mode) (advice-add 'org-edit-src-code :after #'my-enable-anaconda-mode)) - (when (and (fboundp 'my-disable-anaconda-mode) (fboundp 'my-enable-anaconda-mode)) (defun my-toggle-anaconda-mode () @@ -1304,6 +1621,9 @@ Python org-mode edit-buffers in ~anaconda-mode~. (my-enable-anaconda-mode))))) #+end_src +#+caption[Tangle the =example.py= file]: +#+caption: Tangle the =example.py= file. +#+label: lst:example-py #+begin_src python :tangle example.py :comments link import numpy import astropy.units as apu @@ -1314,15 +1634,29 @@ Python org-mode edit-buffers in ~anaconda-mode~. print(q) #+end_src -#+begin_src emacs-lisp - (custom-set-variables - '(python-shell-interpreter-args "-i -E")) - (when (and (executable-find "pyenv") - (require 'pyenv-mode nil 'noerror)) - (pyenv-mode +1) - (pyenv-mode-set "3.9.9/envs/python-3.9.9")) +#+caption[Configure =python=]: +#+caption: Configure =python=. +#+label: lst:configure-python +#+begin_src elisp + (with-eval-after-load 'python + (custom-set-variables + '(python-indent-guess-indent-offset nil) + '(python-shell-interpreter-args "-i -E"))) #+end_src +#+caption[Enable =pyenv-mode=]: +#+caption: Enable =pyenv-mode=. +#+label: lst:enable-pyenv-mode +#+begin_src emacs-lisp + (when (and (executable-find "pyenv") + (require 'pyenv-mode nil 'noerror)) + (pyenv-mode +1) + (pyenv-mode-set "3.9.9/envs/python-3.9.9")) +#+end_src + +#+caption[Configure =info=]: +#+caption: Configure =info=. +#+label: lst:configure-info #+begin_src emacs-lisp (with-eval-after-load 'info (add-to-list 'Info-directory-list @@ -1342,8 +1676,11 @@ boils down to two rules: with respect to the height of the face (those heights default to 1.0 for no scaling). -The next source code blocks implement those rules. +The code in listing [[lst:configure-face-attributes]] source implements those rules. +#+caption[Configure =face-attributse=]: +#+caption: Configure =face-attributes=. +#+label: lst:configure-face-attributes #+begin_src emacs-lisp (unless noninteractive ;; Set face attributes. @@ -1363,8 +1700,11 @@ The next source code blocks implement those rules. #+end_src In case of proper initialization of all face heigths, font scaling is easy as -the next source code block shows. +the the code in [[lst:my-set-default-face-height]] shows. +#+caption[Implement =my-set-default-face-height=]: +#+caption: Implement =my-set-default-face-height=. +#+label: lst:my-set-default-face-height #+begin_src emacs-lisp (defun my-set-default-face-height () "Set the default face height in all current and future frames. @@ -1384,6 +1724,9 @@ the next source code block shows. Allow swapping fhe foreground and background colors of the default face on all frames. +#+caption[Implement =my-invert-default-face=]: +#+caption: Implement =my-invert-default-face=. +#+label: lst:my-invert-default-face #+begin_src emacs-lisp (defun my-invert-default-face () "Invert the default face." @@ -1393,6 +1736,9 @@ frames. Enable =rainbow-mode= to colorize color names in buffers for debugging. +#+caption[Enable =rainbow-mode=]: +#+caption: Enable =rainbow-mode=. +#+label: lst:enable-rainbow-mode #+begin_src emacs-lisp (when (fboundp 'rainbow-mode) (custom-set-variables @@ -1414,6 +1760,9 @@ themes fail to display ~hl-line-mode~ properly with Emacs-27.2 on Darwin. [[https://emacs.stackexchange.com/questions/17431/how-do-i-change-portions-of-a-custom-theme][How to change custom theme faces]] +#+caption[Hack =leuven-theme=]: +#+caption: Hack =leuven-theme=. +#+label: lst:hack-leuven-theme #+begin_src emacs-lisp (unless noninteractive ;; Try to detect `leuven-theme` from MELPA. @@ -1454,16 +1803,9 @@ themes fail to display ~hl-line-mode~ properly with Emacs-27.2 on Darwin. (add-hook hook #'my-leuven-hook-function))) #+end_src -#+begin_src emacs-lisp :tangle no - (unless noninteractive - (custom-set-variables - '(modus-themes-hl-line 'underline) - '(modus-themes-intense-markup 't)) - (when (and (version< emacs-version "28.0") - (require 'modus-themes nil 'noerror)) - (modus-themes-load-themes))) -#+end_src - +#+caption[Implement =my-pulse-one-line=]: +#+caption: Implement =my-pulse-one-line=. +#+label: lst:my-pulse-one-line #+begin_src emacs-lisp (unless noninteractive ;; https://karthinks.com/software/batteries-included-with-emacs/ @@ -1484,6 +1826,9 @@ themes fail to display ~hl-line-mode~ properly with Emacs-27.2 on Darwin. ** Feed reader +#+caption[Enable =elfeed=]: +#+caption: Enable =elfeed=. +#+label: lst:enable-elfeed #+begin_src emacs-lisp (autoload 'elfeed "elfeed" nil t) (global-set-key (kbd "C-x w") #'elfeed) @@ -1512,6 +1857,9 @@ themes fail to display ~hl-line-mode~ properly with Emacs-27.2 on Darwin. ** Multi-media system +#+caption[Enable =emms=]: +#+caption: Enable =emms=. +#+label: lst:enable-emms #+begin_src emacs-lisp (custom-set-variables '(emms-mode-line-format "") @@ -1551,9 +1899,12 @@ themes fail to display ~hl-line-mode~ properly with Emacs-27.2 on Darwin. * [[info:emacs#Init File][Init File (info)]] footer :PROPERTIES: -:CUSTOM_ID: sec:init-file-footer +:CUSTOM_ID: sec:user-init-file-footer :END: +#+caption[Tangle the =user-init-file= footer]: +#+caption: Tangle the =user-init-file= footer. +#+label: lst:tangle-user-init-file-footer #+begin_src emacs-lisp (provide 'init) @@ -1565,7 +1916,7 @@ themes fail to display ~hl-line-mode~ properly with Emacs-27.2 on Darwin. ;;; init.el ends here #+end_src -* Local variables linking back to [[#sec:latex-save-compile-display-loop][LaTeX save-compile-display-loop]] +* Local variables linking to [[#sec:latexmk-save-compile-display-loop][Latexmk save-compile-display-loop]] :PROPERTIES: :CUSTOM_ID: sec:local-variables :END: diff --git a/org-babel-tangle-file b/org-babel-tangle-file index 2b2e5ba..794177e 100755 --- a/org-babel-tangle-file +++ b/org-babel-tangle-file @@ -3,6 +3,7 @@ emacs -Q --batch --eval " (progn (require 'org) + (require 'ob-latex) (defun my-org-eval-blocks-named (name) (when (eq major-mode 'org-mode) (let ((blocks