nixos-config/user/app/doom-emacs/doom.org
2023-05-19 20:25:57 -05:00

56 KiB

Doom Emacs Literate Config

What is Doom Emacs?

Doom Emacs is a distribution of the Emacs Text Editor designed for Vim users. I like to use Emacs due to its extensibility and extra features it is capable of (besides text editing). Some of these extra features include:

I have found Emacs to be incredibly efficient, and transferring my workflow to fit inside of Emacs has allowed me to get much more work done.

Configuration for Doom Emacs

Doom Emacs is configured via 3 main files, written in Elisp, a dialect of the Lisp programming langauge designed for Emacs. These 3 main files are:

  • config.el - Stores your main configuration and allows to set user variables.
  • init.el - Allows quick downloads of groups of Emacs packages. These groups of Emacs packages are curated by the Doom Emacs developers.
  • packages.el - Allows you to download additional packages from Melpa (Emacs package manager).

By storing your configuration in these 3 files, it allows for quick reproducible builds of Doom Emacs.

You can also load separate files inside of config.el via the load! function, like so:

(load! "~/.doom.d/private.el")

I use this functionality to load my private config file with non-public information.

My config.el

Preamble + User Configuration

;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-

;;;------ User configuration ------;;;

;; My default user identity as my yt alias
(setq user-full-name "librephoenix")

;; I prefer visual lines
(setq display-line-numbers-type 'visual
      line-move-visual t)
(use-package-hook! evil
  :pre-init
  (setq evil-respect-visual-line-mode t) ;; sane j and k behavior
  t)

;; I also like evil mode visual movement
(map! :map evil-normal-state-map
      :desc "Move to next visual line"
      "j" 'evil-next-visual-line
      :desc "Move to previous visual line"
      "k" 'evil-previous-visual-line)

;; Theme and font
(setq custom-theme-directory "~/.emacs.d/themes")
(setq doom-theme 'doom-stylix)
(setq doom-font (font-spec :family "Inconsolata" :size 20))

;; Transparent background
(set-frame-parameter (selected-frame) 'alpha '(90 . 90))
(add-to-list 'default-frame-alist '(alpha . (90 . 90)))

;; Icons in completion buffers
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)
(all-the-icons-completion-mode)

;; This makes non-main buffers dimmer, so you can focus on main buffers
(solaire-global-mode +1)

;; Grammar tasing should be voluntary
(setq writegood-mode nil)

;; Beacon shows where the cursor is, even when fast scrolling
(setq beacon-mode t)

;; Quicker window management keybindings
(bind-key* "C-j" #'evil-window-down)
(bind-key* "C-k" #'evil-window-up)
(bind-key* "C-h" #'evil-window-left)
(bind-key* "C-l" #'evil-window-right)
(bind-key* "C-q" #'evil-window-delete)

;; Mouse buffer management
(bind-key* "<mouse-8>" #'previous-buffer)
(bind-key* "<mouse-9>" #'next-buffer)

;; Disables custom.el
(setq custom-file null-device)

;; Fancy splash image
(setq fancy-splash-image "./arch.png")

(setq +doom-dashboard-menu-sections
'(("Open org roam overview" :icon
  (all-the-icons-octicon "globe" :face 'doom-dashboard-menu-title)
  :face
  (:inherit
   (doom-dashboard-menu-title bold))
  :action org-roam-default-overview)
 ("Roam to another db" :icon
  (all-the-icons-fileicon "org" :face 'doom-dashboard-menu-title)
  :action org-roam-switch-db)
 ("Open agenda" :icon
  (all-the-icons-octicon "calendar" :face 'doom-dashboard-menu-title)
  :when
  (fboundp 'org-agenda)
  :action org-agenda-list
  :key "SPC o A a")
 ("Open private configuration" :icon
  (all-the-icons-octicon "tools" :face 'doom-dashboard-menu-title)
  :when
  (file-directory-p doom-user-dir)
  :action doom/open-private-config)
 ("Open documentation" :icon
  (all-the-icons-octicon "book" :face 'doom-dashboard-menu-title)
  :action doom/help)
 ("Quit emacs" :icon
  (all-the-icons-faicon "level-down" :face 'doom-dashboard-menu-title)
  :action save-buffers-kill-terminal)
 )
)

;; Requires for faster loading
(require 'org-agenda)
(require 'dired)

;; Garbage collection to speed things up
(add-hook 'after-init-hook
          #'(lambda ()
              (setq gc-cons-threshold (* 100 1000 1000))))
(add-hook 'focus-out-hook 'garbage-collect)
(run-with-idle-timer 5 t 'garbage-collect)

;; Enable autorevert globally so that buffers update when files change on disk.
;; Very useful when used with file syncing (i.e. syncthing)
(setq global-auto-revert-mode nil)
(setq auto-revert-use-notify t)

Registers

;;;------ Registers ------;;;

(map! :leader
      :desc "Jump to register"
      "r" 'jump-to-register)

(set-register ?f '(file . "/home/librephoenix/Org/Family.s/Notes/hledger.org"))
(set-register ?r '(file . "/home/librephoenix/README.org"))
(set-register ?d '(file . "/home/librephoenix/.doom.d/doom.org"))
(set-register ?h '(file . "/home/librephoenix"))
(set-register ?x '(file . "/home/librephoenix/.xmonad/xmonad.org"))
(set-register ?s '(file . "/home/librephoenix/.install/install.org"))

Org Mode Configuration

Standard Org Mode Configuration

;;;------ Org mode configuration ------;;;

;; Set default org directory
(setq org-directory "~/.Org")

(remove-hook 'after-save-hook #'+literate|recompile-maybe)
(set-company-backend! 'org-mode nil)

;; Automatically show images but manually control their size
(setq org-startup-with-inline-images t
      org-image-actual-width nil)

;; Top-level headings should be bigger!
(custom-set-faces!
  '(org-level-1 :inherit outline-1 :height 1.3)
  '(org-level-2 :inherit outline-2 :height 1.25)
  '(org-level-3 :inherit outline-3 :height 1.2)
  '(org-level-4 :inherit outline-4 :height 1.1)
  '(org-level-5 :inherit outline-5 :height 1.1)
  '(org-level-6 :inherit outline-6 :height 1.05)
  '(org-level-7 :inherit outline-7 :height 1.05)
  )

;(custom-set-faces!
;  '(org-link :foreground nil))

;; Pretty org bullets
;;(use-package org-bullets
;;    :ensure t
;;        :init
;;        (add-hook 'org-mode-hook (lambda ()
;;                                   (org-bullets-mode 1))))

(after! org (org-eldoc-load))

(with-eval-after-load 'org (global-org-modern-mode))

;; Add frame borders and window dividers
(modify-all-frames-parameters
 '((right-divider-width . 10)
   (internal-border-width . 10)))
(dolist (face '(window-divider
                window-divider-first-pixel
                window-divider-last-pixel))
  (face-spec-reset-face face)
  (set-face-foreground face (face-attribute 'default :background)))
(set-face-background 'fringe (face-attribute 'default :background))

(setq
 ;; Edit settings
 org-auto-align-tags nil
 org-tags-column 0
 org-catch-invisible-edits 'show-and-error
 org-special-ctrl-a/e t
 org-insert-heading-respect-content t

 ;; Org styling, hide markup etc.
 org-hide-emphasis-markers t
 org-pretty-entities t
 org-ellipsis "…")

(setq-default line-spacing 0.1)

; Automatic table of contents is nice
(if (require 'toc-org nil t)
    (progn
      (add-hook 'org-mode-hook 'toc-org-mode)
      (add-hook 'markdown-mode-hook 'toc-org-mode))
  (warn "toc-org not found"))

;;---- this block from http://fgiasson.com/blog/index.php/2016/06/21/optimal-emacs-settings-for-org-mode-for-literate-programming/ ----;;
;; Tangle Org files when we save them
(defun tangle-on-save-org-mode-file()
  (when (string= (message "%s" major-mode) "org-mode")
    (org-babel-tangle)))

(add-hook 'after-save-hook 'tangle-on-save-org-mode-file)
;; ---- end block ---- ;;

;; Better org table editing
(setq-default evil-insert-state-exit-hook '(org-update-parent-todo-statistics
 t))
(setq org-table-automatic-realign nil)

;; Better for org source blocks
(setq electric-indent-mode nil)
(setq org-src-window-setup 'current-window)
(delete
  '("^\\*Org Src"
  (+popup-buffer)
  (actions)
  (side . bottom)
  (size . 0.42)
  (window-width . 40)
  (window-height . 0.42)
  (slot)
  (vslot)
  (window-parameters
   (ttl)
   (quit)
   (select . t)
   (modeline . t)
   (autosave . t)
   (transient . t)
   (no-other-window . t)))
 display-buffer-alist)

Org Download, Image Capture, and Opening Files in External Programs

(require 'org-download)

;; Drag-and-drop to `dired`
(add-hook 'dired-mode-hook 'org-download-enable)

(setq org-download-screenshot-method "flameshot gui -p %s")
(after! org-download
   (setq org-download-method 'directory))

(after! org
  (setq-default org-download-image-dir "img/"
        org-download-heading-lvl nil))

(defun my-org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq filename
        (concat
         (make-temp-name
          (concat (buffer-file-name)
                  "_"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (shell-command (concat "emacs-wayshot " filename))
  (insert (concat "[[" filename "]]"))
  (org-display-inline-images))

(defun my-org-paste()
  "Take an image from the clipboard into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq filename
        (concat
         (make-temp-name
          (concat (file-name-directory (buffer-file-name))
                  "img/"
                  (file-name-nondirectory (buffer-file-name))
                  "_"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (shell-command (concat "wl-paste > " filename))
  (insert (concat "[[" filename "]]"))
  (org-display-inline-images))

(defun my-org-new-file-from-template()
  "Copy a template from ~/Templates into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq template-file (completing-read "Template file:" (directory-files "~/Templates")))
  (setq filename
        (concat
         (make-temp-name
          (concat (file-name-directory (buffer-file-name))
                  "files/"
                  (file-name-nondirectory (buffer-file-name))
                  "_"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) (file-name-extension template-file t)))
  (copy-file (concat "/home/librephoenix/Templates/" template-file) filename)
  (setq prettyname (read-from-minibuffer "Pretty name:"))
  (insert (concat "[[./files/" (file-name-nondirectory filename) "][" prettyname "]]"))
  (org-display-inline-images))

(when (require 'openwith nil 'noerror)
   (setq openwith-associations
         (list
         (list (openwith-make-extension-regexp
                '("mpg" "mpeg" "mp3" "mp4"
                  "avi" "wmv" "wav" "mov" "flv"
                  "ogm" "ogg" "mkv"))
                  "mpv"
                  '(file))
         (list (openwith-make-extension-regexp
                '("doc" "xls" "ppt" "odt" "ods" "odg" "odp"))
                  "libreoffice"
                  '(file))
             '("\\.lyx" "lyx" (file))
             '("\\.chm" "kchmviewer" (file))
         (list (openwith-make-extension-regexp
                '("pdf" "ps" "ps.gz" "dvi"))
                  "atril"
                  '(file))
         (list (openwith-make-extension-regexp
                '("kdenlive"))
                  "kdenlive"
                  '(file))
         (list (openwith-make-extension-regexp
                '("kra"))
                  "krita"
                  '(file))
         (list (openwith-make-extension-regexp
                '("blend" "blend1"))
                  "blender"
                  '(file))
         (list (openwith-make-extension-regexp
                '("helio"))
                  "helio"
                  '(file))
         (list (openwith-make-extension-regexp
                '("svg"))
                  "inkscape"
                  '(file))
         (list (openwith-make-extension-regexp
                '("flp"))
                  "~/.local/bin/flstudio"
                  '(file))
             ))
   (openwith-mode 1))

(add-to-list 'display-buffer-alist '("^*Async Shell Command*" . (display-buffer-no-window)))

(map! :leader
      :desc "Insert a screenshot"
;;      "i s" 'my-org-screenshot)
      "i s" 'org-download-screenshot)

(defun org-download-clipboard-basename ()
  (interactive)
  (setq org-download-path-last-dir org-download-image-dir)
  (setq org-download-image-dir (completing-read "directory: " (-filter #'f-directory-p (directory-files-recursively "." "" t)) nil t))
  (org-download-clipboard (completing-read "basename: " '() nil nil))
  (setq org-download-image-dir org-download-path-last-dir)
)

(map! :leader
      :desc "Insert image from clipboard"
      "i p" 'org-download-clipboard
      "i P" 'org-download-clipboard-basename)

(map! :leader
      :desc "Create a new file from a template and insert a link at point"
      "i t" 'my-org-new-file-from-template)

Copy Links/Files into Clipboard

(defun org-copy-link-to-clipboard-at-point ()
  "Copy current link at point into clipboard (useful for images and links)"
  (interactive)
  (if (eq major-mode #'org-mode)
      (link-hint-copy-link-at-point)
  )
  (if (eq major-mode #'ranger-mode)
      (ranger-copy-absolute-file-paths)
  )
  (if (eq major-mode #'image-mode)
      (image-mode-copy-file-name-as-kill)
  )
  (shell-command (concat "~/.doom.d/scripts/copy-link-or-file/copy-link-or-file-to-clipboard.sh " (gui-get-selection 'CLIPBOARD)) nil nil)
)

(map! :leader
      :desc "Copy link/file at point into system clipbord (C-g to escape if copying a file)"
      "y y" 'org-copy-link-to-clipboard-at-point)
Copy Link/File to Clipboard Helper Script

Shamelessly stolen from here and modified for my use.

#!/bin/sh
#command -v xclip >/dev/null 2>&1 || { echo "Need command xclip. Aborting." >&2; exit 1; }
if [[ -f "$1" ]]; then
  TYPE=$(file -b --mime-type "$1")
  xclip -selection clipboard -t "$TYPE" -i "$1"
else
  echo $1 | xclip -selection clipboard -t text/plain &> /dev/null
  exit
fi
exit

Org Online Images

;; Online images inside of org mode is pretty cool
;; This snippit is from Tobias on Stack Exchange
;; https://emacs.stackexchange.com/questions/42281/org-mode-is-it-possible-to-display-online-images
(require 'org-yt)

(defun org-image-link (protocol link _description)
  "Interpret LINK as base64-encoded image data."
  (cl-assert (string-match "\\`img" protocol) nil
             "Expected protocol type starting with img")
  (let ((buf (url-retrieve-synchronously (concat (substring protocol 3) ":" link))))
    (cl-assert buf nil
               "Download of image \"%s\" failed." link)
    (with-current-buffer buf
      (goto-char (point-min))
      (re-search-forward "\r?\n\r?\n")
      (buffer-substring-no-properties (point) (point-max)))))

(org-link-set-parameters
 "imghttp"
 :image-data-fun #'org-image-link)

(org-link-set-parameters
 "imghttps"
 :image-data-fun #'org-image-link)

Org Mermaid Diagrams

;; Mermaid diagrams
(setq ob-mermaid-cli-path "/usr/bin/mmdc")

Org Simple Printing

;; Print org mode
(defun org-simple-print-buffer ()
  "Open an htmlized form of current buffer and open in a web browser to print"
  (interactive)
  (htmlize-buffer)
  (browse-url-of-buffer (concat (buffer-name) ".html"))
  (sleep-for 1)
  (kill-buffer (concat (buffer-name) ".html")))

;; Doesn't work yet, bc htmlize-region takes arguments BEG and END
;(defun org-simple-print-region()
;  "Open an htmlized form of current region and open in a web browser to print"
;  (interactive)
;  (htmlize-region )
;  (browse-url-of-buffer (concat (buffer-name) ".html"))
;  (sleep-for 1)
;  (kill-buffer (concat (buffer-name) ".html")))

(map! :leader
      :prefix ("P" . "Print")
      :desc "Simple print buffer in web browser"
      "p" 'org-simple-print-buffer)

(map! :leader
      :prefix ("P" . "Print")
      :desc "Simple print buffer in web browser"
      "b" 'org-simple-print-buffer)

;(map! :leader
;      :prefix ("P" . "Print")
;      :desc "Simple print region in web browser"
;      "r" 'org-simple-print-region)

Org -> ODP Presentation Export

;; Custom function to convert org mode to ODP presentation
;; Depends on bash, libreoffice, and pandoc
(defun my-ox-odp ()
  "Convert an org mode file to an ODP presentation."
  (interactive)
  (setq file-name (buffer-file-name))
  (setq output-pptx-file-name (replace-regexp-in-string "\.org" "\.pptx" (buffer-file-name)))
  (setq output-odp-file-name (replace-regexp-in-string "\.org" "\.odp" (buffer-file-name)))
  (setq odp-style-file-name (completing-read "Choose style: "
                                             '("/home/librephoenix/.doom.d/scripts/ox-odp/styles/water.odp"
                                                "/home/librephoenix/.doom.d/scripts/ox-odp/styles/dark.odp"
                                              ) nil t))
  (shell-command (concat "~/.doom.d/scripts/ox-odp/ox-odp.sh \"" (buffer-file-name) "\" \"" odp-style-file-name "\" > /dev/null"))
  )

(map! :leader
      :desc "Convert org document to odp presentation"
      "e p" 'my-ox-odp)
Org -> ODP Helper Scripts

These are helper scripts for my-ox-odp (defined above), which converts an org document to an ODP presentation. This fundamentally functions by running a shell script (ox-odp.sh), which also calls a Python script (ox-odp-xml-parse.py).

ox-odp.sh
#!/bin/sh

filename=$1
echo $filename
stylefile=$2
echo $stylefile

filenamebase=$(basename "$filename")
filenameext="${filenamebase##*.}"
echo $filenameext

if [ $filenameext = "org" ]; then
   stylefilebase=$(basename "$stylefile")
   stylefileext="${stylefilebase##*.}"

   if [ $stylefileext = "odp" ]; then
       output="${filename//\.org/\.pptx}"
       finaloutput="${filename//\.org/\.odp}"
       pandoc "$filename" -o "$output"
       soffice --convert-to odp "$output"
       unzip "$finaloutput" content.xml
       unzip "$stylefile" styles.xml

       sed 's~</text:span>~~g' content.xml
       sed 's~<text:span text:style-name="..">~~g' content.xml

       python3 ~/.doom.d/scripts/ox-odp/ox-odp-xml-parse.py

       zip -d $finaloutput styles.xml
       zip -m $finaloutput styles.xml

       zip -d $finaloutput content.xml
       zip -m $finaloutput content.xml

       rm $output

       exit

   else
       echo "Style file is not an odp file."
   fi
else
    echo "Base file is not an org file."
    exit
fi

exit
ox-odp-xml-parse.py

This script parses through the raw LibreOffice XML to fix some common formatting errors with the standard Org to pptx to odp conversion strategy.

#!/usr/bin/env python3

import xml.etree.ElementTree as ET
import copy

# Read content.xml into parser
mytree = ET.parse('./content.xml')
myroot = mytree.getroot()

# Read styles.xml into parser
styletree = ET.parse('./styles.xml')
styleroot = styletree.getroot()

# Remove direct-formatting from text:style-name attributes in text:p elements
counter = 0
for text in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}p'):
    if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in text.keys():
        stylename = text.attrib['{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name']
        if stylename[0] == "P":
            counter += 1
            text.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name')
print('Deleted '+str(counter)+' text:style-name attributes in text:p elements.')

# Remove direct-formatting from text:style-name attributes in text:span elements
counter = 0
for span in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}span'):
    if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in span.keys():
        span.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name')
print('Deleted '+str(counter)+' text:style-name attributes in text:span elements.')

# Remove direct-formatting from draw:text-style-name attributes in draw:frame elements
counter = 0
for drawing in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}frame'):
    if '{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name' in drawing.keys():
        stylename = drawing.attrib['{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name']
        if stylename[0] == "P":
            counter += 1
            drawing.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}text-style-name')
print('Deleted '+str(counter)+' draw:text-style-name attributes in text:p elements.')

# Redefine default styles (style:style elements) and purge unnecessary ones
counter = 0
kounter = 0
for style in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style'):
    if '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name' in style.keys():
        stylename = style.attrib['{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name']
        if stylename == "pr1":
            counter += 1
            style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-title')
        elif stylename == "pr2":
            counter += 1
            style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-subtitle')
        elif stylename == "pr3":
            counter += 1
            style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-notes')
        elif stylename == "pr4":
            counter += 1
            style.set('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}parent-style-name','DefaultTheme-outline1')
print('Redefined '+str(counter)+' style:parent-style-name attributes in style:style elements.')
print('Deleted '+str(kounter)+' style:style elements.')

# Search for automatic-styles element
i = 0
col1 = 0
while (i < len(myroot)):
    print(myroot[i].tag)
    if myroot[i].tag=="{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles":
        col1 = i
    i += 1

# Remove unnecessary style:style and test:list-style elements underneath automatic-styles
i = 0
while (i < len(myroot[col1])):
    if (myroot[col1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style"):
        if ("{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name" in myroot[col1][i].keys()):
            if myroot[col1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"] in ["pr5","pr6","pr7","pr8","pr9"]:
                print("Removing "+myroot[col1][i].tag)
                myroot[col1].remove(myroot[col1][i])
                i -= 1
            elif myroot[col1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"][0] == "P":
                print("Removing "+myroot[col1][i].tag)
                myroot[col1].remove(myroot[col1][i])
                i -= 1
    if (myroot[col1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list-style"):
        print("Removing "+myroot[col1][i].tag)
        myroot[col1].remove(myroot[col1][i])
        i -= 1
    i += 1

#i = 0
#while (i < len(myroot[col1])):
#    print(myroot[col1][i].attrib)
#    i += 1

# Find ML1 in styles.xml and copy it into L1 in content.xml
# Search for automatic-styles element
i = 0
stylecol1 = 0
while (i < len(styleroot)):
    print(styleroot[i].tag)
    if styleroot[i].tag=="{urn:oasis:names:tc:opendocument:xmlns:office:1.0}automatic-styles":
        stylecol1 = i
    i += 1

# Remove unnecessary style:style and test:list-style elements underneath automatic-styles
i = 0
while (i < len(styleroot[stylecol1])):
    if (styleroot[stylecol1][i].tag == "{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list-style"):
        if (styleroot[stylecol1][i].attrib["{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name"] == "ML1"):
            liststyle_copy = copy.deepcopy(styleroot[stylecol1][i])
            myroot[col1].append(liststyle_copy)
            myroot[col1][-1].attrib['{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'] = "L1"
    i += 1

# Update presentation:style-name attribute of all draw:frame elements
counter = 0
for frame in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}frame'):
    if '{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}class' in frame.keys():
        classname = frame.attrib['{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}class']
        if classname == "title":
            counter += 1
            frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr1')
        elif classname == "subtitle":
            counter += 1
            frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr2')
        elif classname == "notes":
            counter += 1
            frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr3')
        elif classname == "outline":
            counter += 1
            frame.set('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}style-name','pr4')
print("Updated "+str(counter)+" draw:frame elements")

# Update draw:master-page-name attributes in all draw:page elements
# Also delete all presentation:presentation-page-layout attributes
counter = 0
for page in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}page'):
    if '{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}master-page-name' in page.keys():
        page.set('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}master-page-name','DefaultTheme')
        counter += 1
    if '{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}presentation-page-layout' in page.keys():
        page.attrib.pop('{urn:oasis:names:tc:opendocument:xmlns:presentation:1.0}presentation-page-layout')

print("Updated "+str(counter)+" draw:page elements")

# Update all text:list elements to have text:style-name = L1
counter = 0
for page in myroot.iter('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}list'):
    if '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name' in page.keys():
        page.set('{urn:oasis:names:tc:opendocument:xmlns:text:1.0}style-name','L1')
        counter += 1

print("Updated "+str(counter)+" text:list elements")

#mytree.canonicalize(out='content.xml')
mytree.write('content.xml')
styletree.write('styles.xml')

Org Roam Configuration

Standard Org Roam Configuration

;;;------ Org roam configuration ------;;;

(require 'org-roam)
(require 'org-roam-dailies)

(setq org-roam-directory "~/Org/Personal/Notes"
      org-roam-db-location "~/Org/Personal/Notes/org-roam.db")

(setq org-roam-node-display-template
      "${title:65}📝${tags:*}")

(org-roam-db-autosync-mode)

Multi Org Roam Configuration

(setq full-org-roam-db-list nil)

(setq full-org-roam-db-list (directory-files "~/Org" t "\\.[p,s]$"))
(dolist (item full-org-roam-db-list)
  (setq full-org-roam-db-list
        (append (directory-files item t "\\.[p,s]$") full-org-roam-db-list)))

(setq org-roam-db-choice "Default")
(setq full-org-roam-db-list-pretty (list "Default"))
(dolist (item full-org-roam-db-list)
  (setq full-org-roam-db-list-pretty
       (append (list
             (replace-regexp-in-string "\\/home\\/librephoenix\\/Org\\/" "" item)) full-org-roam-db-list-pretty)))

(defun org-roam-open-dashboard ()
  "Open ${org-roam-directory}/dashboard.org (I use this naming convention to create dashboards for each of my org roam maps)"
  (interactive)
  (if (file-exists-p (concat org-roam-directory "/dashboard.org"))
      (org-open-file (concat org-roam-directory "/dashboard.org"))
      (dired org-roam-directory))
)

(defun org-roam-switch-db (&optional arg silent)
  "Switch to a different org-roam database, arg"
  (interactive)
  (when (not arg)
  (setq full-org-roam-db-list nil)

  (setq full-org-roam-db-list (directory-files "~/Org" t "\\.[p,s]$"))
  (dolist (item full-org-roam-db-list)
    (setq full-org-roam-db-list
        (append (directory-files item t "\\.[p,s]$") full-org-roam-db-list)))

  (setq full-org-roam-db-list-pretty (list "Default"))
  (dolist (item full-org-roam-db-list)
    (setq full-org-roam-db-list-pretty
        (append (list
                 (replace-regexp-in-string "\\/home\\/librephoenix\\/Org\\/" "" item)) full-org-roam-db-list-pretty)))

  (setq org-roam-db-choice (completing-read "Select org roam database: "
                          full-org-roam-db-list-pretty nil t)))
  (when arg
    (setq org-roam-db-choice arg))

  (if (string= org-roam-db-choice "Default")
      (setq org-roam-directory (file-truename "~/Org/Personal/Notes")
            org-roam-db-location (file-truename "~/Org/Personal/Notes/org-roam.db")
            org-directory (file-truename"~/Org/Personal/Notes"))
      (setq org-roam-directory (file-truename (concat "~/Org/" org-roam-db-choice "/Notes"))
            org-roam-db-location (file-truename (concat "~/Org/" org-roam-db-choice "/Notes/org-roam.db"))
            org-directory (file-truename (concat "~/Org/" org-roam-db-choice "/Notes"))))
  (when (not silent)
  (org-roam-open-dashboard))

  (org-roam-db-sync)

  (message (concat "Switched to " org-roam-db-choice " org-roam database!")))

(defun org-roam-default-overview ()
  (interactive)
  (org-roam-switch-db "Default"))

(defun org-roam-switch-db-id-open (arg ID &optional switchpersist)
  "Switch to another org-roam db and visit file with id arg"
  "If switchpersist is non-nil, stay in the new org-roam db after visiting file"
  (interactive)
  (setq prev-org-roam-db-choice org-roam-db-choice)
  (org-roam-switch-db arg 1)
  (org-roam-id-open ID)
  (when (not switchpersist)
    (org-roam-switch-db prev-org-roam-db-choice 1)))

Org Roam "todos" Tagging for Org Agenda

;;;------ Org-roam-agenda configuration ------;;;
(defun text-in-buffer-p (TEXT)
(save-excursion (goto-char (point-min)) (search-forward TEXT nil t)))

(defun apply-old-todos-tag-maybe (&optional FILE)
   (interactive)
   (if (stringp FILE)
   (setq the-daily-node-filename FILE)
   (setq the-daily-node-filename buffer-file-name))
   (if (org-roam-dailies--daily-note-p the-daily-node-filename)
    (if (<= (nth 2 (org-roam-dailies-calendar--file-to-date the-daily-node-filename)) (nth 2 org-agenda-current-date))
      (if (<= (nth 1 (org-roam-dailies-calendar--file-to-date the-daily-node-filename)) (nth 1 org-agenda-current-date))
        (if (<= (nth 0 (org-roam-dailies-calendar--file-to-date the-daily-node-filename)) (nth 0 org-agenda-current-date))
          (funcall (lambda ()
            (with-current-buffer (get-file-buffer the-daily-node-filename) (org-roam-tag-add '("old-todos")))
            (with-current-buffer (get-file-buffer the-daily-node-filename) (org-roam-tag-remove '("todos")))
            )
          )
        )
      )
    )
  )
)

(defun apply-old-todos-tag-maybe-and-save (FILE)
  (interactive)
  (find-file-noselect FILE)
  (apply-old-todos-tag-maybe FILE)
  (with-current-buffer (get-file-buffer the-daily-node-filename) (save-buffer))
  (with-current-buffer (get-file-buffer the-daily-node-filename) (kill-buffer))
)

; This has a bug where it won't sync a new agenda file
; if I'm editing an org roam node file while set to another
; org roam db
(defun add-todos-tag-on-save-org-mode-file()
  (interactive)
  (when (string= (message "%s" major-mode) "org-mode")
    (if (org-roam-node-p (org-roam-node-at-point))
    (funcall (lambda()
      (if (or (text-in-buffer-p "SCHEDULED: <") (text-in-buffer-p "DEADLINE: <"))
        (org-roam-tag-add '("todos"))
        (org-roam-tag-remove '("todos"))
      )
      (apply-old-todos-tag-maybe)
     )
    )
  )
 )
)

(add-hook 'before-save-hook 'add-todos-tag-on-save-org-mode-file)

Setup Org Agenda from Org Roam

(defun org-roam-filter-by-tag (tag-name)
  (lambda (node)
    (member tag-name (org-roam-node-tags node))))

(defun org-roam-list-notes-by-tag (tag-name)
  (mapcar #'org-roam-node-file
          (seq-filter
           (org-roam-filter-by-tag tag-name)
           (org-roam-node-list))))

(defun org-roam-dailies-apply-old-todos-tags-to-all ()
;  (dolist (daily-node org-roam-dailies-files)
;           (apply-old-todos-tag-maybe-and-save daily-node)
;  )
  (setq num 0)
  (while (< num (list-length (org-roam-list-notes-by-tag "todos")))
    (apply-old-todos-tag-maybe-and-save (nth num (org-roam-list-notes-by-tag "todos")))
  (setq num (1+ num))
  )
)

(defun org-roam-append-notes-to-agenda (tag-name db)
  (org-roam-switch-db db t)
;  (org-roam-dailies-apply-old-todos-tags-to-all)
  (setq org-agenda-files (append org-agenda-files (org-roam-list-notes-by-tag "todos")))
)

(defun org-roam-refresh-agenda-list ()
  (interactive)
  (setq prev-org-roam-db-choice org-roam-db-choice)
  (setq org-agenda-files '())
  (dolist (DB full-org-roam-db-list-pretty)
    (org-roam-append-notes-to-agenda "todos" DB)
  )
  (org-roam-switch-db prev-org-roam-db-choice 1)
)

;; Build agenda for first time during this session
(org-roam-refresh-agenda-list)

Org Roam Keybindings

(map! :leader
      :prefix ("N" . "org-roam notes")

      :desc "Capture new roam node"
      "c" 'org-roam-capture

      :desc "Insert roam node link at point"
      "i" 'org-roam-node-insert

      :desc "Find roam node"
      "." 'org-roam-node-find

      :desc "Switch org-roam database"
      "s" 'org-roam-switch-db

      :desc "Update current org-roam database"
      "u" 'org-roam-db-sync

      :desc "Re-zoom on current node in org-roam-ui"
      "z" 'org-roam-ui-node-zoom

      :desc "Visualize org-roam database with org-roam-ui"
      "O" 'org-roam-default-overview

      :desc "Visualize org-roam database with org-roam-ui"
      "o" 'org-roam-open-dashboard)

Org Roam Capture Templates

(after! org-roam
  (setq org-roam-capture-templates
        '(("d" "default" plain "%?" :target
  (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
  :unnarrowed t))))

Org Roam Olivetti Mode

(defun org-roam-olivetti-mode ()
  (interactive)
  (if (org-roam-file-p)
      (olivetti-mode))
  (if (org-roam-file-p)
      (doom-disable-line-numbers-h)))

(add-hook 'org-mode-hook 'org-roam-olivetti-mode)

Org Roam Dynamic Blocks

(use-package org-roam-dblocks
  :hook (org-mode . org-roam-dblocks-autoupdate-mode))

Org Roam Export Setup

(setq org-id-extra-files 'org-agenda-text-search-extra-files)

TODO Org Roam UI Setup

I want this to be able to automatically open ORUI in EAF Browser in a split to the right. This kinda works now?

;(add-to-list 'display-buffer-alist '("^\\ORUI" display-buffer-in-side-window
;                                    '(side . right)
;                                    (window-width . 50)
;))
;(add-to-list 'display-buffer-alist '("^\\localhost:35901" display-buffer-in-side-window
;                                    '(side . right)
;                                    (window-width . 50)
;))

(defun open-org-roam-ui ()
  (interactive)
  (+evil/window-vsplit-and-follow)
  (org-roam-ui-open)
  (evil-window-left))

(defun kill-org-roam-ui ()
  (interactive)
  (delete-window (get-buffer-window "ORUI" t))
  (kill-buffer "ORUI")
  (kill-buffer "*httpd*")
)

(map! :leader
      :prefix ("N" . "org-roam notes")
      :desc "Visualize org-roam database with org-roam-ui"
      "v" 'open-org-roam-ui)

(map! :leader
      :prefix ("N" . "org-roam notes")
      :desc "Kill all org roam ui buffers"
      "V" 'kill-org-roam-ui)

Org Agenda Configuration

Standard Org Agenda Configuration

;;;------ Org agenda configuration ------;;;

;; Set span for agenda
(setq org-agenda-span 1
      org-agenda-start-day "+0d")

;; Ricing org agenda
(setq org-agenda-current-time-string "")
(setq org-agenda-time-grid '((daily) () "" ""))

(setq org-agenda-prefix-format '(
(agenda . "  %?-2i %t ")
 (todo . " %i %-12:c")
 (tags . " %i %-12:c")
 (search . " %i %-12:c")))

(setq org-agenda-hide-tags-regexp ".*")

(setq org-agenda-category-icon-alist
      `(("Teaching" ,(list (all-the-icons-faicon "graduation-cap" :height 0.8)) nil nil :ascent center)
        ("Family" ,(list (all-the-icons-faicon "home" :v-adjust 0.005)) nil nil :ascent center)
        ("Producer" ,(list (all-the-icons-faicon "youtube-play" :height 0.9)) nil nil :ascent center)
        ("Bard" ,(list (all-the-icons-faicon "music" :height 0.9)) nil nil :ascent center)
        ("Story" ,(list (all-the-icons-faicon "book" :height 0.9)) nil nil :ascent center)
        ("Author" ,(list (all-the-icons-faicon "pencil" :height 0.9)) nil nil :ascent center)
        ("Gamedev" ,(list (all-the-icons-faicon "gamepad" :height 0.9)) nil nil :ascent center)
        ("Tech" ,(list (all-the-icons-faicon "laptop" :height 0.9)) nil nil :ascent center)
))

;; Function to be run when org-agenda is opened
(defun org-agenda-open-hook ()
  "Hook to be run when org-agenda is opened"
  (olivetti-mode))

;; Adds hook to org agenda mode, making follow mode active in org agenda
(add-hook 'org-agenda-mode-hook 'org-agenda-open-hook)

Org Agenda Convenience Functions

;; Function to list all my available org agenda files and switch to them
(defun list-and-switch-to-agenda-file ()
  "Lists all available agenda files and switches to desired one"
  (interactive)
  (setq full-agenda-file-list nil)
  (setq choice (completing-read "Select agenda file:" org-agenda-files nil t))
  (find-file choice))

(map! :leader
      :desc "Switch to specific org agenda file"
      "o a s" 'list-and-switch-to-agenda-file)

(map! :leader
      :desc "Open org calendar"
      "o c" #'cfw:open-org-calendar)

Org Super Agenda Configuration

(require 'org-super-agenda)

(setq org-super-agenda-groups
       '(;; Each group has an implicit boolean OR operator between its selectors.
         (:name "Home Tech"
                :and(:file-path "librephoenix/Agenda" :not (:tag "event"))
                :order 3)

         (:name "Family"
                :and(:file-path "Family" :not (:tag "event"))
                :order 3)

         (:name "Teaching Prep"
                :and(:file-path "Teaching.p" :tag "planning" :not (:tag "grading") :not (:tag "event"))
                :order 3)

         (:name "Teaching Secretarial"
                :and(:file-path "Teaching.p" :tag "secretarial" :not (:tag "grading") :not (:tag "event"))
                :order 3)

         (:name "Teaching Grading"
                :and(:file-path "Teaching.p" :tag "grading" :not (:tag "planning") :not (:tag "event"))
                :order 3)

         (:name "School Side Projects"
                :and(:file-path "Teaching.p" :tag "tech" :not (:tag "planning") :not (:tag "event"))
                :order 3)

         (:name "Gamedev Current Projects"
                :and (:file-path "Gamedev" :todo "STRT")
                :order 5)

         (:name "Youtube"
                :tag "youtube"
                :order 6)

         (:name "Learning"
                :tag "learning"
                :order 7)

          (:name "Today"  ; Optionally specify section name
                :time-grid t
                :date today
                :scheduled today
                :order 1)
))

(org-super-agenda-mode t)

(map! :desc "Next line"
      :map org-super-agenda-header-map
      "j" 'org-agenda-next-line)

(map! :desc "Next line"
      :map org-super-agenda-header-map
      "k" 'org-agenda-previous-line)

Magit Configuration

;;;------ magit configuration ------;;;

;; Need the following two blocks to make magit work with git bare repos
(defun ~/magit-process-environment (env)
  "Add GIT_DIR and GIT_WORK_TREE to ENV when in a special directory.
https://github.com/magit/magit/issues/460 (@cpitclaudel)."
  (let ((default (file-name-as-directory (expand-file-name default-directory)))
        (home (expand-file-name "~/")))
    (when (string= default home)
      (let ((gitdir (expand-file-name "~/.dotfiles.git/")))
        (push (format "GIT_WORK_TREE=%s" home) env)
        (push (format "GIT_DIR=%s" gitdir) env))))
  env)

(advice-add 'magit-process-environment
            :filter-return #'~/magit-process-environment)

Dired Configuration

;;;------ dired configuration ------;;;

(add-hook 'dired-mode-hook 'all-the-icons-dired-mode)

(map! :desc "Increase font size"
      "C-=" 'text-scale-increase

      :desc "Decrease font size"
      "C--" 'text-scale-decrease)

Ranger Configuration

;;;------ ranger configuration ------;;;

(map! :map ranger-mode-map
      :desc "Mark current file"
      "m" 'ranger-mark

      :desc "Toggle mark on current file"
      "x" 'ranger-toggle-mark

      :desc "Open ranger"
      "o d" 'ranger)

hledger-mode Configuration

;;;-- hledger-mode configuration ;;;--

;;; Basic configuration
(require 'hledger-mode)

;; To open files with .journal extension in hledger-mode
(add-to-list 'auto-mode-alist '("\\.journal\\'" . hledger-mode))

;; The default journal location is too opinionated.
(setq hledger-jfile "/home/librephoenix/Org/Family.s/Notes/hledger.journal")

;;; Auto-completion for account names
;; For company-mode users:
(add-to-list 'company-backends 'hledger-company)

(evil-define-key* 'normal hledger-view-mode-map "q" 'kill-current-buffer)
(evil-define-key* 'normal hledger-view-mode-map "[" 'hledger-prev-report)
(evil-define-key* 'normal hledger-view-mode-map "]" 'hledger-next-report)

(map! :leader
      :prefix ("l" . "hledger")
      :desc "Exec hledger command"
      "c" 'hledger-run-command

      :desc "Generate hledger balancesheet"
      "b" 'hledger-balancesheet*

      :desc "Exec hledger command"
      "d" 'hledger-daily-report*)

(map! :localleader
      :map hledger-mode-map

      :desc "Reschedule transaction at point"
      "d s" 'hledger-reschedule

      :desc "Edit amount at point"
      "t a" 'hledger-edit-amount)

Tab Bar Configuration

I don't have this active right now since I'm exploring tab-bar mode instead!

;;;-- tab-bar-mode configuration ;;;--

;; Kbd tab navigation
(map!
  :map evil-normal-state-map
  "H" #'tab-bar-switch-to-prev-tab
  "L" #'tab-bar-switch-to-next-tab
  "C-<iso-lefttab>" #'tab-bar-switch-to-prev-tab
  "C-<tab>" #'tab-bar-switch-to-next-tab)

(evil-global-set-key 'normal (kbd "C-w") 'tab-bar-close-tab)
(evil-global-set-key 'normal (kbd "C-t") 'tab-bar-new-tab)

(setq tab-bar-new-tab-choice "*doom*")

(tab-bar-mode t)

Focus Mode Configuration

(require 'focus)

(map! :leader
      :prefix ("F" . "Focus mode")
      :desc "Toggle focus mode"
      "t" 'focus-mode

      :desc "Pin focused section"
      "p" 'focus-pin

      :desc "Unpin focused section"
      "u" 'focus-unpin)

(add-to-list 'focus-mode-to-thing '(org-mode . org-element))
(add-to-list 'focus-mode-to-thing '(python-mode . paragraph))
(add-to-list 'focus-mode-to-thing '(lisp-mode . paragraph))

;(add-hook 'org-mode-hook #'focus-mode)

EAF

;;;-- Load emacs application framework;;;--
(use-package! eaf
  :load-path "~/.emacs.d/eaf/"
  :init
  :custom
  (eaf-browser-continue-where-left-off t)
  (eaf-browser-enable-adblocker t)
  (browse-url-browser-function 'eaf-open-browser) ;; Make EAF Browser my default browser
  :config
  (defalias 'browse-web #'eaf-open-browser)

  (require 'eaf-browser)

  (require 'eaf-evil)
  (define-key key-translation-map (kbd "SPC")
    (lambda (prompt)
      (if (derived-mode-p 'eaf-mode)
          (pcase eaf--buffer-app-name
            ("browser" (if  (string= (eaf-call-sync "eval_function" eaf--buffer-id "is_focus") "True")
                           (kbd "SPC")
                         (kbd eaf-evil-leader-key)))
            (_  (kbd "SPC")))
        (kbd "SPC")))))

(map! :leader
      :desc "Open web browser"
      "o w" #'eaf-open-browser-with-history)

My init.el

This section is the init.el section, which controls which Doom modules are loaded.

SPC h d h (vim) or C-h d h (non-vim) can be used to access Doom's documentation (including a "Module Index").

K (vim) or C-c c k (non-vim) can be used to view a module's documentation (this can help you discover module flags as well).

gd (vim) or C-c c d (non-vim) will let you browse a module's directory (source code).

(doom! :input
       ;;chinese
       ;;japanese
       ;;layout            ; auie,ctsrnm is the superior home row

       :completion
       company           ; the ultimate code completion backend
       ;;helm              ; the *other* search engine for love and life
       ;;ido               ; the other *other* search engine...
       ;;ivy               ; a search engine for love and life
       vertico           ; the search engine of the future

       :ui
       ;;deft              ; notational velocity for Emacs
       doom              ; what makes DOOM look the way it does
       doom-dashboard    ; a nifty splash screen for Emacs
       doom-quit         ; DOOM quit-message prompts when you quit Emacs
       (emoji +unicode)  ; 🙂
       hl-todo           ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
       ;;hydra
       ;;indent-guides     ; highlighted indent columns
       ;;ligatures         ; ligatures and symbols to make your code pretty again
       ;;minimap           ; show a map of the code on the side
       modeline          ; snazzy, Atom-inspired modeline, plus API
       nav-flash         ; blink cursor line after big motions
       neotree           ; a project drawer, like NERDTree for vim
       ophints           ; highlight the region an operation acts on
       (popup +defaults)   ; tame sudden yet inevitable temporary windows
       ;;tabs              ; a tab bar for Emacs
       treemacs          ; a project drawer, like neotree but cooler
       unicode           ; extended unicode support for various languages
       vc-gutter         ; vcs diff in the fringe
       vi-tilde-fringe   ; fringe tildes to mark beyond EOB
       window-select     ; visually switch windows
       workspaces        ; tab emulation, persistence & separate workspaces
       ;;zen               ; distraction-free coding or writing

       :editor
       (evil +everywhere); come to the dark side, we have cookies
       file-templates    ; auto-snippets for empty files
       fold              ; (nigh) universal code folding
       (format +onsave)  ; automated prettiness
       ;;god               ; run Emacs commands without modifier keys
       ;;lispy             ; vim for lisp, for people who don't like vim
       ;;multiple-cursors  ; editing in many places at once
       ;;objed             ; text object editing for the innocent
       ;;parinfer          ; turn lisp into python, sort of
       ;;rotate-text       ; cycle region at point between text candidates
       snippets          ; my elves. They type so I don't have to
       word-wrap         ; soft wrapping with language-aware indent

       :emacs
       (dired +ranger)   ; making dired pretty [functional]
       electric          ; smarter, keyword-based electric-indent
       ibuffer           ; interactive buffer management
       undo              ; persistent, smarter undo for your inevitable mistakes
       vc                ; version-control and Emacs, sitting in a tree

       :term
       eshell            ; the elisp shell that works everywhere
       ;;shell             ; simple shell REPL for Emacs
       ;;term              ; basic terminal emulator for Emacs
       vterm             ; the best terminal emulation in Emacs

       :checkers
       syntax              ; tasing you for every semicolon you forget
       (spell +flyspell) ; tasing you for misspelling mispelling
       ;;grammar           ; tasing grammar mistake every you make

       :tools
       ;;ansible
       ;;biblio            ; Writes a PhD for you (citation needed)
       ;;debugger          ; FIXME stepping through code, to help you add bugs
       ;;direnv
       ;;docker
       ;;editorconfig      ; let someone else argue about tabs vs spaces
       ;;ein               ; tame Jupyter notebooks with emacs
       (eval +overlay)     ; run code, run (also, repls)
       ;;gist              ; interacting with github gists
       lookup              ; navigate your code and its documentation
       lsp               ; M-x vscode
       magit             ; a git porcelain for Emacs
       ;;make              ; run make tasks from Emacs
       ;;pass              ; password manager for nerds
       ;;pdf               ; pdf enhancements
       ;;prodigy           ; FIXME managing external services & code builders
       rgb               ; creating color strings
       ;;taskrunner        ; taskrunner for all your projects
       ;;terraform         ; infrastructure as code
       ;;tmux              ; an API for interacting with tmux
       ;;upload            ; map local to remote projects via ssh/ftp

       :os
       ;;(:if IS-MAC macos)  ; improve compatibility with macOS
       tty               ; improve the terminal Emacs experience

       :lang
       ;;agda              ; types of types of types of types...
       ;;beancount         ; mind the GAAP
       cc                ; C > C++ == 1
       ;;clojure           ; java with a lisp
       common-lisp       ; if you've seen one lisp, you've seen them all
       ;;coq               ; proofs-as-programs
       ;;crystal           ; ruby at the speed of c
       ;;csharp            ; unity, .NET, and mono shenanigans
       data              ; config/data formats
       ;;(dart +flutter)   ; paint ui and not much else
       ;;dhall
       ;;elixir            ; erlang done right
       ;;elm               ; care for a cup of TEA?
       emacs-lisp        ; drown in parentheses
       ;;erlang            ; an elegant language for a more civilized age
       ;;ess               ; emacs speaks statistics
       ;;factor
       ;;faust             ; dsp, but you get to keep your soul
       ;;fortran           ; in FORTRAN, GOD is REAL (unless declared INTEGER)
       ;;fsharp            ; ML stands for Microsoft's Language
       ;;fstar             ; (dependent) types and (monadic) effects and Z3
       gdscript          ; the language you waited for
       ;;(go +lsp)         ; the hipster dialect
       (haskell +lsp)    ; a language that's lazier than I am
       ;;hy                ; readability of scheme w/ speed of python
       ;;idris             ; a language you can depend on
       json              ; At least it ain't XML
       ;;(java +meghanada) ; the poster child for carpal tunnel syndrome
       ;;javascript        ; all(hope(abandon(ye(who(enter(here))))))
       ;;julia             ; a better, faster MATLAB
       ;;kotlin            ; a better, slicker Java(Script)
       latex             ; writing papers in Emacs has never been so fun
       ;;lean              ; for folks with too much to prove
       ;;ledger            ; be audit you can be
       lua                 ; one-based indices? one-based indices
       markdown            ; writing docs for people to ignore
       ;;nim               ; python + lisp at the speed of c
       nix               ; I hereby declare "nix geht mehr!"
       ;;ocaml             ; an objective camel
       (org +roam2)      ; organize your plain life in plain text
       ;;php               ; perl's insecure younger brother
       ;;plantuml          ; diagrams for confusing people more
       ;;purescript        ; javascript, but functional
       python            ; beautiful is better than ugly
       ;;qt                ; the 'cutest' gui framework ever
       ;;racket            ; a DSL for DSLs
       ;;raku              ; the artist formerly known as perl6
       ;;rest              ; Emacs as a REST client
       ;;rst               ; ReST in peace
       ;;(ruby +rails)     ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
       ;;rust              ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
       ;;scala             ; java, but good
       ;;(scheme +guile)   ; a fully conniving family of lisps
       sh                ; she sells {ba,z,fi}sh shells on the C xor
       ;;sml
       ;;solidity          ; do you need a blockchain? No.
       ;;swift             ; who asked for emoji variables?
       ;;terra             ; Earth and Moon in alignment for performance.
       web               ; the tubes
       yaml              ; JSON, but readable
       ;;zig               ; C, but simpler

       :email
       ;;(mu4e +org)
       ;;notmuch
       ;;(wanderlust +gmail)

       :app
       calendar
       ;;emms
       ;;everywhere        ; *leave* Emacs!? You must be joking
       ;;irc               ; how neckbeards socialize
       ;;(rss +org)        ; emacs as an RSS reader
       ;;twitter           ; twitter client https://twitter.com/vnought

       :config
       ;;literate
       (default +bindings +smartparens))

My packages.el

The packages.el file allows extra packages to be configured outside of the typical Doom modules from init.el.

Packages are declared via (package! some-package) where some-package is from MELPA, ELPA, or emacsmirror.

There are other ways to install packages outside of Emacs package archives, including directly from git. Installing a package directly from git requires a :recipe. Here is a full documentation of the recipe format.

Doom's built-in packages can also be modified here:

  • (package! builtin-package :disable t) to disable
  • (package! builtin-package-2 :recipe (:repo "myfork/package")) to override the recipe

    • Side-note: the full recipe for built-in packages does not need specification, as the override will inherit the unspecified properties directly from Doom

Any git package can be configured for a particular commit or branch:

  • (package! builtin-package :recipe (:branch "develop") for a particular branch
  • (package! builtin-package :pin "1a2b3c4d5e") for a particular commit
  • (unpin! pinned-package another-pinned-package) to get bleeding edge instead of Doom's stability
;;(package! org-bullets)
(package! org-modern)
(package! org-super-agenda)
(package! emacsql :pin "c1a4407")
(package! org-roam-ui)
;;(package! org-roam-nursery :recipe (:repo "https://github.com/chrisbarrett/nursery"))
(package! lister)
(package! org-download)
(package! org-yt)
(package! toc-org)
(package! all-the-icons-dired)
(package! all-the-icons-completion)
(package! ox-reveal)
(package! hledger-mode)
(package! rainbow-mode)
(package! crdt)
(package! ess)
(package! openwith)
(package! ob-mermaid)
(package! focus)
(package! olivetti)