Doom Literate Config
Table of Contents
1. config.el Configuration
This is a doom emacs configuration. If you are not using doom emacs, do not use this document.
1.1. Basic Information
My name, and the org mode directory on my computer, as well as basic editor configuration options. Below is the old documentation.
(setq user-full-name "Preston Pan" user-mail-address "preston@nullring.xyz") (setq display-line-numbers-type t) (setq x-select-enable-clipboard t) (setq save-interprogram-paste-before-kill t) (setq yank-pop-change-selection t) (setq org-directory "~/org/") (setq warning-minimum-level :emergency)
- `load!' for loading external *.el files relative to this one
- `add-load-path!' for adding directories to the `load-path', relative to this file. Emacs searches the `load-path' when you load packages with `require' or `use-package'.
1.2. Modeline
In order to display the time in the modeline:
(display-time-mode 1)
To display the battery percentage:
(display-battery-mode 1)
1.3. Transparency
Let's make emacs transparent.
(set-frame-parameter nil 'alpha-background 90) (add-to-list 'default-frame-alist '(alpha-background . 90))
1.4. EXWM
First we load our packages:
;; (use-package! exwm) ;; (use-package! exwm-config) ;; (exwm-config-example)
Now, we set our keybindings:
;; (setq exwm-input-global-keys ;; `( ;; ([?\s-r] . exwm-reset) ;; ([?\s-w] . exwm-workspace-switch) ;; ,@(mapcar (lambda (i) ;; `(,(kbd (format "s-%d" i)) . ;; (lambda () ;; (interactive) ;; (exwm-workspace-switch-create ,i)))) ;; (number-sequence 0 9)) ;; ([?\s-&] . (lambda (command) ;; (interactive (list (read-shell-command "$ "))) ;; (start-process-shell-command command nil command))) ;; ([?\s-d] . (lambda () ;; (interactive) ;; (dired default-directory))) ;; ([?\s-f] . (lambda () ;; (interactive) ;; (exwm-layout-toggle-mode-line) ;; (exwm-workspace-toggle-minibuffer))) ;; ([?\s-b] . exwm-workspace-switch-to-buffer) ;; ([?\s-w] . (lambda () ;; (interactive) ;; (start-process "" nil "qutebrowser"))) ;; ([?\s-n] . (lambda () ;; (interactive) ;; (start-process "" nil "nyxt"))) ;; ([?\s-k] . (lambda () ;; (interactive) ;; (start-process "" nil "krita"))) ;; ([?\s-g] . (lambda () ;; (interactive) ;; (start-process "" nil "gimp"))) ;; ([?\s-b] . (lambda () ;; (interactive) ;; (start-process "" nil "blender"))) ;; ([?\s-c] . (lambda () ;; (interactive) ;; (start-process "" nil "chromium"))) ;; ([s-f2] . (lambda () ;; (interactive) ;; (start-process "" nil "/usr/bin/slock")))))
And we also need to set up our media keys:
;; (exwm-input-set-key (kbd "<XF86AudioNext>") 'emms-next) ;; (exwm-input-set-key (kbd "<XF86AudioPrev>") 'emms-previous) ;; (exwm-input-set-key (kbd "<XF86AudioPlay>") 'emms-pause) ;; (exwm-input-set-key ;; (kbd "<XF86AudioRaiseVolume>") ;; (lambda () ;; (interactive) (start-process-shell-command ;; "pactl" nil "pactl set-sink-volume 0 +5% && pactl set-sink-volume 1 +5%"))) ;; (exwm-input-set-key ;; (kbd "<XF86AudioLowerVolume>") ;; (lambda () ;; (interactive) (start-process-shell-command ;; "pactl" nil "pactl set-sink-volume 0 -5% && pactl set-sink-volume 1 -5%"))) ;; (exwm-input-set-key ;; (kbd "<XF86AudioMute>") ;; (lambda () ;; (interactive) (start-process-shell-command ;; "pactl" nil "pactl set-sink-mute 0 tog ;; gle && pactl set-sink-mute 1 toggle"))) ;; Things to implement in exwm: ;;Key([], 'XF86MonBrightnessUp', lazy.spawn("light -A 10")), ;;Key([], 'XF86MonBrightnessDown', lazy.spawn("light -U 10")), ;;Key([], "Print", lazy.spawn("scrot '%Y-%m-%d-%s_screenshot_$wx$h.jpg' -e 'mv $f ~/img/scrot")),
1.5. Font
Now we configure fonts:
(setq doom-font (font-spec :family "Hack" :size 16 :weight 'semi-light) doom-variable-pitch-font (font-spec :family "Fira Sans" :size 16) doom-unicode-font (font-spec :family "Symbola" :size 16) doom-serif-font (font-spec :family "Fira Sans" :size 16) doom-big-font (font-spec :family "Hack" :size 28))
1.6. Color Scheme
I'm experimenting with many themes right now. One of these themes is the city-lights theme, another one of them is the catppuccin theme.
;; (setq doom-theme 'doom-ayu-light) (setq doom-theme 'doom-gruvbox) ;; (setq catppuccin-flavor 'mocha) ;; (load-theme 'catppuccin)
1.7. Doom Module and Programs Configuration
1.7.1. Agenda
Now we add these two files to our agenda search path:
(require 'org-habit) (setq org-agenda-files (list "~/org/agenda.org" "~/org/contacts.org" "~/org/notes.org")) (setq org-default-notes-file (concat org-directory "/notes.org"))
And we also want to set up org-habit to start graphing our habits as soon as possible:
(setq org-habit-preceding-days 1)
1.7.2. IRC
Set up circe to connect to my bouncer:
;; (after! circe ;; (set-irc-server! "nullring.xyz" ;; `(:tls t ;; :port 4095 ;; :nick "LiCoO2/AndreiNet" ;; :user "LiCoO2/AndreiNet" ;; :pass ,(+pass-get-secret "ZNC"))))
And another to connect to libera:
(after! circe (set-irc-server! "irc.libera.chat" `(:tls t :port 6697 :nick "ret2pop" :sasl-username "ret2pop" :sasl-password (lambda (&rest _) (+pass-get-secret "libera.chat")) :channels ("#emacs" "#rwx"))))
(after! circe (set-irc-server! "nullring.xyz" `(:tls t :port 6697 :nick "LiCoO2")))
1.7.3. Email
In order to use this configuration, you must install and configure mu and mbsync.
;; (setq send-mail-function 'smtpmail-send-it) ;; (setq smtpmail-default-smtp-server "mail.nullring.xyz") ;; (setq smtpmail-smtp-server "mail.nullring.xyz") ;; (setq smtpmail-smtp-service 465) ;; (setq smtpmail-stream-type 'starttls) (require 'smtpmail) (setq send-mail-function 'smtpmail-send-it) (setq smtpmail-smtp-server "mail.nullring.xyz") (setq smtpmail-default-smtp-server "mail.nullring.xyz") (setq smtpmail-smtp-service 465) (setq smtpmail-smtp-user "preston@nullring.xyz") (setq smtpmail-stream-type 'ssl) (setq smtpmail-debug-info t) (setq smtpmail-auth-credentials '(("mail.nullring.xyz" 465 "preston@nullring.xyz" "lO7Y`\"-si<zU"))) (set-email-account! "prestonpan" '((mu4e-sent-folder . "/Sent") (mu4e-drafts-folder . "/Drafts") (mu4e-trash-folder . "/Trash") (smtpmail-smtp-user . "preston@nullring.xyz") (user-mail-address . "preston@nullring.xyz") ;; only needed for mu < 1.4 (mu4e-compose-signature . "---\nPreston Pan")) t)
1.7.4. RSS
We need to set up elfeed with a list of rss feeds.
(after! elfeed (setq elfeed-search-filter "@1-month-ago +unread")) (add-hook! 'elfeed-search-mode-hook #'elfeed-update) (setq rmh-elfeed-org-files '("~/org/elfeed.org"))
1.7.5. EWW
We want the default search engine of eww to be google because duckduckgo is bad:
(setq search-engines '( (("google" "g") "https://google.com/search?q=%s") (("duckduckgo" "d" "ddg") "https://duckduckgo.com/?q=%s") (("rfc" "r") "https://www.rfc-editor.org/rfc/rfc%s.txt") (("rfc-kw" "rk") "https://www.rfc-editor.org/search/rfc_search_detail.php?title=%s"))) (setq search-engine-default "google") (setq eww-search-prefix "https://google.com/search?q=") (setq browse-url-secondary-browser-function 'browse-url-generic browse-url-generic-program "qutebrowser") (setq browse-url-browser-function 'eww-browse-url) (add-hook 'eww-mode-hook (lambda () (local-set-key (kbd "y Y") #'eww-copy-page-url)))
1.7.6. Music
In order to use this configuration, you must have mpd configured to use the same directory. We automatically connect to mpd.
(emms-all) (setq emms-source-file-default-directory (expand-file-name "~/music/")) (setq emms-player-mpd-music-directory "~/music/") (setq emms-player-mpd-server-name "localhost") (setq emms-player-mpd-server-port "6600") (setq emms-player-list '(emms-player-mpd)) (add-to-list 'emms-info-functions 'emms-info-mpd) (add-to-list 'emms-player-list 'emms-player-mpd) (emms-player-mpd-connect)
1.8. Keybindings
Now we set up our keybindings for our applications:
(map! :leader :desc "Open irc" "i c" #'circe) (map! :leader :desc "Open audio manager" "m m" #'emms) (map! :leader :desc "Open RSS feed reader" "r s" #'elfeed) (map! :leader :desc "Open password manager" "p w" #'ivy-pass) (map! :leader :desc "Open dictionary program" "d i" #'dictionary) (map! :leader :desc "Open rtorrent frontend" "r t" #'mentor) (map! :leader :desc "Open eww web browser" "e w" #'eww)
1.8.1. Journal
First we set the journal to be in the website directory:
(setq org-journal-dir "~/org/website/journal/") (setq org-journal-date-format "%A, %d %B %Y")
And then we add the headers needed to export the journal automatically:
(defun org-journal-file-header-func (time) "Custom function to create journal header." (concat (pcase org-journal-file-type (`daily "#+TITLE: Daily Journal\n#+STARTUP: showeverything\n#+DESCRIPTION: My daily journal entry\n#+AUTHOR: Preston Pan\n#+HTML_HEAD: <link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\" />\n#+html_head: <script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n#+html_head: <script id=\"MathJax-script\" async src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\"></script>\n#+options: broken-links:t") (`weekly "#+TITLE: Weekly Journal\n#+STARTUP: folded") (`monthly "#+TITLE: Monthly Journal\n#+STARTUP: folded") (`yearly "#+TITLE: Yearly Journal\n#+STARTUP: folded")))) (setq org-journal-file-header 'org-journal-file-header-func) (setq org-journal-file-format "%Y%m%d.org")
To add everything to the agenda search path, we toggle:
(setq org-journal-enable-agenda-integration t)
1.8.2. Brain
I don't use this anymore, but it's good to have.
(setq org-brain-path "~/org/website/brain/")
1.8.3. Roam
This is the configuration for my mindmap.
(setq org-roam-graph-viewer "qutebrowser") (setq org-roam-directory (file-truename "~/org/website/mindmap")) (setq org-roam-capture-templates '(("d" "default" plain "%?" :target (file+head "${title}.org" "#+title: ${title}\n#+author: Preston Pan\n#+html_head: <link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\" />\n#+html_head: <script src=\"https://polyfill.io/v3/polyfill.min.js?features=es6\"></script>\n#+html_head: <script id=\"MathJax-script\" async src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\"></script>\n#+options: broken-links:t") :unnarrowed t)))
1.8.4. Publishing
In order to publish my website, we need to configure emacs to publish it somewhere and with diferrent parameters:
(require 'ox-publish) (setq org-publish-project-alist '(("website-org" :base-directory "~/org/website" :base-extension "org" :publishing-directory "~/website_html" :recursive t :publishing-function org-html-publish-to-html :headline-levels 4 :html-preamble t :html-preamble-format (("en" "<p class=\"preamble\"><a href=\"/index.html\">home</a> | <a href=\"./index.html\">section main page</a></p><hr>"))) ("website-static" :base-directory "~/org/website" :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|ico" :publishing-directory "~/website_html/" :recursive t :publishing-function org-publish-attachment) ("website" :auto-sitemap t :components ("website-org" "website-static")))) ;; (setq org-export-html-postamble-format '(("en" "<p class=\"preamble\"><a href=\"../index.html\">previous page</a> | <a href=\"/index.html\">home</a></p>"))) (setq org-html-postamble "Copyright © 2024 Preston Pan")
1.8.5. Contacts
Now we configure org-contacts, which allows me to store contacts in an org mode file:
(setq org-contacts-files '("~/org/contacts.org"))
And then we need to add some templates with org-capture in order to add entries to the contacts easier:
(defvar my/org-contacts-template "* %^{name} :PROPERTIES: :ADDRESS: %^{289 Cleveland St. Brooklyn, 11206 NY, USA} :BIRTHDAY: %^{yyyy-mm-dd} :EMAIL: %^{Email} :NOTE: %^{NOTE} :END:" "Template for org-contacts.") (setq org-capture-templates `(("c" "Contact" entry (file+headline "~/org/contacts.org" "Friends"), my/org-contacts-template :empty-lines 1)))
1.8.6. Org Timer
Sometimes I want a timer to help me keep track of the time.
(setq org-clock-sound "~/audio/ding.wav")
1.9. External Packages
we want to include some packages that don't come with doom emacs.
1.9.1. KBD-Mode
kbd-mode allows us to edit kmonad kbd files with syntax highlighting:
(use-package! kbd-mode)
1.9.2. Pinentry
We now set up pinentry for the pass program. We need to set the mode to loopback in order to enable emacs to start itself as a pinentry program, and we need to allow loopbacks in gpg-agent.conf.
(use-package! pinentry :init (setq epa-pinentry-mode `loopback) (pinentry-start))
1.9.3. Rainbow Mode
This is not used currently but might in the future.
(define-globalized-minor-mode global-rainbow-mode rainbow-mode (lambda () (when (not (memq major-mode (list 'org-agenda-mode))) (rainbow-mode 1))))
1.9.4. Automatically tangle
Tangling manually every single time is kind of painful. Instead, we allow ourselves to set a flag in org that allows org to know we should tangle on save:
(use-package! org-auto-tangle
:hook (org-mode . org-auto-tangle-mode))
1.9.5. Notifications
We use ednc to manage notifications.
(ednc-mode 1) (defun show-notification-in-buffer (old new) (let ((name (format "Notification %d" (ednc-notification-id (or old new))))) (with-current-buffer (get-buffer-create name) (if new (let ((inhibit-read-only t)) (if old (erase-buffer) (ednc-view-mode)) (insert (ednc-format-notification new t)) (pop-to-buffer (current-buffer))) (kill-buffer))))) (add-hook 'ednc-notification-presentation-functions #'show-notification-in-buffer) (evil-define-key 'normal ednc-view-mode-map (kbd "d") 'ednc-dismiss-notification (kbd "RET") 'ednc-invoke-action (kbd "e") 'ednc-toggle-expanded-view)
1.9.6. Playing Video
(setq empv-invidious-instance "https://yewtu.be/api/v1")
1.9.7. Mastodon
(setq mastodon-instance-url "https://types.pl") (setq mastodon-active-user "ret2pop")
1.9.8. Ement
;; (ement-connect :uri-prefix "http://localhost:8009")
1.9.9. Stem
I wrote a major mode for my programming language stem.
(use-package stem-mode) (add-to-list 'auto-mode-alist '("\\.stem\\'" . stem-mode))
1.9.10. Tufte
Our website uses the tufte css styling and we must therefore tell emacs to generate html that is compliant with this html:
(use-package! ox-tufte) (use-package! plan9-theme)
1.9.11. This is supposed to work
but it doesn't
(setq org-export-with-section-numbers nil)
2. packages.el Configuration
These are some external packages that I use that are not provided by doom modules.
(unpin! evil-collection) (package! evil-collection :recipe (:repo "kepi/evil-collection" :branch "mu4e-development")) (package! pinentry) (package! kbd-mode :recipe (:host github :repo "kmonad/kbd-mode")) (package! nasm-mode) (package! org-contrib) (package! exwm) (package! org-auto-tangle) (package! rainbow-mode) (package! ednc) (package! mentor) (package! request) ;; dependency for lemmy client (package! plz) ;; dependency for lemmy client; either request or plz is idk what to use (package! curl-to-elisp) (package! empv) (package! elpher) (package! ement) (package! mastodon) (package! go-translate) (package! ts) (package! chess) (package! ox-tufte) (package! plan9-theme)
3. init.el Configuration
This installs all the doom modules that we are going to be configuring:
(doom! :input ;;bidi ; (tfel ot) thgir etirw uoy gnipleh chinese japanese ;;layout ; auie,ctsrnm is the superior home row :completion company ;;helm ; the *other* search engine for love and life ;;ido ; the other *other* search engine... (ivy +icons +fuzzy) ;; vertico :ui ;;deft ; notational velocity for Emacs doom doom-dashboard doom-quit (emoji +unicode) hl-todo hydra indent-guides (ligatures +extra +fira) minimap modeline ;;nav-flash ; blink cursor line after big motions ;;neotree ; a project drawer, like NERDTree for vim ophints (popup +defaults) ;; tabs treemacs unicode (vc-gutter +pretty) vi-tilde-fringe window-select workspaces zen :editor (evil +everywhere) file-templates fold (format +onsave) ;;god ; run Emacs commands without modifier keys lispy ;;multiple-cursors ; editing in many places at once ;;objed ; text object editing for the innocent parinfer ;;rotate-text ; cycle region at point between text candidates snippets word-wrap :emacs dired electric (ibuffer +icons) undo vc :term eshell ; the elisp shell that works everywhere ;;shell ; simple shell REPL for Emacs ;; term ; basic terminal emulator for Emacs vterm :checkers syntax (spell +flyspell) grammar :tools ;;ansible ;;biblio ; Writes a PhD for you (citation needed) (debugger +lsp) ;;direnv ;;docker editorconfig ein (eval +overlay) gist (lookup +dictionary +offline) lsp magit make pass pdf ;;prodigy ; FIXME managing external services & code builders rgb ;;taskrunner ; taskrunner for all your projects ;;terraform ; infrastructure as code tmux tree-sitter ;;upload ; map local to remote projects via ssh/ftp :os (:if IS-MAC macos) tty :lang ;;agda ; types of types of types of types... ;;beancount ; mind the GAAP (cc +lsp) ;;clojure ; java with a lisp common-lisp ;;coq ; proofs-as-programs ;;crystal ; ruby at the speed of c ;;csharp ; unity, .NET, and mono shenanigans data ;;(dart +flutter) ; paint ui and not much else ;;dhall ;;elixir ; erlang done right ;;elm ; care for a cup of TEA? emacs-lisp ;;erlang ; an elegant language for a more civilized age ess ;;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) ;;(graphql +lsp) ; Give queries a REST (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 +lsp) ;;(java +lsp) ; the poster child for carpal tunnel syndrome (javascript +lsp) ;;julia ; a better, faster MATLAB ;;kotlin ; a better, slicker Java(Script) (latex +lsp +fold +cdlatex) ;;lean ; for folks with too much to prove ;;ledger ; be audit you can be ;;lua ; one-based indices? one-based indices (markdown +grip) ;;nim ; python + lisp at the speed of c nix ;;ocaml ; an objective camel (org +journal +jupyter +gnuplot +brain +pretty +roam2) ;;php ; perl's insecure younger brother ;;plantuml ; diagrams for confusing people more ;;purescript ; javascript, but functional (python +lsp +tree-sitter) ;;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 +lsp) ;;scala ; java, but good (scheme +guile) (sh +fish +lsp) ;;sml solidity ; do you need a blockchain? No. ;;swift ; who asked for emoji variables? ;;terra ; Earth and Moon in alignment for performance. (web +lsp) (yaml +lsp) ;;zig ; C, but simpler :email (mu4e +org) ;;notmuch ;;(wanderlust +gmail) :app calendar emms everywhere irc (rss +org) ;;twitter ; twitter client https://twitter.com/vnought :config literate (default +bindings +smartparens))