2021-11-29 13:14:56 +01:00
#+title : Emacs setup for use with LaTeX, Org, and Python
#+author : Gerard Vermeulen
2021-12-28 08:32:51 +01:00
#+latex_class : article
#+latex_class_options : [11pt,a4paper,english,svgnames,tables]
2021-12-29 10:05:43 +01:00
#+setupfile : "setup-include.org"
#+include : "setup-include.org"
2021-11-29 13:14:56 +01:00
2021-11-30 09:35:15 +01:00
* Quick start
:PROPERTIES:
:CUSTOM_ID: sec:quick-start
:END:
2021-12-23 15:29:03 +01:00
Backup your =user-emacs-directory= (defaults often to =~/.emacs.d= on =Linux= ,
=Unix= , or =Darwin= ) directory and execute the commands in listing
2022-01-09 15:39:14 +01:00
[[lst:prepare-user-emacs-directory ]]. After invoking Emacs interactively (in
interactive mode, neither in batch mode, nor in server mode), Emacs will ask you
to install a selected set of packages. Quit Emacs and invoke Emacs again.
2021-12-11 12:48:46 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Prepare the user-emacs-directory]:
#+caption : Clone and initialize the user-emacs-directory.
2021-12-28 08:48:03 +01:00
#+name : lst:prepare-user-emacs-directory
2021-11-30 09:35:15 +01:00
#+begin_src shell :noeval :tangle no
cd ~
2021-12-23 15:29:03 +01:00
git clone ccdr@mercury.grenoble.cnrs.fr:SERVER/emacs.d.git .emacs.d
2021-11-30 09:35:15 +01:00
make --directory=.emacs.d init
2021-12-23 15:29:03 +01:00
emacs &
2021-11-30 09:35:15 +01:00
#+end_src
2021-11-29 13:14:56 +01:00
* Introduction
:PROPERTIES:
:CUSTOM_ID: sec:introduction
:END:
This Emacs setup aims to install automatically a minimal set of extension
packages that allows to handle my reports and presentations. The file format of
the reports is [[https://orgmode.org/ ][Org Mode ]] plain text with [[https://www.python.org/ ][Python ]] source code blocks and the file
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)
2021-12-23 15:29:03 +01:00
illustrates three methods in my work-flow:
2021-11-30 09:35:15 +01:00
1. How to tangle (or export) source blocks from [[info:org#Top ][org ]] files. This file contains
2022-01-09 15:39:14 +01:00
source blocks to produce the files =early-init.el= , =init.el= , =latexmkrc= ,
2021-11-30 09:35:15 +01:00
=org-store-link= , and =example.py= by tangling.
2021-11-29 13:14:56 +01:00
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
over or click on the links to experiment.
The [[https://en.wikipedia.org/wiki/AUCTeX ][AUCTeX - Aalborg University Center TeX ]] extension package provides a
powerful [[https://en.wikipedia.org/wiki/Text-based_user_interface ][Text-based User Interface (TUI) ]] environment to edit the [[https://www.latex-project.org/ ][LaTeX ]]
presentations.
The [[https://github.com/bdarcus/citar ][citar ]] extension package provides quick filtering and selecting of
bibliographic entries, and the option to run different commands on those
selections. [[https://github.com/bdarcus/citar ][Citar ]] requires [[info:org#Top ][Org-9.5 (info) ]], which is already part of Emacs-28.1.
[[https://github.com/bdarcus/citar ][Citar ]] exploits the enhancements of Emacs' builtin selection mechanism provided
by the extension packages [[https://github.com/minad/vertico ][vertico ]], [[https://github.com/oantolin/orderless ][orderless ]], [[https://github.com/oantolin/embark ][embark ]], [[https://github.com/minad/marginalia ][marginalia ]], and [[https://github.com/minad/consult ][consult ]].
The [[https://github.com/andras-simonyi/citeproc-el ][citeproc ]] extension package provides [[https://citationstyles.org/ ][CSL: citation style language ]] processing
capabilities to [[https://github.com/bdarcus/citar ][citar ]] and [[https://orgmode.org/ ][Org Mode ]].
The [[https://github.com/vedang/pdf-tools ][pdf-tools ]] extension package renders [[https://en.wikipedia.org/wiki/PDF ][PDF ]] file with the possibility to
2021-11-30 09:35:15 +01:00
annotate the file or to click on anchors in the [[https://en.wikipedia.org/wiki/PDF ][PDF ]] file that link back to the
original [[https://www.latex-project.org/ ][LaTeX ]] file of the document. An example of my work-flow are the steps
2021-11-29 13:14:56 +01:00
to convert this [[info:org#Top ][org ]] file to [[https://en.wikipedia.org/wiki/PDF ][PDF ]] and to see the result with [[https://github.com/vedang/pdf-tools ][pdf-tools ]] in Emacs:
execute the commands ~pdf-tools-install~ , ~org-babel-tangle~ ,
~org-latex-export-latex-to-latex~ , and ~compile~ . This sets up an infinite
[[https://www.latex-project.org/ ][LaTeX ]] compilation loop to update and redisplay the [[https://en.wikipedia.org/wiki/PDF ][PDF ]] file after excution of
the ~org-latex-export-latex-to-latex~ command in this buffer.
Here follows a list of interesting Emacs configurations:
2021-12-05 16:25:38 +01:00
1. [[https://github.com/alhassy/emacs.d ][Musa Al-hassy's configuration ]] is an impressive example of producing the Emacs
initialization files and other files by tangling an [[info:org#Top ][org ]] file. His methodology
is impressive, as his [[https://alhassy.github.io/ElispCheatSheet/ ][Elisp Cheat Sheet ]] and [[https://alhassy.github.io/org-special-block-extras/ ][org-special-block-extra package ]]
show. To me, this is a configuration to admire, but his methodology is way
over my head.
2. [[https://github.com/oantolin/emacs-config ][Omar Antolín Camarena's configuration ]] exploits built-in packages, Omar's own
small packages, and large external packages. Omar is the author of [[https://github.com/oantolin/orderless ][orderless ]]
and [[https://github.com/oantolin/embark ][embark ]]. I have stolen his idea of using ~custom-set-variables~ .
3. [[https://gitlab.com/ambrevar/dotfiles ][Pierre Neirhardt's configuration ]] implements lazy loading without help of
2021-11-29 13:14:56 +01:00
external packages. I have stolen his approach of using lazy loading to
silently ignore the setup stanzas of uninstalled extension packages.
2021-12-05 16:25:38 +01:00
4. [[https://sachachua.com/dotemacs/ ][Sacha Chua's configuration ]] is a practical example of producing the Emacs
2021-11-29 13:14:56 +01:00
initialization files by tangling an [[info:org#Top ][org ]] file. It gives me the impression
that she is a very practical person trying to achieve her goals by the most
efficient means. I have stolen her idea of using [[https://github.com/quelpa/quelpa ][quelpa ]] to install packages
from any source.
2021-12-07 05:39:02 +01:00
5. [[https://github.com/purcell/emacs.d ][Steve Purcell's configuration ]] is well organized, a showcase of readable code,
as well helpful commit and issue histories. See for instance the discussion
on [[https://github.com/purcell/emacs.d/issues/778 ][the correctness of order of company candidates in Emacs lisp mode ]].
2021-11-29 13:14:56 +01:00
* [[info:emacs#Early Init File][Early Init File (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:early-init-file
:END:
2021-12-07 08:19:59 +01:00
Try to load [[https://github.com/emacscollective/no-littering ][no-littering ]] as early as possible, since it helps to keep
=~/.emacs.d= clean.
2021-12-23 15:29:03 +01:00
#+caption[Tangle the early-init-file]:
#+caption : Tangle the early-init-file.
2021-12-28 08:48:03 +01:00
#+name : lst:tangle-early-init-file
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp :tangle early-init.el
;;; early-init.el --- user early-init file -*- lexical-binding: t -* -
;;; Commentary:
;;; Code:
2021-12-06 18:35:33 +01:00
(setq load-prefer-newer t)
(require 'no-littering nil 'noerror)
2021-11-29 13:14:56 +01:00
(provide 'early-init)
2021-11-30 09:35:15 +01:00
;; Emacs looks for "Local variables:" after the last "?\n?\f".
2021-11-29 13:14:56 +01:00
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;;; earl-init.el ends here
#+end_src
2021-12-07 05:39:02 +01:00
In order to get help in understanding the code block above in a buffer showing
2022-01-09 15:39:14 +01:00
the original [[info:org#Top ][Org ]] source file, type {{{kbd(C-c C-c)}}} after moving
point (or cursor) to one of the items of the list:
2021-12-23 15:29:03 +01:00
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)}
2022-01-07 16:33:40 +01:00
to execute the code between the curly braces for access to help. This shows
that *Emacs is a self-documenting editor.*
2021-12-07 05:39:02 +01:00
2021-11-29 13:14:56 +01:00
* [[info:emacs#Init File][Init File (info)]] header
:PROPERTIES:
:CUSTOM_ID: sec:init-file-header
:END:
2021-12-23 15:29:03 +01:00
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.
2021-12-28 08:48:03 +01:00
#+name : lst:1st-custom-set-variables-call
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
;;; 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)
2021-12-15 08:13:03 +01:00
`(custom-file ,(locate-user-emacs-file "custom.el"))
2021-11-29 13:14:56 +01:00
'(epg-pinentry-mode 'loopback)
'(global-hl-line-mode t)
'(global-hl-line-sticky-flag t)
'(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)
'(package-archives '(("gnu" . "https://elpa.gnu.org/packages/ ")
("nongnu" . "https://elpa.nongnu.org/nongnu/ ")
2021-12-29 10:03:44 +01:00
("melpa" . "https://melpa.org/packages/ ")))
;; Pin those packages to GNU ELPA to get the info documentation.
2022-01-04 13:10:52 +01:00
'(package-pinned-packages '((consult . "gnu")
(marginalia . "gnu")
2021-12-29 10:03:44 +01:00
(vertico . "gnu"))))
2021-12-23 15:29:03 +01:00
#+end_src
#+caption[Customize the second set of Emacs variables]:
#+caption : Customize the second set of Emacs variables.
2021-12-28 08:48:03 +01:00
#+name : lst:2nd-custom-set-variables-call
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(custom-set-variables
2021-12-06 18:35:33 +01:00
`(package-selected-packages
2021-12-23 15:29:03 +01:00
`(,@(when (version< emacs-version "28.0")
2022-01-31 06:49:34 +01:00
'(org ; plain text thought organizer
python)) ; mode to edit Python code
2021-12-06 18:35:33 +01:00
anaconda-mode ; strangles python-mode
2022-01-31 06:49:34 +01:00
applescript-mode ; mode to edit AppleScript code
2021-12-08 05:00:15 +01:00
async ; asynchroneous processing
2021-12-06 18:35:33 +01:00
auctex ; Aalborg University Center TeX
2022-01-17 06:11:19 +01:00
blacken ; Black Python code formatter client
2021-12-06 18:35:33 +01:00
citar ; bibliography handling
citeproc ; bibliography handling
2021-12-08 05:00:15 +01:00
company ; complete anything
2021-12-06 18:35:33 +01:00
company-anaconda ; complete anything in anaconda-mode
consult ; consult completing-read
eglot ; Emacs polyGLOT LSP client
2021-12-08 05:00:15 +01:00
electric-operator ; automatic spacing around operators
elfeed ; web feed reader
2021-12-06 18:35:33 +01:00
embark ; act on any buffer selection
2021-12-08 05:00:15 +01:00
emms ; Emacs Multi-Media System
2021-12-06 18:35:33 +01:00
htmlize ; convert buffer contents to HTML
2021-12-08 05:00:15 +01:00
iedit ; simultaneous multi-entity editing
2022-01-25 11:27:32 +01:00
keycast ; show current command with binding
2021-12-08 05:00:15 +01:00
magit ; Git Text-based User Interface
2021-12-06 18:35:33 +01:00
marginalia ; minibuffer margin notes
2021-12-08 05:00:15 +01:00
markdown-mode ; markdown text mode
no-littering ; keep `user-emacs-directory' clean
nov ; EPUB reader
2021-12-06 18:35:33 +01:00
orderless ; Emacs completion style
pdf-tools ; interactive docview replacement
2021-12-07 05:45:38 +01:00
pdf-view-restore ; add view history to pdf-tools
2021-12-06 18:35:33 +01:00
pyenv-mode ; Python environment selector
quelpa ; install Emacs packages from source
2021-12-08 05:00:15 +01:00
rainbow-mode ; set background color to color string
2022-01-23 11:56:37 +01:00
sly ; Sylvester the Cat's Common Lisp IDE
2021-12-08 05:00:15 +01:00
smartparens ; smart editing of character pairs
toml-mode ; Tom's Obvious Minimal Language mode
2021-12-29 10:03:44 +01:00
undo-tree ; more advanced yet simpler undo system
2021-12-08 05:00:15 +01:00
vertico ; VERTical Interactive Completion
wgrep ; open a writable grep buffer
which-key ; on the fly key-binding help
wordnut ; WordNet lexical database
writegood-mode ; bullshit and weasel-word detector
ws-butler ; remove trailing whitespace
xr ; undo rx to grok regular expressions
2021-12-23 15:29:03 +01:00
yasnippet))) ; code or text template expansion
#+end_src
#+caption[Customize the third set of Emacs variables]:
#+caption : Customize the third set of Emacs variables.
2021-12-28 08:48:03 +01:00
#+name : lst:3rd-custom-set-variables-call
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(custom-set-variables
2021-11-29 13:14:56 +01:00
'(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)
'(use-short-answer t)
'(view-read-only t))
(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)))
#+end_src
2022-01-25 11:28:05 +01:00
** [[info:emacs#Faces][Text faces or look (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:text-faces-or-look
:END:
Section [[#sec:text-faces-or-styles ][text faces or styles (info) ]] tells that this setup does not use theming.
2022-01-25 15:28:39 +01:00
However, in order to improve visibility, it relies on:
1. Tweaking faces in memory after loading as in listing
[[lst:tweak-faces-faces-after ]].
2. Shadowing the definition of faces before loading as in listing
[[lst:tweak-org-faces-before ]] and [[lst:tweak-sh-script-faces-before ]]. The last
item in the page on [[https://orgmode.org/worg/org-contrib/babel/examples/fontify-src-code-blocks.html#org5c4406f ][fontifying Org mode source code blocks ]] describes this
method.
Section [[#sec:text-faces-or-styles ][text faces or styles (info) ]] also defines the function
src_emacs-lisp{(my-invert-default-face)} to toggle between a dark and a light
background.
2022-01-25 11:28:05 +01:00
#+caption[Improve the visibility of faces in =faces.el= ]:
#+caption : Improve the visibility of faces in =faces.el=.
2022-01-25 15:28:39 +01:00
#+name : lst:tweak-faces-faces-after
2022-01-25 11:28:05 +01:00
#+begin_src emacs-lisp
2022-01-25 15:28:39 +01:00
(defun tweak-region-face-background-color ()
(when (featurep 'gtk)
(set-face-attribute
'region nil
:background (cdr (assoc (face-attribute 'default :background)
'(("white" . "LightGoldenrod2")
("black" . "blue3")))))))
(tweak-region-face-background-color)
#+end_src
2022-01-25 11:28:05 +01:00
#+caption[Improve the visibility of faces in =org-faces.el= ]:
#+caption : Improve the visibility of faces in =org-faces.el=.
2022-01-25 15:28:39 +01:00
#+name : lst:tweak-org-faces-before
2022-01-25 11:28:05 +01:00
#+begin_src emacs-lisp
;; Shadow the definition in org-faces.el:
(defface org-block
;; https://emacs.stackexchange.com/questions/9600/
;; how-can-i-override-a-pre-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.
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'.")
#+end_src
#+caption[Improve the visibility of faces in =sh-script.el= ]:
#+caption : Improve the visibility of faces in =sh-script.el=.
2022-01-25 15:28:39 +01:00
#+name : lst:tweak-sh-script-faces-before
2022-01-25 11:28:05 +01:00
#+begin_src emacs-lisp
;; Shadow the 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
2021-12-30 09:03:28 +01:00
* [[info:emacs#Package Installation][Install the selected packages (info)]]
2021-11-29 13:14:56 +01:00
:PROPERTIES:
2021-12-23 15:29:03 +01:00
:CUSTOM_ID: sec:install-selected-packages
2021-11-29 13:14:56 +01:00
:END:
2021-12-05 07:28:32 +01:00
[[info:emacs#Package Installation ][Emacs installs packages ]] from archives on the internet. This setup uses three
archives:
1. The [[https://elpa.gnu.org/ ][GNU Emacs Lisp Package Archive ]]
2. The [[https://elpa.nongnu.org/ ][NonGNU Emacs Lisp Package Archive ]].
2021-12-07 08:19:59 +01:00
3. The [[https://melpa.org/#/ ][Milkypostman’ s Emacs Lisp Package Archive (MELPA) ]].
2021-12-29 10:03:44 +01:00
In addition, the [[https://github.com/quelpa/quelpa ][quelpa ]] tool allows to fetch code from any source and build a
2021-12-30 09:03:28 +01:00
package on your computer before installation. The code in listing
[[lst:install-selected-packages ]] assumes that the package system is in a *virgin*
state if the package [[https://github.com/emacscollective/no-littering ][no-littering ]] is not present:
1. It installs and loads [[https://github.com/emacscollective/no-littering ][no-littering ]] after ensuring refreshing of the
contents of available packages.
2. It ensures installation of [[https://github.com/quelpa/quelpa ][quelpa ]] before ensuring installation of [[https://www.reddit.com/r/emacs/comments/l6rcqh/undotree_repositorys_new_home_gitlab/ ][undo-tree ]].
3. It calls src_emacs-lisp{(package-install-selected-packages)} to check the
installation status of all packages in
src_emacs-lisp{package-selected-packages} and to install the missing packages
after the user has agreed to its prompt.
2021-12-29 14:13:53 +01:00
In case of normal Emacs usage, src_emacs-lisp{(package-list-packages)} refreshes
2021-12-23 15:29:03 +01:00
the contents of packages and allows to update packages to the latest version.
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Install the selected packages]:
#+caption : Install the selected packages.
2021-12-28 08:48:03 +01:00
#+name : lst:install-selected-packages
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless (require 'no-littering nil 'noerror)
(package-refresh-contents)
(package-install 'no-littering)
(require 'no-littering))
2021-12-29 10:03:44 +01:00
(unless (package-installed-p 'quelpa)
(package-install 'quelpa))
(unless (package-installed-p 'undo-tree)
;; Neither GNU ELPA, nor MELPA have the latest version.
(quelpa '(undo-tree :repo "tsc25/undo-tree" :fetcher gitlab)))
2021-12-07 05:31:52 +01:00
(unless noninteractive
(package-install-selected-packages))
2021-11-29 13:14:56 +01:00
#+end_src
2022-01-06 19:32:36 +01:00
* [[info:dir#Top][Info documentation]]
:PROPERTIES:
:CUSTOM_ID: sec:info-documentation
:END:
2022-01-11 14:22:02 +01:00
Listing [[lst:configure-info ]] fixes what looks like a bug in Emacs-28.0.91 and adds
a path in my home directory to the places where =info= looks for files.
2022-01-06 19:32:36 +01:00
#+caption[Configure =info= ]:
#+caption : Configure =info=.
#+name : lst:configure-info
#+begin_src emacs-lisp
(with-eval-after-load 'info
2022-01-11 14:22:02 +01:00
(unless (version< emacs-version "28.0")
;; Why is this necessary after `package-activate-1'?
(dolist (item package-alist)
(let ((pkg-dir (package-desc-dir (cadr item))))
(when (file-exists-p (expand-file-name "dir" pkg-dir))
(cl-pushnew pkg-dir Info-directory-list :test #'equal)))))
;; Emacs should find my "python.info" file.
2022-01-06 19:32:36 +01:00
(add-to-list 'Info-directory-list
(expand-file-name "~/.local/share/info")))
#+end_src
2022-01-18 07:26:09 +01:00
* [[info:emacs#Key Bindings][Key bindings (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:key-bindings
:END:
** [[info:emacs#Disabling][Disabling Commands (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:enable-disabled-commands
:END:
Execute src_emacs-lisp{(find-library "novice")} to see how Emacs prevents new
users from shooting themselves in the feet. Listing
[[lst:configure-disabled-command-function ]] enables [[https://www.emacswiki.org/emacs/DisabledCommands ][disabled commands on the fly ]].
#+caption[Configure the =disabled-command-function= ]:
#+caption : Configure the =disabled-command-function=.
#+name : lst:configure-disabled-command-function
#+begin_src emacs-lisp
(setq disabled-command-function
(defun my-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
2021-12-05 16:39:07 +01:00
* [[info:emacs#Emacs Server][Using Emacs as a server (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:using-emacs-server
:END:
2021-11-29 13:14:56 +01:00
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
2021-12-23 15:29:03 +01:00
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.
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Start the Emacs server]:
#+caption : Start the Emacs server.
2021-12-28 08:48:03 +01:00
#+name : lst:start-emacs-server
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(when window-system
(unless (or noninteractive (daemonp))
(add-hook 'after-init-hook #'server-start)))
#+end_src
2021-12-23 15:29:03 +01:00
** Latexmk save-compile-display loop
2021-11-29 13:14:56 +01:00
:PROPERTIES:
2021-12-23 15:29:03 +01:00
:CUSTOM_ID: sec:latexmk-save-compile-display-loop
2021-11-29 13:14:56 +01:00
:END:
The =latexmk= resource file in the next source code block shows how to use
=emacsclient= to (re)display the PDF file in Emacs after each succesful
(re)compilation on condition that the settings of the ~compile-command~ local
2021-11-30 18:44:54 +01:00
variable in section are compatible. The local variable ~compile-command~ in the
2021-12-05 16:39:07 +01:00
[[#sec:local-variables ][local variables ]] section (only visible in =org= files, but not in =html= and
2021-12-23 15:29:03 +01:00
=pdf= files) shows how to use the =latexmkrc= file.
2021-11-29 13:14:56 +01:00
2022-01-12 20:19:22 +01:00
#+attr_latex : :options breaklines
2021-12-23 15:29:03 +01:00
#+caption[Tangle the Latexmk resource file]:
#+caption : Tangle the Latexmk resource file.
2021-12-28 08:48:03 +01:00
#+name : lst:latexmkrc
2021-11-30 18:04:16 +01:00
#+begin_src perl :tangle latexmkrc :comments none
2021-11-29 13:14:56 +01:00
# pdf previewer and update pdf previewer
$pdf_previewer = "emacsclient -e '(find-file-other-window %S)'";
$pdf_update_method = 4; # 4 runs a 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' );
2021-12-23 15:29:03 +01:00
$clean_ext .= " acr acn alg bbl glo gls glg ist lol run.xml";
2021-11-29 13:14:56 +01:00
sub makeglossaries {
my ($name, $path) = fileparse( $$Psource );
return system "makeglossaries -d '$path' '$name'";
}
2021-11-30 09:35:15 +01:00
# Emacs looks for "Local variables:" after the last "?\n?\f".
2021-11-29 13:14:56 +01:00
# Local Variables:
# mode: perl
# End:
#+end_src
2021-11-30 09:35:15 +01:00
** [[https://qutebrowser.org/doc/userscripts.html][Qutebrowser userscript]]
2021-12-05 16:39:07 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:qutebrowser-userscript
:END:
2021-11-29 13:14:56 +01:00
The next block contains an userscript that sends a [[info:org#The store-link protocol ][store-link org-protocol ]]
message with the url and the title from [[https://qutebrowser.org ][qutebrowser ]] to =emacsclient= . The
function =urlencode= translates the url and the title for the message. The
[[info:python#Examples<22> ][Python urllib examples ]] show how to use =urlencode= . The final =execvp= call
deals with a [[https://qutebrowser.org ][qutebrowser ]] userscript requirement: the =emacsclient= process must
get the PID of the userscript that must kill itself after the take-over.
Termination of the =emacsclient= process hands control back to [[https://qutebrowser.org ][qutebrowser ]].
On a [[https://en.wikipedia.org/wiki/POSIX ][POSIX ]] system, you can run the userscript from [[https://qutebrowser.org ][qutebrowser ]] or from a
terminal to see whether it works. In case you try to run it from Emacs, Emacs
may hang or die.
2021-12-23 15:29:03 +01:00
#+caption[Tangle a qutebrowser userscript]:
#+caption : Tangle a qutebrowser userscript.
2021-11-29 13:14:56 +01:00
#+header : :comments none
#+header : :tangle-mode (identity #o755)
2021-12-28 08:48:03 +01:00
#+name : lst:qutebrowser-userscript
2021-11-29 13:14:56 +01:00
#+begin_src python :noeval :tangle org-store-link
#!/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))
#+end_src
2021-12-08 04:59:07 +01:00
** TODO Look into: org-protocol handling with other browser on Darwin
1. [[http://rwx.io/posts/osx-uri-protocol-handler/ ][Patrick Goddi: macOS URI protocol handler ]] and his [[https://github.com/fooqri/uri-handler ][URI-Handler ]].
2. [[https://www.hammerspoon.org/ ][Hammerspoon ]]
3. [[https://vritser.github.io/posts/capture-anywhere/ ][Emacs Capture Anywhere ]]
2021-11-29 13:14:56 +01:00
* Completion
:PROPERTIES:
:CUSTOM_ID: sec:completion
:END:
[[info:vertico#Top ][Vertico (info) ]] provides a performant and minimalistic vertical completion UI
based on the default completion system and behaves therefore correctly under all
2021-12-05 16:40:20 +01:00
circumstances. [[https://cestlaz.github.io/post/using-emacs-80-vertico/ ][Using Vertico, Marginalia, Consult, and Embark ]] links to a video
demonstration. Vertico integrates well with fully supported complementary
2021-11-29 13:14:56 +01:00
packages to enrich the completion UI:
2021-12-05 16:40:20 +01:00
1. [[info:orderless#Top ][Orderless (info) ]] for an advanced completion style,
2. [[info:embark#Top ][Embark (info) ]] for minibuffer actions with context menus,
3. [[info:marginalia#Top ][Marginalia (info) ]] for rich annotations in the minibuffer, and
4. [[info:consult#Top ][Consult (info) ]] for useful search and navigation commands,
where the order is that of [[https://github.com/bdarcus/citar#installation ][enhancing citar's experience ]] and the configuration
steps below.
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
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.
2021-11-29 13:14:56 +01:00
2021-12-05 16:40:20 +01:00
** [[info:vertico#Top][Vertico (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:vertico-configuration
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
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=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-vertico-mode
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
2021-12-23 15:29:03 +01:00
(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)
2021-11-29 13:14:56 +01:00
(when (fboundp 'vertico-mode)
2022-01-10 08:47:45 +01:00
(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)))
2021-11-29 13:14:56 +01:00
#+end_src
2022-01-10 08:47:45 +01:00
#+attr_latex : :booktabs yes :float table
#+caption[Vertico key map bindings]:
#+caption : Vertico key map bindings.
#+name : tab:vertico-keymap-bindings
|---------------------------------+---------------------+------------------------------------|
| command | keys | remap |
|---------------------------------+---------------------+------------------------------------|
| =vertico-directory-delete-char= | {{{kbd(DEL)}}} | |
| =vertico-directory-delete-word= | {{{kbd(M-DEL)}}} | |
| =vertico-directory-enter= | {{{kbd(RET)}}} | |
| =vertico-exit= | {{{kbd(C-j)}}} | =exit-minibuffer= |
| =vertico-exit-input= | {{{kbd(C-RET)}}} | |
| =vertico-first= | {{{kbd(M-<)}}} | =beginning-of-buffer= |
| =vertico-first= | {{{kbd(M-<)}}} | =minibuffer-beginning-of-buffer= |
| =vertico-insert= | {{{kbd(TAB)}}} | |
| =vertico-last= | {{{kbd(M->)}}} | =end-of-buffer= |
| =vertico-next-group= | {{{kbd(C-<down>)}}} | =forward-paragraph= |
| =vertico-next= | {{{kbd(<down>)}}} | =next-line-or-history-element= |
| =vertico-next= | {{{kbd(C-n)}}} | =next-line= |
| =vertico-previous-group= | {{{kbd(C-<up>)}}} | =backward-paragraph= |
| =vertico-previous= | {{{kbd(<up>)}}} | =previous-line-or-history-element= |
| =vertico-previous= | {{{kbd(C-p)}}} | =previous-line= |
| =vertico-save= | {{{kbd(M-w)}}} | =kill-ring-save= |
| =vertico-scroll-down= | {{{kbd(M-v)}}} | =scroll-down-command= |
| =vertico-scroll-up= | {{{kbd(C-v)}}} | =scroll-up-command= |
|---------------------------------+---------------------+------------------------------------|
2021-12-05 16:40:20 +01:00
** [[info:orderless#Top][Orderless (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:orderless-configuration
:END:
2021-12-23 15:29:03 +01:00
Listing [[lst:configure-orderless ]] enables =orderless= .
#+caption[Configure =orderless= ]:
#+caption : Configure =orderless=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-orderless
2021-12-05 16:40:20 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(when (fboundp 'orderless-filter)
(custom-set-variables
;; https://github.com/purcell/emacs.d/issues/778
'(completion-styles '(basic completion-partial orderless))
'(completion-category-defaults nil)
'(completion-category-overrides
'((file (styles partial-completion)))))
(add-hook 'minibuffer-setup-hook
(defun my-on-minibuffer-setup-hook()
(setq-default completion-styles '(substring orderless))))))
#+end_src
2021-12-29 10:05:06 +01:00
** [[info:embark#Top][Embark (info)]]
2021-12-05 16:40:20 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:embark-configuration
:END:
2021-12-23 15:29:03 +01:00
Listing [[lst:configure-embark ]] configures =embark= .
#+caption[Configure =embark= ]:
#+caption : Configure =embark=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-embark
2021-12-05 16:40:20 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(when (cl-every #'fboundp '(embark-act embark-bindings embark-dwim))
(global-set-key (kbd "C-,") #'embark-act)
(global-set-key (kbd "C-:") #'embark-dwim)
(global-set-key (kbd "C-h B") #'embark-bindings)))
#+end_src
** [[info:marginalia#Top][Marginalia (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:marginalia-configuration
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
Listing [[lst:enable-marginalia-mode ]] enables =marginalia-mode= .
#+caption[Enable =marginalia-mode= ]:
#+caption : Enable =marginalia-mode=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-marginalia-mode
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(when (fboundp 'marginalia-mode)
(marginalia-mode +1)))
#+end_src
2021-12-05 16:40:20 +01:00
** [[info:consult#Top][Consult (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:consult-configuration
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
Listing [[lst:configure-consult ]] configures =consult= .
2021-12-28 08:38:29 +01:00
#+attr_latex : :booktabs yes :float table
2022-01-10 08:47:45 +01:00
#+caption[Configuration specific key bindings]:
2021-12-28 08:38:29 +01:00
#+caption : Configuration specific key-bindings.
#+name : tab:configuration-specific-key-bindings
|-------------------------------+---------------------+------------------------|
| command | keys | key map |
|-------------------------------+---------------------+------------------------|
| =consult-apropos= | {{{kbd(<help> a)}}} | =global-map= |
| =consult-bookmark= | {{{kbd(C-x r b)}}} | =ctl-x-keymap= |
| =consult-buffer-other-frame= | {{{kbd(C-x 5 b)}}} | =ctl-x-keymap= |
| =consult-buffer-other-window= | {{{kbd(C-x 4 b)}}} | =ctl-x-keymap= |
| =consult-buffer= | {{{kbd(C-x b)}}} | =ctl-x-keymap= |
| =consult-compile-error= | {{{kbd(M-g e)}}} | =goto-map= |
| =consult-complex-command= | {{{kbd(C-x M-:)}}} | =ctl-x-keymap= |
| =consult-find= | {{{kbd(M-s f)}}} | =search-map= |
| =consult-focus-lines= | {{{kbd(M-s u)}}} | =search-map= |
| =consult-git-grep= | {{{kbd(M-s g)}}} | =search-map= |
| =consult-global-mark= | {{{kbd(M-g k)}}} | =goto-map= |
| =consult-goto-line= | {{{kbd(M-g M-g)}}} | =goto-map= |
| =consult-goto-line= | {{{kbd(M-g g)}}} | =goto-map= |
| =consult-history= | {{{kbd(C-c h)}}} | =global-map= |
| =consult-imenu-project= | {{{kbd(M-g i)}}} | =goto-map= |
| =consult-keep-lines= | {{{kbd(M-s k)}}} | =search-map= |
| =consult-line= | {{{kbd(M-s l)}}} | =search-map= |
| =consult-mark= | {{{kbd(M-g m)}}} | =goto-map= |
| =consult-mode-command= | {{{kbd(C-c m)}}} | =global-map= |
| =consult-multi-occur= | {{{kbd(M-s m)}}} | =search-map= |
| =consult-outline= | {{{kbd(M-g o)}}} | =goto-map= |
| =consult-register= | {{{kbd(C-x r x)}}} | =ctl-x-keymap= |
| =consult-yank-pop= | {{{kbd(M-y)}}} | =global-map= |
|-------------------------------+---------------------+------------------------|
| =elfeed= | {{{kbd(C-x w)}}} | =global-map= |
| =embark-act= | {{{kbd(C-\,)}}} | =global-map= |
| =embark-bindings= | {{{kbd(C-h B)}}} | =global-map= |
| =embark-dwim= | {{{kbd(C-:)}}} | =global-map= |
| =iedit-mode= | {{{kbd(C-;)}}} | =global-map= |
| =minibuffer-complete-history= | {{{kbd(C-<tab>)}}} | =minibuffer-local-map= |
| =narrow-or-widen-dwim= | {{{kbd(C-x C-n)}}} | =ctl-x-keymap= |
| =org-agenda= | {{{kbd(C-c a)}}} | =global-map= |
| =org-capture= | {{{kbd(C-c c)}}} | =global-map= |
| =org-cite= | {{{kbd(C-c b)}}} | =org-mode-map= |
| =org-insert-link-global= | {{{kbd(C-c C-l)}}} | =global-map= |
| =org-narrow-to-table= | {{{kbd(C-x n t)}}} | =ctl-x-keymap= |
| =org-store-link= | {{{kbd(C-c l)}}} | =global-map= |
|-------------------------------+---------------------+------------------------|
2021-12-23 15:29:03 +01:00
#+caption[Configure =consult= ]:
#+caption : Configure =consult=.
2021-12-28 08:38:29 +01:00
#+name : lst:configure-consult
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(when (fboundp 'consult-apropos)
(custom-set-variables
'(consult-project-root-function #'vc-root-dir))
;; C-c bindings (mode-specific-map)
(global-set-key (kbd "C-c h") #'consult-history)
(global-set-key (kbd "C-c m") #'consult-mode-command)
;; C-x bindings (ctl-x-map)
2021-12-28 08:38:29 +01:00
(define-key ctl-x-map (kbd "M-:") #'consult-complex-command)
(define-key ctl-x-map (kbd "b") #'consult-buffer)
(define-key ctl-x-map (kbd "4 b") #'consult-buffer-other-window)
(define-key ctl-x-map (kbd "5 b") #'consult-buffer-other-frame)
(define-key ctl-x-map (kbd "r x") #'consult-register)
(define-key ctl-x-map (kbd "r b") #'consult-bookmark)
2021-11-29 13:14:56 +01:00
;; M-g bindings (goto-map)
2021-12-28 08:38:29 +01:00
(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-project)
(define-key goto-map (kbd "e") #'consult-compile-error)
2021-11-29 13:14:56 +01:00
;; M-s bindings (search-map)
2021-12-28 08:38:29 +01:00
(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)
2021-11-29 13:14:56 +01:00
;; Other bindings
(global-set-key (kbd "M-y") #'consult-yank-pop)
(global-set-key (kbd "<help > a") #'consult-apropos)
;; Tweak functions
(advice-add 'completing-read-multiple
:override #'consult-completing-read-multiple)
(fset 'multi-occur #'consult-multi-occur)))
#+end_src
2021-12-05 16:40:20 +01:00
** [[https://company-mode.github.io/][Company: a modular complete anything framework for Emacs]]
:PROPERTIES:
:CUSTOM_ID: sec:company-configuration
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
Listing [[lst:configure-company ]] configures =company= .
#+caption[Configure =company= ]:
#+caption : Configure =company=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-company
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(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
2022-01-24 04:27:47 +01:00
lisp-mode-hook
2021-11-29 13:14:56 +01:00
python-mode-hook
2022-01-24 04:27:47 +01:00
ielm-mode-hook
sly-mrepl-mode-hook))
2021-11-29 13:14:56 +01:00
(add-hook hook #'company-mode))))
#+end_src
2021-12-29 14:05:03 +01:00
** [[https://lists.gnu.org/archive/html/emacs-devel/2021-12/msg00802.html][Minibuffer history completion]]
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:minibuffer-history-completion
:END:
2021-12-11 12:43:59 +01:00
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
2021-12-23 15:29:03 +01:00
previous input in the minibuffer. Listing
[[lst:enable-minibuffer-history-completion ]] enables minibuffer history completion.
2021-12-11 12:43:59 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =minibuffer-history-completion= ]:
#+caption : Enable =minibuffer-history-completion=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-minibuffer-history-completion
2021-12-11 12:43:59 +01:00
#+begin_src emacs-lisp
(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)
2021-12-12 03:31:47 +01:00
;; Stolen from Emacs-28.1 for Emacs-27.2:
(unless (fboundp 'minibuffer--completion-prompt-end)
(defun minibuffer--completion-prompt-end ()
(let ((end (minibuffer-prompt-end)))
(if (< (point) end)
(user-error "Can't complete in prompt")
end))))
2021-12-11 12:43:59 +01:00
;; Adapted from ‘ minibuffer-complete’ :
2021-12-28 08:48:03 +01:00
(defun minibuffer-complete-history ()
2021-12-13 12:11:03 +01:00
"Allow minibuffer completion on previous input."
2021-12-11 12:43:59 +01:00
(interactive)
(completion-in-region (minibuffer--completion-prompt-end) (point-max)
(symbol-value minibuffer-history-variable)
nil))
2022-01-13 11:58:05 +01:00
(define-key minibuffer-local-map (kbd "C-<tab >") #'minibuffer-complete-history)
2021-12-11 12:43:59 +01:00
#+end_src
2021-12-29 14:05:03 +01:00
** [[https://github.com/justbur/emacs-which-key#readme][Prefix key-binding help]]
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:prefix-key-binding-help
:END:
2021-12-12 04:00:09 +01:00
Configure ~which-key-mode~ so that typing =C-h= after a prefix key displays all
2021-12-23 15:29:03 +01:00
keys available after the prefix key. Listing [[lst:enable-which-key-mode ]] enables
2022-01-11 08:12:33 +01:00
[[https://github.com/justbur/emacs-which-key#manual-activation ][manual activation ]] of =which-key-mode= . This uses =prefix-help-command= behind
the scenes and is therefore incompatible with straightforward use of [[info:embark#Quick
start][=embark-prefix-help-command= (info)]].
2021-12-12 04:00:09 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =which-key-mode= ]:
#+caption : Enable =which-key-mode=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-which-key-mode
2021-12-12 04:00:09 +01:00
#+begin_src emacs-lisp
(when (fboundp 'which-key-mode)
(custom-set-variables
'(which-key-idle-delay 10000)
'(which-key-idle-secondary-delay 0.05)
'(which-key-show-early-on-C-h t))
(which-key-mode +1))
#+end_src
2021-11-29 13:14:56 +01:00
* Reading
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:reading
:END:
** Reading EPUB files
:PROPERTIES:
:CUSTOM_ID: sec:reading-epub-files
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
Listing [[lst:enable-nov-mode ]] enables =nov-mode= .
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =nov-mode= ]:
#+caption : Enable =nov-mode=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-nov-mode
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(when (fboundp 'nov-mode)
(add-to-list 'auto-mode-alist `(,(rx ".epub" eos) . nov-mode)))
#+end_src
2021-12-23 15:29:03 +01:00
** Reading PDF files
:PROPERTIES:
:CUSTOM_ID: sec:reading-pdf-files
:END:
2021-11-29 13:14:56 +01:00
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 ]]
files produced with LaTeX to the original LaTeX sources.
In order to use [[https://github.com/vedang/pdf-tools ][pdf-tools ]], you have to type =M-x pdf-tools-install= after
2021-12-07 08:19:59 +01:00
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.
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =pdf-tools= ]:
#+caption : Enable =pdf-tools=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-pdf-tools
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
2021-12-12 16:24:32 +01:00
;; 'pdf-loader-install' is the lazy equivalent of 'pdf-tools-install':
;; see the README file.
(when (fboundp 'pdf-loader-install)
(pdf-loader-install))
2021-12-07 05:45:38 +01:00
2021-12-12 16:24:32 +01:00
(with-eval-after-load 'pdf-view
2021-12-07 05:45:38 +01:00
(when (fboundp 'pdf-view-restore-mode)
(add-hook 'pdf-view-mode-hook #'pdf-view-restore-mode)))
2021-11-29 13:14:56 +01:00
#+end_src
* Writing
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:writing
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
** Writing LaTeX files
:PROPERTIES:
:CUSTOM_ID: sec:writing-latex-files
:END:
2021-11-29 13:14:56 +01:00
Loading =tex.el= immediately instead of lazily ensures proper initialization of
2021-12-26 11:53:40 +01:00
[[https://en.wikipedia.org/wiki/AUCTeX ][AUCTeX ]]. For instance, the ~TeX-master~ safe local variable in the =tex.el=
2021-11-29 13:14:56 +01:00
elisp library file has no autoload cookie. Without prior loading of =tex.el= ,
2021-12-26 11:53:40 +01:00
Emacs will complain that ~TeX-master~ is no safe local variable in case it reads
a LaTeX file that sets ~TeX-master~ . Listing [[lst:require-auctex ]] initializes
[[https://en.wikipedia.org/wiki/AUCTeX ][AUCTeX ]] properly.
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Require =AUCTeX= ]:
#+caption : Require =AUCTeX=.
2021-12-28 08:48:03 +01:00
#+name : lst:require-auctex
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
2021-12-26 11:53:40 +01:00
;; Use `require' to make `TeX-master' a safe local variable.
2021-11-29 13:14:56 +01:00
(when (require 'tex nil 'noerror)
2021-12-23 15:29:03 +01:00
(custom-set-variables
'(TeX-auto-save t)
2021-12-26 11:53:40 +01:00
'(TeX-install-font-lock #'font-latex-setup)
2021-12-23 15:29:03 +01:00
'(TeX-parse-self t)))
#+end_src
2021-12-26 11:53:40 +01:00
Although, the LaTeX =biblatex= is in use, listing [[lst:configure-bibtex ]]
configures the Emacs =bibtex= library for the LaTeX =BiBTeX= package to maintain
backwards compatibility.
2021-12-23 15:29:03 +01:00
#+caption[Configure =bibtex= ]:
#+caption : Configure =bibtex=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-bibtex
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'bibtex
2021-12-26 11:53:40 +01:00
(custom-set-variables '(bibtex-dialect 'BibTeX)))
2021-12-23 15:29:03 +01:00
#+end_src
2021-12-26 11:53:40 +01:00
Listing [[lst:configure-font-latex ]] disables font scaling of section titles.
2021-12-23 15:29:03 +01:00
#+caption[Configure =font-latex= ]:
#+caption : Configure =font-latex=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-font-latex
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'font-latex
(custom-set-variables
'(font-latex-fontify-sectioning 1.0)))
#+end_src
2021-12-26 11:53:40 +01:00
Listing [[lst:configure-latex ]] configures =latex= for a full featured
=LaTeX-section-command= .
2021-12-23 15:29:03 +01:00
#+caption[Configure =latex= ]:
#+caption : Configure =latex=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-latex
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'latex
2021-12-07 17:22:31 +01:00
(custom-set-variables
'(LaTeX-section-hook '(LaTeX-section-heading
LaTeX-section-title
LaTeX-section-toc
LaTeX-section-section
2021-12-23 15:29:03 +01:00
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=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-tex
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'tex
2022-01-23 11:51:26 +01:00
(custom-set-variables
;; Disable `TeX-electric-math' to prevent collisions with `smartparens'.
'(TeX-electric-math nil))
2021-12-23 15:29:03 +01:00
;; https://emacs.stackexchange.com/questions/17396/
;; indentation-in-square-brackets
2021-11-29 13:14:56 +01:00
(defun my-TeX-brace-count-line ()
"Count number of open/closed braces."
(save-excursion
(let ((count 0) (limit (line-end-position)) char)
(while (progn
(skip-chars-forward "^{}[]\\\\" limit)
(when (and (< (point) limit) (not (TeX-in-comment)))
(setq char (char-after))
(forward-char)
(cond ((eq char ?\{)
(setq count (+ count TeX-brace-indent-level)))
((eq char ?\})
(setq count (- count TeX-brace-indent-level)))
((eq char ?\[)
(setq count (+ count TeX-brace-indent-level)))
((eq char ?\])
(setq count (- count TeX-brace-indent-level)))
((eq char ?\\)
(when (< (point) limit)
(forward-char) t))))))
count)))
2022-01-23 11:51:26 +01:00
2021-11-29 13:14:56 +01:00
(advice-add 'TeX-brace-count-line :override #'my-TeX-brace-count-line))
#+end_src
2021-12-11 12:19:35 +01:00
*** TODO Improve the AUCTeX configuration slowly
[[https://github.com/thisirs/dotemacs/blob/master/lisp/init-auctex.el ][AUCTeX setup of an experienced user ]]
2021-12-23 15:29:03 +01:00
** Writing Org files
:PROPERTIES:
:CUSTOM_ID: sec:writing-org-files
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
*** [[info:org#Activation][Org activation (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:activate-org
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Activate =Org= ]:
#+caption : Activate =Org=.
2021-12-28 08:48:03 +01:00
#+name : lst:activate-org
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
;; Inspect:
;; function with "C-h f"
;; symbols with "C-h o"
;; variables with "C-h v"
(global-set-key (kbd "C-c a") #'org-agenda)
(global-set-key (kbd "C-c c") #'org-capture)
(global-set-key (kbd "C-c l") #'org-store-link)
(global-set-key (kbd "C-c C-l") #'org-insert-link-global)
#+end_src
2021-12-23 15:29:03 +01:00
*** Org customization
:PROPERTIES:
:CUSTOM_ID: sec:customize-org
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
The code in listing [[lst:customize-org-babel ]], [[lst:customize-org ]], and
2022-01-09 19:20:15 +01:00
[[lst:customize-org-export ]] does basic customization of [[https://orgmode.org/ ][Org mode ]] variables.
2021-12-23 15:29:03 +01:00
#+caption[Customize =org-babel= ]:
#+caption : Customize =org-babel=.
2021-12-28 08:48:03 +01:00
#+name : lst:customize-org-babel
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
2021-12-23 15:29:03 +01:00
(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")))
2022-01-04 13:11:21 +01:00
(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"))))
2022-01-23 11:56:37 +01:00
(with-eval-after-load 'ob-lisp
(with-eval-after-load 'sly
(custom-set-variables
'(org-babel-lisp-eval-fn #'sly-eval))))
2021-11-29 13:14:56 +01:00
#+end_src
2021-12-23 15:29:03 +01:00
#+caption[Customize =Org= ]:
#+caption : Customize =Org=.
2021-12-28 08:48:03 +01:00
#+name : lst:customize-org
2021-12-23 15:29:03 +01:00
#+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)
(shell . t)))
2022-01-05 17:38:01 +01:00
'(org-export-backends '(ascii beamer html icalendar latex odt texinfo))
2021-12-23 15:29:03 +01:00
'(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")
2022-01-23 11:51:26 +01:00
("v" . "verse")))))
#+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 'org
;; From: "Nicolas Richard" <theonewiththeevillook@yahoo.fr >
;; 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)))
(define-key org-mode-map (kbd "$") #'org-electric-dollar)
2022-01-13 11:56:41 +01:00
(define-key org-mode-map (kbd "M-q") #'org-fill-paragraph))
2021-12-23 15:29:03 +01:00
#+end_src
#+caption[Customize =org-export= ]:
#+caption : Customize =org-export=.
2021-12-28 08:48:03 +01:00
#+name : lst:customize-org-export
2021-12-23 15:29:03 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'ox-latex
(custom-set-variables
'(org-latex-compiler "lualatex")
2021-12-26 11:53:40 +01:00
'(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")
2021-12-23 15:29:03 +01:00
'(org-latex-listings 'minted)
2021-12-28 14:08:56 +01:00
'(org-latex-minted-langs '((cc "c++")
(cperl "perl")
2022-01-01 11:42:28 +01:00
(diff "diff")
2021-12-28 14:08:56 +01:00
(shell-script "bash")
2022-01-19 07:47:56 +01:00
(org "text")
(toml "toml")))
2021-12-23 15:29:03 +01:00
'(org-latex-minted-options '(("bgcolor" "LightGoldenrodYellow")))
2021-12-28 08:48:03 +01:00
`(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)))
2021-12-23 15:29:03 +01:00
#+end_src
*** [[https://github.com/bdarcus/citar][Citar: citing bibliography]] with [[https://orgmode.org/][Org Mode]]
2021-12-05 16:40:20 +01:00
:PROPERTIES:
2021-12-23 15:29:03 +01:00
:CUSTOM_ID: sec:citing-bibliography
2021-12-05 16:40:20 +01:00
:END:
2021-12-23 15:29:03 +01:00
[[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=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-oc-cite+citar
2021-12-23 15:29:03 +01:00
#+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/ "))))
2022-01-13 11:58:05 +01:00
(define-key org-mode-map (kbd "C-c b") #'org-cite-insert))
2021-12-23 15:29:03 +01:00
#+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.
2021-12-28 08:48:03 +01:00
#+name : lst:define-org-link-types
2021-12-06 12:59:24 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'ol
(org-link-set-parameters
"ac*" :export (lambda (path _desc backend _info)
(pcase backend
2021-12-23 15:29:03 +01:00
(`latex (format "\\gls*{%s}" path))
2021-12-06 12:59:24 +01:00
(_ path))))
(org-link-set-parameters
"cite" :export (lambda (path _desc backend _info)
(pcase backend
2021-12-23 15:29:03 +01:00
(`latex (format "\\cite{%s}" path))
2021-12-06 12:59:24 +01:00
(_ path))))
(org-link-set-parameters
"eqref" :export (lambda (path _desc backend _info)
(pcase backend
2021-12-23 15:29:03 +01:00
(`latex (format "\\eqref{%s}" path))
2021-12-06 12:59:24 +01:00
(_ path))))
2021-12-16 17:44:55 +01:00
(org-link-set-parameters
"hyperlink" :export (lambda (path desc backend _info)
2021-12-23 15:29:03 +01:00
(pcase backend
(`latex (format "\\hyperlink{%s}{%s}" path desc))
(_ path))))
2021-12-06 12:59:24 +01:00
(org-link-set-parameters
"label" :export (lambda (path _desc backend _info)
(pcase backend
2021-12-23 15:29:03 +01:00
(`latex (format "\\label{%s}" path))
2021-12-06 12:59:24 +01:00
(_ path))))
(org-link-set-parameters
"ref" :export (lambda (path _desc backend _info)
(pcase backend
2021-12-23 15:29:03 +01:00
(`latex (format "\\ref{%s}" path))
2021-12-06 12:59:24 +01:00
(_ path)))))
#+end_src
2021-12-23 15:29:03 +01:00
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.
2021-12-05 16:40:20 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Patch =ol-info= ]:
#+caption : Patch =ol-info=.
#+name : lst:emacs-lisp-setup-patch-ol-info
2022-01-11 05:40:26 +01:00
#+begin_src emacs-lisp :exports code :silent
2021-12-23 15:29:03 +01:00
(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 "<a href=\"%s#%s\" >%s</a >"
(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))))
2021-12-26 11:53:40 +01:00
(make-variable-buffer-local 'org-info-emacs-documents)
(setq org-info-emacs-documents (delete "org" org-info-emacs-documents))
2021-12-23 15:29:03 +01:00
(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")
2021-12-26 11:53:40 +01:00
("org" . "https://orgmode.org/org.html")
2021-12-23 15:29:03 +01:00
("orderless" . "https://github.com/oantolin/orderless")
2022-01-23 11:56:37 +01:00
("sly" . "https://joaotavora.github.io/sly/ ")
2021-12-23 15:29:03 +01:00
("vertico" . "https://github.com/minad/vertico"))
org-info-other-documents
:test #'equal)))
2021-12-05 16:40:20 +01:00
#+end_src
2021-12-05 17:34:56 +01:00
*** [[https://tecosaur.github.io/emacs-config/#translate-capital-keywords][Translate capital keywords (old) to lower case (new)]]
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:convert-upper-to-lower-case-keywords
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Convert upper to lower case keywords]:
#+caption : Convert upper to lower case keywords.
2021-12-28 08:48:03 +01:00
#+name : lst:convert-upper-to-lower-case-keywords
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'org
(defun org-syntax-convert-keyword-case-to-lower ()
"Convert all #+KEYWORDS to #+keywords."
(interactive)
(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
2021-12-29 14:05:03 +01:00
*** [[https://lists.gnu.org/archive/html/emacs-orgmode/2016-07/msg00394.html][Evaluate specific source blocks at load-time]]
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:load-time-specific-source-block-evaluation
:END:
2021-11-29 13:14:56 +01:00
2021-12-29 14:05:03 +01:00
[[https://emacs.stackexchange.com/questions/12938/how-can-i-evaluate-elisp-in-an-orgmode-file-when-it-is-opened ][How to do load time source block evaluation ]]
2021-12-23 15:29:03 +01:00
#+caption[Evaluate specific source blocks at load-time]:
#+caption : Evaluate specific source blocks at load-time.
2021-12-28 08:48:03 +01:00
#+name : lst:load-time-specific-source-block-evaluation
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
2021-12-23 15:29:03 +01:00
(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)
2021-12-26 11:53:40 +01:00
(let ((name (org-element-property :name block)))
(when (and name (string-match-p infix name))
block))))))
2021-12-23 15:29:03 +01:00
(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")))
2021-12-14 10:15:39 +01:00
#+end_src
2021-12-13 21:01:08 +01:00
2021-12-28 08:32:51 +01:00
*** [[info:org#LaTeX header and sectioning][Easy LaTeX preamble editing]]
2021-12-23 15:29:03 +01:00
:PROPERTIES:
2021-12-28 08:32:51 +01:00
:CUSTOM_ID: sec:easy-latex-preamble-editing
2021-12-23 15:29:03 +01:00
:END:
2021-12-28 08:32:51 +01:00
There are at least two ways (new and old) to edit the LateX preamble
=latex_header= and =latex-extra_header= export options easily in LaTeX source or
export blocks. This [[info:org#Top ][Org (info) ]] file uses the new way, but keeps the old way for
backwards compatibility.
2021-12-23 15:29:03 +01:00
2021-12-28 08:32:51 +01:00
The new way -- exploiting an idea of [[https://www.matem.unam.mx/~omar/ ][Omar Antolin Camarena ]] -- is to code new
[[info:org#Editing Source Code ][<LANGUAGE>-modes ]] allowing to edit in LaTeX mode and to export to LaTeX code with
[[info:org#LaTeX specific export settings ][correct LaTeX preamble export setting prefixes ]]. Here, are links to three posts
exposing his idea:
1. [[https://www.reddit.com/r/orgmode/comments/7u2n0h/tip_for_defining_latex_macros_for_use_in_both/ ][Export LaTeX macros to LaTeX and HTML/MathJax preambles (reddit) ]],
2. [[https://www.reddit.com/r/orgmode/comments/5bi6ku/tip_for_exporting_javascript_source_block_to/ ][Export JavaScript source blocks to script tags in HTML (reddit) ]],
3. [[https://emacs.stackexchange.com/questions/28301/export-javascript-source-block-to-script-tag-in-html-when-exporting-org-file-to ][Export JavaScript source blocks to script tags in HTML (SX) ]].
Listing [[lst:emacs-lisp-setup-latex-header ]] implements this way by means of two
new [[info:org#Editing Source Code ][<LANGUAGE>-modes ]]: =latex-header= and =latex-extra-header= .
#+caption[New =<LANGUAGE>-modes= to edit the LaTeX preamble easily]:
#+caption : Add =latex-header= and =latex-extra-header= language modes to edit
#+caption : LaTeX preamble =latex_header= and =latex_extra_header= export options
#+caption : easily.
#+name : lst:emacs-lisp-setup-latex-header
2022-01-11 05:40:26 +01:00
#+begin_src emacs-lisp :exports code :silent
2021-12-28 14:08:56 +01:00
(with-eval-after-load 'org-src
(defun prefix-all-lines (prefix body)
(with-temp-buffer
(insert body)
(string-insert-rectangle (point-min) (point-max) prefix)
(buffer-string)))
2021-12-28 08:32:51 +01:00
(add-to-list 'org-src-lang-modes '("latex-header" . latex))
2021-12-28 14:08:56 +01:00
(defvar org-babel-default-header-args:latex-header
'((:exports . "results") (:results . "raw")))
2021-12-28 08:32:51 +01:00
(defun org-babel-execute:latex-header (body _params)
2022-01-05 17:38:01 +01:00
"Execute a block of LaTeX preamble lines with org-babel.
This function is called by `org-babel-execute-src-block' and
prefixes all lines with \"#+latex_header: \"."
2021-12-28 08:32:51 +01:00
(prefix-all-lines "#+latex_header: " body))
2021-12-26 11:53:40 +01:00
2021-12-28 08:32:51 +01:00
(add-to-list 'org-src-lang-modes '("latex-extra-header" . latex))
2021-12-26 11:53:40 +01:00
2021-12-28 14:08:56 +01:00
(defvar org-babel-default-header-args:latex-extra-header
'((:exports . "results") (:results . "raw")))
2021-12-26 11:53:40 +01:00
2021-12-28 08:32:51 +01:00
(defun org-babel-execute:latex-extra-header (body _params)
2022-01-05 17:38:01 +01:00
"Execute a block of LaTeX preamble lines with org-babel.
This function is called by `org-babel-execute-src-block' and
prefixes all lines with \"#+latex_extra_header: \"."
2021-12-28 08:32:51 +01:00
(prefix-all-lines "#+latex_extra_header: " body)))
2021-12-26 11:53:40 +01:00
#+end_src
2021-12-28 08:32:51 +01:00
The old way is to use a special export attribute as in the function
=org-latex-header-blocks-filter= in [[https://git.sr.ht/~bzg/org-contrib/tree/master/item/lisp/ox-extra.el ][ox-extra.el ]]. Apparently, nobody is using
this broken function (broken, since it relies on support only in org-mode before
2021-12-29 14:05:03 +01:00
=2014-11-11= ). Listing [[lst:org-latex-header-blocks-filter ]] proposes a fix for
=org-latex-header-blocks-filter= .
2021-12-26 11:53:40 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Convert marked LaTeX export blocks to LaTeX header lines]:
#+caption : Convert marked LaTeX export blocks to LaTeX header lines.
2021-12-28 08:32:51 +01:00
#+name : lst:org-latex-header-blocks-filter
2021-12-14 10:15:39 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'ox
2021-12-13 21:01:08 +01:00
(defun org-latex-header-blocks-filter (backend)
2021-11-30 09:35:15 +01:00
"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
,#+header: :header yes
,#+begin_export latex
% This line converts to a LaTeX header line.
,#+end_export
converts to
\"#+latex_header: % This line converts to a LaTeX header line.\"."
2021-11-29 13:14:56 +01:00
(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)
2021-12-06 08:30:31 +01:00
;; Set point to where to insert LaTeX header lines
;; after deleting the block.
2021-11-29 13:14:56 +01:00
(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")))))
2021-12-06 08:30:31 +01:00
;; Reverse to go upwards to avoid wrecking the list of
;; block positions in the file that would occur in case
;; of going downwards.
2021-12-14 10:15:39 +01:00
(reverse blocks))))))
#+end_src
2021-11-29 13:14:56 +01:00
2021-12-29 14:05:03 +01:00
This file uses the new way, while keeping the old way for backwards
compatibility, because the new way feels less hackish than the old way. A
practical difference is that new way source blocks (contrary to old way export
blocks) do not work in [[info:org#Export Settings ][#+SETUPFILE: <FILE> ]], but only in [[info:org#Export Settings ][#+INCLUDE: <FILE> ]] files.
2021-11-29 13:14:56 +01:00
2021-12-29 10:05:43 +01:00
*** [[info:org#Export Settings][#+SETUPFILE: and #+INCLUDE: usage]]
2021-12-28 14:08:56 +01:00
:PROPERTIES:
2021-12-29 10:05:43 +01:00
:CUSTOM_ID: sec:setupfile+include-usage
2021-12-28 14:08:56 +01:00
:END:
2022-01-01 11:42:28 +01:00
Evaluation of the source block in listing
[[lst:make-source-block-with-export-keyword-settings ]] produces the source block
that exports to listing [[lst:source-file-export-keyword-settings ]] which shows the
first six lines of this [[file:README.org ]] file. The last two lines show that
2022-01-09 19:20:15 +01:00
[[file:setup-include.org ][setup-include.org ]] is the argument for [[info:org#Export Settings ][#+SETUPFILE: ]] *and* [[info:org#Export Settings ][#+INCLUDE: ]].
2022-01-01 11:42:28 +01:00
#+caption[Make setup and include file export keyword settings source block]:
#+caption : The shell script to make the source block containing the export
#+caption : keyword settings.
#+name : lst:make-source-block-with-export-keyword-settings
#+begin_src shell :exports both :results drawer
echo "#+caption[Source file export keyword settings]:"
echo "#+caption: The first six lines of README.org containing the export"
echo "#+caption: keyword settings."
echo "#+name: lst:source-file-export-keyword-settings"
echo "#+begin_src org :tangle no"
head -n 6 README.org
echo -n "#+end_src"
#+end_src
2021-12-30 09:04:38 +01:00
2022-01-01 11:42:28 +01:00
#+RESULTS : lst:make-source-block-with-export-keyword-settings
:results:
2021-12-29 14:05:03 +01:00
#+caption[Source file export keyword settings]:
2022-01-01 11:42:28 +01:00
#+caption : The first six lines of README.org containing the export
#+caption : keyword settings.
2021-12-29 14:05:03 +01:00
#+name : lst:source-file-export-keyword-settings
2021-12-30 09:04:38 +01:00
#+begin_src org :tangle no
2022-01-01 11:42:28 +01:00
#+title : Emacs setup for use with LaTeX, Org, and Python
#+author : Gerard Vermeulen
#+latex_class : article
#+latex_class_options : [11pt,a4paper,english,svgnames,tables]
#+setupfile : "setup-include.org"
#+include : "setup-include.org"
2021-12-29 14:05:03 +01:00
#+end_src
2022-01-01 11:42:28 +01:00
:end:
2021-12-29 14:05:03 +01:00
2022-01-09 19:20:15 +01:00
Listing [[lst:setup-include-export-keyword-settings ]] tangles into the
[[file:setup-include.org ][setup-include.org ]] file and listing [[lst:by-backend-kbd-org-macro ]] defines
the tools for the [[https://orgmode.org/ ][Org mode ]] =kbd= macro in [[file:setup-include.org ][setup-include.org ]].
2021-12-30 09:04:38 +01:00
2021-12-29 14:05:03 +01:00
#+caption[Setup and include file export keyword settings]:
#+caption : Setup and include file export keyword settings.
#+name : lst:setup-include-export-keyword-settings
2021-12-29 10:05:43 +01:00
#+begin_src org
,#+babel: :cache no
2022-01-09 19:20:15 +01:00
,#+macro: kbd (eval (by-backend-kbd-org-macro $1))
2022-01-23 11:51:26 +01:00
,#+options: ^:{}
2021-12-29 10:05:43 +01:00
,#+property: header-args:emacs-lisp :exports code :results silent :tangle init.el
,#+property: header-args:org :tangle setup-include.org
,#+startup: content
#+end_src
2022-01-09 19:20:15 +01:00
#+caption[Define the tools of the org-mode =kbd= macro]:
#+caption : Define the tools for the org-mode =kbd= macro.
#+name : lst:by-backend-kbd-org-macro
#+begin_src emacs-lisp
(with-eval-after-load 'ox
(autoload 'htmlize-protect-string "htmlize" nil t)
(defmacro by-backend (&rest body)
`(cl-case org-export-current-backend ,@body))
(defun by-backend-kbd-org-macro (keys)
(by-backend
(html (format "@@html:<kbd >%s</kbd >@@" (htmlize-protect-string keys)))
(latex (format "@@latex:\\colorbox{PowderBlue}{\\texttt{%s}}@@" keys)))))
#+end_src
Listing [[lst:use-latex-header-1 ]], [[lst:use-latex-header-2 ]], [[lst:use-latex-header-3 ]],
and [[lst:use-latex-header-4 ]] tangle into the [[file:setup-include.org ][setup-include.org ]] file in order to
create the [[https://www.latex-project.org/ ][LaTeX ]] preamble.
2021-12-29 10:05:43 +01:00
#+caption[LaTeX preamble: language, lists and floats]:
#+caption : LaTeX preamble: language, lists and floats.
#+name : lst:use-latex-header-1
#+begin_src org
,#+begin_src latex-header
% LANGUAGE:
\usepackage{babel}
\usepackage{fvextra}
\usepackage{csquotes}
% 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}
% 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_src
#+end_src
#+caption[LaTeX preamble: page layout]:
#+caption : LaTeX preamble: page layout.
#+name : lst:use-latex-header-2
#+begin_src org
,#+begin_src latex-header
% PAGE LAYOUT:
\usepackage{fancyhdr}
\usepackage{lastpage}
\usepackage[
headheight=20mm,
top=40mm,
bottom=20mm,
left=60pt,
right=60pt,
heightrounded,
verbose,
]{geometry}
% TECHNICS:
\usepackage{siunitx}
\usepackage{tikz}
,#+end_src
#+end_src
#+caption[LaTeX preamble: float barriers]:
#+caption : LaTeX preamble: float barriers.
#+name : lst:use-latex-header-3
#+begin_src org
,#+begin_src latex-header
% 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
}%
}
\makeatother
,#+end_src
#+end_src
#+caption[LaTeX preamble: fancy headers and footers]:
#+caption : LaTeX preamble: fancy headers and footers.
#+name : lst:use-latex-header-4
#+begin_src org
,#+begin_src latex-header
% 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}}
\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}}
}
% #+latex_header: END.
,#+end_src
2021-12-28 14:08:56 +01:00
#+end_src
2021-12-29 14:05:03 +01:00
*** [[info:org#LaTeX specific export settings][Advanced LaTeX export settings]]
:PROPERTIES:
:CUSTOM_ID: sec:advanced-latex-export-settings
:END:
[[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[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 :results silent
(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}"))
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
Listing [[lst:emacs-lisp-setup-call ]] initializes the buffer local variables
=org-export-before-parsing-hook= , =org-latex-classes= ,
=org-latex-title-command= , =org-latex-toc-command= , and
=org-latex-subtitle-format= .
#+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=lst/title-page
#+begin_src emacs-lisp :tangle no
(my-ox-latex-export-buffer-local-variables title-page)
#+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}
#+end_src
2022-01-05 17:37:03 +01:00
*** [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-LaTeX.html#orgcc214c1][Worg: backend dependent execution]]
:PROPERTIES:
:CUSTOM_ID: sec:backend-dependent-execution-update
:END:
#+caption[Worg update: backend dependent header arguments]:
#+caption : Worg update: backend dependent header arguments.
#+name : lst:backend-dependent-execution-update
#+begin_src org :tangle worg-backend-dependent-execution-update.org
,#+latex_header: \usepackage{tikz}
,#+header: :file (by-backend (html "tree.svg") (latex nil))
,#+header: :results (by-backend (html "raw file") (latex "latex replace"))
,#+header: :headers '("\\usepackage{tikz}\n")
,#+begin_src latex
\usetikzlibrary{trees}
\begin{tikzpicture}
\node [circle, draw, fill=red!20] at (0,0) {1}
child { node [circle, draw, fill=blue!30] {2}
child { node [circle, draw, fill=green!30] {3} }
child { node [circle, draw, fill=yellow!30] {4} }};
\end{tikzpicture}
,#+end_src
2022-01-07 16:33:40 +01:00
# Setup
,#+begin_src emacs-lisp :exports none
2022-01-05 17:37:03 +01:00
(with-eval-after-load 'ox
(setq org-babel-latex-htlatex "htlatex")
(defmacro by-backend (&rest body)
`(cl-case org-export-current-backend ,@body)))
,#+end_src
#+end_src
This section updates the outdated [[https://orgmode.org/worg/org-contrib/babel/languages/ob-doc-LaTeX.html#orgcc214c1 ][Worg: backend dependent execution ]] example to
Emacs-27.2 and Org-9.5.2. It shows how to export [[https://en.wikipedia.org/wiki/PGF/TikZ ][PGF/TikZ ]] images to:
1. [[https://en.wikipedia.org/wiki/PDF ][PDF ]] by embedding in [[https://www.latex-project.org/ ][LaTeX ]].
2. [[https://en.wikipedia.org/wiki/HTML ][HTML ]] by passing from [[https://www.latex-project.org/ ][LaTeX ]] by [[https://en.wikipedia.org/wiki/PDF ][PDF ]] and to [[https://en.wikipedia.org/wiki/Scalable_Vector_Graphics ][SVG ]].
Listing [[lst:backend-dependent-execution-update ]] tangles to
[[file:worg-backend-dependent-execution-update.org ][worg-backend-dependent-execution-update.org ]] as either a standalone example or an
2022-01-09 19:20:15 +01:00
example for inclusion. Finally, inclusion of
[[file:worg-backend-dependent-execution-update.org ][worg-backend-dependent-execution-update.org ]] produces here the figure with the
nodes 1, 2, 3, and 4:\\
2022-01-05 17:37:03 +01:00
#+include : worg-backend-dependent-execution-update.org
2022-01-07 16:33:40 +01:00
How to include such figures as floats remains an open question.
2022-01-05 17:37:03 +01:00
2022-01-17 07:56:55 +01:00
*** [[https://orgmode.org/worg/dev/org-syntax-edited.html][Org Syntax]]
:PROPERTIES:
:CUSTOM_ID: sec:org-syntax
:END:
Two tools to grok how [[https://orgmode.org/worg/dev/org-element-api.html ][Org mode parsing ]] works are the [[https://orgmode.org/worg/dev/org-syntax-edited.html ][Org Syntax ]] specification
and the [[http://xahlee.info/emacs/emacs/elisp_parse_org_mode.html ][Org mode parser tutorial ]]. The [[https://orgmode.org/worg/dev/org-element-api.html ][Org element parsing API ]] boils down to three
functions:
1. The function [[https://orgmode.org/worg/dev/org-element-api.html#global ][~org-element-parse-buffer~ ]] implements a fully recursive buffer
parser that returns an abstract syntax tree.
2. The functions [[https://orgmode.org/worg/dev/org-element-api.html#local ][~org-element-at-point~ and ~org-element-context~ ]] return
information on the document structure around point either at the element
level or at the object level in case of ~org-element-context~ .
Listing [[lst:grok-org-element-tree ]] improves the [[http://xahlee.info/emacs/emacs/elisp_parse_org_mode.html ][Org mode parser tutorial ]] by
defining interactive wrappers that pretty print the results of those
non-interactive =org-element= functions to an =Emacs-lisp= buffer.
#+caption[Grok how =org-element= parses your document]:
#+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 (autoload 'pp-display-expression "pp")
(defconst grok-org-output
"*Grok Org Element Output* "
"Grok Org output buffer name.")
(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-parse-buffer what) grok-org-output)))
(defun grok-org-heading-components ()
(interactive)
(pp-display-expression
(org-heading-components) grok-org-output))))
#+end_src
2022-01-01 11:42:28 +01:00
* Programming
:PROPERTIES:
:CUSTOM_ID: sec:programming
:END:
2022-01-23 11:56:37 +01:00
** Common Lisp programming
:PROPERTIES:
:CUSTOM_ID: sec:common-lisp-programming
:END:
Listing [[lst:configure-sly ]] configures the [[info:sly#Top ][Sly (info) ]] Common Lisp IDE for Emacs
for use with [[http://www.sbcl.org/ ][Steel Bank Common Lisp (sbcl) ]]:
1. It configures =sly-default-lisp= and =sly-lisp-implementations= as in the
2022-01-24 04:27:47 +01:00
~sly~ documentation string instead of in the [[info:sly#Multiple Lisps ][multiple lisps (info) ]] manual.
2022-01-23 11:56:37 +01:00
2. It ensures the [[info:sly#Auto-SLY ][automatic connection to the lisp server (info) ]] when opening a
Common Lisp file.
3. It configures searching documentation in the [[http://www.lispworks.com/documentation/HyperSpec/Front/ ][Common Lisp HyperSpec ]] according
to the [[info:sly#Basic customization ][basic customization (info) ]] manual.
2022-01-24 04:27:47 +01:00
Finally, listing [[lst:configure-sly ]] uses a technique to [[info:sly#Loading Slynk faster ][load Slynk faster (info) ]]
by means of a custom core file in src_emacs-lisp{no-littering-var-directory}.
Listing [[lst:sbcl-core-for-sly ]] tangles to a script to dump such a [[http://www.sbcl.org/ ][SBCL ]] core.
2022-01-23 11:56:37 +01:00
#+caption[Configure =sly= ]:
#+caption : Configure =sly=.
#+name : lst:configure-sly
#+begin_src emacs-lisp
(with-eval-after-load 'sly
(custom-set-variables
;; Customize `sly-default-lisp' instead of `inferior-lisp-program',
;; because `sly' uses `inferior-lisp-program' only as a backwards
;; compatibility fallback option.
'(sly-default-lisp 'sbcl)
`(sly-lisp-implementations
'((sbcl (,(executable-find "sbcl")
"--core"
,(no-littering-expand-var-file-name "sbcl.core-for-sly"))))))
(add-hook 'sly-mode-hook
(defun on-sly-mode-hook ()
(unless (sly-connected-p)
(save-excursion (sly)))))
(cond
((eq system-type 'darwin)
(setq common-lisp-hyperspec-root
"file:///usr/local/share/doc/hyperspec/HyperSpec/ ")
(setq common-lisp-hyperspec-symbol-table
(concat common-lisp-hyperspec-root "Data/Map_Sym.txt")))
((eq system-type 'gnu/linux)
(setq common-lisp-hyperspec-root
"file:///usr/share/doc/hyperspec-7.0/HyperSpec/ "))
(t (message "Default Common Lisp HyperSpec access")))
(define-key sly-prefix-map (kbd "M-h") #'sly-documentation-lookup))
#+end_src
2022-01-24 04:27:47 +01:00
#+caption[Script to dump a SBCL core for the Sly Common Lisp IDE]:
#+caption : Script to dump a SBCL core for the Sly Common Lisp IDE.
#+header : :tangle-mode (identity #o755)
#+name : lst:sbcl-core-for-sly
#+begin_src shell :noeval :tangle ~/bin/sbcl.core-for-sly
#!/bin/sh
sbcl <<EOF
(mapc 'require '(sb-bsd-sockets sb-posix sb-introspect sb-cltl2 asdf))
(save-lisp-and-die "sbcl.core-for-sly")
EOF
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# sh-basic-offset: 2
# End:
#+end_src
*** [[https://courses.cs.northwestern.edu/325/][CS 325 AI Programming]]
:PROPERTIES:
:CUSTOM_ID: sec:quicklisp
:END:
The [[https://courses.cs.northwestern.edu/325/ ][CS 325 AI Programming ]] course allows to learn Common Lisp by self-study and
the page [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php ][CS 325: Setting up Lisp ]] gives instructions how to:
1. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#lisp ][Download and install common lisp ]].
2. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#quicklisp ][Install Quicklisp ]].
3. [[https://courses.cs.northwestern.edu/325/admin/lisp-setup.php#install-325 ][Install the CS325 library ]].
*** [[https://www.quicklisp.org/][Quicklisp]]
:PROPERTIES:
:CUSTOM_ID: sec:quicklisp
:END:
[[https://www.quicklisp.org/ ][Quicklisp ]] is a library manager for Common Lisp. Listing
[[lst:download+verify-quicklisp ]] downloads the [[https://www.quicklisp.org/ ][Quicklisp ]] file and verifies its
signature to prevent tampering. Listing [[lst:bootstrap-quicklisp ]] tangles to a
shell script allowing to bootstrap [[https://www.quicklisp.org/ ][Quicklisp ]] with [[http://www.sbcl.org/ ][SBCL ]]. Listing
[[lst:quicklisp-sbclrc-file ]] tangles to the a [[http://www.sbcl.org/ ][SBCL ]] resource file with [[https://www.quicklisp.org/ ][Quicklisp ]]
support.
#+caption[Download and verify =quicklisp= ]:
#+caption : Download and verify =quicklisp=.
#+name : lst:download+verify-quicklisp
#+begin_src shell :dir ~ :results none :tangle no
curl -sS -O https://beta.quicklisp.org/quicklisp.lisp
curl -sS -O https://beta.quicklisp.org/quicklisp.lisp.asc
curl -sS -O https://beta.quicklisp.org/release-key.txt
gpg --import release-key.txt
gpg --verify quicklisp.lisp.asc quicklisp.lisp
#+end_src
#+caption[Bootstrap =quicklisp= ]:
#+caption : Bootstrap =quicklisp=.
#+header : :tangle-mode (identity #o755)
#+name : lst:bootstrap-quicklisp
#+begin_src shell :noeval :tangle ~/bin/quicklisp-sbcl-bootstrap
#!/bin/sh
sbcl --load ~/quicklisp.lisp <<EOF
(quicklisp-quickstart:install)
(quit)
EOF
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# sh-basic-offset: 2
# End:
#+end_src
#+caption[A =quicklisp= sbclrc file]:
#+caption : A =quicklisp= sbclrc file.
#+name : lst:quicklisp-sbclrc-file
#+begin_src lisp :tangle ~/.sbclrc
;;; Hey Emacs, this is my -*- lisp -* - .sbclrc file.
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
#+end_src
2022-01-23 11:56:37 +01:00
2022-01-27 09:50:39 +01:00
** [[info:eintr#Top][Emacs Lisp Programming (info)]]
2022-01-01 11:42:28 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:emacs-lisp-programming
:END:
2022-01-27 09:50:39 +01:00
1. [[https://www.masteringemacs.org/article/evaluating-elisp-emacs ][Evaluating Elisp in Emacs ]]
2. [[https://endlessparentheses.com/debugging-emacs-lisp-part-1-earn-your-independence.html ][Debugging Elisp Part 1: Earn your independence ]]
3. [[https://endlessparentheses.com/debugging-elisp-part-2-advanced-topics.html ][Debugging Elisp Part 2: Advanced topics ]]
4. [[http://xahlee.info/talk_show/xah_talk_show_2022-01-20.html ][Xah talk show: Elisp coding: xah-add-space-after-comma ]]
5. [[http://xahlee.info/talk_show/xah_talk_show_2022-01-22.html ][Xah talk show: Elisp coding: narrow-to-region, sort-lines, hilight-unicode ]]
2022-01-01 11:42:28 +01:00
** [[https://www.seas.upenn.edu/~chaoliu/2017/09/01/python-programming-in-emacs/][Python programming]]
:PROPERTIES:
2022-01-23 11:56:37 +01:00
:CUSTOM_ID: sec:python-programming
2022-01-01 11:42:28 +01:00
: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 ]].
In my opinion, [[https://github.com/joaotavora/eglot ][eglot ]] has more potential than [[https://github.com/pythonic-emacs/anaconda-mode ][anaconda ]], but [[https://github.com/pythonic-emacs/anaconda-mode ][anaconda ]] is
2022-01-19 07:47:56 +01:00
compatible with [[info:org#Editing Source Code ][source code block editing ]] while [[https://github.com/joaotavora/eglot ][eglot ]] is not.
Here are a few links covering how to integrate Emacs, Python and a Python LSP
server, before plunging into the configuring steps:
1. [[https://taingram.org/blog/emacs-lsp-ide.html ][Building Your Own Emacs IDE with LSP ]]
2. [[https://rgoswami.me/posts/emacs-lang-servers/ ][Doom Emacs and Language Servers ]]
3. [[https://ddavis.io/posts/eglot-python-ide/ ][Eglot based Emacs Python IDE ]]
4. [[https://www.mattduck.com/lsp-python-getting-started.html ][Getting started with lsp-mode for Python ]]
5. [[https://ddavis.io/posts/python-emacs-3/ ][Python & Emacs, Take 3 ]]
6. [[https://ddavis.io/posts/emacs-python-lsp/ ][Python with Emacs: py(v)env and lsp-mode ]]
2022-01-01 11:42:28 +01:00
*** [[https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/progmodes/python.el][Python-mode]]
2022-01-04 13:10:26 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:python-mode
:END:
2022-01-19 07:47:56 +01:00
Listing [[lst:configure-python ]] tells the Python shell to disregard its environment
variables (in particular =PYTHONSTARTUPFILE= ).
2022-01-01 11:42:28 +01:00
#+caption[Configure =python= ]:
#+caption : Configure =python=.
#+name : lst:configure-python
2022-01-04 13:10:26 +01:00
#+begin_src emacs-lisp
2022-01-01 11:42:28 +01:00
(with-eval-after-load 'python
(custom-set-variables
'(python-indent-guess-indent-offset nil)
'(python-shell-interpreter-args "-i -E")))
#+end_src
2022-01-04 13:10:26 +01:00
*** [[https://github.com/pyenv/pyenv][Pyenv]]
:PROPERTIES:
:CUSTOM_ID: sec:pyenv
:END:
Listing [[lst:enable-pyenv-mode ]] configures and enables =pyenv-mode= .
#+caption[Enable =pyenv-mode= ]:
#+caption : Enable =pyenv-mode=.
#+name : lst:enable-pyenv-mode
#+begin_src emacs-lisp
(when (and (executable-find "pyenv")
(require 'pyenv-mode nil 'noerror))
(pyenv-mode +1)
2022-01-18 06:47:25 +01:00
(pyenv-mode-set "3.9.10/envs/python-3.9.10")
2022-01-18 05:02:43 +01:00
;; Stop shadowing the org-mode-map "C-c C-s" binding.
(define-key pyenv-mode-map (kbd "C-c C-s") nil))
2022-01-04 13:10:26 +01:00
#+end_src
2022-01-19 07:47:56 +01:00
2022-01-01 11:42:28 +01:00
*** [[https://github.com/joaotavora/eglot][Eglot]]
2022-01-04 13:10:26 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:eglot
:END:
2022-01-19 07:47:56 +01:00
Listing [[lst:configure-eglot+python-lsp-server-for-python ]] tangles to
=user-init-file= and configures [[https://github.com/joaotavora/eglot ][eglot ]] for [[https://www.python.org ][Python ]] using the [[https://github.com/python-lsp/python-lsp-server ][python-lsp-server ]].
In order to enable all builtin [[https://github.com/python-lsp/python-lsp-server ][python-lsp-server ]] capabilities, ensure
installation of the Python packages [[https://github.com/hhatto/autopep8#readme ][autopep8 ]], [[https://github.com/PyCQA/flake8 ][flake8 ]], [[https://github.com/PyCQA/pydocstyle#readme ][pydocstyle ]], [[https://github.com/PyCQA/pylint#readme ][pylint ]], [[https://github.com/python-rope/rope#readme ][rope ]],
and [[https://github.com/google/yapf#readme ][yapf ]]. In addition, install the [[https://github.com/emanspeaks/pyls-flake8#readme ][pyls-flake8 ]] plugin to let [[https://github.com/python-lsp/python-lsp-server ][python-lsp-server ]]
use [[https://github.com/PyCQA/flake8 ][flake8 ]].
Listing [[lst:on-hack-local-variables-hook-eglot-maybe ]] defines a hook function to
launch [[https://github.com/joaotavora/eglot ][eglot ]] in presence of a proper [[info:emacs#Directory Variables ][.dir-locals.el ]] file in the root directory
of any [[https://www.python.org ][Python ]] project. Listing [[lst:eglot-directory-variables-for-python ]] shows
such a proper [[info:emacs#Directory Variables ][.dir-locals.el ]] file.
2022-01-07 16:34:21 +01:00
#+caption[Configure =eglot= with =python-lsp-server= for Python]:
#+caption : Configure =eglot= with =python-lsp-server= for Python.
#+name : lst:configure-eglot+python-lsp-server-for-python
2022-01-01 11:42:28 +01:00
#+begin_src emacs-lisp
(with-eval-after-load 'eglot
2022-01-07 16:34:21 +01:00
;; (setq eglot-server-programs '((python-mode "pylsp")))
2022-01-01 11:42:28 +01:00
(add-to-list 'eglot-server-programs '(python-mode "pylsp"))
(setq-default
eglot-workspace-configuration
2022-01-19 07:47:56 +01:00
'(;; Disable the `:pyls_flake8' plugin to fall back to pycodestyle.
(:pylsp . (:plugins (:pyls_flake8 (:enabled t))))
(:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"]))))
(:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"])))))))
2022-01-07 16:34:21 +01:00
#+end_src
#+caption[Start =eglot= in case of a proper =dir-local-variables-alist= ]:
#+caption : Start =eglot= in case of a proper =dir-local-variables-alist=.
#+name : lst:on-hack-local-variables-hook-eglot-maybe
#+begin_src emacs-lisp
2022-01-01 11:42:28 +01:00
(when (fboundp 'eglot-ensure)
;; The two hooks `after-change-major-mode-hook' and
2022-01-07 16:34:21 +01:00
;; `hack-local-variables-hook' are OK, but language mode hooks like
;; `python-mode-hook' are not.
2022-01-01 11:42:28 +01:00
(add-hook 'hack-local-variables-hook
(defun on-hack-local-variables-hook-eglot-maybe ()
(when (and (derived-mode-p 'python-mode)
(assoc 'eglot-workspace-configuration
dir-local-variables-alist))
(eglot-ensure)))))
#+end_src
#+caption[Propose =directory-variables= to launch =eglot= ]:
#+caption : Propose =directory-variables= in the root of any Python project to
#+caption : launch =eglot=.
#+name : lst:eglot-directory-variables-for-python
2022-01-07 17:29:01 +01:00
#+begin_src emacs-lisp :tangle dir-locals.el
2022-01-01 11:42:28 +01:00
;; Proposal for a .dir-locals.el file in the root of any Python project.
((python-mode
. ((eglot-workspace-configuration
2022-01-19 07:47:56 +01:00
. (;; Disable the `:pyls_flake8' plugin to fall back to pycodestyle.
(:pylsp . (:plugins (:pyls_flake8 (:enabled t))))
(:pylsp . (:plugins (:jedi (:auto_import_modules ["numpy"]))))
(:pylsp . (:plugins (:jedi_completion (:cache_for ["astropy"])))))))))
#+end_src
Allthough the configuration of [[https://github.com/pythonic-emacs/blacken#readme ][blacken ]] is not explicit, I use it to format all
new Python code with the [[https://black.readthedocs.io/en/stable/index.html ][Python Black code formatter ]]. Listing
[[lst:pyproject-toml-kick-off ]] and [[lst:setup-cfg-kick-off ]] implement the rules in
[[https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html ][using black with other tools ]] in order to make [[https://flake8.pycqa.org/en/latest/ ][flake8 ]] or [[https://pycodestyle.pycqa.org/en/latest/ ][pycodestyle ]] agree with
[[https://black.readthedocs.io/en/stable/index.html ][black's uncompromising style ]].
#+caption[Kick starting a =pyproject.toml= file]:
#+caption : Kick starting a =pyproject.toml= file.
#+name : lst:pyproject-toml-kick-off
#+begin_src toml :tangle pyproject.toml
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[tool.black]
line-length = 88
#+end_src
#+caption[Kick starting a =setup.cfg= file]:
#+caption : Kick starting a =setup.cfg= file.
#+name : lst:setup-cfg-kick-off
#+begin_src toml :tangle setup.cfg
[flake8]
max-line-length = 88
extend-ignore = E203
[pycodestyle]
ignore = E203
max-line-length = 88
2022-01-01 11:42:28 +01:00
#+end_src
[[https://jedi.readthedocs.io/en/latest/ ][Jedi ]] provides grammar checking and completion candidates to [[https://github.com/python-lsp/python-lsp-server ][python-lsp-server ]].
2022-01-19 07:47:56 +01:00
Only [[https://jedi.readthedocs.io/en/latest/docs/changelog.html ][jedi-0.18.1 ]] works with for instance [[https://numpy.org/ ][numpy-1.22.0 ]] in the sense that it does
not choke on universal functions provided that [[https://jedi.readthedocs.io/en/latest/ ][jedi ]] does not parse but imports
[[https://numpy.org/ ][numpy-1.22.0 ]] (see [[https://github.com/davidhalter/jedi/issues/1744 ][jedi issue #1744 ]], [[https://github.com/davidhalter/jedi/issues/1745 ][#1745 ]], and [[https://github.com/davidhalter/jedi/issues/1746 ][#1746 ]]). Since the universal
functions are neither builtin methods nor data instances but a kind of "callable
instances", the [[https://docs.python.org/3/library/inspect.html ][Python inspect ]] module also fails to handle the universal
functions properly.
2022-01-12 20:19:22 +01:00
Listing [[lst:make-pylsp-server-patch ]] generates listing
[[lst:show-pylsp-server-patch ]] that shows the patch to make [[https://jedi.readthedocs.io/en/latest/ ][jedi ]] import
[[https://numpy.org/ ][numpy-1.22.0 ]] in order to serve the information to [[https://github.com/python-lsp/python-lsp-server ][python-lsp-server ]] allowing it
to handle universal functions. Listing [[lst:show-pylsp-server-patch ]] tangles to
=pylsp-auto-import-modules.patch= .
#+caption[Make =pylsp-auto-import-modules.patch= listing]:
#+caption : Make =pylsp-auto-import-modules.patch= listing.
#+name : lst:make-pylsp-server-patch
#+begin_src shell :exports both :results drawer :shebang
echo "#+attr_latex: :options breaklines"
echo "#+caption[Show and tangle =pylsp-auto-import-modules.patch= ]:"
echo "#+caption: Show and tangle =pylsp-auto-import-modules.patch= ."
echo "#+name: lst:show-pylsp-server-patch"
echo "#+begin_src diff :exports code :tangle pylsp-auto-import-modules.patch"
2022-01-01 11:42:28 +01:00
git -C $HOME/VCS/python-lsp-server diff
2022-01-12 20:19:22 +01:00
echo "#+end_src"
2022-01-01 11:42:28 +01:00
#+end_src
2022-01-12 20:19:22 +01:00
#+RESULTS : lst:make-pylsp-server-patch
:results:
#+attr_latex : :options breaklines
#+caption[Show and tangle =pylsp-auto-import-modules.patch= ]:
#+caption : Show and tangle =pylsp-auto-import-modules.patch=.
#+name : lst:show-pylsp-server-patch
2022-01-01 11:42:28 +01:00
#+begin_src diff :exports code :tangle pylsp-auto-import-modules.patch
diff --git a/pylsp/config/schema.json b/pylsp/config/schema.json
2022-01-07 16:34:21 +01:00
index c29d78b..4f30101 100644
2022-01-01 11:42:28 +01:00
--- a/pylsp/config/schema.json
+++ b/pylsp/config/schema.json
@@ -69,6 +69,14 @@
"default": null,
"description": "List of errors and warnings to enable."
},
+ "pylsp.plugins.jedi.auto_import_modules": {
+ "type": "array",
2022-01-07 16:34:21 +01:00
+ "default": ["numpy", "gi"],
2022-01-01 11:42:28 +01:00
+ "items": {
+ "type": "string"
+ },
+ "description": "List of module names for jedi to import (jedi.settings.auto_import_modules)."
+ },
"pylsp.plugins.jedi.extra_paths": {
"type": "array",
"default": [],
diff --git a/pylsp/workspace.py b/pylsp/workspace.py
2022-01-07 16:34:21 +01:00
index bf312f6..4758b53 100644
2022-01-01 11:42:28 +01:00
--- a/pylsp/workspace.py
+++ b/pylsp/workspace.py
@@ -14,6 +14,8 @@ from . import lsp, uris, _utils
log = logging.getLogger(__name__)
2022-01-07 16:34:21 +01:00
+DEFAULT_AUTO_IMPORT_MODULES = ["numpy", "gi"]
2022-01-01 11:42:28 +01:00
+
# TODO: this is not the best e.g. we capture numbers
RE_START_WORD = re.compile('[A-Za-z_0-9]*$')
RE_END_WORD = re.compile('^[A-Za-z_0-9]*')
@@ -252,6 +254,8 @@ class Document:
if self._config:
jedi_settings = self._config.plugin_settings('jedi', document_path=self.path)
+ jedi.settings.auto_import_modules = jedi_settings.get('auto_import_modules',
+ DEFAULT_AUTO_IMPORT_MODULES)
environment_path = jedi_settings.get('environment')
extra_paths = jedi_settings.get('extra_paths') or []
env_vars = jedi_settings.get('env_vars')
#+end_src
2022-01-12 20:19:22 +01:00
:end:
2022-01-01 11:42:28 +01:00
*** [[https://github.com/pythonic-emacs/anaconda-mode][Anaconda]]
2022-01-04 13:10:26 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:anaconda
:END:
2022-01-07 16:34:21 +01:00
Listing [[lst:configure-anaconda+company-for-python ]] and
[[lst:define-my-toggle-anaconda-mode ]] configure [[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 in listing
[[lst:configure-anaconda+company-for-python ]]. The call to [[info:elisp#Advising Functions ][advice-add ]] in listing
[[lst:define-my-toggle-anaconda-mode ]] opens Python =org-edit-src-code= buffers in
~anaconda-mode~ .
2022-01-01 11:42:28 +01:00
2022-01-07 16:34:21 +01:00
#+caption[Configure =anaconda= with =company= for Python]:
#+caption : Configure =anaconda= with =company= for Python.
#+name : lst:configure-anaconda+company-for-python
2022-01-01 11:42:28 +01:00
#+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)
(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)
(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
2022-01-07 16:34:21 +01:00
(if (file-remote-p default-directory) -1 1)))))))
#+end_src
2022-01-01 11:42:28 +01:00
2022-01-07 16:34:21 +01:00
#+caption[Define =my-toggle-anaconda-mode= for Python]:
#+caption : Define =my-toggle-anaconda-mode= for Python.
#+name : lst:define-my-toggle-anaconda-mode
#+begin_src emacs-lisp
(with-eval-after-load 'python
2022-01-01 11:42:28 +01:00
(unless (and (fboundp 'my-disable-anaconda-mode)
(fboundp 'my-enable-anaconda-mode))
(when (fboundp 'anaconda-mode)
(defun my-disable-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)
(anaconda-eldoc-mode
(if (file-remote-p default-directory) -1 1))))))
(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 ()
"Toggle anaconda-mode with bells and whistles."
(interactive)
(if (bound-and-true-p anaconda-mode)
(my-disable-anaconda-mode)
(my-enable-anaconda-mode)))))
#+end_src
*** [[https://jedi.readthedocs.io/en/latest/][Jedi]]
2022-01-04 13:10:26 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:jedi
:END:
2022-01-01 11:42:28 +01:00
Listing [[lst:example-py ]] is a [[https://www.python.org ][Python ]] example to test whether [[https://jedi.readthedocs.io/en/latest/ ][jedi ]] in combination
with and either [[https://github.com/pythonic-emacs/anaconda-mode ][anaconda ]] or [[https://github.com/joaotavora/eglot ][eglot ]] works when coding certain functions of for
instance [[https://numpy.org/ ][numpy ]] and [[https://scipy.org/ ][scipy ]].
#+caption[Tangle the =example.py= file]:
#+caption : Tangle the =example.py= file.
#+name : lst:example-py
#+begin_src python :tangle example.py
import numpy
import astropy.units as apu
a = numpy.arange(0, 11)
a = numpy.linspace(0, 10, num=11)
a = numpy.arccos(a)
q = apu.Quantity(a, apu.meter)
print(q)
#+end_src
*** TODO Look into: editing facilities
1. [[https://github.com/douglasdavis/numpydoc.el/blob/main/numpydoc.el ][Emacs extension to insert numpy style docstrings in function definitions ]]
2022-01-21 06:56:03 +01:00
* [[https://github.com/emacs-tw/awesome-emacs#library][Libraries]]
:PROPERTIES:
:CUSTOM_ID: sec:libraries
:END:
** [[info:dash.info#Top][Library dash.el (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:dash-library
:END:
The library [[info:dash.info#Top ][dash.el (info) ]]positions itself as a modern alternative for the list
processing API of [[info:cl#Top ][cl ]]. It is a requirement of several important packages in this
Emacs setup (for instance [[https://github.com/pythonic-emacs/anaconda-mode#readme ][anaconda ]], [[https://github.com/andras-simonyi/citeproc-el#readme ][citeproc ]], [[https://github.com/magit/magit#readme ][magit ]], and [[https://github.com/Fuco1/smartparens#readme ][smartparens ]]). Listing
[[lst:configure-dash ]] enables fontification of =dash= macros and makes
=info-lookup-symbol= take into account the =dash= macros.
#+caption[Configure =dash= fontification and info lookup]:
#+caption : Configure =dash= fontification and info lookup.
#+name : lst:configure-dash
#+begin_src emacs-lisp
(when (fboundp #'global-dash-fontify-mode)
(global-dash-fontify-mode))
(when (fboundp #'dash-register-info-lookup)
(with-eval-after-load 'info-look
(dash-register-info-lookup)))
#+end_src
** [[https://github.com/rejeep/f.el][Library f.el]]
:PROPERTIES:
:CUSTOM_ID: sec:s-library
:END:
The library [[https://github.com/rejeep/f.el ][f.el ]] positions itself as a modern API for working with files and
directories in Emacs. It is a requirement of several packages in this Emacs
setup ([[https://github.com/pythonic-emacs/anaconda-mode#readme ][anaconda ]], [[https://github.com/andras-simonyi/citeproc-el#readme ][citeproc ]], [[https://github.com/pythonic-emacs/pythonic#readme ][pythonic ]]) and requires no configuration.
** [[https://github.com/magnars/s.el][Library s.el]]
:PROPERTIES:
:CUSTOM_ID: sec:s-library
:END:
The library [[https://github.com/magnars/s.el ][s.el ]] positions itself as the long lost Emacs string manipulation
library. It is a requirement of several packages in this Emacs setup ([[https://github.com/pythonic-emacs/anaconda-mode#readme ][anaconda ]],
[[https://github.com/andras-simonyi/citeproc-el#readme ][citeproc ]], [[https://github.com/bdarcus/citar#readme ][citar ]], and [[https://github.com/pythonic-emacs/company-anaconda ][company-anaconda ]]) and requires no configuration.
2022-01-17 07:56:55 +01:00
* [[info:emacs#Minor Modes][Minor Modes (info)]]
2021-12-06 08:31:40 +01:00
:PROPERTIES:
2022-01-17 07:56:55 +01:00
:CUSTOM_ID: sec:minor-modes
2021-12-06 08:31:40 +01:00
:END:
2022-01-09 15:39:14 +01:00
** [[https://github.com/victorhge/iedit#readme][Synchronal multiple-region editing]]
:PROPERTIES:
:CUSTOM_ID: sec:synchronal-multiple-region-editing
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =iedit= ]:
#+caption : Enable =iedit=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-iedit
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(require 'iedit nil 'noerror))
#+end_src
2022-01-09 15:39:14 +01:00
** [[https://github.com/lewang/ws-butler#readme][Unobtrusive whitespace trimming]]
:PROPERTIES:
:CUSTOM_ID: sec:unobtrusive-whitespace-trimming
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Configure =ws-butler= ]:
#+caption : Configure =ws-butler=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-ws-butler
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
(when (require 'ws-butler nil 'noerror)
(custom-set-variables
'(ws-butler-keep-whitespace-before-point nil))
(add-hook 'prog-mode-hook #'ws-butler-mode)
(add-hook 'text-mode-hook #'ws-butler-mode)))
#+end_src
2022-01-01 11:42:28 +01:00
** [[https://countvajhula.com/2021/09/25/the-animated-guide-to-symex/][Structural editing]]
2021-12-16 09:00:35 +01:00
:PROPERTIES:
2021-12-29 10:05:06 +01:00
:CUSTOM_ID: sec:structural-editing
2021-12-16 09:00:35 +01:00
:END:
2021-11-29 13:14:56 +01:00
2021-12-29 10:05:06 +01:00
Structural editing keeps character pairs (for instance parentheses, curly and
2021-12-16 09:00:35 +01:00
square brackets as well as single and double quotes) balanced to leave code (for
instance Lisp and Python) and text (for instance LaTeX and Org) structure
intact. I use [[https://github.com/Fuco1/smartparens ][smartparens ]] which offers a normal mode (=smartparens-mode= ) and a
a strict mode (=smartparens-strict-mode= ). Although both modes insert character
2022-01-07 16:32:43 +01:00
pairs, the normal mode allows to delete one of the paired characters easily
2021-12-16 09:00:35 +01:00
while the strict mode does not. Therefore, the strict mode is more for code
editing since it never breaks programming language rules and the normal mode is
more for text editing where structure is a matter of convention instead of
programming language rules.
For instance, the strict mode in Python allows to delete entire lists, tuples,
or the arguments after the cursor (what Emacs calls =point= ) in a function call
without breaking the character pair balance. In order to repair a broken
character pair balance, insert a single character by prefixing it with "C-q"
bound to =quoted-insert= .
The [[https://smartparens.readthedocs.io/en/latest/index.html ][smartparens documentation ]] targets experienced Emacs users. The
following links show how to put the documentation to practical use:
1. [[https://gist.github.com/oantolin ][Omar Antolin's gist "my-smartparens-config.el" ]] is the first place to look for
how to tweak [[https://github.com/Fuco1/smartparens ][smartparens ]]. However, the gist may be partially obsolete, since
it is not part of his current [[https://github.com/oantolin/emacs-config ][Emacs configuration ]].
2. [[https://lists.gnu.org/archive/html/help-gnu-emacs/2014-07/msg00135.html ][How to enable smartparens in the minibuffer after eval-expression ]] explains
how the machinery after the first and after later usages of =eval-expression=
differ and discusses options how to handle those differences.
2021-12-23 15:29:03 +01:00
Listing [[lst:configure-smartparens ]] aims to configure [[https://github.com/Fuco1/smartparens ][smartparens ]] for Elisp,
LaTeX, Org, and Python.
2021-12-15 17:59:15 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Configure =smartparens= ]:
#+caption : Configure =smartparens=.
2021-12-28 08:48:03 +01:00
#+name : lst:configure-smartparens
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
2021-12-15 17:59:15 +01:00
;; To disables pairing of the quote character for lisp modes,
;; require smartparens-config instead of smartparens.
2021-11-29 13:14:56 +01:00
(when (require 'smartparens-config nil 'noerror)
(custom-set-variables
'(sp-base-key-bindings 'sp)
'(sp-override-key-bindings '(("C-(" . sp-backward-barf-sexp)
("C-)" . sp-forward-slurp-sexp))))
2022-01-23 11:56:37 +01:00
(dolist (hook '(prog-mode-hook text-mode-hook))
2021-12-15 17:59:15 +01:00
(add-hook hook #'smartparens-mode))
2021-11-29 13:14:56 +01:00
2021-12-15 17:59:15 +01:00
;; Hook on the specific `eval-expression-minibuffer-setup-hook'
;; and not on the general `minibuffer-setup-hook'.
2021-12-11 12:46:51 +01:00
(dolist (hook '(emacs-lisp-mode-hook
eval-expression-minibuffer-setup-hook
ielm-mode-hook
2022-01-23 11:56:37 +01:00
lisp-mode-hook
python-mode-hook
sly-mrepl-mode-hook))
2021-12-12 03:27:06 +01:00
(add-hook hook #'smartparens-strict-mode))
2021-11-29 13:14:56 +01:00
2021-12-16 09:00:35 +01:00
;; Tweak for the call to `smartparens-strict-mode' hooked on
;; `eval-expression-minibuffer-setup-hook'.
2021-12-15 17:59:15 +01:00
(sp-with-modes '(fundamental-mode ; first usage.
minibuffer-inactive-mode) ; later usage.
(sp-local-pair "'" nil :actions nil))
2021-11-29 13:14:56 +01:00
;; https://xenodium.com/emacs-smartparens-auto-indent/index.html
(defun indent-between-pair (&rest _ignored)
(newline)
(indent-according-to-mode)
(forward-line -1)
(indent-according-to-mode))
2022-01-07 16:32:43 +01:00
(dolist (left '("(" "[" "{"))
(sp-local-pair 'prog-mode left
nil :post-handlers '((indent-between-pair "RET"))))
2021-11-29 13:14:56 +01:00
(show-smartparens-global-mode +1)))
#+end_src
2022-01-09 15:39:14 +01:00
** [[https://github.com/davidshepherd7/electric-operator#readme][Electric operators]]
2021-12-06 08:32:39 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:electric-operators
:END:
2021-11-29 13:14:56 +01:00
2021-12-28 08:44:00 +01:00
Listing [[lst:configure-electric-operator-mode ]] configures =electric-operator-mode=
2021-12-29 10:05:06 +01:00
to add spaces around operators for compatibility with for instance the [[https://black.readthedocs.io/en/stable/ ][Black
code formatter for Python]].
2021-12-28 08:44:00 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Configure =electric-operator-mode= ]:
#+caption : Configure =electric-operator-mode=.
2021-12-28 08:44:00 +01:00
#+name : lst:configure-electric-operator-mode
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(when (fboundp 'electric-operator-mode)
(add-hook 'c-mode-common #'electric-operator-mode)
(add-hook 'python-mode-hook #'electric-operator-mode))
#+end_src
2022-01-09 15:39:14 +01:00
** [[https://joaotavora.github.io/yasnippet/][Smart snippets]]
2021-12-23 15:29:03 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:smart-snippets
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =yas-global-mode= ]:
#+caption : Enable =yas-global-mode=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-yas-global-mode
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(when (require 'yasnippet nil 'noerror)
(custom-set-variables
'(yas-alias-to-yas/prefix-p nil))
(yas-global-mode +1))
#+end_src
2022-01-17 07:56:55 +01:00
* [[info:emacs#Display][Display (info)]]
2022-01-09 15:39:14 +01:00
:PROPERTIES:
2022-01-17 07:56:55 +01:00
:CUSTOM_ID: sec:display
2022-01-09 15:39:14 +01:00
:END:
2021-12-29 14:05:03 +01:00
2022-01-17 07:56:55 +01:00
** [[info:emacs#Narrowing][Narrowing]]
:PROPERTIES:
:CUSTOM_ID: sec:narrowing
:END:
Narrowing means focusing in on some portion of the buffer and widening means
focussing out on the whole buffer. This allows to concentrate temporarily on
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. Here, the function =narrow-or-widen-dwim= operates also
on tables by means of =org-narrow-to-table= .
#+caption[Configure =narrow-or-widen-dwim= ]:
#+caption : Configure =narrow-or-widen-dwim=.
#+name : lst:configure-narrow-or-widen-dwim
#+begin_src emacs-lisp
(defun org-narrow-to-table ()
"Narrow buffer to current table."
(interactive)
(if (org-table-p)
(narrow-to-region (org-table-begin) (org-table-end))
(user-error "Not in a table")))
(defun narrow-or-widen-dwim (p)
"Widen if buffer is narrowed, narrow-dwim otherwise.
Dwim means: region, org-src-block, org-subtree, or defun,
whichever applies first. Narrowing to org-src-block actually
calls `org-edit-src-code'.
With prefix P, don't widen, just narrow even if buffer is
already narrowed."
(interactive "P")
(declare (interactive-only))
(cond ((and (buffer-narrowed-p) (not p)) (widen))
((and (bound-and-true-p org-src-mode) (not p))
(org-edit-src-exit))
((region-active-p)
(narrow-to-region (region-beginning) (region-end)))
((derived-mode-p 'org-mode)
(or (ignore-errors (org-edit-src-code))
(ignore-errors (org-narrow-to-block))
(ignore-errors (org-narrow-to-table))
(org-narrow-to-subtree)))
((derived-mode-p 'latex-mode)
(LaTeX-narrow-to-environment))
((derived-mode-p 'tex-mode)
(TeX-narrow-to-group))
(t (narrow-to-defun))))
(define-key ctl-x-map (kbd "n t") #'org-narrow-to-table)
(define-key ctl-x-map (kbd "C-n") #'narrow-or-widen-dwim)
#+end_src
2022-01-25 11:28:05 +01:00
** [[info:emacs#Faces][Text faces or styles (info)]]
2022-01-09 15:39:14 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:text-faces-or-styles
:END:
2021-11-29 13:14:56 +01:00
2022-01-18 07:26:09 +01:00
This setup does not configure [[info:emacs#Custom Themes ][custom themes (info) ]] in order to prevent endless
useless tweaking. See the [[https://protesilaos.com/codelog/2020-09-05-emacs-note-mixed-font-heights/ ][note on mixed font heights in Emacs ]] for how to setup
fonts properly. It boils down to two rules:
2021-12-07 05:35:31 +01:00
1. The height of the default face must be an integer number to make the height a
physical quantity.
2. The heights of all other faces must be real numbers to scale those heights
with respect to the height of the face (those heights default to 1.0 for no
scaling).
2021-12-23 15:29:03 +01:00
The code in listing [[lst:configure-face-attributes ]] source implements those rules.
2022-01-09 15:39:14 +01:00
In case of proper initialization of all face heigths, font scaling is easy as
listing [[lst:my-set-default-face-height ]] shows. Finally, the code in listing
[[lst:my-invert-default-face ]] allows swapping the foreground and background colors
2022-01-25 11:28:05 +01:00
of the default face on all frames.
2021-12-07 05:35:31 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Configure =face-attributse= ]:
#+caption : Configure =face-attributes=.
2021-12-28 08:42:19 +01:00
#+name : lst:configure-face-attributes
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
;; 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
2021-12-23 15:29:03 +01:00
#+caption[Implement =my-set-default-face-height= ]:
#+caption : Implement =my-set-default-face-height=.
2021-12-28 08:42:19 +01:00
#+name : lst:my-set-default-face-height
2021-12-07 05:35:31 +01:00
#+begin_src emacs-lisp
2021-12-28 08:42:19 +01:00
(unless noninteractive
(defun my-set-default-face-height ()
"Set the default face height in all current and future frames.
2021-12-07 05:35:31 +01:00
Scale all other faces with a height that is a real number."
2021-12-28 08:42:19 +01:00
(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))))
2021-12-07 05:35:31 +01:00
#+end_src
2021-12-23 15:29:03 +01:00
#+caption[Implement =my-invert-default-face= ]:
#+caption : Implement =my-invert-default-face=.
2021-12-28 08:42:19 +01:00
#+name : lst:my-invert-default-face
2021-12-13 12:41:06 +01:00
#+begin_src emacs-lisp
2021-12-28 08:42:19 +01:00
(unless noninteractive
(defun my-invert-default-face ()
"Invert the default face."
(interactive)
2022-01-25 15:28:39 +01:00
(invert-face 'default)
(tweak-region-face-background-color)))
2021-12-13 12:41:06 +01:00
#+end_src
2021-12-29 14:05:03 +01:00
** [[https://jblevins.org/log/rainbow-mode][Visualize color codes and names]]
2022-01-09 15:39:14 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:rainbow-mode
:END:
2021-12-29 14:05:03 +01:00
Listing [[lst:enable-rainbow-mode ]] enables =rainbow-mode= to colorize color codes
and names in buffers for debugging.
2021-12-13 12:41:06 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =rainbow-mode= ]:
#+caption : Enable =rainbow-mode=.
2021-12-28 08:42:19 +01:00
#+name : lst:enable-rainbow-mode
2021-12-13 12:41:06 +01:00
#+begin_src emacs-lisp
(when (fboundp 'rainbow-mode)
(custom-set-variables
'(rainbow-x-colors-major-mode-list
'(c++-mode
c-mode
emacs-lisp-mode
inferior-emacs-lisp-mode
java-mode
lisp-interaction-mode
org-mode
python-mode)))
(rainbow-mode +1))
#+end_src
2021-12-29 14:05:03 +01:00
** [[https://karthinks.com/software/batteries-included-with-emacs/][Flash the line around point for visual feedback]]
2022-01-09 15:39:14 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:flash-line-around-point
:END:
2021-12-29 14:05:03 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Implement =my-pulse-one-line= ]:
#+caption : Implement =my-pulse-one-line=.
2021-12-28 08:48:03 +01:00
#+name : lst:my-pulse-one-line
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(unless noninteractive
;; https://karthinks.com/software/batteries-included-with-emacs/
;; https://www.reddit.com/r/emacs/comments/jwhr6g/batteries_included_with_emacs/
(defun my-pulse-one-line (&rest _)
"Pulse the current line."
(let ((pulse-iterations 16)
(pulse-delay 0.1))
(pulse-momentary-highlight-one-line (point))))
(dolist (command '(scroll-up-command
scroll-down-command
recenter-top-bottom
other-window))
(advice-add command :after #'my-pulse-one-line)))
#+end_src
* Applications
2022-01-09 15:39:14 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:applications
:END:
2021-11-29 13:14:56 +01:00
2022-01-09 15:39:14 +01:00
** [[https://github.com/skeeto/elfeed#readme][Elfeed: Emacs web feed reader]]
:PROPERTIES:
:CUSTOM_ID: sec:emacs-web-feed-reader
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =elfeed= ]:
#+caption : Enable =elfeed=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-elfeed
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(autoload 'elfeed "elfeed" nil t)
(global-set-key (kbd "C-x w") #'elfeed)
(with-eval-after-load 'elfeed
(custom-set-variables
'(elfeed-feeds
'(("http://www.howardism.org/index.xml" h-abrams)
("https://ambrevar.xyz/atom.xml" p-neirhardt)
("https://emacshorrors.com/feed.atom" v-schneidermann)
("https://emacsninja.com/emacs.atom" v-schneidermann)
("https://feeds.feedburner.com/InterceptedWithJeremyScahill" j-scahill)
("https://nullprogram.com/feed/ " c-wellons)
("https://oremacs.com/atom.xml" o-krehel)
("https://planet.emacslife.com/atom.xml" planet-emacs)
("https://protesilaos.com/codelog.xml" p-stavrou)
("https://sachachua.com/blog/category/emacs/feed" s-chua)
("https://sciencescitoyennes.org/feed/ " sciences)
("https://updates.orgmode.org/feed/updates" org-updates)
("https://www.aclu.org/taxonomy/feed-term/2152/feed" aclu)
("https://www.bof.nl/rss/ " bof)
("https://www.democracynow.org/podcast-video.xml" dn)
("https://www.laquadrature.net/fr/rss.xml" lqdn)
("https://www.lemonde.fr/blog/huet/feed/ " sciences)))))
#+end_src
2022-01-09 15:39:14 +01:00
** [[info:emms#Top][Emacs Multimedia System (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:emacs-multimedia-system
:END:
2021-11-29 13:14:56 +01:00
2021-12-23 15:29:03 +01:00
#+caption[Enable =emms= ]:
#+caption : Enable =emms=.
2021-12-28 08:48:03 +01:00
#+name : lst:enable-emms
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(custom-set-variables
'(emms-mode-line-format "")
'(emms-player-list '(emms-player-mpd emms-player-mpv))
`(emms-player-mpd-music-directory ,(expand-file-name "~/Music"))
'(emms-player-mpd-server-name "localhost")
'(emms-player-mpd-server-port "6600")
'(emms-player-mpd-verbose t)
'(emms-playing-time-display-format " %s ")
'(emms-playlist-mode-center-when-go t))
(defun my-emms-print-metadata-find ()
(require 'find-func)
(locate-file
"emms-print-metadata"
(expand-file-name
"src"
(file-name-directory (find-library-name "emms")))
exec-suffixes #'file-executable-p))
(with-eval-after-load 'emms
(require 'emms-info-libtag)
(let ((emms-print-metadata (my-emms-print-metadata-find)))
(when emms-print-metadata
(custom-set-variables
'(emms-info-functions nil)
`(emms-info-libtag-program-name ,emms-print-metadata))
(add-hook 'emms-info-functions #'emms-info-libtag))))
(with-eval-after-load 'elfeed-show
(when (require 'emms-setup nil 'noerror)
(emms-all)))
(autoload 'emms-streams "emms-streams" nil 'interactive)
(with-eval-after-load 'emms-streams (emms-all))
#+end_src
* [[info:emacs#Init File][Init File (info)]] footer
:PROPERTIES:
2021-12-23 15:29:03 +01:00
:CUSTOM_ID: sec:user-init-file-footer
2021-11-29 13:14:56 +01:00
:END:
2021-12-23 15:29:03 +01:00
#+caption[Tangle the =user-init-file= footer]:
#+caption : Tangle the =user-init-file= footer.
2021-12-28 08:48:03 +01:00
#+name : lst:tangle-user-init-file-footer
2021-11-29 13:14:56 +01:00
#+begin_src emacs-lisp
(provide 'init)
2021-11-30 09:35:15 +01:00
;; Emacs looks for "Local variables:" after the last "?\n?\f".
2021-11-29 13:14:56 +01:00
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;;; init.el ends here
#+end_src
2021-12-23 15:29:03 +01:00
* Local variables linking to [[#sec:latexmk-save-compile-display-loop][Latexmk save-compile-display-loop]]
2021-11-29 13:14:56 +01:00
:PROPERTIES:
2021-11-30 09:35:15 +01:00
:CUSTOM_ID: sec:local-variables
2021-11-29 13:14:56 +01:00
:END:
2021-11-30 18:44:54 +01:00
Only the [[info:org#Top ][Org ]] source file shows the local variables footer.
2021-11-29 13:14:56 +01:00
2021-11-30 09:35:15 +01:00
# Emacs looks for "Local variables:" after the last "\?n\?f".
2021-11-29 13:14:56 +01:00
# Local Variables:
# compile-command: "latexmk -interaction=nonstopmode -lualatex -pvc -shell-escape README.tex"
2021-11-30 09:35:15 +01:00
# eval: (apply 'my-org-eval-blocks-named '("emacs-lisp-setup"))
2021-11-29 13:14:56 +01:00
# fill-column: 80
# End: