grszkth.fr blog


My Doom Emacs configuration

Published: 25 Aug 2020
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.

Table of Contents

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:

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))))

🔗

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 🔗

🔗


(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)

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))))

  1. https://orgmode.org/manual/Capture.html ↩︎