emacs.d/README.org

1324 lines
54 KiB
Org Mode
Raw Normal View History

2021-11-29 13:14:56 +01:00
#+startup: content
#+title: Emacs setup for use with LaTeX, Org, and Python
#+author: Gerard Vermeulen
#+babel: :cache no
#+property: header-args :tangle init.el :comments link
#+property: header-args:emacs-lisp :results silent
#+latex_class: article
#+latex_class_options: [11pt,a4paper,svgnames]
#+latex_header: \hypersetup{
#+latex_header: citecolor=blue,
#+latex_header: colorlinks=true,
#+latex_header: filecolor=blue,
#+latex_header: hyperfootnotes=false,
#+latex_header: linkcolor=blue,
#+latex_header: unicode=true,
#+latex_header: urlcolor=blue
#+latex_header: }
#+latex_header: \usepackage{minted}
#+latex_header: \usemintedstyle{xcode}
#+latex_header: \usepackage[
#+latex_header: headheight=20mm,
#+latex_header: top=40mm,
#+latex_header: bottom=20mm,
#+latex_header: left=0.1\paperwidth,
#+latex_header: right=0.1\paperwidth,
#+latex_header: heightrounded,
#+latex_header: verbose,
#+latex_header: ]{geometry}
* Quick start
:PROPERTIES:
:CUSTOM_ID: sec:quick-start
:END:
Backup your =~/.emacs.d= directory to execute the following commands:
#+begin_src shell :noeval :tangle no
cd ~
git clone ccdr@mercury.grenoble.cnrs.fr:SERVER/.emacs.d
make --directory=.emacs.d init
#+end_src
After its invokation, Emacs will install a minimal set of packages. Now, you
have the option to install all optional packages using the command
=my-install-optional-packages=, but you can do this any time, or you can install
any package using the command =package-install= whenever you like. Quit Emacs
and invoke Emacs again.
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)
illustrates my work-flow by showing:
1. How to tangle (or export) source blocks from [[info:org#Top][org]] files. This file contains
source blocks to produce the files =early-init.el=, =init.el=, =latexmkrc=,
=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
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-05 16:25:38 +01:00
5. [[https://github.com/purcell/emacs.d][Steve Purcell's configuration]] is well organized and a show-case of readable
2021-11-29 13:14:56 +01:00
[[info:elisp#Top][Emacs lisp (info)]] code. I have stolen his idea of versioning the
~package-user-dir~ variable to prevent clashes between the byte-compiler
output of different Emacs versions.
2021-12-05 16:25:38 +01:00
6. [[https://github.com/tecosaur/emacs-config][Timothy E. Chapman's configuration]]
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-05 16:35:35 +01:00
The configuration inhibits enabling of [[info:emacs#Packages][Emacs' package management system]] at
startup in order to get more control in the [[#sec:package-bootstrapping][Package Bootstrapping]] section.
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp :tangle early-init.el
;;; early-init.el --- user early-init file -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(setq package-enable-at-startup nil)
(setq-default load-prefer-newer t)
(provide 'early-init)
;; 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
* [[info:emacs#Init File][Init File (info)]] header
:PROPERTIES:
:CUSTOM_ID: sec:init-file-header
:END:
The [[info:elisp#Quoting][quoting (info)]] and the [[info:elisp#Backquote][backquote (info)]] pages explain how to understand the
reader macros ~'~ (quote), ~`~ (backquote), ~,~ (substitute) and ~@,~ (splice)
2021-12-05 16:36:49 +01:00
in the ~custom-set-variable~ function call below. A tutorial of how to use those
reader macro's is the [[https://mullikine.github.io/posts/macro-tutorial/][didactic emacs-lisp macro example]].
Because of the ~custom-set-variable~ function call, the [[info:emacs#Init File][init file (info)]] does
not load the ~custom-file~ as [[info:emacs#Saving Customizations][saving customizations (info)]] recommends.
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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)
`(custom-file
,(locate-user-emacs-file
(format "custom-%s.%s.el" emacs-major-version emacs-minor-version)))
'(epg-pinentry-mode 'loopback)
'(global-hl-line-mode t)
'(global-hl-line-sticky-flag t)
'(history-delete-duplicates t)
'(history-length 500)
'(indent-tabs-mode nil)
'(inhibit-startup-buffer-menu t)
'(inhibit-startup-screen t)
'(initial-buffer-choice t)
'(initial-scratch-message "")
`(insert-directory-program ,(or (executable-find "gls")
(executable-find "ls")))
'(kill-ring-max 300)
'(package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/")))
`(package-user-dir
,(locate-user-emacs-file
(format "elpa-%s.%s" emacs-major-version emacs-minor-version)))
'(python-indent-guess-indent-offset nil)
2021-11-29 13:14:56 +01:00
'(recentf-mode t)
'(save-place-mode t)
'(savehist-additional-variables
'(eww-history
kill-ring
regexp-search-string
search-ring
search-string))
'(savehist-mode t)
'(savehist-save-minibuffer-history 1)
'(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
* Package bootstrapping
:PROPERTIES:
:CUSTOM_ID: sec:package-bootstrapping
:END:
[[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-11-29 13:14:56 +01:00
3. The [[https://melpa.org/#/][MELPA - Milkypostmans Emacs Lisp Package Archive]].
Finally, the [[https://github.com/quelpa/quelpa][quelpa]] tool allows to fetch code from any source and build a
package on your computer before installation.
2021-11-29 13:14:56 +01:00
The output of the byte-compiler may change with each new Emacs release.
Therefore, in order to prevent collisions between different Emacs versions, the
package-user-directory has a suffix containing the major- and minor-version
numbers of Emacs.
The order of the next 1nd, 2nd, and 3rd package-bootstrapping blocks matters
because each of those blocks prepares Emacs for the next block.
If present, the package [[https://github.com/emacscollective/no-littering][no-littering]] helps to keep =~/.emacs.d= clean.
The code assumes that the package system is in a *virgin* state in case the
package [[https://github.com/emacscollective/no-littering][no-littering]] is not present. Refreshing the contents of available
packages at least once is a requirement in order to be able to install and load
any packages, hence also [[https://github.com/emacscollective/no-littering][no-littering]].
You have to refresh the list of available packages yourself before updating
the installed packages.
Finally, ~my-install-packages~ facilitates installation of all packages in a
list of packages.
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
;; The is the 1st package bootstrapping block.
(require 'package)
(package-initialize)
(unless (require 'no-littering nil 'noerror)
(package-refresh-contents)
(package-install 'no-littering)
(require 'no-littering))
(defun my-install-packages (packages)
"Ensure installation of all packages in PACKAGES."
(dolist (package packages)
(unless (package-installed-p package)
(package-install package))))
#+end_src
Install the basic packages and in case this is Emacs-27.2, upgrade [[https://orgmode.org/][Org Mode]] for
compatibility with Emacs-28.1. 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 definition of ~my-packages~ variable
below.
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
;; The is the 2nd package bootstrapping block.
(defvar my-packages
`(
,@(when (version< emacs-version "28.0")
'(org)) ; plain text thought organizer
anaconda-mode ; strangles python-mode
2021-11-29 13:14:56 +01:00
auctex ; Aalborg University Center TeX
blacken ; Black Python-code formatter client
citar ; bibliography handling
citeproc ; bibliography handling
company-anaconda ; complete anything in anaconda-mode
2021-11-29 13:14:56 +01:00
consult ; consult completing-read
eglot ; Emacs polyGLOT LSP client
2021-11-29 13:14:56 +01:00
embark ; act on any buffer selection
htmlize ; convert buffer contents to HTML
leuven-theme ; beautiful color theme
marginalia ; minibuffer margin notes
orderless ; Emacs completion style
pdf-tools ; interactive docview replacement
pyenv-mode ; Python environment selector
quelpa ; install Emacs packages from source
vertico) ; VERTical Interactive Completion
"List of packages required packages.")
(my-install-packages my-packages)
#+end_src
Facilitate installlation of the optional packages.
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
;; The is the 3rd package bootstrapping block.
2021-11-29 13:14:56 +01:00
(defvar my-optional-packages
`(
,@(when (version< emacs-version "28.0")
'(modus-themes)) ; high foreground/background contrast themes
2021-11-29 13:14:56 +01:00
async ; asynchroneous processing
company ; complete anything
electric-operator ; automatic spacing around operators
elfeed ; web feed reader
emms ; Emacs Multi-Media System
iedit ; simultaneous multi-entity editing
laas ; LaTeX Auto-Activating Snippets
magit ; Git Text-based User Interface
markdown-mode ; markdown text mode
2021-11-29 13:14:56 +01:00
nov ; EPUB reader
rainbow-mode ; set background color to color string
2021-11-29 13:14:56 +01:00
smartparens ; smart editing of character pairs
toml-mode ; Tom's Obvious Minimal Language mode
2021-11-29 13:14:56 +01:00
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
yasnippet)) ; code or text template expansion
(defun my-install-optional-packages ()
(interactive)
(my-install-packages my-optional-packages))
#+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
command =emacsclient=.
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(when window-system
(unless (or noninteractive (daemonp))
(add-hook 'after-init-hook #'server-start)))
#+end_src
2021-12-05 16:39:07 +01:00
The next two configuration blocks show how to use ~emacsclient~ to:
1. Install an asynchronous (or background) loop of saving a LaTeX file,
compiling it, and redisplaying the output in Emacs.
2. Make [[https://qutebrowser.org][qutebrowser]] send html links with document titles to Emacs.
** LaTeX save-compile-display loop
2021-11-29 13:14:56 +01:00
:PROPERTIES:
2021-12-05 16:39:07 +01:00
:CUSTOM_ID: sec:latex-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
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
=pdf= files) shows how to use the =latexmkrc= file..
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
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-11-30 18:04:16 +01:00
$clean_ext .= " acr acn alg bbl glo gls glg ist run.xml";
2021-11-29 13:14:56 +01:00
sub makeglossaries {
my ($name, $path) = fileparse( $$Psource );
return system "makeglossaries -d '$path' '$name'";
}
# 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
** [[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.
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+header: :comments none
#+header: :tangle-mode (identity #o755)
#+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
* 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-05 16:40:20 +01:00
Finally, [[https://company-mode.github.io/][company: a modular complete-anything framework for Emacs]] fills another
niche than the five packages above.
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
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(unless noninteractive
(when (fboundp 'vertico-mode)
(vertico-mode +1)))
#+end_src
2021-12-05 16:40:20 +01:00
** [[info:orderless#Top][Orderless (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:orderless-configuration
:END:
#+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
** [[info:embark#Top][Embark (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:embark-configuration
:END:
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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)
(global-set-key (kbd "C-x M-:") #'consult-complex-command)
(global-set-key (kbd "C-x b") #'consult-buffer)
(global-set-key (kbd "C-x 4 b") #'consult-buffer-other-window)
(global-set-key (kbd "C-x 5 b") #'consult-buffer-other-frame)
(global-set-key (kbd "C-x r x") #'consult-register)
(global-set-key (kbd "C-x r b") #'consult-bookmark)
;; M-g bindings (goto-map)
(global-set-key (kbd "M-g g") #'consult-goto-line)
(global-set-key (kbd "M-g M-g") #'consult-goto-line)
(global-set-key (kbd "M-g o") #'consult-outline)
(global-set-key (kbd "M-g m") #'consult-mark)
(global-set-key (kbd "M-g k") #'consult-global-mark)
(global-set-key (kbd "M-g i") #'consult-imenu-project)
(global-set-key (kbd "M-g e") #'consult-error)
;; M-s bindings (search-map)
(global-set-key (kbd "M-s g") #'consult-git-grep)
(global-set-key (kbd "M-s f") #'consult-find)
(global-set-key (kbd "M-s k") #'consult-keep-lines)
(global-set-key (kbd "M-s l") #'consult-line)
(global-set-key (kbd "M-s m") #'consult-multi-occur)
(global-set-key (kbd "M-s u") #'consult-focus-lines)
;; 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
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
python-mode-hook
ielm-mode-hook))
(add-hook hook #'company-mode))))
#+end_src
* Reading
** EPUB files
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(when (fboundp 'nov-mode)
(add-to-list 'auto-mode-alist `(,(rx ".epub" eos) . nov-mode)))
#+end_src
** PDF files
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
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.
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(when (fboundp 'pdf-tools-install)
(autoload 'pdf-view-mode "pdf-view")
(add-to-list 'magic-mode-alist '("%PDF" . pdf-view-mode)))
#+end_src
* Writing
** LaTeX
Loading =tex.el= immediately instead of lazily ensures proper initialization of
the [[https://en.wikipedia.org/wiki/AUCTeX][AUCTeX]]. For instance, the ~TeX-master~ safe local variable in the =tex.el=
elisp library file has no autoload cookie. Without prior loading of =tex.el=,
Emacs will complain that ~TeX-master~ is no safe local variable in case it
reads a LaTeX file that sets ~TeX-master~.
Out of the box, [[https://en.wikipedia.org/wiki/AUCTeX][AUCTeX]] does not indent text between square brackets. The code
below corrects this by advising to override ~TeX-brace-count-line~ with
~my-TeX-brace-count-line~.
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
;; Try to get the `safe-local-variable` predicate for `TeX-master`
(when (require 'tex nil 'noerror)
;; https://emacs.stackexchange.com/questions/17396/indentation-in-square-brackets
(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)))
(advice-add 'TeX-brace-count-line :override #'my-TeX-brace-count-line))
#+end_src
** Org-mode
*** [[info:org#Activation][Activation (info)]]
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
*** Customization
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(custom-set-variables
'(org-babel-python-command "python -E")
'(org-babel-load-languages '((C . t)
(calc . t)
(dot . t)
(emacs-lisp . t)
(eshell . t)
(fortran . t)
(gnuplot . t)
(latex . t)
(lisp . t)
(maxima . t)
(org . t)
(perl . t)
(python . t)
(scheme . t)
(shell . t)))
'(org-cite-export-processors '((latex biblatex)
(t csl)))
'(org-cite-global-bibliography '("~/VCS/research/refs.bib"))
'(org-file-apps '((auto-mode . emacs)
(directory . emacs)
("\\.mm\\'" . default)
("\\.x?html?\\'" . default)
("\\.pdf\\'" . emacs)))
'(org-confirm-babel-evaluate nil)
'(org-latex-compiler "lualatex")
'(org-latex-hyperref-template nil)
'(org-latex-listings 'minted)
'(org-latex-logfiles-extensions '("blg" "lof" "log" "lot" "out" "toc"))
'(org-latex-prefer-user-labels t)
'(org-modules '(ol-bibtex
ol-doi
ol-eww
ol-info
org-id
org-protocol
org-tempo))
'(org-src-fontify-natively t)
'(org-structure-template-alist
'(("a" . "export ascii")
("c" . "center")
("C" . "comment")
("e" . "example")
("E" . "export")
("h" . "export html")
("l" . "export latex")
("q" . "quote")
("s" . "src")
("p" . "src python :session :async")
("v" . "verse"))))
#+end_src
2021-12-05 16:40:20 +01:00
*** [[info:org#External Links][Export external links (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:export-external-links
:END:
In order to export the [[info:org#External Links][info links (info)]] in this document to =html= correctly,
modify the constant ~org-info-other-documents~ defined in =ol-info.el=.
Note: how to make it work without tangling?
#+begin_src emacs-lisp
(add-hook
'org-mode-hook
(lambda ()
(when (boundp 'org-info-other-documents)
(dolist (recipe '(("consult" . "https://github.com/minad/consult")
("embark" . "https://github.com/oantolin/embark")
("marginalia" . "https://github.com/minad/marginalia")
("orderless" . "https://github.com/oantolin/orderless")
("vertico" . "https://github.com/minad/vertico")))
(cl-pushnew recipe org-info-other-documents :test #'equal)))))
#+end_src
2021-11-29 13:14:56 +01:00
*** [[info:org#Citation export processors][Citation export processors (info)]]
2021-12-05 16:40:20 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:citation-export-processors
:END:
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(with-eval-after-load 'oc
(require 'oc-biblatex)
(require 'oc-csl))
#+end_src
2021-12-05 17:02:39 +01:00
*** [[https://tecosaur.github.io/emacs-config/#translate-capital-keywords][Convert keywords to lower case]]
:PROPERTIES:
:CUSTOM_ID: sec:convert-keywords-to-lower-case
:END:
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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-05 17:02:39 +01:00
*** [[info:org#Advanced Export Configuration][Advanced export configuration (info)]]
:PROPERTIES:
:CUSTOM_ID: sec:advanced-export-configuration
:END:
2021-11-29 13:14:56 +01:00
Stolen from [[https://git.sr.ht/~bzg/org-contrib/tree/master/item/lisp/ox-extra.el][ox-extra.el]]
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(with-eval-after-load 'ox
(defun my-org-export-ignore-headline-filter (_)
"Ignore all headlines with the \":ignore:\" tag."
(org-map-entries
(lambda ()
(delete-region (point) (line-beginning-position 2)))
":ignore:"))
2021-11-29 13:14:56 +01:00
(defun my-org-latex-header-blocks-filter (backend)
"Convert marked LaTeX export blocks to \"#+latex_header: \" lines.
The marker is a line \"#+header: :header yes\" preceding the block.
For instance, the LaTeX export block
,#+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))))))
;; Set point to where to insert LaTeX header lines after
;; deleting the block.
(mapc (lambda (block)
(goto-char (org-element-property :post-affiliated block))
(let ((lines
(split-string (org-element-property :value block) "\n")))
(delete-region (org-element-property :begin block)
(org-element-property :end block))
(dolist (line lines)
(insert (concat "#+latex_header: "
(replace-regexp-in-string "\\` *" "" line)
"\n")))))
;; Reverse to go upwards to avoid wrecking the numeric
;; positions earlier in the file.
(reverse blocks)))))
(defun my-activate-buffer-local-org-export-filters ()
"Activate my export filters locally in the current buffer."
(add-hook 'org-export-before-parsing-hook
#'my-org-export-ignore-headline-filter nil 'local)
(add-hook 'org-export-before-parsing-hook
#'my-org-latex-header-blocks-filter nil 'local)))
#+end_src
#+name: emacs-lisp-setup
#+begin_src emacs-lisp :tangle no
(with-eval-after-load 'ox
(my-activate-buffer-local-org-export-filters))
2021-11-29 13:14:56 +01:00
#+end_src
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(with-eval-after-load 'ox-latex
(mapc (lambda (item)
(add-to-list 'org-latex-classes item))
'(;; The postfixes +1, +2, +3, -1, -2, and -3 denote:
;; +1 => [DEFAULT-PACKAGES]
;; +2 => [PACKAGES]
;; +3 => [EXTRA]
;; -1 => [NO-DEFAULT-PACKAGES]
;; -2 => [NO-PACKAGES]
;; -3 => [NO-EXTRA]
("elsarticle-1+2+3" ; Elsevier journals
"\\documentclass{elsarticle}
[NO-DEFAULT-PACKAGES]
[PACKAGES]
[EXTRA]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
("article-1+2+3"
"\\documentclass{article}
[NO-DEFAULT-PACKAGES]
[PACKAGES]
[EXTRA]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
("report-1+2+3"
"\\documentclass[11pt]{report}
[NO-DEFAULT-PACKAGES]
[PACKAGES]
[EXTRA]"
("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
("book-1+2+3"
"\\documentclass[11pt]{book}
[NO-DEFAULT-PACKAGES]
[PACKAGES]
[EXTRA]"
("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))))
#+end_src
*** Evaluate source blocks on loading
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(defun my-org-eval-blocks-named (name)
"Evaluate all source blocks named NAME."
(when (eq major-mode 'org-mode)
2021-11-30 11:58:15 +01:00
(let ((blocks
(org-element-map
(org-element-parse-buffer 'greater-element nil) 'src-block
(lambda (block)
(when (string= name (org-element-property :name block))
block)))))
(dolist (block blocks)
(goto-char (org-element-property :begin block))
(org-babel-execute-src-block)))))
2021-11-29 13:14:56 +01:00
;; Emacs looks for "Local variables:" after the last "?\n?\f".
2021-11-29 13:14:56 +01:00
(add-to-list 'safe-local-eval-forms
2021-11-29 14:09:51 +01:00
'(apply 'my-org-eval-blocks-named '("emacs-lisp-setup")))
2021-11-29 13:14:56 +01:00
(add-to-list 'safe-local-eval-forms
'(apply 'my-org-eval-blocks-named '("python-setup")))
#+end_src
** Citing bibliography
:PROPERTIES:
:CUSTOM_ID: sec:citing-bibliography
:END:
[[https://github.com/bdarcus/citar][Citar]] provides a completing-read front-end to browse and act on BibTeX,
BibLaTeX, and CSL JSON bibliographic data, and LaTeX, markdown, and org-cite
editing support.
[[https://github.com/bdarcus/citar][Citar]] -- in combination with vertico, embark, and marginalia -- provides quick
filtering and selecting of bibliographic entries from the minibuffer, and the
option to run different commands on those selections.
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(when (cl-every #'fboundp '(citar-insert-citation
citar-insert-preset
citar-org-activate
citar-org-follow
citar-org-insert))
(custom-set-variables
'(org-cite-activate-processor 'citar)
'(org-cite-follow-processor 'citar)
'(org-cite-insert-processor 'citar))
(global-set-key (kbd "C-c b") #'citar-insert-citation)
(define-key minibuffer-local-map (kbd "M-b") #'citar-insert-preset))
#+end_src
* Editing
** Synchronal multiple-region editing
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(unless noninteractive
(require 'iedit nil 'noerror))
#+end_src
** Extraneous whitespace trimming
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
** Smart character-pair handling
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(unless noninteractive
(when (require 'smartparens-config nil 'noerror)
;; Requiring smartparens-config disables pairing of the quote
;; character for lisp modes, contrary to requiring smartparens.
(custom-set-variables
'(sp-base-key-bindings 'sp)
'(sp-override-key-bindings '(("C-(" . sp-backward-barf-sexp)
("C-)" . sp-forward-slurp-sexp))))
(add-hook 'LaTeX-mode-hook #'turn-off-smartparens-mode)
(add-hook 'prog-mode-hook #'turn-on-smartparens-mode)
(add-hook 'text-mode-hook #'turn-on-smartparens-mode)
(add-hook 'emacs-lisp-mode-hook #'turn-on-smartparens-strict-mode)
(add-hook 'ielm-mode-hook #'turn-on-smartparens-strict-mode)
(add-hook 'python-mode-hook #'turn-on-smartparens-strict-mode)
;; 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))
(sp-local-pair 'prog-mode "(" nil :post-handlers '((indent-between-pair "RET")))
(sp-local-pair 'prog-mode "[" nil :post-handlers '((indent-between-pair "RET")))
(sp-local-pair 'prog-mode "{" nil :post-handlers '((indent-between-pair "RET")))
(show-smartparens-global-mode +1)))
#+end_src
** Operators
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
** Smart snippets
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
* Coding
#+begin_src emacs-lisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs '(python-mode "pylsp"))
(setq-default
eglot-workspace-configuration
`((:pylsp . (:plugins (:jedi_completion (:eager nil))))
(:pylsp . (:plugins (:jedi_completion (:cache_for ,(vconcat '("astropy"
"numpy"
"scipy")))))))))
2021-11-29 13:14:56 +01:00
#+end_src
** Python coding
The [[https://www.emacswiki.org/emacs/PythonProgrammingInEmacs][Python Programming in Emacs]] wiki page lists options to enhance Emacs's
built-in ~python-mode~. Here, the focus is on two packages:
1. [[https://github.com/pythonic-emacs/anaconda-mode][Anaconda - code navigation, documentation lookup, and completion for Python]].
2. [[https://github.com/joaotavora/eglot][Eglot - Emacs polyGLOT: an Emacs LSP client that stays out of your way]]. The
2021-11-29 13:14:56 +01:00
maintainer also contributes to Emacs itself and has a deep understanding of
[[https://sheer.tj/the_way_of_emacs.html][the Way of Emacs]]. He refuses to add new features without seeing how they fit
into [[https://sheer.tj/the_way_of_emacs.html][the Way of Emacs]] as this discussion on [[https://github.com/joaotavora/eglot/issues/523][org-mode source code blocks]]
shows.
The snippet below initializes [[https://github.com/pythonic-emacs/anaconda-mode][anaconda]]. See [[https://github.com/jorgenschaefer/elpy/blob/8d0de310d41ebf06b22321a8534546447456870c/elpy.el#L2775][elpy-module-company]] for how to
handle ~company-backends~ as a local variable and the call to ~advice~ opens
Python org-mode edit-buffers in ~anaconda-mode~.
#+begin_src emacs-lisp
(with-eval-after-load 'python
(with-eval-after-load 'company
(when (and (fboundp 'anaconda-mode)
(fboundp 'company-anaconda))
(defun my-disable-anaconda-mode ()
(when (derived-mode-p 'python-mode)
(anaconda-mode -1)
(set (make-local-variable 'company-backends)
(delq 'company-anaconda
(mapcar #'identity company-backends)))
(anaconda-eldoc-mode -1)))
(defun my-enable-anaconda-mode ()
(when (derived-mode-p 'python-mode)
(anaconda-mode +1)
(set (make-local-variable 'company-backends)
(cons 'company-anaconda
(delq 'company-semantic
(delq 'company-capf
(mapcar #'identity company-backends)))))
(anaconda-eldoc-mode
(if (file-remote-p default-directory) -1 1))))))
(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 ()
(interactive)
(if (bound-and-true-p anaconda-mode)
(my-disable-anaconda-mode)
(my-enable-anaconda-mode)))))
#+end_src
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src python :tangle example.py :comments link
import numpy
import astropy.units as apu
a = numpy.arange(0, 11)
2021-11-29 13:14:56 +01:00
a = numpy.linspace(0, 10, num=11)
q = apu.Quantity(a, apu.meter)
print(q)
#+end_src
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(custom-set-variables
'(python-shell-interpreter-args "-i -E"))
(when (and (executable-find "pyenv")
(require 'pyenv-mode nil 'noerror))
(pyenv-mode +1)
2021-12-03 15:28:37 +01:00
(pyenv-mode-set "3.9.9/envs/python-3.9.9"))
2021-11-29 13:14:56 +01:00
#+end_src
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(with-eval-after-load 'info
(add-to-list 'Info-directory-list
(expand-file-name "~/.local/share/info")))
#+end_src
Look into:
1. [[https://github.com/douglasdavis/numpydoc.el/blob/main/numpydoc.el][Emacs extension to insert numpy style docstrings in function definitions]]
* Appearance
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
This setup prefers the ~leuven~ and ~leuven-dark~ themes from [[https://melpa.org/#/][MELPA]], because the
very popular ~modus-operandi~ and ~modus-vivendi~ themes feel quirky: for
instance those themes fail to display ~hl-line-mode~ with Emacs-27.2 on Darwin.
[[https://emacs.stackexchange.com/questions/17431/how-do-i-change-portions-of-a-custom-theme][How to change custom theme faces]]
2021-11-29 13:14:56 +01:00
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(unless noninteractive
;; Try to detect `leuven-theme` from MELPA.
(when (fboundp 'leuven-scale-font)
(custom-set-variables
'(leuven-scale-org-agenda-structure 1.0)
'(leuven-scale-org-document-title 1.0)
'(leuven-scale-outline-headlines 1.0)
'(leuven-scale-volatile-highlight 1.0)))
(defun my-leuven-hook-function ()
(when (member 'leuven custom-enabled-themes)
(let ((custom-inhibit--theme-enable nil)
(ol1 (list :height 1.0 :weight 'bold
:foreground "#3C3C3C" :background "#F0F0F0"))
(ol2 (list :height 1.0 :weight 'bold
:foreground "#123555" :background "#E5F4FB")))
(custom-theme-set-faces
'leuven
`(font-latex-sectioning-2-face ((t ,ol1)))
`(font-latex-sectioning-3-face ((t ,ol2)))
`(info-title-1 ((t ,ol1)))
`(markdown-header-face-1 ((t ,ol1)))
`(markdown-header-face-2 ((t ,ol2)))
`(org-level-1 ((t ,ol1)))
`(org-level-2 ((t ,ol2)))
`(outline-1 ((t ,ol1)))
`(outline-2 ((t ,ol1)))))
(enable-theme 'leuven)))
(load-theme 'leuven 'no-confirm nil)
(dolist (hook '(Info-mode-hook
latex-mode-hook
markdown-mode-hook
org-mode-hook
outline-mode-hook))
(add-hook hook #'my-leuven-hook-function)))
2021-11-29 13:14:56 +01:00
#+end_src
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp :tangle no
(unless noninteractive
(custom-set-variables
'(modus-themes-hl-line 'underline)
'(modus-themes-intense-markup 't))
(when (and (version< emacs-version "28.0")
(require 'modus-themes nil 'noerror))
(modus-themes-load-themes)))
#+end_src
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
** Feed reader
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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
** Multi-media system
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+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:
:CUSTOM_ID: sec:init-file-footer
:END:
#+attr_latex: :options bgcolor=LightGoldenrodYellow
#+begin_src emacs-lisp
(provide 'init)
;; 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-05 16:40:20 +01:00
* Local variables linking back to [[#sec:latex-save-compile-display-loop][LaTeX save-compile-display-loop]]
2021-11-29 13:14:56 +01:00
:PROPERTIES:
:CUSTOM_ID: sec:local-variables
2021-11-29 13:14:56 +01:00
:END:
Only the [[info:org#Top][Org]] source file shows the local variables footer.
2021-11-29 13:14:56 +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"
# eval: (apply 'my-org-eval-blocks-named '("emacs-lisp-setup"))
2021-11-29 13:14:56 +01:00
# fill-column: 80
# End: