Updated: 05 Apr 2025
Note, I haven’t used Doom / my config below in a couple of years, as I have switched to a lightwight vanilla config.
Personal configuration file for Doom Emacs.
To get started from scratch, follow the instructions at
github.com/hlissner/doom-emacs#install and run doom sync
.
Me 🔗
(setq user-full-name "Jonas D. Großekathöfer"
user-mail-address "mail@grszkth.fr")
Font and appearance 🔗
Font 🔗
(setq doom-font (font-spec :family "FiraCode" :size 18)
doom-variable-pitch-font (font-spec :family "sans" :size 14))
Color theme 🔗
(setq doom-theme 'doom-gruvbox)
Transparency 🔗
(set-frame-parameter nil 'alpha 75)
Line numbers 🔗
Use relative line numbers, but disable them for text buffer.
(setq display-line-numbers-type 'relative)
(remove-hook! 'text-mode-hook
#'display-line-numbers-mode)
Spell checker 🔗
Default for the spell checker is english.
(setq ispell-dictionary "en")
Fill width 🔗
(setq fill-column 100)
Keybindings 🔗
Some modifications/additions to the given Keybindings.
Insert lines, without entering insert mode 🔗
(map! :leader
;;; <leader> i --- insert
(:prefix-map ("i" . "insert")
:desc "Insert line above" "k" #'+evil/insert-newline-above
:desc "Insert line below" "j" #'+evil/insert-newline-below))
Increase and decrease font size 🔗
(map! :n "C-=" #'doom/reset-font-size
;; Buffer-local font resizing
:n "C-+" #'text-scale-increase
:n "C--" #'text-scale-decrease)
Avy 🔗
Navigating through emacs, across buffer.
(setq avy-all-windows t)
Workspace 🔗
Overwrite keybinding to quickly switch between workspaces by double TAB
.
(map! :leader
(:when (featurep! :ui workspaces)
(:prefix-map ("TAB" . "workspace")
:desc "Switch to last workspace" "TAB" #'+workspace/other)))
Dired 🔗
(use-package! dired
:custom ((dired-listing-switches "-agho --group-directories-first")))
Orgmode 🔗
General 🔗
Paths 🔗
(setq org-directory "~/org/"
org-agenda-files (list
"~/org/"
"~/org/jobs2021/"
"~/lehre/ws21_empra/"
"~/Documents/doktorarbeit/"
;; "~/org/zettelkasten/"
"\.org$")
org-archive-location (concat org-directory ".archive/%s::"))
Style 🔗
Styling of the appearance of my org buffer to please my liking.
First, define visual appearance for an org buffer.
(defun gkh/org-mode-visual()
(setq visual-fill-column-width 100
visual-fill-column-center-text t
display-fill-column-indicator nil
display-line-numbers nil)
(visual-fill-column-mode 1))
Change symbol for folded headings and start with an overview of all headings when opening an org file.
(after! org
(setq org-startup-folded 'overview
org-ellipsis " ▾ "
org-list-demote-modify-bullet '(("+" . "-") ("-" . "+"))))
(add-hook! 'org-mode-hook
#'+org-pretty-mode #'mixed-pitch-mode #'gkh/org-mode-visual)
Font settings: Use different font sizes for headlines and define sections for a fixed-pitch font.
(after! org
(custom-set-faces!
'(org-document-title :height 1.3)
'(org-level-1 :inherit outline-1 :weight extra-bold :height 1.4)
'(org-level-2 :inherit outline-2 :weight bold :height 1.15)
'(org-level-3 :inherit outline-3 :weight bold :height 1.12)
'(org-level-4 :inherit outline-4 :weight bold :height 1.09)
'(org-level-5 :inherit outline-5 :weight semi-bold :height 1.06)
'(org-level-6 :inherit outline-6 :weight semi-bold :height 1.03)
'(org-level-7 :inherit outline-7 :weight semi-bold)
'(org-level-8 :inherit outline-8 :weight semi-bold)
;; Ensure that anything that should be fixed-pitch in org buffers appears
;; that way
'(org-block nil :foreground nil :inherit 'fixed-pitch)
'(org-code nil :inherit '(shadow fixed-pitch))
'(org-table nil :inherit '(shadow fixed-pitch))
'(org-verbatim nil :inherit '(shadow fixed-pitch))
'(org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
'(org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
'(org-checkbox nil :inherit 'fixed-pitch)))
Timing is everything 🔗
This is a not very sophisticated way of handling TODOs.
(after! org
(setq org-log-done 'time
org-log-into-drawer 't
org-todo-keywords '((sequence "TODO(t)" "WAITING(w@)" "|" "DONE(d!)" "CANCELLED(c@)"))
org-todo-keyword-faces
'(("TODO" :foreground "#7c7c75" :weight normal :underline t)
("WAITING" :foreground "#9f7efe" :weight normal :underline t)
("DONE" :foreground "#50a14f" :weight normal :underline t)
("CANCELLED" :foreground "#ff6480" :weight normal :underline t))))
Export settings 🔗
From ox-extra
the headline tag :ignore:
enables to export content without the
headline. Additionally the mimosis for thesis’ is made available as export
#+latex_class
.
(after! ox
(require 'ox-extra)
(ox-extras-activate '(ignore-headlines)))
(use-package! ox-latex
:after ox
:init (setq org-latex-pdf-process
'("%latex -interaction nonstopmode -output-directory %o %f"
"bibtex %b"
"%latex -interaction nonstopmode -output-directory %o %f"
"%latex -interaction nonstopmode -output-directory %o %f"))
:config
;; Mimosis is a class I used to write my Ph.D. thesis.
(add-to-list 'org-latex-classes
'("mimosis"
"\\documentclass{mimosis}
[NO-DEFAULT-PACKAGES]
[PACKAGES]
[EXTRA]
\\newcommand{\\mboxparagraph}[1]{\\paragraph{#1}\\mbox{}\\\\}
\\newcommand{\\mboxsubparagraph}[1]{\\subparagraph{#1}\\mbox{}\\\\}"
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\mboxparagraph{%s}" . "\\mboxparagraph*{%s}")
("\\mboxsubparagraph{%s}" . "\\mboxsubparagraph*{%s}"))))
;; (use-package! ox-leanpub
;; :after org)
;; alternative org-latex-pdf-process?
(setq org-latex-pdf-process
'("latexmk -pdflatex='pdflatex -shell-escape -interaction nonstopmode' -pdf -bibtex -f %f"))
Capture 🔗
From the documentation for capture1:
Capture lets you quickly store notes with little interruption of your work flow.
How does it do it?
It opens a mini-buffer (or so) where you can enter your note or to do entry.
Depending on what template you choose this note will be added to a certain .org
file to a certain heading (if wanted).
personal templates 🔗
My templates let me control to which file/heading a to do note goes. Below I have 3 types of notes:
- t for general or not-easy to sort notes
- p for projects I am currently working on, it opens a menu for further
specification:
- m for my meta analysis
- j for Julius master thesis
- v for vrrl study
- b for the browser extension, to capture
- l links to websites
- q quotes from websites
For my templates to work I require
these packages. I don’t know why, but I am
happy when it works.
(require 'org-protocol)
(require 'org-capture)
Here are the above mentioned templates specified.
(setq org-capture-templates
'(("t" "todo" entry (file "~/org/todo.org")
"* TODO %?")
("p" "projekte")
("pm" "Meta-Analyse Gaze cueing" entry (file+headline "~/org/projects.org" "ma_gazecueing" )
"** TODO %?")
("pj" "Julius Masterarbeit" entry (file+headline "~/org/projects.org" "Lab-intern Meta-Analysis (Julius)" )
"** TODO %?\n")
("pv" "vrrl" entry (file+headline "~/org/projects.org" "vrrl" )
"** TODO %?")
("l" "lehre (ss20)" entry (file+headline "~/org/zettelkasten/ss20empra.org" "orga" )
"** TODO %?")
;; browser extension
("b" "browser extension")
("bq" "with quote" entry (file "~/org/todo.org")
"* %^{Title}\nSource: %u, %c\n #+begin_quote\n%i\n#+END_QUOTE\n\n\n%?")
("bl" "only link" entry (file "~/org/todo.org")
"* %? [[%:link][%:description]] :web:\nCaptured On: %U")))
Org-Roam 🔗
There is a lot of momentum around roam and note taking in general, and therefore although for org-roam. This is my basic configuration. For an general introduction I would start at org-roams documentation.
Although I am not yet a 100% sold, this is my configuration, taken unchanged from the docs.
(setq org-roam-directory (concat org-directory "zettelkasten/"))
For further reading and inspiration one can have a look here.
Browser extensions 🔗
See org-roam protocol how to setup your os and browser for the communication between org-roam and your browser.
Markdown 🔗
(defun gkh/md-mode-visual()
(setq visual-fill-column-width 100
visual-fill-column-center-text t
display-fill-column-indicator nil
markdown-header-scaling t
display-line-numbers nil)
(visual-fill-column-mode 1))
Change symbol for folded headings and start with an overview of all headings when opening an org file.
(add-hook! 'markdown-mode-hook #'gkh/md-mode-visual)
Bibliography 🔗
(setq bibtex-completion-bibliography "~/meine-bibliothek/meine-bibliothek.bib"
bibtex-completion-library-path "~/meine-bibliothek/"
bibtex-completion-notes-path (concat org-directory "zettelkasten/")
;; bibtex-completion-notes-template-multiple-files
;; (concat
;; "${title}\n"
;; "#+ROAM_KEY: cite:${=key=}\n"
;; "#+ROAM_ALIAS: ${=key=} cite:${=key=}\n"
;; ;; does not work, tags with spaces need "x"
;; ;; "#+ROAM_TAGS: ${keywords}\n"
;; "\n"
;; "* Notes\n"
;; ":PROPERTIES:\n"
;; ":Custom_ID: ${=key=}\n"
;; ":NOTER_DOCUMENT: %(orb-process-file-field \"${=key=}\")\n"
;; ":AUTHOR: ${author-abbrev}\n"
;; ":JOURNAL: ${journal}\n"
;; ":YEAR: ${year}\n"
;; ":DOI: ${doi}\n"
;; ":URL: ${url}\n"
;; ":TIMESTAMP: ${timestamp}\n"
;; ":END:\n\n"
;; "** What\n"
;; "** Why\n"
;; "** How\n"
;; "** And?")
;; bibtex-completion-format-citation-functions
;; '((org-mode . org-ref-bibtex-completion-format-org)
;; (latex-mode . bibtex-completion-format-citation-cite)
;; (markdown-mode . bibtex-completion-format-citation-pandoc-citeproc)
;; (default . bibtex-completion-format-citation-default))
;; ivy-bibtex-default-action 'ivy-bibtex-insert-citation
;; ;; no pre or post note
;; bibtex-completion-cite-prompt-for-optional-arguments nil
;; ;; how to open odfs
;; bibtex-completion-pdf-open-function (lambda (fpath) (call-process "microsoft-edge" nil 0 nil fpath))
;; ;;
;; bibtex-completion-pdf-symbol "📰"
;; bibtex-completion-notes-symbol "🗒"
;; ;; bibtex-completion-pdf-symbol "⌘"
;; ;; bibtex-completion-notes-symbol "✎"
)
org-roam-bibtex 🔗
This configures a nice integration of BibTex notes with an org-roam workflow.
;; (use-package! org-roam-bibtex
;; :after (org-roam)
;; :hook (org-roam-mode . org-roam-bibtex-mode)
;; :config
;; (setq org-roam-bibtex-preformat-keywords
;; '("=key=" "title" "url" "file" "author-or-editor" "keywords"))
;; (setq orb-templates
;; '((\"r\" \"reference\" plain (function org-roam-capture--get-point)
;; "#+ROAM_KEY: %^{=key=}%? %^{author} published %^{entry-type} in %^{date}: fullcite:%\\1."
;; :file-name "references/${=key=}"
;; :head "#+title: ${title}"
;; :unnarrowed t))))
R 🔗
If you do statistics with emacs you need ESS, which (also) has a mode for R.
Together with polymode
, this is how I want my editor to handle and ease my work
with .R scripts and .RMD files.
ESS 🔗
- Map nice and easy keybindings for assignment arrow
<-
- get a function for the pipe
%>%
working & map nice keybindings
R 🔗
(after! ess-mode
(setq ess-style 'C++
;; don't wait when evaluating
ess-eval-visibly-p 'nowait
;; scroll buffer to bottom
comint-scroll-to-bottom-on-output t))
;; Open ESS R window to the left iso bottom.
;; (set-popup-rule! "^\\*R.*\\*$" :side 'left :size 0.38 :select nil :ttl nil :quit nil :modeline t)
-
Pipe
I found a code snippet online. Not sure how I like it.
(defun gkh-r-add-pipe () (interactive) (end-of-line) (unless (looking-back "%>%" nil) (just-one-space 1) (insert "%>%")) (newline-and-indent))
-
Rmarkdown snippet
And also found this snippet online.
(defun gkh-rmd-insert-r-chunk (header) "Insert an r-chunk in markdown mode. Necessary due to interactions between polymode and yas snippet" (interactive "sHeader: ") (insert (concat "```{r " header "}\n\n```")) (forward-line -1))
Julia 🔗
(setq lsp-julia-default-environment "~/.julia/environments/v1.0")
CSV 🔗
In german .csv
-files often =,=
is reserved as a decimal separator (as in 3,14),
consequently we need another column separator ;
.
But now it splits the .csv
-file at both separators. This is not helpful at all!
(setq csv-separators '("," " " ";"))
Polymode 🔗
Polymode
handles multiple modes in emacs. I need it to ease my work with
.Rmarkdown
files, using markdown mode together with ESS. However, it does not
give me a nice time, so I prefer using org babel within emacs and fallback to
Rstudio regularly. I suspect, there are problem with the syntax checker…
Again I found this code-snippet, but I mainly keep it just in case to have it as a reference.
(use-package! poly-R
:config
(map! (:localleader
:map polymode-mode-map
:desc "Export" "e" 'polymode-export
:desc "Errors" "$" 'polymode-show-process-buffer
:desc "Weave" "w" 'polymode-weave
;; (:prefix ("n" . "Navigation")
;; :desc "Next" "n" . 'polymode-next-chunk
;; :desc "Previous" "N" . 'polymode-previous-chunk)
;; (:prefix ("c" . "Chunks")
;; :desc "Narrow" "n" . 'polymode-toggle-chunk-narrowing
;; :desc "Kill" "k" . 'polymode-kill-chunk
;; :desc "Mark-Extend" "m" . 'polymode-mark-or-extend-chunk)
)))
Other inspriring configs 🔗
Dotfiles 🔗
Tangle all .org
files in ~/.dotfiles/
(defun gkh/tangle-dotfiles ()
"If the current file is in '~/.dotfiles', the code blocks are tangled"
(when (equal (file-name-directory (directory-file-name buffer-file-name))
(concat (getenv "HOME") "/.dotfiles/"))
(org-babel-tangle)
(message "%s tangled" buffer-file-name)))
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'gkh/tangle-dotfiles)))
.dir-locals.el
🔗
Not sure, if this is a good idea, but in emacs one can apply settings for a
directory (recursively) with a .dir-locals.el
file. I would like to
automatically tangle files on save.
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'gkh/tangle-dotfiles))))