#+title: Doom Literate Config
#+author: Preston Pan
#+date: <2023-06-09 Fri>
#+description: My doom emacs configuration
#+html_head:
* config.el Configuration
This is a doom emacs configuration. If you are not using doom emacs, do not use this document.
** Basic Information
My name, and the org mode directory on my computer, as well as basic editor configuration options.
Below is the old documentation.
#+begin_src emacs-lisp :tangle yes
(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)
#+end_src
- `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'.
** Modeline
In order to display the time in the modeline:
#+begin_src emacs-lisp :tangle yes
(display-time-mode 1)
#+end_src
To display the battery percentage:
#+begin_src emacs-lisp :tangle yes
(display-battery-mode 1)
#+end_src
** Transparency
Let's make emacs transparent.
#+begin_src emacs-lisp :tangle yes
(set-frame-parameter nil 'alpha-background 90)
(add-to-list 'default-frame-alist '(alpha-background . 90))
#+end_src
** EXWM
First we load our packages:
#+begin_src emacs-lisp :tangle yes
;; (use-package! exwm)
;; (use-package! exwm-config)
;; (exwm-config-example)
#+end_src
Now, we set our keybindings:
#+begin_src emacs-lisp :tangle yes
;; (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")))))
#+end_src
And we also need to set up our media keys:
#+begin_src emacs-lisp :tangle yes
;; (exwm-input-set-key (kbd "") 'emms-next)
;; (exwm-input-set-key (kbd "") 'emms-previous)
;; (exwm-input-set-key (kbd "") 'emms-pause)
;; (exwm-input-set-key
;; (kbd "")
;; (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 "")
;; (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 "")
;; (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")),
#+end_src
** Font
Now we configure fonts:
#+begin_src emacs-lisp :tangle yes
(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))
#+end_src
** 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.
#+begin_src emacs-lisp :tangle yes
;; (setq doom-theme 'doom-ayu-light)
(setq doom-theme 'doom-gruvbox)
;; (setq catppuccin-flavor 'mocha)
;; (load-theme 'catppuccin)
#+end_src
** Doom Module and Programs Configuration
*** Agenda
Now we add these two files to our agenda search path:
#+begin_src emacs-lisp :tangle yes
(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"))
#+end_src
And we also want to set up org-habit to start graphing our habits as soon as possible:
#+begin_src emacs-lisp :tangle yes
(setq org-habit-preceding-days 1)
#+end_src
*** IRC
Set up circe to connect to my bouncer:
#+begin_src emacs-lisp :tangle yes
;; (after! circe
;; (set-irc-server! "nullring.xyz"
;; `(:tls t
;; :port 4095
;; :nick "LiCoO2/AndreiNet"
;; :user "LiCoO2/AndreiNet"
;; :pass ,(+pass-get-secret "ZNC"))))
#+end_src
And another to connect to libera:
#+begin_src emacs-lisp :tangle yes
(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"))))
#+end_src
#+begin_src emacs-lisp :tangle yes
(after! circe (set-irc-server! "nullring.xyz"
`(:tls t
:port 6697
:nick "LiCoO2")))
#+end_src
*** Email
In order to use this configuration, you must install and configure mu and mbsync.
#+begin_src emacs-lisp :tangle yes
;; (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\n#+html_head: \n#+html_head: \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")
#+end_src
To add everything to the agenda search path, we toggle:
#+begin_src emacs-lisp :tangle yes
(setq org-journal-enable-agenda-integration t)
#+end_src
*** Brain
I don't use this anymore, but it's good to have.
#+begin_src emacs-lisp :tangle yes
(setq org-brain-path "~/org/website/brain/")
#+end_src
*** Roam
This is the configuration for my mindmap.
#+begin_src emacs-lisp :tangle yes
(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: \n#+html_head: \n#+html_head: \n#+options: broken-links:t")
:unnarrowed t)))
#+end_src
*** Publishing
In order to publish my website, we need to configure emacs to publish it somewhere and with diferrent parameters:
#+begin_src emacs-lisp :tangle yes
(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" "home | section main page
")))
("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" "previous page | home
")))
(setq org-html-postamble "Copyright © 2024 Preston Pan")
#+end_src
*** Contacts
Now we configure org-contacts, which allows me to store contacts in an org mode file:
#+begin_src emacs-lisp :tangle yes
(setq org-contacts-files '("~/org/contacts.org"))
#+end_src
And then we need to add some templates with org-capture in order to add entries to the contacts easier:
#+begin_src emacs-lisp :tangle yes
(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)))
#+end_src
*** Org Timer
Sometimes I want a timer to help me keep track of the time.
#+begin_src emacs-lisp :tangle yes
(setq org-clock-sound "~/audio/ding.wav")
#+end_src
** External Packages
we want to include some packages that don't come with doom emacs.
*** KBD-Mode
kbd-mode allows us to edit kmonad kbd files with syntax highlighting:
#+begin_src emacs-lisp :tangle yes
(use-package! kbd-mode)
#+end_src
*** 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.
#+begin_src emacs-lisp :tangle yes
(use-package! pinentry
:init (setq epa-pinentry-mode `loopback)
(pinentry-start))
#+end_src
*** Rainbow Mode
This is not used currently but might in the future.
#+begin_src emacs-lisp :tangle yes
(define-globalized-minor-mode global-rainbow-mode rainbow-mode
(lambda ()
(when (not (memq major-mode
(list 'org-agenda-mode)))
(rainbow-mode 1))))
#+end_src
*** 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:
#+begin_src emacs-lisp :tangle yes
(use-package! org-auto-tangle
:hook (org-mode . org-auto-tangle-mode))
#+end_src
*** Notifications
We use ednc to manage notifications.
#+begin_src emacs-lisp :tangle yes
(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)
#+end_src
*** Playing Video
#+begin_src emacs-lisp :tangle yes
(setq empv-invidious-instance "https://yewtu.be/api/v1")
#+end_src
*** Mastodon
#+begin_src emacs-lisp :tangle yes
(setq mastodon-instance-url "https://types.pl")
(setq mastodon-active-user "ret2pop")
#+end_src
*** Ement
#+begin_src emacs-lisp :tangle yes
;; (ement-connect :uri-prefix "http://localhost:8009")
#+end_src
*** Stem
I wrote a [[https://github.com/ret2pop/stem-mode][major mode]] for my programming language [[https://github.com/ret2pop/stem][stem]].
#+begin_src emacs-lisp :tangle yes
(use-package stem-mode)
(add-to-list 'auto-mode-alist '("\\.stem\\'" . stem-mode))
#+end_src
*** Tufte
Our website uses the tufte css styling and we must therefore tell emacs to generate html that is compliant with this html:
#+begin_src emacs-lisp
(use-package! ox-tufte)
(use-package! plan9-theme)
#+end_src
*** This is supposed to work
but it doesn't
#+begin_src emacs-lisp
(setq org-export-with-section-numbers nil)
#+end_src
* packages.el Configuration
These are some external packages that I use that are not provided by doom modules.
#+begin_src emacs-lisp :tangle packages.el
(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)
#+end_src
* init.el Configuration
This installs all the doom modules that we are going to be configuring:
#+begin_src emacs-lisp :tangle init.el
(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))
#+end_src