+** [[https://github.com/seagle0128/doom-modeline][doom-modeline]]
+
+#+begin_src emacs-lisp
+(use-package doom-modeline
+ :demand t
+ :config (setq doom-modeline-height 32)
+ :hook (after-init . doom-modeline-init))
+#+end_src
+
+** [[https://github.com/11111000000/tao-theme-emacs][tao-theme]]
+
+#+begin_src emacs-lisp :tangle no
+(use-package tao-theme
+ :demand t
+ :config (load-theme 'tao-yang t))
+#+end_src
+
+** [[https://github.com/maio/eink-emacs][eink-theme]]
+
+#+begin_src emacs-lisp
+(load-theme 'eink t)
+#+end_src
+
+* Email
+** [[https://notmuchmail.org][notmuch]]
+
+See [[notmuch:id:87muuqsvci.fsf@fencepost.gnu.org][bug follow-up]].
+
+#+begin_src emacs-lisp
+(defun ab/notmuch ()
+ "Delete other windows, then launch `notmuch'."
+ (interactive)
+ (require 'notmuch)
+ (delete-other-windows)
+ (notmuch))
+
+;; (ab--leader-keys
+;; "m" 'ab/notmuch
+;; "s" 'save-buffer
+;; "SPC" 'counsel-M-x)
+
+;; (map!
+;; :leader
+;; :desc "notmuch" :n "m" #'ab/notmuch
+;; (:desc "search" :prefix "/"
+;; :desc "notmuch" :n "m" #'counsel-notmuch))
+#+end_src
+
+#+begin_src emacs-lisp
+(defvar ab-maildir "~/mail")
+
+(use-package sendmail
+ ;; :ensure nil
+ :config
+ (setq sendmail-program "/usr/bin/msmtp"
+ mail-specify-envelope-from t
+ mail-envelope-from 'header))
+
+(use-package message
+ ;; :ensure nil
+ :config
+ (setq message-kill-buffer-on-exit t
+ message-send-mail-function 'message-send-mail-with-sendmail
+ message-sendmail-envelope-from 'header
+ message-directory "drafts"
+ message-user-fqdn "aminb.org")
+ (add-hook 'message-mode-hook
+ (lambda () (setq fill-column 65
+ message-fill-column 65)))
+ (add-hook 'message-mode-hook
+ #'flyspell-mode)
+ ;; (add-hook 'notmuch-message-mode-hook #'+doom-modeline|set-special-modeline)
+ ;; TODO: is there a way to only run this when replying and not composing?
+ ;; (add-hook 'notmuch-message-mode-hook
+ ;; (lambda () (progn
+ ;; (newline)
+ ;; (newline)
+ ;; (forward-line -1)
+ ;; (forward-line -1))))
+ ;; (add-hook 'message-setup-hook
+ ;; #'mml-secure-message-sign-pgpmime)
+ )
+
+(after! mml-sec
+ (setq mml-secure-openpgp-encrypt-to-self t
+ mml-secure-openpgp-sign-with-sender t))
+
+(use-package notmuch
+ :general (ab--leader-keys "m" 'ab/notmuch)
+ :config
+ (setq notmuch-hello-sections
+ '(notmuch-hello-insert-header
+ notmuch-hello-insert-saved-searches
+ ;; notmuch-hello-insert-search
+ notmuch-hello-insert-alltags)
+ notmuch-search-oldest-first nil
+ notmuch-show-all-tags-list t
+ notmuch-message-headers ; see bug follow-up above
+ '("Subject" "To" "Cc" "Date" "List-Id" "X-RT-Originator")
+ notmuch-hello-thousands-separator ","
+ notmuch-fcc-dirs
+ '(("amin@aminb.org" . "amin/Sent")
+ ("abandali@uwaterloo.ca" . "\"uwaterloo/Sent Items\"")
+ ("amin.bandali@uwaterloo.ca" . "\"uwaterloo/Sent Items\"")
+ ("aminb@gnu.org" . "gnu/Sent")
+ (".*" . "sent"))
+ notmuch-search-result-format
+ '(("date" . "%12s ")
+ ("count" . "%-7s ")
+ ("authors" . "%-40s ")
+ ("subject" . "%s ")
+ ("tags" . "(%s)")))
+ ;; (add-hook 'visual-fill-column-mode-hook
+ ;; (lambda ()
+ ;; (when (string= major-mode 'notmuch-message-mode)
+ ;; (setq visual-fill-column-width 70))))
+ ;; (set! :evil-state 'notmuch-message-mode 'insert)
+ ;; (advice-add #'notmuch-bury-or-kill-this-buffer
+ ;; :override #'kill-this-buffer)
+ :bind
+ (:map notmuch-hello-mode-map
+ ("g" . notmuch-poll-and-refresh-this-buffer)
+ ("i" . (lambda ()
+ "Search for `inbox' tagged messages"
+ (interactive)
+ (notmuch-hello-search "tag:inbox")))
+ ("u" . (lambda ()
+ "Search for `unread' tagged messages"
+ (interactive)
+ (notmuch-hello-search "tag:unread")))
+ ("l" . (lambda ()
+ "Search for `latest tagged messages"
+ (interactive)
+ (notmuch-hello-search "tag:latest")))
+ ("M" . (lambda ()
+ "Compose new mail and prompt for sender"
+ (interactive)
+ (let ((current-prefix-arg t))
+ (call-interactively #'notmuch-mua-new-mail)))))
+ (:map notmuch-search-mode-map
+ ("g" . notmuch-poll-and-refresh-this-buffer)
+ ("k" . (lambda ()
+ "Mark message read"
+ (interactive)
+ (notmuch-search-tag '("-unread"))
+ ;; (notmuch-search-archive-thread)
+ (notmuch-search-next-thread)))
+ ("u" . (lambda ()
+ "Mark message unread"
+ (interactive)
+ (notmuch-search-tag '("+unread"))
+ (notmuch-search-next-thread)))
+ ("K" . (lambda ()
+ "Mark message deleted"
+ (interactive)
+ (notmuch-search-tag '("-unread" "-inbox" "+deleted"))
+ (notmuch-search-archive-thread)))
+ ("S" . (lambda ()
+ "Mark message as spam"
+ (interactive)
+ (notmuch-search-tag '("-unread" "-inbox" "-webmasters" "+spam"))
+ (notmuch-search-archive-thread))))
+ (:map notmuch-tree-mode-map ; TODO: additional bindings
+ ("S" . (lambda ()
+ "Mark message as spam"
+ (interactive)
+ (notmuch-tree-tag '("-unread" "-inbox" "-webmasters" "+spam"))
+ (notmuch-tree-archive-thread))))
+)
+
+;; (use-package counsel-notmuch
+;; :commands counsel-notmuch)
+
+(after! notmuch-crypto
+ (setq notmuch-crypto-process-mime t))
+
+;; (after! evil
+;; (mapc (lambda (str) (evil-set-initial-state (car str) (cdr str)))
+;; '((notmuch-hello-mode . emacs)
+;; (notmuch-search-mode . emacs)
+;; (notmuch-tree-mode . emacs))))
+
+(after! recentf
+ (add-to-list 'recentf-exclude (expand-file-name ab-maildir)))
+#+end_src
+
+** supercite
+
+#+begin_src emacs-lisp :tangle no
+(use-package supercite
+ :commands sc-cite-original
+ :init
+ (add-hook 'mail-citation-hook 'sc-cite-original)
+
+ (defun sc-remove-existing-signature ()
+ (save-excursion
+ (goto-char (region-beginning))
+ (when (re-search-forward message-signature-separator (region-end) t)
+ (delete-region (match-beginning 0) (region-end)))))
+
+ (add-hook 'mail-citation-hook 'sc-remove-existing-signature)
+
+ (defun sc-remove-if-not-mailing-list ()
+ (unless (assoc "list-id" sc-mail-info)
+ (setq attribution sc-default-attribution
+ citation (concat sc-citation-delimiter
+ sc-citation-separator))))
+
+ (add-hook 'sc-attribs-postselect-hook 'sc-remove-if-not-mailing-list)
+
+ :config
+ (defun sc-fill-if-different (&optional prefix)
+ "Fill the region bounded by `sc-fill-begin' and point.
+Only fill if optional PREFIX is different than
+`sc-fill-line-prefix'. If `sc-auto-fill-region-p' is nil, do not
+fill region. If PREFIX is not supplied, initialize fill
+variables. This is useful for a regi `begin' frame-entry."
+ (if (not prefix)
+ (setq sc-fill-line-prefix ""
+ sc-fill-begin (line-beginning-position))
+ (if (and sc-auto-fill-region-p
+ (not (string= prefix sc-fill-line-prefix)))
+ (let ((fill-prefix sc-fill-line-prefix))
+ (unless (or (string= fill-prefix "")
+ (save-excursion
+ (goto-char sc-fill-begin)
+ (or (looking-at ">+ +")
+ (< (length
+ (buffer-substring (point)
+ (line-end-position)))
+ 65))))
+ (fill-region sc-fill-begin (line-beginning-position)))
+ (setq sc-fill-line-prefix prefix
+ sc-fill-begin (line-beginning-position)))))
+nil))
+#+end_src
+
+* Blogging
+** [[https://ox-hugo.scripter.co][ox-hugo]]
+
+#+begin_src emacs-lisp
+(use-package ox-hugo
+ :after ox)
+#+end_src
+