#+TITLE: Doom Emacs Literate Config
#+AUTHOR: Emmet

* Table of Contents :TOC:QUOTE:
#+BEGIN_QUOTE
- [[#what-is-doom-emacs][What is Doom Emacs?]]
- [[#configuration-for-doom-emacs][Configuration for Doom Emacs]]
- [[#my-configel][My config.el]]
  - [[#preamble--user-configuration][Preamble + User Configuration]]
  - [[#registers][Registers]]
  - [[#org-mode-configuration][Org Mode Configuration]]
  - [[#org-roam-configuration][Org Roam Configuration]]
  - [[#org-agenda-configuration][Org Agenda Configuration]]
  - [[#magit-configuration][Magit Configuration]]
  - [[#ibuffer-configuration][Ibuffer Configuration]]
  - [[#dired-configuration][Dired Configuration]]
  - [[#ranger-configuration][Ranger Configuration]]
  - [[#hledger-mode-configuration][hledger-mode Configuration]]
  - [[#tab-bar-configuration][Tab Bar Configuration]]
  - [[#focus-mode-configuration][Focus Mode Configuration]]
  - [[#helpful-mode-configuration][Helpful Mode Configuration]]
  - [[#eaf][EAF]]
- [[#my-initel][My init.el]]
- [[#my-packagesel][My packages.el]]
- [[#nix-integration][Nix Integration]]
#+END_QUOTE

* What is Doom Emacs?
[[https://github.com/doomemacs/doomemacs][Doom Emacs]] is a distribution of the [[https://www.gnu.org/software/emacs/][Emacs Text Editor]] designed for [[https://www.vim.org/][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:
- [[https://orgmode.org/][Org Mode]] (Hierarchical text-based document format)
- [[https://www.orgroam.com/][Org Roam]] (A second brain / personal wiki)
- [[https://orgmode.org/][Org Agenda]] (Calendar and todo list)
- [[https://magit.vc/][magit]] (Git Client)

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.  I primarily use Emacs for writing, note-taking, task/project management and organizing information.

* 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][config.el]] - Stores your main configuration and allows to set user variables.
- [[./init.el][init.el]] - Allows quick downloads of groups of Emacs packages. These groups of Emacs packages are curated by the Doom Emacs developers.
- [[./packages.el][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][config.el]] via the =load!= function, like so:

#+BEGIN_SRC emacs-lisp
(load! "~/.doom.d/private.el")
#+END_SRC

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

Doom Emacs is traditionally installed by cloning the repository ([[https://github.com/doomemacs/doomemacs][https://github.com/doomemacs/doomemacs]]) and running =./bin/doom install=.  I instead install Doom Emacs via Nix Doom Emacs ([[https://github.com/nix-community/nix-doom-emacs][https://github.com/nix-community/nix-doom-emacs]]), which packages Doom Emacs as a Nix derivation.  The advantage to this is that I get more reproducibility and the ability to rollback updates (if anything breaks), but the downside is that every time the config is changed/updated, the entire derivation must be rebuilt from scratch (this is often time-consuming).  I load this as a Nix derivation in my flake using the [[./doom.nix][doom.nix]] module.

* My config.el
** Preamble + User Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-

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

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

;; 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))
;; +unicode-init-fonts-h often errors out
(remove-hook 'doom-init-ui-hook '+unicode-init-fonts-h)

;; 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 "~/.emacs.d/dashboard-logo.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)

#+END_SRC
** Registers
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ Registers ------;;;

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

(set-register ?f '(file . "/home/emmet/Org/Family.s/Notes/hledger.org"))
(set-register ?h '(file . "/home/emmet"))
(set-register ?r '(file . "/home/emmet/.dotfiles/README.org"))
(set-register ?x '(file . "/home/emmet/.dotfiles/user/wm/xmonad/xmonad.org"))
(set-register ?d '(file . "/home/emmet/.dotfiles/user/app/doom-emacs/doom.org"))

#+END_SRC
** Org Mode Configuration
*** Standard Org Mode Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

(require 'evil-org)
(require 'evil-org-agenda)
(add-hook 'org-mode-hook 'evil-org-mode -100)

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

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

#+END_SRC
*** Org Download, Image Capture, and Opening Files in External Programs
#+BEGIN_SRC emacs-lisp :tangle config.el
(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/emmet/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)

#+END_SRC
*** Copy Links/Files into Clipboard
#+BEGIN_SRC emacs-lisp :tangle config.el
(defun org-copy-link-to-clipboard-at-point ()
  "Copy current link at point into clipboard (useful for images and links)"
  ;; Remember to press C-g to kill this foreground process if it hangs!
  (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 "~/.emacs.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)

#+END_SRC
**** Copy Link/File to Clipboard Helper Script
Shamelessly stolen from [[https://unix.stackexchange.com/questions/30093/copy-image-from-command-line-to-clipboard][here]] and modified for my use.
#+BEGIN_SRC shell :tangle ./scripts/copy-link-or-file/copy-link-or-file-to-clipboard.sh :tangle-mode (identity #o755)
#!/bin/sh
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
#+END_SRC
*** Org Online Images
#+BEGIN_SRC emacs-lisp :tangle config.el
;; 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)
#+END_SRC
*** Org Mermaid Diagrams
#+BEGIN_SRC emacs-lisp :tangle config.el
;; Mermaid diagrams
(setq ob-mermaid-cli-path "~/.nix-profile/bin/mmdc")
#+END_SRC
*** Org Simple Printing
#+BEGIN_SRC emacs-lisp :tangle config.el
;; 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)

#+END_SRC
** Org Roam Configuration
*** Standard Org Roam Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

#+END_SRC
*** Multi Org Roam Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
(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\\/emmet\\/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\\/emmet\\/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)))

#+END_SRC
*** Org Roam "todos" Tagging for Org Agenda
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

#+END_SRC
*** Setup Org Agenda from Org Roam
#+BEGIN_SRC emacs-lisp :tangle config.el
(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)


(map! :leader
      :prefix ("o a")

      :desc "Refresh org agenda from roam dbs"
      "r" 'org-roam-refresh-agenda-list)


#+END_SRC
*** Org Roam Keybindings
#+BEGIN_SRC emacs-lisp :tangle config.el
(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)

#+END_SRC
*** Org Roam Capture Templates
#+BEGIN_SRC emacs-lisp :tangle config.el
(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))))

#+END_SRC
*** Org Roam Olivetti Mode
#+BEGIN_SRC emacs-lisp :tangle config.el
(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)

#+END_SRC
*** Org Roam Dynamic Blocks
This needs fixing on NixOS:
#+BEGIN_SRC emacs-lisp :tangle config.el
(add-load-path! "~/.emacs.d/org-nursery/lisp")
(require 'org-roam-dblocks)
(use-package org-roam-dblocks
  :hook (org-mode . org-roam-dblocks-autoupdate-mode))

#+END_SRC
*** Org Roam Export Setup
#+BEGIN_SRC emacs-lisp :tangle config.el
(setq org-id-extra-files 'org-agenda-text-search-extra-files)

#+END_SRC
*** 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?
#+BEGIN_SRC emacs-lisp :tangle config.el
;(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)

#+END_SRC
** Org Agenda Configuration
*** Standard Org Agenda Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

#+END_SRC
*** Org Agenda Convenience Functions
#+BEGIN_SRC emacs-lisp :tangle config.el
;; 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)

(defun org-agenda-switch-with-roam ()
  "Switches to org roam node file and database from org agenda view"
  (interactive)
  (org-agenda-switch-to)
  (if (f-exists-p (concat (dir!) "/org-roam.db"))
    (org-roam-switch-db (f-filename (f-parent (dir!))) t))
  (org-roam-olivetti-mode)
)

(map!
  :map evil-org-agenda-mode-map
  :after org-agenda
  :nvmeg "<RET>" #'org-agenda-switch-with-roam
  :nvmeg "<return>" #'org-agenda-switch-with-roam)
(map!
  :map org-agenda-mode-map
  :after org-agenda
  :nvmeg "<RET>" #'org-agenda-switch-with-roam
  :nvmeg "<return>" #'org-agenda-switch-with-roam)

#+END_SRC
*** Org Super Agenda Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
(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 "emmet/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)

#+END_SRC
** Magit Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

(evil-set-initial-state 'magit-status-mode 'motion)
(evil-set-initial-state 'magit-log-mode 'motion)
(evil-set-initial-state 'magit-diff-mode 'motion)
(evil-set-initial-state 'magit-refs-mode 'motion)
(evil-define-key 'motion magit-status-mode-map
  "j" 'evil-next-visual-line
  "k" 'evil-previous-visual-line
  "c" 'magit-commit
  "s" 'magit-stage
  "u" 'magit-unstage
  "l" 'magit-log
  "F" 'magit-pull
  "p" 'magit-push
  "q" '+magit/quit
  (kbd "<return>") 'magit-diff-visit-file-worktree)
(evil-define-key 'motion magit-log-mode-map
  "j" 'evil-next-visual-line
  "k" 'evil-previous-visual-line
  "q" '+magit/quit
  (kbd "<return>") 'magit-visit-ref)
(evil-define-key 'motion magit-diff-mode-map
  "j" 'evil-next-visual-line
  "k" 'evil-previous-visual-line
  "q" '+magit/quit
  (kbd "<return>") 'magit-visit-ref)
(evil-define-key 'motion magit-refs-mode-map
  "j" 'evil-next-visual-line
  "k" 'evil-previous-visual-line
  "q" '+magit/quit
  (kbd "<return>") 'magit-visit-ref)

#+END_SRC
** Ibuffer Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
(evil-set-initial-state 'ibuffer-mode 'motion)
(evil-define-key 'motion 'ibuffer-mode
  "j" 'evil-next-visual-line
  "k" 'evil-previous-visual-line
  "d" 'ibuffer-mark-for-delete
  "q" 'kill-buffer
  (kbd "<return>") 'ibuffer-visit-buffer)
#+END_SRC
** Dired Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

#+END_SRC
** Ranger Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ 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)

#+END_SRC
** hledger-mode Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;-- 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/emmet/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)

#+END_SRC
** Tab Bar Configuration
I don't have this active right now since I'm exploring tab-bar mode instead!
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;-- 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)

#+END_SRC
** Focus Mode Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
(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)

#+END_SRC
** Helpful Mode Configuration
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;------ helpful configuration ------;;;

(evil-set-initial-state 'helpful-mode 'normal)
(evil-define-key 'normal helpful-mode-map
  "j" 'evil-next-visual-line
  "k" 'evil-previous-visual-line
  "q" 'helpful-kill-buffers)

#+END_SRC
** EAF
#+BEGIN_SRC emacs-lisp :tangle config.el
;;;-- 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)

#+END_SRC
* My init.el
This section is the [[./init.el][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).

#+BEGIN_SRC emacs-lisp :tangle init.el
(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))

#+END_SRC

* My packages.el
The [[./packages.el][packages.el]] file allows extra packages to be configured outside of the typical Doom modules from [[./init.el][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 [[https://github.com/raxod502/straight.el#the-recipe-format][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

#+BEGIN_SRC emacs-lisp :tangle packages.el
(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)
#+END_SRC
* Nix Integration
In order to have Nix load my Doom Emacs configuration [[./doom.nix][doom.nix]], which I source in the =imports= block of my [[../../home.nix][home.nix]].
#+BEGIN_SRC nix :tangle doom.nix
{ config, lib, pkgs, eaf, eaf-browser, org-nursery, myThemePolarity, ... }:
let
  myDashboardLogo = ./. + "/nix-" + myThemePolarity + ".png";
in
{
  programs.doom-emacs = {
    enable = true;
    doomPrivateDir = ./.;
    # This block from https://github.com/znewman01/dotfiles/blob/be9f3a24c517a4ff345f213bf1cf7633713c9278/emacs/default.nix#L12-L34
    # Only init/packages so we only rebuild when those change.
    doomPackageDir = let
      filteredPath = builtins.path {
        path = ./.;
        name = "doom-private-dir-filtered";
        filter = path: type:
          builtins.elem (baseNameOf path) [ "init.el" "packages.el" ];
      };
      in pkgs.linkFarm "doom-packages-dir" [
        {
          name = "init.el";
          path = "${filteredPath}/init.el";
        }
        {
          name = "packages.el";
          path = "${filteredPath}/packages.el";
        }
        {
          name = "config.el";
          path = pkgs.emptyFile;
        }
      ];
  # End block
  };

  home.file.".emacs.d/themes/doom-stylix-theme.el".source = config.lib.stylix.colors {
      template = builtins.readFile ./themes/doom-stylix-theme.el.mustache;
      extension = ".el";
  };

  home.packages = with pkgs; [
  git
  file
  nodejs
  wmctrl
  jshon
  aria
  hledger
  hunspell hunspellDicts.en_US-large
  pandoc
  nodePackages.mermaid-cli
  (python3.withPackages (p: with p; [
    pandas
    requests
    pyqt6 sip qtpy qt6.qtwebengine epc lxml pyqt6-webengine
    pysocks
    pymupdf
    markdown
  ]))];

  home.sessionVariables = {
    EDITOR = "emacsclient";
  };

  home.file.".emacs.d/eaf" = {
    source = "${eaf}";
    recursive = true;
  };
  home.file.".emacs.d/eaf/app/browser" = {
    source = "${eaf-browser}";
    recursive = true;
    onChange = "
      pushd ~/.emacs.d/eaf/app/browser;
      rm package*.json;
      npm install darkreader @mozilla/readability && rm package*.json;
      popd;
    ";
  };
  home.file.".emacs.d/org-nursery" = {
    source = "${org-nursery}";
  };
  home.file.".emacs.d/dashboard-logo.png".source = myDashboardLogo;
  home.file.".emacs.d/scripts/copy-link-or-file/copy-link-or-file-to-clipboard.sh" = {
    source = ./scripts/copy-link-or-file/copy-link-or-file-to-clipboard.sh;
    executable = true;
  };
}
#+END_SRC
