2023-09-18 18:45:14 +02:00
#+title : Spacemacs
2021-10-20 13:57:46 +02:00
#+setupfile : ../headers
2020-12-07 18:34:48 +01:00
#+PROPERTY : header-args: :mkdirp yes :lexical t
2020-01-30 01:53:20 +01:00
2023-09-18 18:45:14 +02:00
* Spacemacs
2021-10-20 13:57:46 +02:00
#+begin_center
*Before proceeding, be aware that I deprecated this i3 config on October 20th 2021, meaning I won’ t update it anymore unless I use it again some day in the future. I will keep it on my website though.*
#+end_center
2021-06-09 17:38:26 +02:00
This file is the main source file for my Spacemacs configuration which
contains most of the user code. It is exported thanks to Emacs’ code
tangling from the original Org file which you can find on my dotfiles’
repository[fn: 1 ] if you are reading the web version of it. You can
also find there my ~.spacemacs~ [fn:2] and its code which isn’ t part of
the present file. As you can see in my ~.spacemacs~ , at init-time, if
Emacs detects the tangled configuration files are older than the Org
file, then Emacs tangles them again, and then loads them.
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
** Spacemacs layers and packages
2020-11-14 02:21:26 +01:00
:PROPERTIES:
2021-04-21 22:00:50 +02:00
:header-args:emacs-lisp: :mkdirp yes :tangle ~/.emacs.spacemacs/private/spacemacs-layers.el :exports code :results silent :lexical t
2020-11-14 02:21:26 +01:00
:END:
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp :exports none
2021-10-12 11:31:20 +02:00
;; -*- lexical-binding: t -* -
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Here will be our layer configuration set. Everything here is set with a
~setq-default~ in the ~dotspacemacs/layers~ function like so:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :tangle no
2021-10-12 11:31:20 +02:00
(defun dotspacemacs/layers ()
(setq-default
;; configuration goes here
))
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** General configuration
2021-02-04 14:43:09 +01:00
First, we need to tell Spacemacs which base distribution we are using. This is a
layer contained in the directory ~+distribution~ . For now, available
distributions are ~spacemacs-base~ and ~spacemacs~ (the default one).
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-distribution 'spacemacs)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
We can seet a lazy installation of layers —i.e. layers are installed only when a
file with a supported type is opened. Possible values are:
- ~all~ :: will lazy install any layer that support lazy installation even the
layers listed in ~dotspacemacs-configuration-layers~
- ~unused~ :: will lazy install only unused layers (i.e. layers not listed in
the variable ~dotspacemacs-configuration-layers~ )
- ~nil~ :: disables the lazy installation feature and you have to explicitly
list a layer in the variable ~dotspacemacs-configuration-layers~ to install
it.
2020-11-13 00:39:34 +01:00
The default value is ~unused~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-enable-lazy-installation nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If the following variable is non-nil, Spacemacs will ask for confirmation before
installing a layer lazily. The default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-ask-for-lazy-installation t)
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Package management
2021-02-04 14:43:09 +01:00
It is possible to indicate to Spacemacs a list of additional paths where to look
for configuration layers. Paths must have a trailing slash, i.e.
=~/.mycontribs/= . As you can see, I added only one:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-configuration-layer-path
'("~/fromGIT/emacs-packages"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-30 01:53:20 +01:00
2021-02-04 14:43:09 +01:00
However, I do have additional packages I installed either from the Elpa or the
Melpa. These are set in ~dotspacemacs-additional-packages~ , a list of additional
packages that will be installed without being wrapped in a layer. If I need some
configuration for these packages, then I should consider creating a layer. I can
also puth the configuration in ~dotspacemacs/user-config~ . To use a local
version of a package, use the ~:location~ property, for instance:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :tangle no
2021-10-12 11:31:20 +02:00
'(your-package :location "~/path/to/your-package/ ")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
With the variable ~dotspacemacs-additional-packages~ , it is possible to install
extra packages which are not already included in any layers. Dependencies should
be explicitly included as they won’ t be resolved automatically. Here is a table
of all the extra packages I use:
2020-11-13 00:39:34 +01:00
#+NAME : extra-packages
2021-01-08 03:38:31 +01:00
| name of the package | why is it installed |
|----------------------------+--------------------------------------------------------|
| caddyfile-mode | Major mode for editing Caddyfiles |
| dired-git-info | Git information in Dired buffers |
| diredfl | Extra font lock rules for a more colourful dired |
| edit-indirect | edit region in separate buffer |
| elcord | rich integration of Emacs in Discord |
| eshell-syntax-highlighting | Syntax highlighting for Eshell |
| info-colors | Extra colors for Emacs's Info-mode |
| multiple-cursors | I don’ t like the layer, I prefer this package alone |
2021-01-18 01:42:09 +01:00
| ob-latex-as-png | Inline arbitrary LaTeX snippets as PNGs in Emacs |
2021-01-08 03:38:31 +01:00
| org-sidebar | display on the side the outline of an Org buffer |
| org-tree-slide | presentation tool for org-mode |
| outorg | edit comments as Org-mode buffers |
2021-02-04 09:21:24 +01:00
| ox-ssh | SSH config export for org-mode |
2021-01-08 03:38:31 +01:00
| pinentry | enter a GPG password from Emacs |
| nord-theme | An arctic, north-bluish clean and elegant Emacs theme. |
| s | The long lost Emacs string manipulation library. |
| sicp | Texinfo version of the [[https://mitpress.mit.edu/sites/default/files/sicp/index.html][SICP]] |
2021-05-21 14:36:38 +02:00
| visual-fill-column | allow the use of ~fill-column~ in ~visual-line-mode~ |
2021-01-08 03:38:31 +01:00
| wrap-region | easily wrap region with delimiters |
| wttrin | weather in Emacs |
| yasnippet-snippets | snippets for YaSnippet |
2020-11-13 00:39:34 +01:00
#+name : make-extra-pkg
#+begin_src emacs-lisp :var packages=extra-packages[,0] :tangle no :exports none
2021-10-12 11:31:20 +02:00
(mapcar 'make-symbol packages)
2020-11-13 00:39:34 +01:00
#+end_src
#+begin_src emacs-lisp :noweb yes :exports none
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-additional-packages '<<make-extra-pkg() >>)
2020-11-13 00:39:34 +01:00
#+end_src
It is possible to also list packages that cannot be updated:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-frozen-packages '(helm-icons))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
And to list packages which won’ t be installed nor loaded:
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-excluded-packages '(company-tern))
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Finally, it is possible to define the behaviour of Spacemacs when installing
packages. Possible values are:
- ~used-only~ :: installs only explicitly used packages and deletes any unused
packages as well as their unused dependencies
- ~used-but-keep-unused~ :: installs only the used packages but won’ t delete
unused ones
- ~all~ :: installs *all* packages supported by Spacemacs and never uninstalls
them.
2020-11-13 00:39:34 +01:00
The default value is ~used-only~ .
#+BEGIN_SRC emacs-lisp
2020-12-19 17:24:17 +01:00
(setq-default dotspacemacs-install-packages 'used-only)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Layers
2021-02-04 14:43:09 +01:00
All layers are set one variable: ~dotspacemacs-configuration-layers~ . This
variable is a list of layers, some of them will have some custom variables.
Typically, the variable will be set like so:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :tangle no
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-configuration-layers
'(emacs-lisp
helm
multiple-cursors
org
(shell :variables shell-default-height 30
shell-default-position 'bottom)
treemacs))
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
# Don’ t delete this code block, it wraps the layers
#+BEGIN_SRC emacs-lisp :exports none
(setq-default dotspacemacs-configuration-layers '(
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Checkers
2021-02-04 14:43:09 +01:00
The two first checkers I use are for spell and syntax checking. ~spell-checking~
is disabled by default, however it should auto-detect the dictionary to use.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(spell-checking :variables
spell-checking-enable-by-default nil
spell-checking-enable-auto-dictionary t)
syntax-checking
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Completion
2021-02-04 14:43:09 +01:00
~auto-completion~ is a layer enabled in order to provide auto-completion to all
supported language layers. It is set so that the =RET= key has no behavior with
this layer, however the =TAB= key cycles between candidates displayed by the
auto-completion toolbox. I also want the autocompletion to include snippets in
the popup, and the content of the popup is sorted by usage. It is also disabled
for two modes: magit and Org.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(auto-completion :variables
auto-completion-complete-with-key-sequence-delay 0.2
auto-completion-enable-help-tooltip 'manual
auto-completion-enable-sort-by-usage t
:disabled-for
org
git)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
~helm~ is also enabled, with its header disabled.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(helm :variables helm-no-header t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Email
2021-02-04 14:43:09 +01:00
I use as my daily Email client ~mu4e~ , so let’ s enable it and tell Emacs where
mu4e is installed. I also tell mu4e to use maildirs extensions, use async
operations, where to keep attachments, and enable the mu4e modeline.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(mu4e :variables
mu4e-installation-path "/usr/share/emacs/site-lisp"
mu4e-use-maildirs-extension t
mu4e-enable-mode-line t
mu4e-attachment-dir "~/Documents/mu4e")
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Emacs
2021-02-04 14:43:09 +01:00
The first layer enabled in this category is ~better-defaults~ . I also made it so
that when a command equivalent to ~C-a~ or ~C-e~ is pressed, the cursor will
respectively first move to the beginning of code first before going past the
indentation and to the end of the code before going to the end of the line
before going over the end of the comments on the same line.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(better-defaults :variables
better-defaults-move-to-beginning-of-code-first t
better-defaults-move-to-end-of-code-first t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
I also enabled ~ibuffer~ and made it so that buffers are sorted by projects.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(ibuffer :variables
ibuffer-group-buffers-by 'projects)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Most important of all, the ~org~ layer is also enabled. I enabled support for
Epub exports, Github, Reveal.JS exports, and sticky headers. Project support is
also enabled through files named ~TODOs.org~ . I also set the org-download folder
for images in =~/Pictures/org/= , and I set the =RET= key to follow org links if
the cursor is on one.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(org :variables
org-enable-epub-support t
org-enable-github-support t
org-enable-hugo-support t
org-enable-reveal-js-support t
org-enable-sticky-header t
org-enable-appear-support t
spaceline-org-clock-p t
org-projectile-file "TODOs.org"
org-download-image-dir "~/Pictures/org/ "
org-return-follows-link t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
The ~semantic~ layer is also enabled.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
semantic
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** File trees
2021-02-04 14:43:09 +01:00
In this category, I only enabled one layer: ~treemacs~ . In this layer, I set is
so that treemacs syncs with my current buffer, and it automatically refreshes
its buffer when there is a change in the part of the file system shown by
treemacs.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(treemacs :variables
treemacs-use-follow-mode t
treemacs-use-filewatch-mode t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Fonts
2021-02-04 14:43:09 +01:00
In this category, again, one layer is enabled: ~unicode-fonts~ . This layer
addssupport for the ~unicode-fonts~ package.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(unicode-fonts :variables
unicode-fonts-enable-ligatures t
unicode-fonts-ligature-modes '(prog-mode)
unicode-fonts-ligature-set '("|||>" "<|||" "<== >" "<!--" "####" "~~ >" "***" "||=" "||>"
":::" "::=" "= :=" "= ==" "= =>" "= !=" "= >>" "=<<" "= /=" "!= ="
"!!." ">=>" ">>= " ">>>" ">>-" ">->" "->>" "-->" "---" "-<<"
"<~~" "<~ >" "<* >" "<||" "<| >" "<$ >" "<==" "<= >" "<=<" "<- >"
"<--" "<-<" "<<=" "<<-" "<<<" "<+ >" "</ >" "###" "#_(" "..<"
"..." "+++" "/==" "/ //" "_|_ " "www" "&&" "^=" "~~" "~@" "~= "
"~>" "~ -" "**" "* >" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
"[|" "]#" "::" ":=" ":>" ":<" "$>" "= =" "= >" "!=" "!!" ">:"
">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~ " "<*" "<|" "<:"
"<$" "<=" "<>" "<-" "<<" "<+" "</" "#{" "#[" "#:" "#= " "#!"
"##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "+ +" "?:"
"?=" "?." "??" ";;" "/*" "/= " "/>" "/ /" "__" "~~" "(*" "* )"
"\\\\" "://"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Fun
2020-11-13 00:39:34 +01:00
In this category, I only enabled two layers: ~selectric~ and ~xkcd~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
selectric xkcd
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Internationalization
2021-02-04 14:43:09 +01:00
In this category, I enabled the ~keyboard-layout~ layer to enable compatibility
with the bépo layout. This layer, however, is disabled for magit, Dired and eww.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(keyboard-layout :variables
kl-layout 'bepo
kl-disabled-configurations '(magit dired eww))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Programming languages
***** Domain-specific (DSLs)
2021-02-04 14:43:09 +01:00
In this category, I enabled support for the ~major-modes~ layer for the Arch
Linux PKGBUILDs support, ~emacs-lisp~ and ~scheme~ layers, support for the CSV
format with the ~csv~ layer, the ~yaml~ language, shell scripting languages and
support for the ~dot~ tool with the ~graphviz~ layer.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
major-modes emacs-lisp scheme graphviz yaml shell-scripts
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
I also added support for HTML and CSS with the ~html~ layer, with the web
formatting tool set to ~web-beautify~ , and the LSP layer compatibility enabled
for CSS, less, SCSS and HTML.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(html :variables
web-fmt-tool 'web-beautify
css-enable-lsp t
less-enable-lsp t
scss-enable-lsp t
html-enable-lsp t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
The ~json~ layer is also enabled, with the format tool set to ~web-beautify~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(json :variables
json-fmt-tool 'web-beautify)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The LaTeX layer has also been enabled, with its default compiler set to XeLaTeX.
I also enabled the auto-fill feature, the folding capacity and the “magic”
symbols.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(latex :variables
latex-build-command "xelatex"
latex-enable-auto-fill t
latex-enable-folding t
latex-enable-magic t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The Markdown layer has been enabled, with support for live preview with ~vmd~ ,
and and automatic MMM-mode generation for C, C++, Python, Rust and Emacs Lisp.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(markdown :variables
markdown-live-preview-engine 'vmd
markdown-mmm-auto-modes '("c"
"c++"
"python"
"rust"
("elisp" "emacs-lisp")))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
PlantUML is a very useful DSL for creating UML diagrams from some text
description. As you can see below, this layer will be enabled, both as a
standalone mode for opening ~.pum~ files, but also for org-mode code blocks.
2020-12-05 16:10:25 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(plantuml :variables
plantuml-jar-path "~/.local/bin/plantuml.jar"
org-plantuml-jar-path "~/.local/bin/plantuml.jar")
2020-12-05 16:10:25 +01:00
#+END_SRC
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(bibtex :variables
org-ref-default-bibliography '("~/Documents/Papers/references.bib")
org-ref-pdf-directory "~/Documents/Papers"
org-ref-bibliography-notes "~/Documents/Papers/notes.org")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-04-29 17:51:15 +02:00
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
csv
2020-12-05 16:10:25 +01:00
#+END_SRC
2020-04-29 17:51:15 +02:00
2023-09-18 18:45:14 +02:00
***** Frameworks
2021-02-04 14:43:09 +01:00
Only one framework support has been enabled so far, and is is for the Django
framework.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
django
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
***** General-purpose
2021-02-04 14:43:09 +01:00
Among the layers I activated, the only one without any specific configuration is
the ~asm~ layer for the Assembly language.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
asm
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Next, you can find the C/C++ layer for which I set the default language for ~.h~
files to be C. I also enabled support for subprojects and organization of the
include directives on a file save. I also set a couple of LSP-related variables,
such as the LSP executable for C/C++ for its CCLS backend and some highlight
variables.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(c-c++ :variables
c-c++-default-mode-for-headers 'c-mode
c-c++-adopt-subprojects t
c-c++-enable-c+ +11 t
c-c++-backend 'lsp-clangd
c-c++-lsp-enable-semantic-highlight t
c-c++-lsp-semantic-highlight-method 'overlay
c-c++-lsp-semantic-highlight-rainbow t
c++-enable-organize-includes-on-save t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Dart has also been enabled, with a custom path to the SDK of the Dart server,
and to the LSP server of Dart.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(dart :variables
lsp-dart-project-sdk-dir "/opt/dart-sdk/ "
lsp-dart-sdk-dir "/opt/dart-sdk/ ")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
When it comes to the Python layer, I set its backend and formatter to be bound
to the LSP layer. Its fill columnn was also set to 80 characters, imports are
sorted on save, and the tests can be run using either nose.el or pytest.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(python :variables
python-fill-column 80
python-test-runner '(pytest nose))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
With the Rust layer, the only custom configuration set is the backend being
bound to the LSP layer.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(rust :variables rust-backend 'lsp)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
As regards the JavaScript layer, I set its backend to the LSP layer, and bound
its format tool to ~web-beautify~ and its REPL is browser-based. I also want to
include ~node_modules/.bin~ to be automatically added to the buffer local
~exec_path~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(javascript :variables
javascript-backend 'lsp
javascript-fmt-tool 'web-beautify
javascript-repl 'skewer
node-add-modules-path t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Alternatively, I also use Typescript which is a sort of better Javascript as it
should have been, with the LSP backend.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(typescript :variables
typescript-backend 'lsp)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-05-17 15:04:07 +02:00
2021-02-04 14:43:09 +01:00
I am also currently using the Awesome window manager which requires the Lua
programming language, so here it is.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(lua :variables
lua-backend 'lsp-emmy
lua-lsp-emmy-jar-path "~/.config/awesome/EmmyLua-LS-all.jar"
lua-lsp-emmy-java-path "java"
lua-lsp-emmy-enable-file-watchers t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-03-25 13:10:10 +01:00
2021-05-21 14:01:15 +02:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(php :variables php-backend 'lsp)
2021-05-21 14:01:15 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Readers
***** Epub and Pdf readers
2021-02-04 14:43:09 +01:00
In this category, only the ~epub~ and ~pdf~ layers are enabled without any
special configuration, so I can read these files from Emacs directly.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
epub pdf
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-04-14 21:56:40 +02:00
2023-09-18 18:45:14 +02:00
***** Elfeed
2021-02-04 14:43:09 +01:00
Elfeed is an Emacs feeed and RSS reader which can be managed through org files.
Actually, through only one file in my case, located in my =~/org= directory.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(elfeed :variables
rmh-elfeed-org-files '("~/org/elfeed.org"))
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Version control
2021-02-04 14:43:09 +01:00
Only the ~git~ layer is enabled in this category.
#+BEGIN_SRC emacs-lisp
git
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Themes
2021-02-04 14:43:09 +01:00
Here, the ~colors~ layer is the only one enabled. It activates support for
identifiers colorization, and strings representing colors.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
colors
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Tools
2021-02-04 14:43:09 +01:00
In this category, the first layer to be enabled is the CMake layer for which I
enabled support for the ~cmake-ide~ package.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(cmake :variables
cmake-enable-cmake-ide-support t)
2021-02-04 14:43:09 +01:00
#+END_SRC
Next, we have the Docker, Nginx, Pass (the standard Unix password manager),
2021-03-31 16:24:54 +02:00
Prettier, Systemd, Meson, Imenu-list, Web-beautify, Dap, and Helpful.
2021-02-04 14:43:09 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
dap docker helpful imenu-list meson nginx pass prettier systemd web-beautify
2021-03-31 16:24:54 +02:00
#+END_SRC
Of course, let’ s not forget about the awesome LSP layer:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(lsp :variables lsp-lens-enable t
lsp-use-lsp-ui t
lsp-rust-server 'rust-analyzer)
2021-02-04 14:43:09 +01:00
#+END_SRC
We also have the RestClient layer enabled for which I enabled the Org
compatibility support.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(restclient :variables
restclient-use-org t)
2021-02-04 14:43:09 +01:00
#+END_SRC
LanguageTool works with Flyspell and will check for grammatical issues in my
english texts.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(languagetool :variables
langtool-default-language "en-US"
languagetool-show-error-on-jump t
langtool-java-classpath "/usr/share/languagetool:/usr/share/java/languagetool/ *")
2021-02-04 14:43:09 +01:00
#+END_SRC
And finally, we also have the Shell layer for which I specified its default
height when spawning at the bottom of the screen should be 40 lines high, and
the default shell to invoke is Eshell.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(shell :variables
shell-default-height 40
shell-default-position 'bottom
shell-default-shell 'eshell)
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Web Services
2021-02-04 14:43:09 +01:00
In this category, I have only enabled a layer for Twitter support.
#+BEGIN_SRC emacs-lisp
twitter
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Custom layers
2021-02-04 14:43:09 +01:00
Lastly, one custom layers have been enabled: my custom layer for conlanging
tools.
2020-12-07 17:39:33 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
conlanging
2020-12-07 17:39:33 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
# Don’ t delete this code block, it wraps the layers
#+BEGIN_SRC emacs-lisp :exports none
))
#+END_SRC
2023-09-18 18:45:14 +02:00
** Init
2020-11-14 02:21:26 +01:00
:PROPERTIES:
2021-04-21 22:00:50 +02:00
:header-args:emacs-lisp: :mkdirp yes :tangle ~/.emacs.spacemacs/private/spacemacs-init.el :exports code :results silent :lexical t
2020-11-14 02:21:26 +01:00
:END:
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp :exports none
2021-10-12 11:31:20 +02:00
;; -*- lexical-binding: t -* -
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
The ~dotspacemacs/init~ function is the one called at the very begining of the
Spacemacs startup, before any kind of configuration, including the layer
configuration. Only the values of the Spacemacs settings should be modified
here. By default, every values are set in a ~setq-default~ sexp, and they
represent all the supported Spacemacs settings. Hence, the function looks like
this:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :tangle no
2021-10-12 11:31:20 +02:00
(defun dotspacemacs/init ()
(setq-default
;; default Spacemacs configuration here
))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Handling my Spacemacs litterate config
2020-12-23 02:13:45 +01:00
:PROPERTIES:
2020-12-24 22:17:40 +01:00
:header-args:emacs-lisp: :tangle no :exports code :results silent :lexical t
2020-12-23 02:13:45 +01:00
:END:
2021-02-04 14:43:09 +01:00
Just before we get onto the usual content of the ~dotspacemacs/init~ function
you would find in a typical Spacemacs installation, I would like to talk a bit
about how I manage writing a litterate config for Spacemacs and ensure Emacs
starts with an up-to-date configuration from said litterate config. For that, I
actually declared a couple of variables:
2020-12-23 02:13:45 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak--dotspacemacs-src-dir "~/.emacs.spacemacs/private/ "
"Directory for my exported Elisp configuration files")
(defvar phundrak--dotspacemacs-src "~/org/config/emacs.org"
"My litterate config file for Emacs")
(defvar phundrak--dotspacemacs-si (concat phundrak--dotspacemacs-src-dir "spacemacs-init"))
(defvar phundrak--dotspacemacs-sl (concat phundrak--dotspacemacs-src-dir "spacemacs-layers"))
(defvar phundrak--dotspacemacs-uc (concat phundrak--dotspacemacs-src-dir "user-config"))
(defvar phundrak--dotspacemacs-ui (concat phundrak--dotspacemacs-src-dir "user-init"))
(defvar phundrak--dotspacemacs-files (list phundrak--dotspacemacs-si phundrak--dotspacemacs-sl
phundrak--dotspacemacs-uc phundrak--dotspacemacs-ui))
2020-12-24 22:17:40 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
I also declared the following function that tells me if my Elisp files are more
recent than my ~emacs.org~ file. The ~compiled?~ argument lets me compare either
the ~.el~ files if it is ~nil~ , or the ~.elc~ files if it is ~t~ .
2020-12-24 22:17:40 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-update-config-files-p (&optional compiled?)
"Verify if any of my exported Elisp configuration files are
newer than my litterate configuration.
2020-12-24 22:17:40 +01:00
2021-10-12 11:31:20 +02:00
If `COMPILED?' is `t', check the `.elc' files instead of the
`.el' files."
(catch 'ret
(dolist (file phundrak--dotspacemacs-files)
(when (file-newer-than-file-p phundrak--dotspacemacs-src
(format "%s.%s"
file
(if compiled? "elc" "el")))
(throw 'ret t)))))
2020-12-23 02:13:45 +01:00
#+END_SRC
2020-12-24 22:17:40 +01:00
2021-02-04 14:43:09 +01:00
Now I know a couple of my files that get exported by this document. If I compare
how recent these files are compared to my litterate config, I know if Emacs
missed tangling its configuration before launching, so if any of my ~si~ , ~sl~ ,
~uc~ , or ~ui~ files are older than my ~emacs.org~ , then I’ ll tangle the latter;
and since my user config is growing longer and longer, I want Emacs to be able
to parse it fast next time it boots, so let’ s compile my exported ~.el~ files!
2020-12-23 02:13:45 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(when (or (file-newer-than-file-p phundrak--dotspacemacs-src (concat phundrak--dotspacemacs-si ".el"))
(file-newer-than-file-p phundrak--dotspacemacs-src (concat phundrak--dotspacemacs-sl ".el"))
(file-newer-than-file-p phundrak--dotspacemacs-src (concat phundrak--dotspacemacs-ui ".el"))
(file-newer-than-file-p phundrak--dotspacemacs-src (concat phundrak--dotspacemacs-uc ".el")))
(message "Exporting new Emacs configuration from spacemacs.org through org-babel...")
(with-temp-buffer
(shell-command (format "emacs -Q --batch %s %s %s"
"--eval \"(require 'ob-tangle)\""
"--eval \"(setq org-confirm-babel-evaluate nil)\""
(format "--eval '(org-babel-tangle-file \"%s\")'"
phundrak--dotspacemacs-src))
(current-buffer)))
(message "Exporting new Emacs configuration from spacemacs.org through org-babel...done")
(with-temp-buffer
(byte-recompile-directory phundrak--dotspacemacs-src-dir
0 t)))
2020-12-23 02:13:45 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
All that’ s left to do in the Spacemacs functions is to call ~load~ on ~si~ ,
~sl~ , ~uc~ , and ~ui~ . Be aware this sub-chapter won’ t be tangled, so it might
not be up to date with the [[https://labs.phundrak.com/phundrak/dotfiles/src/branch/master/.spacemacs ][actual dotspacemacs file ]]. Please check it just in
case something changed and I forgot to update this part of ~emacs.org~ .
2020-12-23 02:13:45 +01:00
2023-09-18 18:45:14 +02:00
*** Emacs with pdumper
2021-02-04 14:43:09 +01:00
It is possible to compile Emacs 27 from source with support for the portable
dumper, as shown in Spacemacs’ ~EXPERIMENTAL.org~ file. I do not use this
feature yet, as I am still on Emacs 26 provided from Arch Linux’ s repositories,
so I’ ll disable the Spacemacs support for this feature. The default value of
this variable is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-enable-emacs-pdumper t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
In case the support for pdumper was enabled, Spacemacs needs to know the name of
the Emacs executable which supports such a feature. The executable must be in
the user’ s ~PATH~ . By default, the value of the variable is ~"emacs"~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-emacs-pdumper-executable-file "emacs")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
And finally, we can name the Spacemacs dump file. This is the file that will be
created by the portable dumper in the cache directory under the ~dumps~
sub-directory. To load it when starting Emacs, the parameter ~--dump-file~
should be added when invoking Emacs 27.1 executable from the command line, for
instance:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC sh :tangle no :exports code
2021-10-12 11:31:20 +02:00
./emacs --dump-file=~/ .emacs.spacemacs/.cache/dumps/spacemacs.pdmp
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2020-11-13 00:39:34 +01:00
The default value of this variable is ~"spacemacs.pdmp"~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-emacs-dumper-dump-file
(format "spacemacs-%s.pdmp" emacs-version))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Package managment and updates
2021-02-04 14:43:09 +01:00
Spacemacs’ core configuration can be updated via git commands using Github
services. If Spacemacs is not set to the ~develop~ branch, it can check by
itself if any update is available. However, I am using said branch, therefore I
should set this variable to ~nil~ . The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-check-for-update nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
When it comes to package management, Spacemacs is able to store them in
different directories depending on the version of Emacs used or based on other
variables. I personally prefer to use the value ~emacs-version~ since it makes
it easier to upgrade or downgrade Emacs without any conflict with the already
installed packages. The default value is ~emacs-version~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-elpa-subdirectory 'emacs-version)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Spacemacs has a capacity of performing rollbacks after updates. We can set the
maximum number of rollback slots to keep in the cache. The default value is ~5~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-max-rollback-slots 5)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Elpa repository
2021-02-04 14:43:09 +01:00
It is possible to ask Emacs to use an HTTPS connection when contacting the Elpa
whenever possible. This value should be set to ~nil~ when the user has no way to
contact the Elpa though HTTPS, otherwise it is strongly recommended to let it
set to ~t~ . This variable however has no effect if Emacs is launched with the
parameter ~--insecure~ which forces the value of this variable to ~nil~ . The
default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-elpa-https t)
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
We can set a maximum amount of seconds which will represent the maximum allowed
time to contact the Elpa repository. By default, this setting is set on ~5~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-elpa-timeout 5)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
**** Spacelpa repository
2021-02-04 14:43:09 +01:00
The Spacelpa repository is a Spacemacs-specific package repository. It is
possible to use it as the primary source to install a locked version of a
package. If the below value is set to ~nil~ , then Spacemacs will install the
latest version of packages from MELPA. I personally don’ t use it, so I let it
set to ~nil~ . The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-use-spacelpa nil)
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If the below value is not ~nil~ , then the signature for the downloaded Spacelpa
packages must be verified.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-verify-spacelpa-archives t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Editing style
2021-02-04 14:43:09 +01:00
By default, Spacemacs encourages the use of evil-mode, which brings vim
keybinding in Emacs. Still, it has three different styles available:
- ~vim~ , which goes full evil-mode usage and most adapted to Emacs newcomers,
especially if they were used to vim before, with the use of a normal mode and
an insert mode.
- ~emacs~ which keeps an Emacs-like feel to the keybindings, without any
difference between an insert or normal mode.
- ~hybrid~ is a modification of the ~vim~ mode which brings the ~emacs~ style in
insert mode, but otherwise behaves like the ~vim~ style in normal mode. This
is the style I personally use.
The value can also be a list with the ~:variables~ keyword (similar to layers).
Check the editing styles section of the documentation for details on available
variables. The default value is ~vim~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-editing-style
'(hybrid :variables
hybrid-mode-enable-evilified-state t
hybrid-mode-default-state 'normal))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, the paste transient-state is enabled. While enabled, after you paste
something, pressing ~C-j~ and ~C-k~ several times cycles through the elements in
the ~kill-ring~ . Default ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-enable-paste-transient-state t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2023-09-18 18:45:14 +02:00
*** Spacemacs home configuration
2021-02-04 14:43:09 +01:00
The value below specifies the startup banner of Spacemacs. The default value is
~official~ , it displays the official Spacemacs logo. An integer value is the
index of text banner, ~random~ chooses a random text banner in the
~core/banners~ directory. A string value must be a path to an image format
supported by your Emacs build. If the value is nil, then no banner is displayed.
The default value is ~official~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-startup-banner 'official)
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
On the Spacemacs homepage, a list of elements can also be shown, be it recent
files, projects, agenda items,… Each of the elements making up the list value of
the below variable are pairs in the form ~(list-type . list-size)~ . If the value
is ~nil~ , then it is disabled. The possible values for ~list-type~ are:
2020-11-13 00:39:34 +01:00
- ~recents~ :: displays recently opened files
- ~bookmarks~ :: displays saved bookmarks
- ~projects~ :: displays projectile projects recently opened
- ~agenda~ :: displays upcoming events from Org-mode agendas
- ~todos~ :: displays recent TODOs detected in projectile projects
2021-02-04 14:43:09 +01:00
The order in which they are set in the below list affects their order on the
Spacemacs startup page. List sikes may be ~nil~ , in which case
~spacemacs-buffer-startup-lists-length~ takes effect.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-startup-lists '((recents . 15)
(projects . 15)))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The below variable allows the startup page to respond to resize events. Its
default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-startup-buffer-responsive t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil show the version string in the Spacemacs buffer. It will appear as
~(spacemacs version)@(emacs version)~ . Default ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-startup-buffer-show-version t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2023-09-18 18:45:14 +02:00
*** Default major modes
2021-02-04 14:43:09 +01:00
The below variable sets a default major mode for a new empty buffer. Possible
values are mode names such as ~text-mode~ , or ~nil~ to use Fundamental mode. The
default value is ~text-mode~ , but I prefer to use ~org-mode~ by default.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-new-empty-buffer-major-mode 'org-mode)
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Similarly, the below variable sets the default mode for the scratch buffer. Its
default value is ~text-mode~ , but I set it to use ~emacs-lisp-mode~ by default.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-scratch-mode 'emacs-lisp-mode)
#+END_SRC
2020-08-25 06:16:28 +02:00
2021-02-04 14:43:09 +01:00
By the way, it is possible to set a default message for the scratch buffer, such
as “Welcome to Spacemacs!”. I prefer to keep it clean. The default value is
~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-initial-scratch-message nil)
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Visual configuration
**** Themes
2021-02-04 14:43:09 +01:00
Spacemacs makes it quite easy to use themes and organize them. The below value
is a list of themes, the first of the list is loaded when Spacemacs starts. The
user can press ~SPC T n~ to cycle to the next theme in the list.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-themes '(nord doom-nord doom-vibrant spacemacs-dark
doom-one doom-opera doom-dracula doom-molokai
doom-peacock doom-sourcerer doom-spacegrey
kaolin-dark kaolin-aurora kaolin-bubblegum
kaolin-galaxy kaolin-mono-dark kaolin-temple
kaolin-valley-dark))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Emacs also makes use of themes for the Spaceline at the bottom of buffers.
Supported themes are:
2020-11-13 00:39:34 +01:00
- ~spacemacs~
- ~all-the-icons~
- ~custom~
- ~doom~ (the one I use)
- ~vim-powerline~
- ~vanilla~
2021-02-04 14:43:09 +01:00
The first three are Spaceline themes. ~doom~ is the Doom-Emacs mode-line, and
~vanilla~ is the default Emacs mode-line. ~custom~ is a user defined theme,
refer to Spacemacs’ ~DOCUMENTATION.org~ file for more info on how to create your
own Spaceline theme. Value can be a symbol or list with additional properties.
The default value is ~'(spacemacs :separator wave :separator-scale 1.5))~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-mode-line-theme '(doom
:separator wave
:separator-scale 1.0))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
It is also possible to color the cursor depending on which mode Spacemacs is in,
in order to mach the state color in GUI Emacs. The default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-colorize-cursor-according-to-state t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The below variable sets either the default font or a prioritized list of fonts
to be used by Emacs. The ~:size~ can be specified as a non-negative integer
(pixel size), or a floating-point (point size). Point size is recommended,
because it’ s device independent (add a ~.0~ to make an integer a floating
point). The default size is ~10.0~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-default-font '("Cascadia Code"
:size 9.0))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
I also added the following code in order to define a fallback font for emojis,
defined only on their unicode range:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(set-fontset-font "fontset-default" '(#x1f600 . #x1f64f) "NotoEmoji Nerd Font")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-05-17 15:04:07 +02:00
2023-09-18 18:45:14 +02:00
**** Other on-screen elements
2021-02-04 14:43:09 +01:00
~which-key~ is a helper which displays available keyboard shortcuts. This
variable sets in seconds the time Spacemacs should wait between a key press and
the moment ~which-key~ should be shown.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-which-key-delay 1)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
This variable sets ~which-key~ 's frame position. Possible values are:
- ~right~
- ~bottom~
- ~right-then-bottom~
2021-02-04 14:43:09 +01:00
~right-then-bottom~ tries to display the frame to the right, but if there is
insufficient space it displays it at the bottom. The default value is ~bottom~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-which-key-position 'right-then-bottom)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
This controls where ~switch-to-buffer~ displays the buffer. If the value is
~nil~ , ~switch-to-buffer~ displays the buffer in the current window even if
another same-purpose window is available. If non-nil, ~switch-to-buffer~
displays the buffer in a same-purpose window even if the buffer can be displayed
in the current window. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-switch-to-buffer-prefers-purpose nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If this variable is non-nil, a progress bar is displayed when Spacemacs is
loading. This may increase the boot time on some systems and emacs builds, set
it to ~nil~ to boost the loading time. The default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-loading-progress-bar t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If the value is non-nil, Emacs will show the title of the transient states. The
default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-show-transient-state-title t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, this will show the color guide hint for transient state keys. The
default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-show-transient-state-color-guide t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, unicode symbols are displayed in the mode line. If you use Emacs as
a daemon and want unicode characters only in GUI set the value to quoted
~display-graphic-p~ . The default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-mode-line-unicode-symbols t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, smooth scrolling (native-scrolling) is enabled. Smooth scrolling
overrides the default behavior of Emacs which recenters point when it reaches
the top or bottom of the screen. The default value is ~t~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-smooth-scrolling t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The following value controls the line number activation. If set to ~t~ ,
~relative~ or ~visual~ then line numbers are enabled in all ~prog-mode~ and
~text-mode~ derivatives. If set to ~relative~ , line numbers are relative. If set
to ~visual~ , line numbers are also relative, but only visual lines are counted.
For example, folded lines will not be counted and wrapped lines are counted as
multiple lines. This variable can also be set to a property list for finer
control:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :tangle no
2021-10-12 11:31:20 +02:00
'(:relative nil
:visual nil
:disabled-for-modes dired-mode
doc-view-mode
markdown-mode
org-mode
pdf-view-mode
text-mode
:size-limit-kb 1000)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-14 18:38:22 +02:00
2020-11-13 00:39:34 +01:00
When used in a plist, ~visual~ takes precendence over ~relative~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-line-numbers '(:relative nil
:visual nil
:disabled-for-modes org-mode pdf-view-mode
dired-mode doc-view-mode
text-mode))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
Select a scope to highlight delimiter. Possible values are:
- ~any~
- ~current~
- ~all~
- ~nil~
The default value is ~all~ (highlights any scope and emphasis the current one).
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-highlight-delimiters 'all)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
After a certain amount of time in seconds, Spacemacs can zone-out. The default
value is ~nil~ . I set it so Spacemacs zones out after 15 minutes.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-zone-out-when-idle 900)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Run ~spacemacs/prettify-org-buffer~ when visiting the ~README.org~ files of
Spacemacs. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-pretty-docs nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If ~nil~ , the home buffer shows the full path of agenda items and todos. If non
~nil~ , only the file name is shown.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-home-shorten-agenda-source t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-14 18:38:22 +02:00
2023-09-18 18:45:14 +02:00
**** Appearance of Emacs frames
2021-02-04 14:43:09 +01:00
Starting from Emacs 24.4, it is possible to make the Emacs frame fullscreen when
Emacs starts up if the variable is set to a non-nil value. The default value is
~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-fullscreen-at-startup nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
This variable is to be used if the user does not want to use native fullscreen
with ~spacemacs/toggle-fullscreen~ . This disables for instance the fullscreen
animation under OSX. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-fullscreen-use-non-native nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If you do not start Emacs in fullscreen at startup, you might want it to be
maximized by default. If the value for the variable below is set to be non-nil,
the frame will be maximized. This can only work if
~dotspacemacs-fullscreen-at-startup~ is set to ~nil~ , and it is only available
from Emacs 24.4 onwards. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-maximized-at-startup nil)
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, the frame is undecorated when Emacs starts up. Combine this with the
variable ~dotspacemacs-maximized-at-startup~ in OSX to obtain borderless
fullscreen. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-undecorated-at-startup nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
You can also set a transparency level for Emacs when you toggle the transparency
of the frame with ~toggle-transparency~ . The value of the transparency, going
from 0 to 100 in increasing opacity, describes the transparency level of a frame
when it’ s active or selected. The default value is ~90~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-active-transparency 85)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Similarly, you can set a value from 0 to 100 in increasing opacity which
describes the transparency level of a frame when it’ s inactive or deselected.
The default value is ~90~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-inactive-transparency 80)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
The variable below sets the format of frame title. You can use:
- ~%a~ :: the ~abbreviated-file-name~ or ~buffer-name~
- ~%t~ :: ~projectile-project-name~
- ~%I~ :: ~invocation-name~
- ~%S~ :: ~system-name~
- ~%U~ :: contents of ~$USER~
- ~%b~ :: buffer name
- ~%f~ :: visited file name
- ~%F~ :: frame name
- ~%s~ :: process status
- ~%p~ :: percent of buffer above top of window, or Top, Bot, or All
2021-02-04 14:43:09 +01:00
- ~%P~ :: percent of buffer above bottom of window, perhaps plus Top, or Bot, or
All
2020-11-13 00:39:34 +01:00
- ~%m~ :: mode name
- ~%n~ :: Narrow if appropriate
- ~%z~ :: mnemonics of buffer, terminal, and keyboard coding systems
- ~%Z~ :: like ~%z~ , but including the end-of-line format
The default value is ~"%I@%S"~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-frame-title-format "Emacs: %b (%t) %U@%S")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Format specification for setting the icon title format. The default value is
~nil~ , same as ~frame-title-format~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-icon-title-format nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Spacemacs leader keys and shortcuts
2021-02-04 14:43:09 +01:00
The below setting sets the Spacemacs leader key. By default, this is the ~SPC~
key.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-leader-key "SPC")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Once the leader key has been pressed, it is possible to set another key in order
to call Emacs’ command ~M-x~ . By default, it is again the ~SPC~ key.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-emacs-command-key "SPC")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
It is also possible to invoke Vim Ex commands with the press of a key, and by
default it is the ~:~ key.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-ex-command-key ":")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The below variable sets the leader key accessible in ~emacs-state~ and
~insert-state~ :
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-emacs-leader-key "M-m")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
The major mode leader key is a shortcut key which is the equivalent of pressing
~<leader> m~ . Set it to ~nil~ to disable it. Its default value is ~,~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-major-mode-leader-key ",")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
In ~emacs-state~ and ~insert-state~ , the same major mode leader key can be
accessible from another shortcut, which by default is ~C-M-m~ in terminal mode,
or ~M-return~ in GUI mode.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-major-mode-emacs-leader-key
(if window-system "<M-return >" "C-M-m"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
These variables control whether separate commands are bound in the GUI to the
key pairs ~C-i~ and ~TAB~ , and ~C-m~ and ~RET~ . Setting it to a non-nil value
allows for separate commands under ~C-i~ and ~TAB~ , and ~C-m~ and ~RET~ . In the
terminal, these pairs are generally indistinguishable, so this only works in the
GUI. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-distinguish-gui-tab nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Layouts
2021-02-04 14:43:09 +01:00
The variable belows sets the name of the default layout. Its default value is
~"Default"~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-default-layout-name "Default")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, the default layout name is displayed in the mode-line. The default
value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-display-default-layout nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, then the last auto saved layouts are resumed automatically upon
start. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-auto-resume-layouts nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, the layout name will be auto-generated when creating new layouts. It
only has an effect when using the “jump to layout by number” command. The
default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-auto-generate-layout-names nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Files-related settings
2021-02-04 14:43:09 +01:00
The below value sets the size in MB above which Spacemacs will prompt to open
the file literally in order to avoid preformance issues. Opening a file
literally means that no major or minor mode is active. The default value is ~1~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
(setq-default dotspacemacs-large-file-size 5)
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
This variable sets the location where to auto-save files. Possible values are:
- ~original~ :: auto-saves files in-place
- ~cache~ :: auto-saves files in another file stored in the cache directory
- ~nil~ :: disables auto-saving.
The default value is ~cache~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-auto-save-file-location 'original)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Emacs server
2021-02-04 14:43:09 +01:00
Emacs can be launched as a server if the following value is set to non-nil and
if one isn’ t already running. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-enable-server nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
You can also set a custom emacs server socket location. If the value is ~nil~ ,
Emacs will use whatever the Emacs default is, otherwise a directory path like
="$HOME/.config/emacs/server"= . It has no effect if ~dotspacemacs-enable-server~
is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-server-socket-dir nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
It is also possible to tell Emacs that the quit function should keep the server
open when quitting. The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-persistent-server t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
*** Miscellaneous
2021-02-04 14:43:09 +01:00
This value changes the folding method of code blocks. The possible values are
either ~evil~ , the default value, or ~origami~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-folding-method 'evil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, ~smartparens-strict-mode~ will be enabled in programming modes. The
default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-smartparens-strict-mode nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
If non-nil, pressing the closing parenthesis ~)~ key in insert mode passes over
any automatically added closing parenthesis, bracket, quote, etc… This can
temporarily disabled by pressing ~C-q~ before ~)~ . The default value is ~nil~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-smart-closing-parenthesis nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
List of search tool executable names. Spacemacs uses the first installed tool of
the list. Supported tools are:
2020-11-13 00:39:34 +01:00
- ~rg~
- ~ag~
- ~pt~
- ~ack~
- ~grep~
The default value is ~'("rg" "ag" "pt" "ack" "grep")~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-search-tools '("rg" "grep"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
Delete whitespace while saving buffer. Possible values are:
- ~all~ :: aggresively delete empty lines and long sequences of whitespace
- ~trailing~ :: only detele the whitespace at end of lines
- ~changed~ :: to delete only whitespace for changed lines
- ~nil~ :: disable cleanup
The default value is ~nil~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-whitespace-cleanup nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Set ~gc-cons-threshold~ and ~gc-cons-percentage~ when startup finishes. This is
an advanced option and should not be changed unless you suspect performance
issues due to garbage collection operations. The default is ~'(100000000 0.1)~
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-gc-cons '(100000000 0.1))
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2021-02-04 14:43:09 +01:00
If non nil activate ~clean-aindent-mode~ which tries to correct virtual
indentation of simple modes. This can interfer with mode specific indent
handling like has been reported for ~go-mode~ . If it does deactivate it here.
Default ~t~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-use-clean-aindent-mode t)
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2021-02-04 14:43:09 +01:00
If non ~nil~ , shift your number row to match the entered keyboard layout (only
in insert state). Currently supported keyboard layouts are ~querty-us~ ,
~quertz-de~ and ~querty-ca-fr~ . New layouts can be added in ~spacemacs-editing~
layer. Default ~nil~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-swap-number-row nil)
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2021-02-04 14:43:09 +01:00
Set ~read-process-output-max~ when startup finishes. This defines how much data
is read from a foreign process. Setting this >= 1 MB should increase performance
for lsp servers in emacs 27.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq-default dotspacemacs-read-process-output-max (* 1024 1024 8))
2021-02-04 14:43:09 +01:00
#+END_SRC
2020-08-25 06:16:28 +02:00
2023-09-18 18:45:14 +02:00
** User Initialization
*** User Init
2021-04-06 09:43:52 +02:00
:PROPERTIES:
2021-04-21 22:00:50 +02:00
:header-args:emacs-lisp: :mkdirp yes :tangle ~/.emacs.spacemacs/private/user-init.el :exports code :results silent :lexical t
2021-04-06 09:43:52 +02:00
:END:
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp :exports none
2021-10-12 11:31:20 +02:00
;; -*- lexical-binding: t -* -
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
While Emacs and especially Spacemacs loads, I want it to initialize some
elements and load some packages. First of all, I want it to load my private
Emacs config file:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(load "~/.emacs.spacemacs/private/private_emacs")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-22 16:08:44 +02:00
2021-02-04 14:43:09 +01:00
I would also like to enable the setup of flycheck for Rust when Flycheck is
loaded:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
By default, Flyspell should be disabled and only enabled manually.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(flyspell-mode 0)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Finally, here is a quick workaround for Tramp, sometimes it cannot connect to my
hosts if I don’ t have this code snippet.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq tramp-ssh-controlmaster-options
"-o ControlMaster=auto -o ControlPath= 'tramp.%%C' -o ControlPersist=no")
2020-11-13 00:39:34 +01:00
#+END_SRC
2021-04-11 16:07:28 +02:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(require 'org)
2021-04-11 16:07:28 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
*** User Load
2021-04-06 09:43:52 +02:00
:PROPERTIES:
2021-04-21 22:00:50 +02:00
:header-args:emacs-lisp: :mkdirp yes :tangle ~/.emacs.spacemacs/private/user-load.el :exports code :results silent :lexical t
2021-04-06 09:43:52 +02:00
:END:
Then, I want a couple of requires:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(require 'org-id)
(require 'org-protocol)
(require 'package)
(require 'ox-latex)
(require 'ox-publish)
(require 'tramp)
2021-04-06 09:43:52 +02:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
** User Configuration
2020-11-14 02:21:26 +01:00
:PROPERTIES:
2021-04-21 22:00:50 +02:00
:header-args:emacs-lisp: :mkdirp yes :tangle ~/.emacs.spacemacs/private/user-config.el :exports code :results silent :lexical t
2020-11-14 02:21:26 +01:00
:END:
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp :exports none
2021-10-12 11:31:20 +02:00
;; -*- lexical-binding: t -* -
2020-12-23 04:26:27 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
*** Custom functions, macros, and variables
2021-02-04 14:43:09 +01:00
In this section, I will put my various custom functions that do not fit in other
sections and which are more oriented towards general usage throughout Emacs and
in Elisp code.
2020-11-13 00:39:34 +01:00
2021-02-04 14:43:09 +01:00
Almost all of my code snippets will be prefixed by either my name or the name of
the package or layer they are part of, unless they are an explicit overwrite of
a function that already exists.
2023-09-18 18:45:14 +02:00
**** Elisp Utilities and Predicates
***** ~phundrak-filter~
2021-04-17 12:46:05 +02:00
#+name : elisp-phundrak-filter
#+BEGIN_SRC emacs-lisp
(defun phundrak-filter (fn list)
"Filter `LIST' according to the predicate `FN'.
All elements from `LIST' that do not satisfy the predicate `FN'
will be left out of the result, while all elements that do
satisfy it will be included in the resulting list. This function
also preserves the relative position between elements that
satisfy the predicate."
(declare (pure t) (side-effect-free t))
(when list
(let ((rest (phundrak-filter fn
(cdr list))))
(if (funcall fn
(car list))
(cons (car list) rest)
rest))))
#+END_SRC
2023-09-18 18:45:14 +02:00
***** ~phundrak-all?~
2021-04-17 12:46:05 +02:00
This function is inspired by dash’ s ~-all?~ function: it will test all the
elements of the list ~seq~ against the predicate ~fn~ which should return either
~t~ or ~nil~ . If all of them return something else than ~nil~ , then it is a
success, otherwise it is a failure. Note that empty lists will always return
~t~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-all? (fn seq)
"Check if all members of `SEQ' satisfy predicate `FN'. Note that
it will return t if `SEQ' is nil."
(declare (pure t) (side-effect-free t))
(if seq
(and (funcall fn (car seq))
(phundrak-all? fn (cdr seq)))
t))
2021-04-17 12:46:05 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** ~phundrak-none?~
2021-04-17 12:46:05 +02:00
In the same vein as ~phundrak-all?~ , ~phundrak-none?~ checks if all elements of
~seq~ do not satify the predicate ~fn~ . Again, if the list is empty, it will
return ~t~ .
#+name : elisp-phundrak-none
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-none? (fn seq)
"Check if all members of `SEQ' do not satisfy predicate `FN'.
Note that it will return t if `SEQ' is nil."
(declare (pure t) (side-effect-free t))
(if seq
(and (not (funcall fn (car seq)))
(phundrak-none? fn (cdr seq)))
t))
2021-04-17 12:46:05 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** ~phundrak-zip~
2021-04-17 12:46:05 +02:00
#+name : elisp-phundrak-zip
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-zip (&rest lists)
"Zip `LISTS' together.
Be aware only the amount of elements of the smallest list will be zipped."
(declare (pure t) (side-effect-free t))
(when lists
(let ((lists (if (= 1 (length lists)) ; only one element = > a list of lists was passed
(car lists)
lists)))
(when (phundrak-none? 'null lists)
(cons (mapcar 'car lists)
(phundrak-zip (mapcar 'cdr lists)))))))
2021-04-17 12:46:05 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Eshell Prompt-Related Functions
***** ~phundrak-eshell-git-status~
This function is used in my Eshell prompt which you can consult [[file:./spacemacs.md#eshell-theme-and-prompt ][here ]].
This function basically executes two git calls to get some information
about a git repo, which path we provide as an argument. Based on the
result of these git calls, the function will know what it needs to
know about the repo to build a git prompt that will be inserted in my
Eshell prompt. And just for shit and giggles, I’ ve made it so it is a
powerline prompt.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-eshell-git-status ($path &optional $background-color)
"Returns a string indicating the status of the repository located
in `$PATH' if it exists. It should also append the name of the
current branch if it is not `master' or `main'.
`$BACKGROUND-COLOR' allows to choose the color that will be
visible behind the powerline characters. The theme is inspired by
the bobthefish theme for the fish shell which you can find here:
https://github.com/oh-my-fish/theme-bobthefish
Color code:
- green:
- orange: tracked stuff is staged but not commited
- red: tracked stuff is modified and not commited
Symbols:
- `*': dirty working dir, RED
- `~': staged changes, ORANGE
- `…': untracked files, GREEN
- `$': stashed changes
- `-': unpulled commits
- `-': unpushed commits
- `±': unpulled and unpushed commits"
(let* ((git-status-command (concat "cd " $path "; git status"))
(git-stash-status-command (concat "cd " $path "; git stash list"))
(status (eshell-command-result git-status-command))
(stashstat (eshell-command-result git-stash-status-command))
(detached (s-contains? "HEAD detached" status))
(dirty (s-contains? "Changes not staged for commit" status))
(staged (s-contains? "Changes to be committed" status))
(untracked (s-contains? "Untracked files" status))
(pullable (s-contains? "git pull" status))
(pushable (s-contains? "git push" status))
(branch (replace-regexp-in-string "On Branch \\(.*\\)\n\\(.\\|\n\\)* " "\\1" status))
(branch (unless (or (string= "master" branch)
(string= "main" branch)
detached)
branch)))
(let ((prompt (concat " "
(if detached ">" "")
(when branch (concat " " branch " "))
(when dirty "*")
(when staged "~")
(when untracked "…")
(cond ((and pullable pushable) "±")
(pullable "-")
(pushable "+"))
(when stashstat "$")
" "))
(accent (cond
(dirty phundrak-nord11)
(staged phundrak-nord13)
(t phundrak-nord14)))
(background (if $background-color
$background-color
phundrak-nord0)))
(concat (with-face ""
:background accent
:foreground background)
(with-face prompt
:background accent
:foreground (if dirty phundrak-nord6 background))
(with-face ""
:background background
:foreground accent)))))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-21 23:03:43 +02:00
2023-09-18 18:45:14 +02:00
***** ~phundrak-git-repo-root~
2021-03-26 14:22:42 +01:00
This function detects if the path passed as an argument points to a git
directory or to one of its subdirectories. If it is, it will return the path to
the root of the git repository, else it will return ~nil~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-git-repo-root ($path)
"Return `$PATH' if it points to a git repository or one of its
subdirectories."
(when $path
(if (f-dir? (concat $path "/.git"))
$path
(phundrak-git-repo-root (f-parent $path)))))
2021-03-26 14:22:42 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** ~phundrak-prompt-toggle-abbreviation~
2021-03-26 14:22:42 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak-prompt--abbreviate t
"Whether or not to abbreviate the displayed path in the Eshell
prompt.")
2021-03-26 14:22:42 +01:00
2021-10-12 11:31:20 +02:00
(defun phundrak-prompt-toggle-abbreviation ()
"Toggles whether the Eshell prompt should shorten the name of
the parent directories or not. See `phundrak-eshell-prompt'."
(interactive)
(setq phundrak-prompt--abbreviate (not phundrak-prompt--abbreviate)))
2021-03-26 14:22:42 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** ~phundrak-abbr-path~
2021-03-26 14:22:42 +01:00
The following is a nice little function I use in my Eshell prompt. It shortens
the name of all the parent directories of the current one in its path, but
leaves the current one written in full. It also abbreviates the equivalent of
the ~$HOME~ (~/home/<username>/~ ) directory to a simple =~= .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-abbr-path ($path &optional $abbreviate)
"Abbreviate `$PATH'. If `$ABBREVIATE' is t, then all parent
directories of the current directory will be abbreviated to one
letter only. If a parent directory is a hidden directory (i.e.
preceeded by a dot), the directory will be abbreviated to the dot
plus the first letter of the name of the directory (e.g.
\".config\" -> \".c\").
For public use of the function, `$PATH' should be a string
representing a UNIX path. For internal use, `$PATH' can also be a
list. If `$PATH' is neither of those, an error will be thrown by
the function."
(cond
((stringp $path) (f-short
(if $abbreviate
(phundrak-abbr-path (f-split (phundrak-abbr-path $path)))
$path)))
((null $path) "")
((listp $path)
(f-join (cond ((= 1 (length $path)) (car $path))
(t (let* ((dir (car $path))
(first-char (s-left 1 dir)))
(if (string= "." first-char)
(s-left 2 dir)
first-char))))
(phundrak-abbr-path (cdr $path))))
(t (error "Invalid argument %s, neither stringp nor listp" $path))))
2021-03-26 14:22:42 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Files-Related Functions
***** ~phundrak-file-to-string~
2021-02-04 14:44:07 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-file-to-string (FILE)
"Returns the content of `FILE' as a string."
(with-temp-buffer
(insert-file-contents FILE)
(buffer-string)))
2021-02-04 14:44:07 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** ~phundrak-find-org-files~
2021-02-04 14:43:09 +01:00
There are lots of files which I want to be able to quickly open. I used to have
one shortcut for each one of these files, but as their number grew, I decided to
switch to helm for my file selector which will be called by only one common
shortcut. Most of my files will be located in =~/org= , but I have some
conlanging files which are located in =~/Documents/conlanging= , and all my
university notes are in =~/Documents/university= . Let’ s declare these
directories in a variable:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak-org-directories '("~/org"
"~/Documents/university/S8"
"~/Documents/conlanging")
"Directories in which to look for org files with the function
`phundrak-find-org-files'.")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-09 18:08:58 +02:00
2021-02-04 14:43:09 +01:00
With this established, let’ s write some emacs-lisp that will allow me to get a
list of all these files and select them through helm. Be aware that I will be
using some functions from third party packages, such as [[https://github.com/magnars/s.el ][s.el ]] and [[https://github.com/magnars/dash.el ][dash ]], as well
as [[https://github.com/sharkdp/fd ][fd ]].
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-find-org-files ()
"Find all org files in the directories listed in
`phundrak-org-directories', then list them in an ido buffer where
the user can match one and open it."
(interactive)
(find-file
(ivy-completing-read
"Org File: "
(s-split "\n"
(mapconcat (lambda (path)
(shell-command-to-string
(format "fd . %s -e org -c never" path)))
phundrak-org-directories
"\n")))))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-09 18:08:58 +02:00
2023-09-18 18:45:14 +02:00
***** ~phundrak-open-marked-files~
2021-03-26 14:22:42 +01:00
This function is particularly useful in Dired buffers when someone wants to open
multiple files. This function will basically look for all marked files in the
current dired buffer and open each one of them in their individual buffer.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-open-marked-files ()
"This function allows the user to open all marked files in a
Dired buffer at once."
(interactive)
(let ((file-list (if (string= major-mode "dired-mode")
(dired-get-marked-files)
(list (buffer-file-name)))))
(mapc (lambda (file)
(find-file file))
file-list)))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-22 00:52:01 +02:00
2023-09-18 18:45:14 +02:00
***** ~xah/open-in-external-app~
2021-03-26 14:22:42 +01:00
Here is another of Xah’ s functions, this time to open a file externally to
Emacs. For instance, I sometimes want to open a PDF in Zathura rather than in
Emacs, or an HTML file in Firefox. With this function, it is now possible!
2021-03-26 13:45:47 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun xah/open-in-external-app (&optional files)
"Open the current file or dired marked files in external app.
The app is chosen from your OS’ preference.
When called in emacs lisp, if `FILES' is given, open that.
URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html'
Version 2019-01-18"
(interactive)
(let* (($file-list (if files
(progn (list files))
(if (string-equal major-mode "dired-mode")
(dired-get-marked-files)
(list (buffer-file-name)))))
($do-it-p (if (<= (length $file-list) 5)
t
(y-or-n-p "Open more than 5 files? "))))
(when $do-it-p
(mapc (lambda ($fpath)
(let ((process-connection-type nil))
(start-process "" nil "xdg-open" $fpath)))
$file-list))))
2021-03-26 13:45:47 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Theming
***** Nord theming variables
2021-03-26 14:22:42 +01:00
Yes, I do use a preconfigured theme, as mentioned above, but for some elements
such as Eshell, I need to define some variables for color, and I’ ll do it here.
2020-12-06 00:55:33 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak-nord0 "#2e3440")
(defvar phundrak-nord1 "#3b4252")
(defvar phundrak-nord2 "#434c5e")
(defvar phundrak-nord3 "#4c566a")
(defvar phundrak-nord4 "#d8dee9")
(defvar phundrak-nord5 "#e5e9f0")
(defvar phundrak-nord6 "#eceff4")
(defvar phundrak-nord7 "#8fbcbb")
(defvar phundrak-nord8 "#88c0d0")
(defvar phundrak-nord9 "#81a1c1")
(defvar phundrak-nord10 "#5e81ac")
(defvar phundrak-nord11 "#bf616a")
(defvar phundrak-nord12 "#d08770")
(defvar phundrak-nord13 "#ebcb8b")
(defvar phundrak-nord14 "#a3be8c")
(defvar phundrak-nord15 "#b48ead")
2021-03-26 14:22:42 +01:00
#+END_SRC
2020-12-06 00:55:33 +01:00
2023-09-18 18:45:14 +02:00
***** ~with-face~
2021-03-26 14:22:42 +01:00
~with-face~ is a simple yet very useful macro that allows me to easily create
strings with faces defined as properties to the string passed as the first
argument. Here is how it is implemented:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defmacro with-face ($str &rest $properties)
"Helper macro for creating strings `$STR' with `$PROPERTIES'"
`(propertize ,$str 'face (list ,@$properties)))
2020-12-06 00:55:33 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** ~phundrak-blog-publish~
2021-03-26 14:22:42 +01:00
This function is quite a simple function made to automatically publish [[https://blog.phundrak.com ][my blog ]]
based on Hugo. After exporting my blog using ~ox-hugo~ , I simply have to call
this function which will look for all files located in =~/org/blog/public= and
copy them to my remote server once ~hugo~ has been executed in =~/org/blog= .
2020-12-07 17:39:33 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-blog-publish ()
"Publish my blog through Hugo and rsync to my remote server."
(interactive)
(let* ((blog-path "~/org/blog")
(public-path (concat blog-path "/public"))
(target-path "/rsync:Tilo:/home/phundrak/www/phundrak.com/blog"))
(shell-command (format "cd %s && hugo" blog-path))
(let ((files (mapcar (lambda (file)
(f-relative file public-path))
(f-files (format "%s/public" blog-path) nil t))))
(dolist (file files)
(copy-file (concat public-path "/" file)
(concat target-path "/" file)
t nil t)))))
2020-12-07 17:39:33 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** ~phundrak-yas-rust-new-assignments~
2021-02-04 14:43:09 +01:00
The following function is a function that will allow me to easily create ~new~
functions for Rust structs. Inspired from [[https://github.com/jorgenschaefer/elpy ][elpy ]]’ s ~elpy-snippet-init-assignments~
function, it will automatically write assignments to my new struct as I write
new parameters in the ~new~ function. It also comes with a helper function that
parses the arguments given to the ~new~ function.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak--yas-snippet-split-rust-args ($arg-string)
"Split a Rust argument string `$ARG-STRING' into ((name,
default)...) tuples"
(mapcar (lambda ($elem)
(split-string $elem "[[:blank: ]]*:[[:blank:]]* " t))
(split-string $arg-string "[[:blank: ]]*,[[:blank:]]* " t)))
(defun phundrak-yas-rust-new-assignments ($arg-string)
"Return a typical new assignment for arguments.
Inspired from elpy’ s functions https://github.com/jorgenschaefer/elpy"
(let ((indentation (make-string (save-excursion
(goto-char start-point)
(current-indentation))
?\s)))
(mapconcat (lambda ($elem)
(if (string-match "^\\*" (car $elem))
""
(format "%s,\n%s" (car $elem) indentation)))
(phundrak--yas-snippet-split-rust-args $arg-string)
"")))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-10-21 23:03:43 +02:00
2023-09-18 18:45:14 +02:00
**** ~screenshot-svg~
2021-02-04 14:43:09 +01:00
This function allows for taking SVG screenshots of Emacs from itself using
Cairo. The function definition was taken [[https://github.com/caiohcs/my-emacs#screenshots ][from here ]].
2020-12-07 16:24:44 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun screenshot-svg ()
"Save a screenshot of the current frame as an SVG image.
Saves to a temp file and puts the filename in the kill ring."
(interactive)
(let* ((filename (make-temp-file "Emacs" nil ".svg"))
(data (x-export-frames nil 'svg)))
(with-temp-file filename
(insert data))
(kill-new filename)
(message filename)))
2020-12-07 16:24:44 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** ~xah/dired-sort~
2021-02-04 14:43:09 +01:00
This function comes directly from Xah Lee’ s website and allows the user to sort
files in a dired buffer depending on four factors:
2021-09-01 21:58:52 +02:00
- File name
- File size
- Last modification date
- File extension
2020-12-07 17:39:33 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun xah/dired-sort ()
"Sort dired dir listing in different ways. Prompt for a choice.
URL `http://ergoemacs.org/emacs/dired_sort.html'
Version 2018-12-23, modified by Phundrak on 2019-08-06"
(interactive)
(let ($sort-by $arg)
(setq $sort-by (ido-completing-read "Sort by:" '( "name" "size" "date" "extension" )))
(cond
((equal $sort-by "name") (setq $arg "-ahl --group-directories-first"))
((equal $sort-by "date") (setq $arg "-ahl -t --group-directories-first"))
((equal $sort-by "size") (setq $arg "-ahl -S --group-directories-first"))
((equal $sort-by "extension") (setq $arg "-ahlD -X --group-directories-first"))
(t (error "logic error 09535" )))
(dired-sort-other $arg )))
2020-12-07 17:39:33 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
*** Editing and modes
2021-04-21 22:14:14 +02:00
There is first a setting I would like to enable to make the navigation through
text a bit easier which is to enable the subword mode. This allows me to iterate
through words that are in CamelCase more easily, I don’ t have to go either to
the beginning or the end of the word and then move my cursor a bunch of times to
get to the subword I want to modify.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(global-subword-mode 1)
2021-04-21 22:14:14 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Default modes
2021-04-06 09:46:24 +02:00
Some buffers sometimes won’ t have a default mode at all, such as the ~*scratch*~
buffer. In any vanilla configuration, they will then default to ~text-mode~ . I
personally prefer ~org-mode~ to be my default mode, so let’ s set it so!
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq edit-server-default-major-mode 'org-mode)
2021-04-06 09:46:24 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Evil
2021-04-21 22:14:14 +02:00
Evil is not really smart by default when I ask it to undo stuff. As an example,
let’ s say I enter insert-mode and write a whole paragraph, and then I exit
insert-mode back to normal-mode, and I notice a small mistake I made when typing
my stuff down, like accidentally using a snippet from yasnippet, and I want to
undo that. My initial reaction would be to press ~u~ to undo, and so would be
yours too right? That’ s the wrong answer with evil, since it considers your
actions between entering and leaving insert-mode as only one action, and it
would thus erase your /WHOLE PARAGRAPH/ . Fortunately, there is a way to make the
undo action more granular, but it comes at the cost of increasing the amount of
undo actions you can do (which shouldn’ t really matter if you don’ t have a
potato PC).
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq undo-limit 500000
evil-want-fine-undo t)
2021-04-06 09:46:24 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** File extensions
2021-04-06 09:46:24 +02:00
Sometimes, Emacs doesn’ t recognize or misrecognizes some extensions, resulting
in a wrong mode set for said file. Let’ s fix that by associating the extension
with the desired mode:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(dolist (e '(("xml" . web-mode)
("xinp" . web-mode)
("aiml" . web-mode)
("C" . c++-mode)
("dconf" . conf-mode)
("yy" . bison-mode)
("ll" . flex-mode)
("s" . asm-mode)
("pl" . prolog-mode)
("l" . scheme-mode)
("vs" . glsl-mode)
("fs" . glsl-mode)))
(push (cons (concat "\\."
(car e)
"\\'") (cdr e))
auto-mode-alist))
2021-04-06 09:46:24 +02:00
#+END_SRC
We also have a couple of extensions which should all be in ~conf-unix-mode~ ,
let’ s indicate that to Emacs:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(dolist (e '("service" "timer" "target" "mount" "automount"
"slice" "socket" "path" "netdev" "network"
"link"))
(push (cons (concat "\\." e "\\'") 'conf-unix-mode)
auto-mode-alist))
2021-04-06 09:46:24 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Hooks
2021-04-06 09:46:24 +02:00
I also have some hooks I use for enabling some major and minor modes. The first
one here allows the execution of the deletion of trailing space each time I save
a file.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'before-save-hook 'delete-trailing-whitespace)
2021-04-06 09:46:24 +02:00
#+END_SRC
I also want to always be in ~visual-line-mode~ so Emacs soft-wraps lines that
are too long for the buffer they are displayed in. This will also be enabled for
Elfeed.
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'prog-mode-hook 'visual-line-mode)
(add-hook 'elfeed-read-mode-hook 'visual-line-mode)
2021-04-06 09:46:24 +02:00
#+END_SRC
I also want for some non-programming modes to enable a hard-limit in terms of
how many characters can fit on one line. The modes that benefit are
~message-mode~ , ~org-mode~ , ~text-mode~ and ~markdown-mode~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(mapc (lambda (x)
(add-hook x 'visual-line-mode))
'(message-mode-hook
text-mode-hook
markdown-mode-hook))
2021-04-06 09:46:24 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Twittering mode
2021-04-06 09:46:24 +02:00
For ~twittering-mode~ , a Twitter major mode for Emacs, I want to encrypt my data
using a master password, which I do thanks to this option:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq twittering-use-master-password t)
2021-04-06 09:46:24 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Wrapping regions
2021-04-06 09:46:24 +02:00
I really like the ~M-(~ keybinding for wrapping a selected region between
parenthesis. However, parenthesis are not everything (even in Lisp dialects),
and other wrappers could be nice. And they are! Here is how they are declared:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(global-set-key (kbd "M-[") 'insert-pair)
(global-set-key (kbd "M-{") 'insert-pair)
(global-set-key (kbd "M-<") 'insert-pair)
(global-set-key (kbd "M-'") 'insert-pair)
(global-set-key (kbd "M-`") 'insert-pair)
(global-set-key (kbd "M-\"") 'insert-pair)
2021-04-06 09:46:24 +02:00
#+END_SRC
For the record, this is from [[http://www.howardism.org/ ][Howard Abram ]]’ s [[https://github.com/howardabrams/dot-files ][dotfiles ]].
2023-09-18 18:45:14 +02:00
*** Emacs builtins
**** Dired
2021-02-04 14:43:09 +01:00
When it comes to dired, I chose do modify some elements on how things are sorted
and shown, but there isn’ t much configuration. First, I want to always copy
folders in a recursive way, no questions asked.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq dired-recursive-copies 'always)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Also, when I have two Dired buffers opened side by side, I generally want them
to interact with each other, for example if I want to move around or copy stuff.
So, let’ s tell Emacs that:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq dired-dwim-target t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
Finally, let’ s tell Dired how to sort the elements to be displayed: directories
first, non-hidden first.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq dired-listing-switches "-ahl --group-directories-first")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2020-11-13 00:39:34 +01:00
By the way, let’ s enable ~org-download~ when we are in a Dired buffer:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'dired-mode-hook 'org-download-enable)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-02-04 14:43:09 +01:00
Finally, let’ s enable globally ~diredfl~ so we can get a colourful Dired buffer
each time we open one:
2020-12-07 17:39:33 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(diredfl-global-mode 1)
2020-12-07 17:39:33 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Emacs Lisp
2021-03-31 16:31:40 +02:00
For some reason, =flycheck-mode= is not enabled by default when in an elisp
buffer. Let’ s add that:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'emacs-lisp-mode-hook 'flycheck-mode)
2021-03-31 16:31:40 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Eshell
2021-02-04 14:43:09 +01:00
Eshell is a built-in shell available from Emacs which I use almost as often as
Fish. Some adjustments are necessary for making this shell usable for me.
2020-01-16 19:48:14 +01:00
2021-02-04 14:43:09 +01:00
But first, here is a screenshot of what to expect visually from my configuration
of Eshell when it is launched:
2020-12-07 16:24:44 +01:00
2023-09-18 18:45:14 +02:00
[[file:../emacs/img/eshell.svg ]]
2020-12-07 16:24:44 +01:00
2023-09-18 18:45:14 +02:00
***** Aliases
2021-02-04 14:43:09 +01:00
This function is a function that will come in very handy for Eshell functions
that call shell processes. It concatenates the initial string ~command~ with all
the arguments ~args~ , each separated with a space.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak/concatenate-shell-command ($command &rest $args)
(string-join (cons $command $args) " "))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-02-04 14:43:09 +01:00
Just like most shells, it is possible to declare in Eshell aliases. First, I
would like to be able to use ~open~ to open files in Emacs:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defalias 'open 'find-file)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-02-04 14:43:09 +01:00
I also have ~openo~ which allows me to perform the same action, but in another
window:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defalias 'openo 'find-file-other-window)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-02-04 14:43:09 +01:00
The function ~yes-or-no-p~ is also aliased to ~y-or-n-p~ so I only have to
answer by ~y~ or ~n~ instead of typing ~yes~ or ~no~ .
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defalias 'yes-or-no-p 'y-or-n-p)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2020-11-13 00:39:34 +01:00
For some ease of use, I’ ll also declare ~list-buffers~ as an alias of ~ibuffer~ .
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defalias 'list-buffers 'ibuffer)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-02-04 14:43:09 +01:00
~mkcd~ is a function that allows me to create a directory and ~cd~ into it at
the same time.
2020-11-13 00:39:34 +01:00
#+begin_src emacs-lisp
2021-10-12 11:31:20 +02:00
(defun eshell/mkcd ($directory)
(eshell/mkdir "-p" $directory)
(cd $directory))
2020-11-13 00:39:34 +01:00
#+end_src
2020-08-28 16:09:47 +02:00
2023-09-18 18:45:14 +02:00
***** Custom functions
2021-02-04 14:43:09 +01:00
When I’ m in Eshell, sometimes I wish to open multiple files at once in Emacs.
For this, when I have several arguments for ~find-file~ , I want to be able to
open them all at once. Let’ s modify ~find-file~ like so:
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defadvice find-file (around find-files activate)
"Also find all files within a list of files. This even works recursively."
(if (listp filename)
(cl-loop for f in filename do (find-file f wildcards))
ad-do-it))
2020-12-01 21:55:00 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
I also want to be able to have multiple instances of Eshell opened at once. For
that, I declared the function ~eshell-new~ that does exactly that.
2020-12-01 21:55:00 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun eshell-new()
"Open a new instance of eshell."
(interactive)
(eshell 'N))
2020-12-01 21:55:00 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** Redirect text editors to Emacs
2021-02-04 14:43:09 +01:00
I still have some stupid muscle memory telling me to open ~emacs~ in the
terminal, which is stupid with Eshell since I’ m already inside Emacs. So, let’ s
open each file passed to the ~emacs~ command and bury the eshell buffer (we’ ll
get back to it later).
2020-12-01 21:55:00 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun eshell/emacs (&rest $files)
"Open a file in a new buffer. Old habits die hard"
(if $files
(mapc #'find-file
(mapcar #'expand-file-name
(eshell-flatten-list (reverse $files))))
(bury-buffer)))
2020-12-01 21:55:00 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** Environment variables
2021-02-04 14:43:09 +01:00
Some environment variables need to be correctly set so Eshell can correctly
work. The first environment variable to be set is the ~PATH~ , as I have a couple
of directories where executables are located. Let’ s add them to our path.
2020-12-01 21:55:00 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setenv "PATH"
(concat
(getenv "HOME") "/.pub-cache/bin"
":" (getenv "HOME") "/.local/bin"
":" (getenv "HOME") "/go/bin"
":" (getenv "HOME") "/.cargo/bin"
":" (getenv "HOME") "/.gem/ruby/2.6.0/bin"
":" (getenv "PATH")))
2020-12-01 21:55:00 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
I would also like to set two environment variables related to Dart development:
the ~DART_SDK~ and ~ANDROID_HOME~ variables.
2020-12-01 21:55:00 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setenv "DART_SDK" "/opt/dart-sdk/bin")
(setenv "ANDROID_HOME" (concat (getenv "HOME") "/Android/Sdk/ "))
2020-12-01 21:55:00 +01:00
#+END_SRC
Finally, I’ d like to add a custom directory to the ~PKG_CONFIG_PATH~ :
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setenv "PKG_CONFIG_PATH" (concat
"/usr/local/lib/pkgconfig/ " ":"
(getenv "PKG_CONFIG_PATH")))
2020-12-01 21:55:00 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
The ~EDITOR~ variable also needs to be set for git commands, especially the
~yadm~ commands.
2020-12-01 21:55:00 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setenv "EDITOR" "emacsclient -c")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-04-06 09:46:24 +02:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setenv "SHELL" "/bin/sh")
2021-04-06 09:46:24 +02:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** Eshell banner
2021-02-04 14:43:09 +01:00
The code creating the Eshell banner is a bit lengthy and requires some
2023-09-18 18:45:14 +02:00
additional explanations that would make the following chapter [[file:./spacemacs.md#eshell-theme-and-prompt][Eshell
theme and prompt]] too long. So, here it is!
2020-12-07 14:58:30 +01:00
2021-02-04 14:43:09 +01:00
The banner for Eshell will collect some system information and display them
gracefully. These pieces of information are:
2020-12-07 14:58:30 +01:00
- The GNU/Linux distribution running (I do not use any other OS on my computer)
- The kernel name and its version
- The machine’ s hostname
- Its uptime
- Its RAM and Swap usage
- How full are its mountpoints
2021-02-04 14:43:09 +01:00
Some of these information can be grabbed directly from Emacs built-in functions,
but some others need to be retrieved manually. Let’ s first get into it with the
mounted partitions for which we’ ll define a structure:
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(cl-defstruct phundrak/mounted-partitions
"Object representing a mounted partition found in the system"
path size used percent)
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
We’ ll also define a variable setting the maximum length of a partition path
before it gets abbreviated:
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak//eshell-banner--max-length-part 13
"Maximum length of a partition path")
2020-12-07 14:58:30 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
Now, we can get our partitions. For this, we’ ll make a call to the
shell command ~df -lH~ and we’ ll keep only the partitions mounted on a
device stored in ~/dev~ , for instance on ~/dev/sda~ . And as mentioned
above, if the mount path of the partition exceeds the length specified
by ~phundrak//eshell-banner--max-length-part~ , it will get abbreviated
by [[file:./spacemacs.md#phundrak-abbr-path ][=phundrak-abbr-path= ]].
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak/get-mounted-partitions ()
(let ((partitions (s-split "\n"
(shell-command-to-string "df -lH")
t)))
(-keep (lambda (partition)
(let* ((partition (s-split " " partition t))
(filesystem (nth 0 partition))
(size (nth 1 partition))
(used (nth 2 partition))
(percent (nth 4 partition))
(mount (nth 5 partition)))
(when (s-prefix? "/dev" filesystem)
(make-phundrak/mounted-partitions
:path (if (> phundrak//eshell-banner--max-length-part (length mount))
mount
(phundrak-abbr-path mount t))
:size size
:used used
:percent (string-to-number (s-chop-suffix "%" percent))))))
partitions)))
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
We’ ll need some padding for the name of the information displayed on the left
hand side of the banner. The maximum length without any partitions is eight
characters due to the text ~Hostname~ , so if any partition path is longer than
this, the left padding will increase.
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak//eshell-banner--get-left-pad (initial-pad partitions)
(if partitions
(let ((part-length (length (phundrak/mounted-partitions-path (car partitions)))))
(phundrak//eshell-banner--get-left-pad (if (> part-length initial-pad)
part-length
initial-pad)
(cdr partitions)))
initial-pad))
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Now, Let’ s set three variables that will be used in the function following this
declaration. They will be used to determine in which color a percentage should
be displayed. I’ ll consider any percentage below 60% to be acceptable and
therefore displayed in green. However, starting from this threshold, I want the
user to be noticed of the usage of whatever percentage shown that it has gone up
and it should be watched and displayed in yellow. Above 75%, the user should
consider this a warning, and the percentage will be displayed in orange. Above
90%, it is considered critical and the percentage will be displayed in red.
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak//eshell-banner--critical-percentage 90)
(defvar phundrak//eshell-banner--warning-percentage 75)
(defvar phundrak//eshell-banner--notice-percentage 60)
2020-12-07 14:58:30 +01:00
2021-10-12 11:31:20 +02:00
(defun phundrak//eshell-banner--color-percentage (percentage)
(cond
((> percentage phundrak//eshell-banner--critical-percentage)
(with-face (format "%2d" percentage) :foreground phundrak-nord11))
((> percentage phundrak//eshell-banner--warning-percentage)
(with-face (format "%2d" percentage) :foreground phundrak-nord12))
((> percentage phundrak//eshell-banner--notice-percentage)
(with-face (format "%2d" percentage) :foreground phundrak-nord13))
(t
(with-face (format "%2d" percentage) :foreground phundrak-nord14))))
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
This function will be used when displaying progress bars. These will be used for
displaying the Ram, Swap and partitions usage of the system, displaying the used
part in red and the free part in green. For this, we just need to know the size
of the progress bar we wish to use as well as how full it should be. Note that
the percentage should be between 0 and 100.
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak//eshell-banner--progress-bar (length percentage)
(let* ((length-green (if (= 0 percentage)
0
(/ (* length percentage) 100)))
(length-red (- length length-green)))
(concat (with-face "[" :weight 'bold)
(with-face (s-repeat length-green "=")
:weight 'bold :foreground phundrak-nord14)
(with-face (s-repeat length-red "=")
:weight 'bold :foreground phundrak-nord11)
(with-face "]" :weight 'bold))))
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-04-02 19:33:58 +02:00
This function will be used in two distinct functions: ~phundrak-eshell-banner~
2021-02-04 14:43:09 +01:00
which we will see later, and ~phundrak//eshell-banner--display-memory~ which we
will see now. This function displays information for the two types of memory we
have, RAM and Swap memory. Here is the definition of this function:
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak//eshell-banner--display-memory (type used total text-padding ramp-length)
(let ((percentage (if (= used 0)
0
(/ (* 100 used) total))))
(concat (s-pad-right text-padding "." type)
": "
(phundrak//eshell-banner--progress-bar ramp-length
percentage)
(format " %6s / %-5s ("
(file-size-human-readable used)
(file-size-human-readable total))
(phundrak//eshell-banner--color-percentage
percentage)
"%)\n")))
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
We now need a function for displaying partitions. As you can see, it will be
quite similar to the above one:
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak//eshell-banner--display-partition (part left-pad ramp-length)
(concat (s-pad-right left-pad "."
(with-face (phundrak/mounted-partitions-path part)
:weight 'bold))
": "
(phundrak//eshell-banner--progress-bar ramp-length
(phundrak/mounted-partitions-percent part))
(format " %6s / %-5s (%s%%)"
(phundrak/mounted-partitions-used part)
(phundrak/mounted-partitions-size part)
(phundrak//eshell-banner--color-percentage (phundrak/mounted-partitions-percent part)))))
2020-12-07 14:58:30 +01:00
#+END_SRC
And we can now build our banner! Here is our function that does exactly that:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-eshell-banner ()
(let* ((partitions (phundrak/get-mounted-partitions))
(os (replace-regexp-in-string
".*\"\\(.+\\)\""
"\\1"
(car (-filter (lambda (line)
(s-contains? "PRETTY_NAME" line))
(s-lines (phundrak-file-to-string "/etc/os-release"))))))
(memory (-map (lambda (line)
(s-split " " line t))
(s-split "\n"
(shell-command-to-string "free -b | tail -2")
t)))
(ram (nth 0 memory))
(swap (nth 1 memory))
(ramp-length 41)
(left-pad (phundrak//eshell-banner--get-left-pad phundrak/ /eshell-banner--max-length-part partitions))
(right-pad 8)
(left-column-width 27))
(concat (format "%s\n" (s-repeat 79 "="))
;; OS and Kernel
(format "%s: %s%s: %s\n"
(s-pad-right left-pad "." "OS")
(s-pad-right left-column-width
" "
(with-face (s-trim os)
:weight 'bold))
(s-pad-right right-pad "." "Kernel")
(with-face (concat "Linux " operating-system-release)
:weight 'bold))
;; Hostname and Uptime
(format "%s: %s%s: %s\n"
(s-pad-right left-pad "." "Hostname")
(s-pad-right left-column-width
" "
(with-face (system-name) :weight 'bold))
(s-pad-right right-pad "." "Uptime")
(with-face (s-chop-prefix "up "
(s-trim (shell-command-to-string "uptime -p")))
:weight 'bold))
;; RAM ramp
(phundrak//eshell-banner--display-memory "Ram"
(string-to-number (nth 2 ram))
(string-to-number (nth 1 ram))
left-pad
ramp-length)
;; SWAP ramp
(phundrak//eshell-banner--display-memory "Swap"
(string-to-number (nth 2 swap))
(string-to-number (nth 1 swap))
left-pad
ramp-length)
;; Partitions
(mapconcat (lambda (part)
(phundrak//eshell-banner--display-partition part left-pad ramp-length))
partitions
"\n")
(format "\n%s\n" (s-repeat 79 "=")))))
2020-12-07 14:58:30 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
We now only have to set the result of this function as our Eshell banner. Since
2021-04-02 19:33:58 +02:00
a simple ~setq~ would only run ~phundrak-eshell-banner~ once when Emacs starts,
2021-02-04 14:43:09 +01:00
we’ ll actually make Emacs set the value of ~eshell-banner-message~ each time it
is required by Eshell with a hook:
2020-12-07 14:58:30 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'eshell-banner-load-hook
(lambda ()
(setq eshell-banner-message (phundrak-eshell-banner))))
2020-12-07 14:58:30 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** Eshell theme and prompt
As with most shells, again, it is possible to customize the appearance
of the Eshell prompt. As you can see, my prompt has some Nord colors,
a shortened path, a git prompt, and an indicator of whether the
previous command succeeded or failed. Note however that the
abbreviation of the current path depends on the value of
~phundrak-prompt--abbreviate~ , if it is ~t~ it is abbreviated; otherwise,
it is kept in full. It can be toggled with a keyboard shortcut, see
[[file:./spacemacs.md#toggle ][Keybinds: Toggle ]].
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak-eshell-prompt ()
"Definition of my prompt for Eshell
It displays a powerline prompt, with first an abbreviated path to
the current directory. If `phundrak-prompt--abbreviate' is `t',
then all preceding directories will be abbreviated to one
character, except hidden directory which first character will be
preceded by a dot. Otherwise, the full name of the directories is
displayed.
Then, if the current directory is a git repository or one of its
subdirectories, it will display the current state of the
repository. See `phundrak-eshell-git-status'
Finally, a lambda character is displayed, either in blue or in
red depending on if the last eshell command was a success or a
failure respectively."
(let* ((header-bg phundrak-nord0)
($path (phundrak-abbr-path (eshell/pwd)))
($git-path (phundrak-git-repo-root $path))
($abbr-path (phundrak-abbr-path $path phundrak-prompt--abbreviate))
($background phundrak-nord1)
($foreground phundrak-nord14)
($success phundrak-nord10)
($error phundrak-nord11))
(concat (with-face (concat " "
(phundrak-abbr-path (if $git-path
$git-path
$path)
phundrak-prompt--abbreviate)
" ")
:foreground $foreground
:background $background)
(when $git-path
(concat (phundrak-eshell-git-status $path $background)
(with-face (format "%s "
(let (($in-git-path (phundrak-abbr-path (f-relative $path $git-path)
phundrak-prompt--abbreviate)))
(if (string= "." $in-git-path)
""
(concat " " $in-git-path))))
:foreground $foreground
:background $background)))
(with-face "λ "
:foreground (if (zerop eshell-last-command-status)
$success
$error)
:background $background)
(with-face "" :foreground $background)
" ")))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2020-11-13 00:39:34 +01:00
Now, let’ s declare our prompt regexp and our prompt functions:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq eshell-prompt-regexp "^[^\n]*λ "
eshell-prompt-function 'phundrak-eshell-prompt)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-02-07 21:17:29 +01:00
2021-02-04 14:43:09 +01:00
I also don't want the banner to be displayed, I know I entered the Elisp shell,
no need to remind me. Maybe I’ ll do something with it one day.
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq eshell-banner-message "")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-11-06 14:41:29 +01:00
2021-01-04 14:16:37 +01:00
Finally, let’ s enable some fish-like syntax highlighting:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(eshell-syntax-highlighting-global-mode +1)
2021-01-04 14:16:37 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** TODO Fix right column padding :noexport:
2021-04-17 13:00:29 +02:00
The uptime can get longer than allocated in the banner and be longer than the
theoretical longest line the banner can be. Execute the ~uptime~ command, find
out the length of the result and compute the padding based on the maximum length
between the kernel’ s name and the uptime’ s length.
2023-09-18 18:45:14 +02:00
****** TODO Add battery level to banner :noexport:
2021-04-17 12:46:29 +02:00
Add battery level to banner if computer is a laptop, and display if it is
charging or discharging. See [[https://tecosaur.github.io/emacs-config/config.html#simple-settings ][Tecosaur’ s config ]] for a way to detect if a battery
is present or not (basically use the function ~battery~ ).
2023-09-18 18:45:14 +02:00
***** Visual commands
2021-02-04 14:43:09 +01:00
With Eshell, some commands don’ t work very well, especially commands that create
a TUI. So, let’ s declare them as visual commands or subcommands:
2020-12-01 21:55:00 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq eshell-visual-commands
'("fish" "zsh" "bash" "tmux" "htop" "top" "vim" "bat" "nano")
eshell-visual-subcommands
'("git" "log" "l" "diff" "show"))
2020-12-01 21:55:00 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
**** Org-mode
2020-11-14 02:21:26 +01:00
:PROPERTIES:
2020-12-24 22:17:40 +01:00
:header-args:emacs-lisp: :tangle no :exports code :results silent
2020-11-14 02:21:26 +01:00
:END:
2021-02-04 14:43:09 +01:00
Org-mode is probably one of the best if not the best Emacs feature I have ever
discovered. It is awesome for writing documents, regardless of the format you
need it to be exported to, for agenda management, and for literary programming,
such as with this document.
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(with-eval-after-load 'org
;; configuration goes here
)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2021-04-21 22:00:50 +02:00
#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.spacemacs/private/user-config.el :exports none :noweb yes
2021-10-12 11:31:20 +02:00
(with-eval-after-load 'org
;; agenda
<<org-agenda-files >>
<<org-agenda-commands >>
;; Babel
<<org-babel-load-languages >>
<<org-babel-set-geiser >>
<<org-src-tab-acts-natively >>
<<org-confirm-babel >>
;; Beautiful org
<<beautiful-org-hooks >>
<<beautiful-org-options >>
<<beautiful-org-fontify-blocks >>
<<beautiful-org-fontify-inline >>
<<beautiful-org-images >>
<<beautiful-org-latex-inline >>
<<beautiful-org-latex-inline-transparent >>
<<beautiful-org-macro-ellipsis-markers >>
<<beautiful-org-hide-dots >>
;; Capture
<<org-capture-target-files >>
<<org-capture-templates >>
;; Custom functions
;;;; Better IDs
<<org-better-id-new >>
<<org-better-id-get >>
<<org-better-id-add-ids >>
<<org-better-id-hooks >>
;; File export
<<org-use-sub-superscripts >>
;;;; Latex
<<org-latex-compiler >>
<<org-latex-listings >>
<<org-latex-default-packages >>
<<org-export-latex-hyperref-format >>
<<org-latex-pdf-process >>
;;;; HTML
<<org-re-reveal-root >>
<<org-html-validation >>
;; Latex Formats
<<org-latex-classes >>
;; Projects
<<org-publish-projects >>
;; Variables
;;;; Behavior
<<org-use-property-inheritance >>
<<org-list-allow-alphabetical >>
<<org-src-block-lsp >>
<<org-M-RET-may-split-line >>
<<org-src-window-setup >>
<<org-src-window-toggle >>
<<org-id-link-to-org >>
;;;; User information
<<org-user-information >>
)
2020-12-24 12:30:19 +01:00
#+END_SRC
2020-01-16 19:48:14 +01:00
2023-09-18 18:45:14 +02:00
***** Agenda
2021-02-04 14:43:09 +01:00
One awesome feature of Org mode is the agenda. By default, my agendas are stored
in =~/org/agenda= .
2020-12-24 12:30:19 +01:00
#+NAME : org-agenda-files
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-agenda-files (list "~/org/agenda" "~ /org/notes.org"))
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
I also have a custom command in Org agenda to mark some tasks as daily tasks
with the =:DAILY:= tag,:
2020-12-24 12:30:19 +01:00
#+NAME : org-agenda-custom-commands
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-agenda-custom-commands
'(("h" "Daily habits"
((agenda ""))
((org-agenda-show-log t)
(org-agenda-ndays 7)
(org-agenda-log-mode-items '(state))
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notregexp
":DAILY:"))))
("Y" "Yearly events"
((agenda ""))
((org-agenda-show-log t)
(org-agenda-ndays 365)
(org-agenda-log-mode-items '(state))
(org-agenda-skip-entry-if 'notregexp
":YEARLY:")))))
2020-12-23 04:26:27 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** Babel
2021-02-04 14:43:09 +01:00
One of the amazing features of org-mode is its literary programming capacities
by running code blocks from within Org-mode itself. But for that, only a couple
of languages are supported directly by Org-mode itself, and they need to be
activated. Here are the languages I activated in my Org-mode configuration:
2020-12-23 04:26:27 +01:00
#+NAME : org-babel-languages-table
2021-01-18 01:42:09 +01:00
| C |
| dot |
| emacs-lisp |
| gnuplot |
| latex |
| latex-as-png |
| makefile |
| plantuml |
| python |
2021-04-02 19:34:51 +02:00
| restclient |
2021-01-18 01:42:09 +01:00
| sass |
| scheme |
| shell |
2020-12-23 04:26:27 +01:00
#+NAME : org-babel-languages-gen
#+header : :cache yes :results replace
#+header : :var languages=org-babel-languages-table[,0]
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp :exports none
2021-10-12 11:31:20 +02:00
(format "'(%s)"
(mapconcat (lambda ($language)
(format "(%s . t)" $language))
languages
"\n "))
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-04-11 16:08:03 +02:00
#+RESULTS[71d98616bf4f1351ca93aea4972be0ba58057230]: org-babel-languages-gen
2021-02-04 09:20:52 +01:00
#+begin_example
2020-12-27 19:00:30 +01:00
'((C . t)
(dot . t)
(emacs-lisp . t)
(gnuplot . t)
(latex . t)
2021-02-04 09:20:52 +01:00
(latex-as-png . t)
2020-12-27 19:00:30 +01:00
(makefile . t)
(plantuml . t)
(python . t)
2021-04-02 19:34:51 +02:00
(restclient . t)
2020-12-27 19:00:30 +01:00
(sass . t)
(scheme . t)
2021-02-04 09:20:52 +01:00
(shell . t))
#+end_example
2020-12-23 04:26:27 +01:00
The corresponding code is as follows:
2020-12-24 12:30:19 +01:00
#+NAME : org-babel-load-languages
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp :noweb yes
2021-10-12 11:31:20 +02:00
(org-babel-do-load-languages
'org-babel-load-languages
<<org-babel-languages-gen() >>)
2020-12-23 04:26:27 +01:00
#+END_SRC
Scheme requires a default implementation for geiser:
2020-12-24 12:30:19 +01:00
#+NAME : org-babel-set-geiser
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq geiser-default-implementation 'racket)
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
By the way, I wish to see source code behave the same way in the source blocks
as in their own major mode. Let’ s tell Emacs so:
2020-12-24 12:30:19 +01:00
#+NAME : org-src-tab-acts-natively
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-src-tab-acts-natively t)
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Lastly, I know this can be a terrible idea, but I want Emacs to just evaluate
Org code blocks without asking me. Of course, this could represent some big
security issue if not careful enough, but I generaly just open my own org files.
2020-12-24 12:30:19 +01:00
#+NAME : org-confirm-babel
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-confirm-babel-evaluate nil)
2020-12-24 12:30:19 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** Beautify Org-mode
2021-02-04 14:43:09 +01:00
As I will always say, orgmode is an amazing piece of software that deserves
particular care and love. That is why I want to give it a unique look and feel
compared to the rest of my Emacs configuration, in order to make it feel much
more comfortable. You will find below how my org buffers look like when I open
one of them.
2020-12-21 14:56:55 +01:00
2020-12-21 18:19:10 +01:00
#+begin_export html
<p ><img src="./img/org-mode.svg" alt="Screenshot of an org-mode buffer" style="max-height: 900px" / ></p >
#+end_export
2020-12-21 14:56:55 +01:00
2021-02-04 14:43:09 +01:00
In order to make org-mode even sexier, let’ s enable ~variable-pitch-mode~ for
org-mode so we can get some proportional font. I’ ll also remove ~auto-fill-mode~
2021-03-26 13:46:17 +01:00
which seems to stick to Orgmode like hell and I don’ t know why.
2020-12-24 12:30:19 +01:00
#+NAME : beautiful-org-hooks
2020-12-21 14:56:55 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'org-mode-hook 'visual-line-mode)
(remove-hook 'org-mode-hook 'auto-fill-mode)
(add-hook 'org-mode-hook 'variable-pitch-mode)
(auto-fill-mode -1)
2020-12-21 14:56:55 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
You can then see the modified faces for org-mode [[file:./spacemacs.md#org-mode ][here ]].
2020-12-21 14:56:55 +01:00
2021-03-26 13:46:17 +01:00
By default, I would like my org-mode buffers to be indented and tables to be
aligned.
2020-12-24 12:30:19 +01:00
#+NAME : beautiful-org-options
2020-12-21 14:56:55 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-startup-indented t
org-startup-align-all-tables t)
2021-03-26 13:46:17 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** Fontifying parts of org-mode
2021-03-26 13:46:17 +01:00
Some blocks of org-mode should have their own face, such as the whole heading
line, the done headline, the quote and the verse blocks,… actually, let’ s enable
that for all of them.
#+name : beautiful-org-fontify-blocks
#+BEGIN_SRC emacs-lisp
(setq org-pretty-entities t
org-fontify-whole-heading-line t
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t)
#+END_SRC
2023-09-18 18:45:14 +02:00
****** Fontifying inline src blocks
2021-03-26 13:46:17 +01:00
When it comes to source blocks in org-mode, Emacs handle them really well with
some beautiful syntax highlight thanks to the the languages’ major mode and
their font-locks. But inline src blocks are the forgotten child and get next to
no love, which is really sad ; I want it to feel loved, to stand out from the
crowd and to give me what its brother gives me already!
Enters [[https://tecosaur.github.io/emacs-config/config.html#fontifying-inline-src ][Tecosaur’ s config ]]! With ~org-src-font-lock-fontify-block~ , anything’ s
possible! And ~{{{results(...)}}}~ can also have the ~org-block~ face applied to
match and make org-mode even more beautiful! Let’ s do it:
#+name : beautiful-org-fontify-inline
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar org-prettify-inline-results t
"Whether to use (ab)use prettify-symbols-mode on
{{{results(...)}}} .")
(defun org-fontify-inline-src-blocks (limit)
"Try to apply `org-fontify-inline-src-blocks-1'."
(condition-case nil
(org-fontify-inline-src-blocks-1 limit)
(error (message "Org mode fontification error in %S at %d"
(current-buffer)
(line-number-at-pos)))))
(defun org-fontify-inline-src-blocks-1 (limit)
"Fontify inline src_LANG blocks, from `point' up to `LIMIT'."
(let ((case-fold-search t))
(when
; stolen from `org-element-inline-src-block-parser'
(re-search-forward "\\_<src_ \\([^ \t\n[{]+\\)[{[]?" limit t)
(let ((beg (match-beginning 0))
pt
(lang-beg (match-beginning 1))
(lang-end (match-end 1)))
(remove-text-properties beg lang-end '(face nil))
(font-lock-append-text-property lang-beg lang-end 'face 'org-meta-line)
(font-lock-append-text-property beg lang-beg 'face 'shadow)
(font-lock-append-text-property beg lang-end 'face 'org-block)
(setq pt (goto-char lang-end))
(when (org-element--parse-paired-brackets ?\[)
(remove-text-properties pt (point) '(face nil))
(font-lock-append-text-property pt
(point)
'face
'org-block)
(setq pt (point)))
(when (org-element--parse-paired-brackets ?\{)
(remove-text-properties pt (point) '(face nil))
(font-lock-append-text-property pt
(1+ pt)
'face
'(org-block shadow))
(unless (= (1+ pt) (1- (point)))
(if org-src-fontify-natively
(org-src-font-lock-fontify-block
(buffer-substring-no-properties lang-beg
lang-end)
(1+ pt)
(1- (point)))
(font-lock-append-text-property (1+ pt)
(1- (point))
'face
'org-block)))
(font-lock-append-text-property (1- (point))
(point)
'face
'(org-block shadow))
(setq pt (point)))
(when (and org-prettify-inline-results
(re-search-forward "\\= {{{results(" limit t))
(font-lock-append-text-property pt
(1+ pt)
'face
'org-block)
(goto-char pt))))
(when (and org-prettify-inline-results
(re-search-forward "{{{results(\\(.+?\\))}}} "
limit t))
(remove-list-of-text-properties (match-beginning 0)
(point)
'(composition prettify-symbols-start prettify-symbols-end))
(font-lock-append-text-property (match-beginning 0)
(match-end 0)
'face
'org-block)
(let ((start (match-beginning 0))
(end (match-beginning 1)))
(with-silent-modifications (compose-region start end "⟨")
(add-text-properties start
end
`(prettify-symbols-start ,start prettify-symbols-end
,end))))
(let ((start (match-end 1))
(end (point)))
(with-silent-modifications (compose-region start end "⟩")
(add-text-properties start
end
`(prettify-symbols-start ,start prettify-symbols-end
,end)))))))
(defun org-fontify-inline-src-blocks-enable ()
"Add inline src fontification to font-lock in Org.
Must be run as part of `org-font-lock-set-keywords-hook'."
(setq org-font-lock-extra-keywords
(append org-font-lock-extra-keywords '((org-fontify-inline-src-blocks)))))
(add-hook 'org-font-lock-set-keywords-hook #'org-fontify-inline-src-blocks-enable)
2021-03-26 13:46:17 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** Images in org-mode
2021-03-26 13:46:17 +01:00
By default, images should be displayed inline, but not with a too large width. I
found that 550px fits well, since that is roughly the average width of the text
when ~org-fill-paragraph~ is called. Let’ s also tell org-mode to display images
as inline images and redisplay them when needed.
#+NAME : beautiful-org-images
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-image-actual-width 550
org-redisplay-inline-images t
org-display-inline-images t
org-startup-with-inline-images "inlineimages")
2020-12-21 14:56:55 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** Prettier LaTeX inline rendering
2021-03-26 13:46:17 +01:00
[[https://tecosaur.github.io/emacs-config/config.html#prettier-rendering ][Tecosaur strikes again ]]! Let’ s admit it, inline LaTeX code looks cool, properly
formatted LaTeX inline fragments look rad! Let’ s fix their appearance:
#+name : beautiful-org-latex-inline
2020-12-21 14:56:55 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-format-latex-header "\\documentclass{article}
\\usepackage[usenames]{color}
\\usepackage[T1]{fontenc}
\\usepackage{booktabs}
\\pagestyle{empty} % do not remove
% The settings below are copied from fullpage.sty
\\setlength{\\textwidth}{\\paperwidth}
\\addtolength{\\textwidth}{-3cm}
\\setlength{\\oddsidemargin}{1.5cm}
\\addtolength{\\oddsidemargin}{-2.54cm}
\\setlength{\\evensidemargin}{\\oddsidemargin}
\\setlength{\\textheight}{\\paperheight}
\\addtolength{\\textheight}{-\\headheight}
\\addtolength{\\textheight}{-\\headsep}
\\addtolength{\\textheight}{-\\footskip}
\\addtolength{\\textheight}{-3cm}
\\setlength{\\topmargin}{1.5cm}
\\addtolength{\\topmargin}{-2.54cm}
% my custom stuff
\\usepackage[nofont,plaindd]{bmc-maths}
\\usepackage{arev}
")
2021-03-26 13:46:17 +01:00
#+END_SRC
And I much prefer when LaTeX fragments are transparent, so let’ s make them.
#+name : beautiful-org-latex-inline-transparent
#+BEGIN_SRC emacs-lisp
(setq org-format-latex-options
(plist-put org-format-latex-options :background "Transparent"))
2020-12-21 14:56:55 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** Symbols
2021-03-26 13:46:17 +01:00
I visually prefer to have a nicer folding icon in Emacs and the markers of macros hidden.
#+NAME : beautiful-org-macro-ellipsis-markers
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-hide-macro-markers t
org-ellipsis " ")
2020-12-24 12:30:19 +01:00
#+END_SRC
I also have an issue where small dots precede my org headers. Let’ s fix that:
#+NAME : beautiful-org-hide-dots
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-hide-leading-stars nil
org-superstar-leading-bullet ?\s)
2020-12-24 12:30:19 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** TODO Fix org-appear :noexport:
***** Behavior
2021-02-04 14:43:09 +01:00
Something really neat I learned about is the ability of org headers to inherit
properties from parent headers. Let’ s enable that!
2020-12-27 17:01:50 +01:00
#+NAME : org-use-property-inheritance
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-use-property-inheritance t)
2020-12-27 17:01:50 +01:00
#+END_SRC
Sometimes, I also want to have alphabetical lists in org-mode:
#+NAME : org-list-allow-alphabetical
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-list-allow-alphabetical t)
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
LSP can work in source blocks, but some work is needed (shamelessly stolen [[https://tecosaur.github.io/emacs-config/config.html#lsp-support-src][from
here]], though modified a tiny bit). Here are the languages I want to activate LSP
for in this environment:
2020-12-27 17:01:50 +01:00
#+NAME : org-lsp-languages-src-blocks-table
| c |
| c++ |
| dart |
| python |
| rust |
#+NAME : org-lsp-languages-src-blocks-gen
#+header : :cache yes :results replace
#+header : :var languages=org-lsp-languages-src-blocks-table[,0]
#+BEGIN_SRC emacs-lisp :exports none
2021-10-12 11:31:20 +02:00
(mapconcat (lambda (lang)
(format "\"%s\"" lang))
languages
" ")
2020-12-27 17:01:50 +01:00
#+END_SRC
#+RESULTS[cbfba838da4510647d09bfd0fd2f20996c8cad38]: org-lsp-languages-src-blocks-gen
: "c" "c++" "dart" "python" "rust"
And here is the code to activate that:
#+NAME : org-src-block-lsp
#+BEGIN_SRC emacs-lisp :noweb yes
2021-10-12 11:31:20 +02:00
(cl-defmacro lsp-org-babel-enable (lang)
"Support LANG in org source code block."
(setq centaur-lsp 'lsp-mode)
(cl-check-type lang stringp)
(let* ((edit-pre (intern (format "org-babel-edit-prep:%s" lang)))
(intern-pre (intern (format "lsp--%s" (symbol-name edit-pre)))))
`(progn
(defun ,intern-pre (info)
(let ((file-name (->> info caddr (alist-get :file))))
(unless file-name
(setq file-name (make-temp-file "babel-lsp-")))
(setq buffer-file-name file-name)
(lsp-deferred)))
(put ',intern-pre 'function-documentation
(format "Enable lsp-mode in the buffer of org source block (%s)."
(upcase ,lang)))
(if (fboundp ',edit-pre)
(advice-add ',edit-pre :after ',intern-pre)
(progn
(defun ,edit-pre (info)
(,intern-pre info))
(put ',edit-pre 'function-documentation
(format "Prepare local buffer environment for org source block (%s)."
(upcase ,lang))))))))
(defvar org-babel-lsp-lang-list
'(<<org-lsp-languages-src-blocks-gen() >>))
(dolist (lang org-babel-lsp-lang-list)
(eval `(lsp-org-babel-enable ,lang)))
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Here is one behavior that I really want to see modified: the ability to use
~M-RET~ without slicing the text the marker is on.
2020-12-27 17:01:50 +01:00
#+NAME : org-M-RET-may-split-line
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-M-RET-may-split-line nil)
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Since Org 9.3, Org no longer attempts to restore the window configuration in the
frame to which the user returns after editing a source block with
~org-edit-src-code~ . This means with the original value of
~org-src-window-setup~ (~reorganize-frame~ ), the current frame will be split in
two between the original org window and the source window, and once we quit the
source window only the org window will remain. This is not a desired behavior
for me, so I chose to set this variable to ~split-window-right~ in order to keep
my windows organization and have a similar behavior to the old one.
2020-12-27 17:01:50 +01:00
#+NAME : org-src-window-setup
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-src-window-setup 'split-window-below)
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
However, it is not rare that I want to change that for an horizontal split,
which can be achieved with the value ~split-window-below~ . Thus, I have made
this function that allows me to switch between the (default) vertical split and
the horizontal split.
2020-12-27 17:01:50 +01:00
#+NAME : org-src-window-toggle
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun phundrak/toggle-org-src-window-split ()
"This function allows the user to toggle the behavior of
`org-edit-src-code'. If the variable `org-src-window-setup' has
the value `split-window-right', then it will be changed to
`split-window-below'. Otherwise, it will be set back to
`split-window-right'"
(interactive)
(if (equal org-src-window-setup 'split-window-right)
(setq org-src-window-setup 'split-window-below)
(setq org-src-window-setup 'split-window-right))
(message "Org-src buffers will now split %s"
(if (equal org-src-window-setup 'split-window-right)
"vertically"
"horizontally")))
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
When creating a link to an Org flie, I want to create an ID only if the link is
created interactively, and only if there is no custom ID already created.
2020-12-27 17:01:50 +01:00
#+NAME : org-id-link-to-org
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
The tag ~:noexport:~ is fine and all, but it doesn’ t allow for hidden org
structures, that is headers that are visible in the org buffer but once the file
is exported to another format the header disappears but its content stays.
~ox-extra~ has such a feature through ~ignore-headlines~ .
2020-12-27 17:01:50 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(require 'ox-extra)
(ox-extras-activate '(ignore-headlines))
2020-12-27 17:01:50 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
This gives us access to the ~:ignore:~ tag which allows the behavior above
2021-09-01 21:58:52 +02:00
mentioned.
2020-12-27 17:01:50 +01:00
2023-09-18 18:45:14 +02:00
***** Capture
2020-11-14 02:21:26 +01:00
:PROPERTIES:
2021-03-26 13:46:17 +01:00
:header-args:org: :mkdirp yes :padline no
2020-11-14 02:21:26 +01:00
:END:
2021-02-04 14:43:09 +01:00
Org-capture is an amazing feature of Org-mode which allows me to quickly save
links, resources, reminders, and notes in neatly organized org files. Here they
are described:
2020-12-24 12:30:19 +01:00
#+NAME : org-capture-target-files
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar org-conlanging-file "~/org/conlanging.org")
(defvar org-default-notes-file "~/org/notes.org")
(defvar org-journal-file "~/org/journal.org")
(defvar org-linguistics-notes-file "~/org/linguistics-notes.org")
(defvar org-novel-notes-file "~/org/novel-notes.org")
(defvar org-private-agenda-file "~/org/agenda/private.org")
(defvar org-school-agenda-file "~/org/agenda/school.org")
(defvar org-wordbuilding-file "~/org/worldbuilding.org")
2020-11-13 00:39:34 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
With Spacemacs, an Org capture can be invoked with the shortcut ~SPC a o c~ . It
will then ask which template I wish to use. In the table below are described the
shortcuts that are available after ~SPC a o c~ is invoked. The /name/ will be
the one displayed in Org capture’ s interface, the /title/ is the headline where
to save the capture (if it does not differ from the capture’ s name, the cell
will be blank). The /insertion mode/ tells Emacs how to add the capture to the
/file/ , using which /template/ . A line with no insertion mode, file, or template
is just a category. All of the following insert entries to their org files, that
is a new org node with a headline and some content.
2020-12-23 04:26:27 +01:00
#+NAME : org-capture-shortcuts-table
2021-01-02 15:36:26 +01:00
| Shortcut | Name | Title | Insertion mode | file | template |
|----------+---------------+-----------+----------------+-------------------------+--------------------------|
| e | Email | | | | |
| ew | Write Email | Emails | file+headline | org-default-notes-file | emails.orgcaptmpl |
| j | Journal | | file+datetree | org-journal-file | journal.orgcaptmpl |
| l | Link | | | | |
| ll | General | | file+headline | org-default-notes-file | link.orgcaptmpl |
| ly | YouTube | | file+headline | org-default-notes-file | youtube.orgcaptmpl |
| L | Protocol Link | Link | file+headline | org-default-notes-file | protocol-link.orgcaptmpl |
| n | Notes | | | | |
| nc | Conlanging | Note | file+headline | org-conlanging-file | notes.orgcaptmpl |
| nn | General | | file+headline | org-default-notes-file | notes.orgcaptmpl |
| nN | Novel | Note | file+headline | org-novel-notes-file | notes.orgcaptmpl |
| nq | Quote | | file+headline | org-default-notes-file | notes-quote.orgcaptmpl |
| nw | Worldbuilding | Note | file+headline | org-wordbuilding-file | notes.orgcaptmpl |
| N | Novel | | | | |
| Ni | Ideas | | file+headline | org-novel-notes-file | notes.orgcaptmpl |
| p | Protocol | Link | file+headline | org-default-notes-file | protocol.orgcaptmpl |
| r | Resources | | | | |
| rc | Conlanging | Resources | file+headline | org-conlanging-file | resource.orgcaptmpl |
| re | Emacs | | file+headline | org-default-notes-file | resource.orgcaptmpl |
| ri | Informatique | | file+headline | org-default-notes-file | resource.orgcaptmpl |
| rl | Linguistics | | file+headline | org-default-notes-file | resource.orgcaptmpl |
| rL | Linux | | file+headline | org-default-notes-file | resource.orgcaptmpl |
| rw | Worldbuilding | Resources | file+headline | org-wordbuilding-file | resource.orgcaptmpl |
| t | Tasks | | | | |
| tb | Birthday | | file+headline | org-private-agenda-file | birthday.orgcaptmpl |
| te | Event | | file+headline | org-private-agenda-file | event.orgcaptmpl |
| th | Health | | file+headline | org-private-agenda-file | health.orgcaptmpl |
| ti | Informatique | | file+headline | org-private-agenda-file | informatique.orgcaptmpl |
2020-11-13 00:39:34 +01:00
2020-12-23 04:26:27 +01:00
#+NAME : org-capture-shortcut-gen
2021-04-02 19:32:01 +02:00
#+header : :exports none :cache yes :results replace
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp :var table=org-capture-shortcuts-table
2021-10-12 11:31:20 +02:00
(format "'(%s)"
(mapconcat (lambda (entry)
(let* ((shortcut (nth 0 entry))
(name (nth 1 entry))
(title (nth 2 entry))
(insertmode (nth 3 entry))
(fileinsert (nth 4 entry))
(sourceorg (nth 5 entry)))
(if (string= "" insertmode)
(format "(\"%s\" \"%s\")" shortcut name)
(concat (format "(\"%s\" \"%s\" entry\n" shortcut name)
(format " (%s %s%s)\n" insertmode fileinsert
(if (string= "file+datetree" insertmode) ""
(format " \"%s\"" (if (string= "" title) name title))))
(format " (file \"~/org/capture/ %s\"))" sourceorg)))) )
table "\n "))
2020-12-27 19:00:30 +01:00
#+END_SRC
2021-01-02 15:36:26 +01:00
#+RESULTS[ec10a65e789d0f3d318de419a7c08e1f41dcb65a]: org-capture-shortcut-gen
2020-11-13 00:39:34 +01:00
#+begin_example
2020-12-27 19:00:30 +01:00
'(("e" "Email")
("ew" "Write Email" entry
(file+headline org-default-notes-file "Emails")
(file "~/org/capture/emails.orgcaptmpl"))
("j" "Journal" entry
(file+datetree org-journal-file)
(file "~/org/capture/journal.orgcaptmpl"))
("l" "Link")
("ll" "General" entry
(file+headline org-default-notes-file "General")
2020-12-30 00:11:22 +01:00
(file "~/org/capture/link.orgcaptmpl"))
2020-12-27 19:00:30 +01:00
("ly" "YouTube" entry
(file+headline org-default-notes-file "YouTube")
(file "~/org/capture/youtube.orgcaptmpl"))
("L" "Protocol Link" entry
(file+headline org-default-notes-file "Link")
(file "~/org/capture/protocol-link.orgcaptmpl"))
("n" "Notes")
("nc" "Conlanging" entry
(file+headline org-conlanging-file "Note")
(file "~/org/capture/notes.orgcaptmpl"))
("nn" "General" entry
(file+headline org-default-notes-file "General")
(file "~/org/capture/notes.orgcaptmpl"))
("nN" "Novel" entry
(file+headline org-novel-notes-file "Note")
(file "~/org/capture/notes.orgcaptmpl"))
("nq" "Quote" entry
(file+headline org-default-notes-file "Quote")
(file "~/org/capture/notes-quote.orgcaptmpl"))
("nw" "Worldbuilding" entry
(file+headline org-wordbuilding-file "Note")
(file "~/org/capture/notes.orgcaptmpl"))
("N" "Novel")
("Ni" "Ideas" entry
(file+headline org-novel-notes-file "Ideas")
(file "~/org/capture/notes.orgcaptmpl"))
("p" "Protocol" entry
(file+headline org-default-notes-file "Link")
(file "~/org/capture/protocol.orgcaptmpl"))
("r" "Resources")
("rc" "Conlanging" entry
2021-01-02 15:36:26 +01:00
(file+headline org-conlanging-file "Resources")
2020-12-27 19:00:30 +01:00
(file "~/org/capture/resource.orgcaptmpl"))
("re" "Emacs" entry
(file+headline org-default-notes-file "Emacs")
(file "~/org/capture/resource.orgcaptmpl"))
("ri" "Informatique" entry
(file+headline org-default-notes-file "Informatique")
(file "~/org/capture/resource.orgcaptmpl"))
("rl" "Linguistics" entry
(file+headline org-default-notes-file "Linguistics")
(file "~/org/capture/resource.orgcaptmpl"))
2020-12-30 00:11:22 +01:00
("rL" "Linux" entry
(file+headline org-default-notes-file "Linux")
(file "~/org/capture/resource.orgcaptmpl"))
2020-12-27 19:00:30 +01:00
("rw" "Worldbuilding" entry
2021-01-02 15:36:26 +01:00
(file+headline org-wordbuilding-file "Resources")
2020-12-27 19:00:30 +01:00
(file "~/org/capture/resource.orgcaptmpl"))
("t" "Tasks")
("tb" "Birthday" entry
(file+headline org-private-agenda-file "Birthday")
(file "~/org/capture/birthday.orgcaptmpl"))
("te" "Event" entry
(file+headline org-private-agenda-file "Event")
(file "~/org/capture/event.orgcaptmpl"))
("th" "Health" entry
(file+headline org-private-agenda-file "Health")
(file "~/org/capture/health.orgcaptmpl"))
("ti" "Informatique" entry
(file+headline org-private-agenda-file "Informatique")
(file "~/org/capture/informatique.orgcaptmpl")))
2020-11-13 00:39:34 +01:00
#+end_example
Below you can find the equivalent code as described above.
2020-12-24 12:30:19 +01:00
#+NAME : org-capture-templates
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :noweb yes
2021-10-12 11:31:20 +02:00
(setq
org-capture-templates
<<org-capture-shortcut-gen() >>)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2021-02-04 14:43:09 +01:00
You may notice a capture entry for my journal, and this is due to the fact I do
not use ~org-journal~ anymore: it was too overpowered for me, and I prefer to
keep it simple with a single file. And as you can see, and unlike a lot of other
Emacs configurations, the content of the template is not set in the variable,
but in external files which can be modified freely as actual Org buffers instead
of trying to get a proper one with loads of ~\n~ characters and such. All these
templates are declared below.
2020-08-28 16:09:47 +02:00
2021-09-01 21:58:52 +02:00
My org capture templates are not tangled into my Emacs configuration
files, but into separate ~.orgcaptmpl~ files stored into =~/org/capture/= .
You can find these in my repository [[https://labs.phundrak.com/phundrak/dotfiles/src/branch/master/org/capture ][here ]] or [[https://github.com/Phundrak/dotfiles/tree/master/org/capture ][here ]].
2020-12-23 04:26:27 +01:00
2023-09-18 18:45:14 +02:00
***** Custom org-mode functions
2020-12-23 04:26:27 +01:00
We begin with a couple of custom functions that I use in my org-mode files.
2023-09-18 18:45:14 +02:00
****** Custom and unique headings ID
2021-02-04 14:43:09 +01:00
The first ones are dedicated to provide org-mode headings a fixed and unique ID
that won’ t change over time. This code was taken from
[[https://writequit.org/articles/emacs-org-mode-generate-ids.html ][https://writequit.org/articles/emacs-org-mode-generate-ids.html ]]. The first
function’ s job is to create these unique IDs
2020-12-24 12:30:19 +01:00
#+NAME : org-better-id-new
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun eos/org-id-new (&optional prefix)
"Create a new globally unique ID.
An ID consists of two parts separated by a colon:
- a prefix
- a unique part that will be created according to
`org-id-method'.
PREFIX can specify the prefix, the default is given by the
variable `org-id-prefix'. However, if PREFIX is the symbol
`none', don't use any prefix even if `org-id-prefix' specifies
one.
So a typical ID could look like \"Org-4nd91V40HI\"."
(let* ((prefix (if (eq prefix 'none)
""
(concat (or prefix org-id-prefix)
"-"))) unique)
(when (equal prefix "-")
(setq prefix ""))
(cond
((memq org-id-method
'(uuidgen uuid))
(setq unique (org-trim (shell-command-to-string org-id-uuid-program)))
(unless (org-uuidgen-p unique)
(setq unique (org-id-uuid))))
((eq org-id-method 'org)
(let* ((etime (org-reverse-string (org-id-time-to-b36)))
(postfix (when org-id-include-domain
(progn
(require 'message)
(concat "@"
(message-make-fqdn))))))
(setq unique (concat etime postfix))))
(t (error "Invalid `org-id-method'")))
(concat prefix (car (split-string unique "-")))))
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Now, let’ s see the function that will be used to get the custom id of a heading
at point. If the function does not detect any custom ID, then one should be
created and inserted.
2020-12-24 12:30:19 +01:00
#+NAME : org-better-id-get
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun eos/org-custom-id-get (&optional pom create prefix)
"Get the CUSTOM_ID property of the entry at point-or-marker POM.
If POM is nil, refer to the entry at point. If the entry does not
have an CUSTOM_ID, the function returns nil. However, when CREATE
is non nil, create a CUSTOM_ID if none is present already. PREFIX
will be passed through to `eos/org-id-new'. In any case, the
CUSTOM_ID of the entry is returned."
(interactive)
(org-with-point-at pom
(let* ((orgpath (mapconcat #'identity (org-get-outline-path) "-"))
(heading (replace-regexp-in-string
"[_-]+$" ""
(replace-regexp-in-string
"[-_]+" "-"
(replace-regexp-in-string
"[^a-zA-Z0-9-_]" "-"
(if (string= orgpath "")
(org-get-heading t t t t)
(concat orgpath "_" (org-get-heading t t t t)))))))
(id (org-entry-get nil "CUSTOM_ID")))
(cond
((and id
(stringp id)
(string-match "\\S-" id)) id)
(create (setq id (eos/org-id-new (concat prefix heading)))
(org-entry-put pom "CUSTOM_ID" id)
(org-id-add-location id
(buffer-file-name (buffer-base-buffer)))
id)))))
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Finally, this is the function that gets called on file saves. If the function
detects ~auto-id:t~ among the org options in the ~#+OPTIONS:~ header, then the
above function is called.
2020-12-24 12:30:19 +01:00
#+NAME : org-better-id-add-ids
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun eos/org-add-ids-to-headlines-in-file ()
"Add CUSTOM_ID properties to all headlines in the current file
which do not already have one.
2020-12-23 04:26:27 +01:00
2021-10-12 11:31:20 +02:00
Only adds ids if the `auto-id' option is set to `t' in the file
somewhere. ie, #+OPTIONS: auto-id:t"
(interactive)
(save-excursion
(widen)
(goto-char (point-min))
(when (re-search-forward "^#\\+OPTIONS:.*auto-id:t" (point-max) t)
(org-map-entries (lambda () (eos/org-custom-id-get (point) 'create))))))
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Let’ s add a hook to the above function so it is called automatically on save,
and only in read-write functions.
2020-12-24 12:30:19 +01:00
#+NAME : org-better-id-hooks
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(add-hook 'org-mode-hook
(lambda ()
(add-hook 'before-save-hook
(lambda ()
(when (and (eq major-mode 'org-mode)
(eq buffer-read-only nil))
(eos/org-add-ids-to-headlines-in-file))))))
2020-12-23 04:26:27 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** File export
2021-02-04 14:43:09 +01:00
I want to disable by default behavior of ~^~ and ~_~ for only one character,
making it compulsory to use instead ~^{}~ and ~_{}~ respectively. This is due to
my frequent usage of the underscore in my org files as a regular character and
not a markup one, especially when describing phonetics evolution. So, let’ s
disable it:
2020-12-24 12:30:19 +01:00
#+NAME : org-use-sub-superscripts
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-use-sub-superscripts (quote {}))
2020-12-24 12:30:19 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
****** LaTeX
2021-02-04 14:43:09 +01:00
When it comes to exports, I want the LaTeX and PDF exports to be done with
XeLaTeX only. This implies the modification of the following variable:
2020-12-24 12:30:19 +01:00
#+NAME : org-latex-compiler
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-latex-compiler "xelatex")
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
I also want to get by default ~minted~ for LaTeX listings so I can have syntax
highlights:
2020-12-24 12:30:19 +01:00
#+NAME : org-latex-listings
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-latex-listings 'minted)
2020-12-23 04:26:27 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
The default packages break my LaTeX exports: for some reasons, images are not
loaded and exported in PDFs, so I needed to redifine the default packages
excluding the one that broke my exports. I also added two default packages,
~minted~ and ~xeCJK~ for syntax highlighting and Japanese (and additionally
Chinese and Korean) support.
2020-12-24 12:30:19 +01:00
#+NAME : org-latex-default-packages
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-latex-default-packages-alist '(("" "graphicx" t)
("T1" "fontspec" t ("pdflatex"))
("" "longtable" nil)
("" "wrapfig" nil)
("" "rotating" nil)
("normalem" "ulem" t)
("" "amsmath" t)
("" "textcomp" t)
("" "amssymb" t)
("" "capt-of" nil)
("" "minted" nil)
("" "hyperref" nil)))
2020-12-23 04:26:27 +01:00
#+END_SRC
By the way, reference links in LaTeX should be written in this format:
2020-12-24 12:30:19 +01:00
#+NAME : org-export-latex-hyperref-format
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-export-latex-hyperref-format "\\ref{%s}")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2021-02-04 14:43:09 +01:00
When it comes to the export itself, the latex file needs to be processed several
times through XeLaTeX in order to get some references right. Don’ t forget to
also run bibtex!
2020-12-24 12:30:19 +01:00
#+NAME : org-latex-pdf-process
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-latex-pdf-process
'("xelatex -8bit -shell-escape -interaction nonstopmode -output-directory %o %f"
"bibtex %b"
"xelatex -8bit -shell-escape -interaction nonstopmode -output-directory %o %f"
"xelatex -8bit -shell-escape -interaction nonstopmode -output-directory %o %f"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2023-09-18 18:45:14 +02:00
****** HTML
2020-12-23 04:26:27 +01:00
For Reveal.JS exports, I need to set where to find the framework by default:
2020-12-24 12:30:19 +01:00
#+NAME : org-re-reveal-root
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2021-02-04 14:43:09 +01:00
On HTML exports, Org-mode tries to include a validation link for the exported
HTML. Let’ s disable that since I never use it.
2020-12-24 12:30:19 +01:00
#+NAME : org-html-validation
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(setq org-html-validation-link nil)
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2021-03-26 13:46:17 +01:00
However, something I very often use are metadata information in my HTML files. I
just want to automate that. Fortunately, [[https://tecosaur.github.io/emacs-config/config.html#extra-header-content,code--3 ][Tecosaur comes to the rescue ]]! First,
here is our function that will generate all the meta tags in our HTML:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defun org-html-meta-tags-fancy (info)
"Use the INFO plist to construct the meta tags, as described in
`org-html-meta-tags'."
(message "%s" info)
(let ((title (org-html-plain-text
(org-element-interpret-data (plist-get info :title)) info))
(author (and (plist-get info :with-author)
(let ((auth (plist-get info :author)))
;; Return raw Org syntax.
(and auth (org-html-plain-text
(org-element-interpret-data auth) info))))))
(list
(when (org-string-nw-p author)
(list "name" "author" author))
(when (org-string-nw-p (plist-get info :description))
(list "name" "description"
(plist-get info :description)))
'("name" "generator" "org mode (Emacs)")
'("name" "theme-color" "#3b4252")
'("property" "og:type" "article")
(list "property" "og:title" title)
(let ((subtitle (org-export-data (plist-get info :subtitle) info)))
(when (org-string-nw-p subtitle)
(list "property" "og:description" subtitle)))
(let ((meta-image (org-export-data (plist-get info :metaimage) info)))
(when (org-string-nw-p meta-image)
(list "property" "og:image" meta-image)))
(let ((meta-image-type (org-export-data (plist-get info :metaimagetype) info)))
(when (org-string-nw-p meta-image-type)
(list "property" "og:image:type" meta-image-type)))
(let ((meta-image-width (org-export-data (plist-get info :metaimagewidth) info)))
(when (org-string-nw-p meta-image-width)
(list "property" "og:image:width" meta-image-width)))
(let ((meta-image-height (org-export-data (plist-get info :metaimageheight) info)))
(when (org-string-nw-p meta-image-height)
(list "property" "og:image:height" meta-image-height)))
(let ((meta-image-alt (org-export-data (plist-get info :metaimagealt) info)))
(when (org-string-nw-p meta-image-alt)
(list "property" "og:image:alt" meta-image-alt)))
(when (org-string-nw-p author)
(list "property" "og:article:author:first_name" (car (s-split-up-to " " author 2))))
(when (and (org-string-nw-p author) (s-contains-p " " author))
(list "property" "og:article:author:last_name" (cadr (s-split-up-to " " author 2))))
(list "property" "og:article:published_time" (format-time-string "%FT%T%z")))))
2021-03-26 13:46:17 +01:00
#+END_SRC
This will use some special keywords in our org buffer and insert their content in
Now let’ s bind it to when we export our org buffer to HTML:
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(unless (functionp #'org-html-meta-tags-default)
(defalias 'org-html-meta-tags-default #'ignore))
(setq org-html-meta-tags #'org-html-meta-tags-fancy)
2021-03-26 13:46:17 +01:00
#+END_SRC
2023-09-18 18:45:14 +02:00
***** LaTeX formats
2021-02-04 14:43:09 +01:00
I currently have two custom formats for my Org-mode exports: one for general use
(initialy for my conlanging files, hence its ~conlang~ name), and one for beamer
exports.
2020-12-23 04:26:27 +01:00
Below is the declaration of the ~conlang~ LaTeX class:
#+NAME : org-latex-class-conlang
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
'("conlang"
"\\documentclass{book}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2020-12-23 04:26:27 +01:00
And here is the declaration of the ~beamer~ class:
#+NAME : org-latex-class-beamer
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
`("beamer"
,(concat "\\documentclass[presentation]{beamer}\n"
"[DEFAULT-PACKAGES]"
"[PACKAGES]"
"[EXTRA]\n")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2020-12-23 04:26:27 +01:00
Both these classes have to be added to ~org-latex-classes~ like so:
2020-12-24 12:30:19 +01:00
#+NAME : org-latex-classes
2020-12-23 04:26:27 +01:00
#+BEGIN_SRC emacs-lisp :noweb yes
2021-10-12 11:31:20 +02:00
(eval-after-load "ox-latex"
'(progn
(add-to-list 'org-latex-classes
<<org-latex-class-conlang >>
)
(add-to-list 'org-latex-classes
<<org-latex-class-beamer >>
)))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2023-09-18 18:45:14 +02:00
***** Projects
2021-02-04 14:43:09 +01:00
Another great features of Org-mode is the Org projects that allow the user to
easily publish a bunch of org files to a remote location. Here is the current
declaration of my projects, which will be detailed later:
2020-12-24 12:30:19 +01:00
#+NAME : org-publish-projects
2020-11-13 00:39:34 +01:00
#+BEGIN_SRC emacs-lisp :noweb yes
2021-10-12 11:31:20 +02:00
<<org-proj-config-setup >>
<<org-proj-lang-setup >>
(setq org-publish-project-alist
`(
<<org-proj-config-html >>
<<org-proj-config-static >>
<<org-proj-config >>
<<org-proj-lang-html >>
<<org-proj-lang-pdf >>
<<org-proj-lang-static >>
<<org-proj-lang >>))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2023-09-18 18:45:14 +02:00
****** Configuration website
2021-02-04 14:43:09 +01:00
This is my configuration for exporting my dotfiles to my website in a web format
only. No PDFs or anything, just HTML. Please note that I do not use that often
anymore, I much prefer the automatic script that I have which deploys through my
Drone instance my website on git pushes.
2020-11-13 00:39:34 +01:00
2021-02-04 14:43:09 +01:00
And before we get into the actual configuration, I would like to introduce a
couple of variables. This is a bit more verbose than if I declared everything
manually, but now I can change all three values at the same time without a
hasle.
2020-11-13 00:39:34 +01:00
#+NAME : org-proj-config-setup
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak//projects-config-target
"/rsync:Tilo:~/www/phundrak.com/config"
"Points to where exported files for config.phundrak.com should be put")
(defvar phundrak//projects-config-source
"~/org/config/ "
"Points to where the sources for config.phundrak.com are")
(defvar phundrak//projects-config-language
"en"
"Language of config.phundrak.com")
(defvar phundrak//projects-config-recursive
t
"Defines whether subdirectories should be parsed for config.phundrak.com")
2020-11-13 00:39:34 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
Now, here is my configuration. In this snippet, my org files located in my
source directory get exported in the HTML format and published to my target
directory on my remote server through RSYNC via TRAMP. A sitemap is
automatically generated, which comes in handy with the online sitemap that is
available through the navigation bar.
2020-11-13 00:39:34 +01:00
#+NAME : org-proj-config-html
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
("config-website-org"
:base-directory ,phundrak//projects-config-source
:base-extension "org"
:publishing-directory ,phundrak//projects-config-target
:recursive ,phundrak//projects-config-recursive
:language ,phundrak//projects-config-language
:publishing-function org-html-publish-to-html
:headline-levels 5
:auto-sitemap t
:auto-preamble t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
We also have the component for all the static files needed to run the website
(mostly images tbh).
2020-11-13 00:39:34 +01:00
#+NAME : org-proj-config-static
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
("config-website-static"
:base-directory ,phundrak//projects-config-source
:base-extension "png\\|jpg\\|gif\\|webp\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub\\|md"
:publishing-directory ,phundrak//projects-config-target
:recursive ,phundrak//projects-config-recursive
:language ,phundrak//projects-config-language
:publishing-function org-publish-attachment)
2020-11-13 00:39:34 +01:00
#+END_SRC
The project is then defined like so:
#+NAME : org-proj-config
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
("config-website"
:components ("config-website-org"
"config-website-static"))
2020-11-13 00:39:34 +01:00
#+END_SRC
2020-08-28 16:09:47 +02:00
2023-09-18 18:45:14 +02:00
****** Linguistics website
2021-02-04 14:43:09 +01:00
My linguistics website is made out of three projects. As for the previous
project, let’ s declare the common values for these.
2020-11-13 00:39:34 +01:00
#+NAME : org-proj-lang-setup
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
(defvar phundrak//projects-conlanging-target
"/rsync:Tilo:~/www/phundrak.com/langue/ "
"Points to where exported files for langue.phundrak.com should be put")
(defvar phundrak//projects-conlanging-source
"~/Documents/conlanging/content/ "
"Points to where the sources for langue.phundrak.com are")
(defvar phundrak//projects-conlanging-language
"fr"
"Language of langue.phundrak.com")
(defvar phundrak//projects-conlanging-recursive
t
"Defines whether subdirectories should be parsed for langue.phundrak.com")
2020-11-13 00:39:34 +01:00
#+END_SRC
The first component is the one generating the HTML files from the org files.
#+NAME : org-proj-lang-html
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
("langue-phundrak-com-org"
:base-directory ,phundrak//projects-conlanging-source
:base-extension "org"
:exclude "\\./\\(CONTRIB\\|README\\|head\\|temp\\|svg-ink\\).*"
:publishing-directory ,phundrak//projects-conlanging-target
:recursive ,phundrak//projects-conlanging-recursive
:language ,phundrak//projects-conlanging-language
:publishing-function org-html-publish-to-html
:headline-levels 5
:auto-sitemap t
:auto-preamble t)
2020-11-13 00:39:34 +01:00
#+END_SRC
We also have the component for the LaTeX and PDF part of the website:
#+NAME : org-proj-lang-pdf
2020-12-24 12:30:19 +01:00
#+BEGIN_SRC emacs-lisp
2021-10-12 11:31:20 +02:00
("langue-phundrak-com-pdf"
:base-directory ,phundrak//projects-conlanging-source
:base-extension "org"
:exclude "\\./\\(CONTRIB\\|README\\|index\\|head\\|temp\\|svg-ink\\).*"
:publishing-directory ,phundrak//projects-conlanging-target
:recursive ,phundrak//projects-conlanging-recursive
:language ,phundrak//projects-conlanging-language
:publishing-function org-latex-publish-to-pdf
:headline-levels 5
:auto-preamble t)
2020-11-13 00:39:34 +01:00
#+END_SRC
2021-02-04 14:43:09 +01:00
And lastly, we have the component for all the static files needed to run the