[emacs] update packages
[~bandali/configs] / init.org
index 7a75546..ee75041 100644 (file)
--- a/init.org
+++ b/init.org
@@ -1,4 +1,4 @@
-#+title: =aminb='s Literate Emacs Configuration
+#+title: Literate Emacs Configuration of Amin Bandali
 #+author: Amin Bandali
 #+babel: :cache yes
 #+property: header-args :tangle yes
@@ -9,10 +9,10 @@
 :END:
 
 This org file is my literate configuration for GNU Emacs, and is
-tangled to [[./init.el][init.el]]. Packages are installed and managed using
-[[https://github.com/emacscollective/borg][Borg]]. Over the years, I've taken inspiration from configurations of
-many different people. Some of the configurations that I can remember
-off the top of my head are:
+tangled to [[./init.el][init.el]].  Packages are installed and managed using
+[[https://github.com/raxod502/straight.el][straight.el]].  Over the years, I've taken inspiration from
+configurations of many different people.  Some of the configurations
+that I can remember off the top of my head are:
 
 - [[https://github.com/dieggsy/dotfiles][dieggsy/dotfiles]]: literate Emacs and dotfiles configuration, uses
   straight.el for managing packages
@@ -28,26 +28,48 @@ off the top of my head are:
 I'd like to have a fully reproducible Emacs setup (part of the reason
 why I store my configuration in this repository) but unfortunately out
 of the box, that's not achievable with =package.el=, not currently
-anyway. So, I've opted to use Borg. For what it's worth, I briefly
-experimented with [[https://github.com/raxod502/straight.el][straight.el]], but found that it added about 2 seconds
-to my init time; which is unacceptable for me: I use Emacs as my
-window manager (via EXWM) and coming from bspwm, I'm too used to
-having fast startup times.
+anyway.  So, I've opted to use =straight.el=.  I also used Borg for a
+few months, but decided to try =straight.el= which allows direct use
+of the various package archives.
 
 ** Installation
+:PROPERTIES:
+:CUSTOM_ID: installation
+:END:
 
 To use this config for your Emacs, first you need to clone this repo,
-then bootstrap Borg, tell Borg to retrieve package submodules, and
-byte-compiled the packages. Something along these lines should work:
+then tangle =init.org= into =init.el=, and optionally byte-compile
+=init.el=.
+
+First, clone the repository and =cd= into it:
 
 #+begin_src sh :tangle no
-git clone https://github.com/aminb/dotfiles ~/.emacs.d
+git clone https://git.sr.ht/~bandali/dotfiles ~/.emacs.d
 cd ~/.emacs.d
-make bootstrap-borg
-make bootstrap
-make build
 #+end_src
 
+Then, decide if you would like to use a byte-compiled init file, and
+set the [[#byte-compiled-init][a/byte-compiled-init]] variable accordingly.
+
+Now, first tangle =init.org=, and only if you chose to have a
+byte-compiled init, build init as well:
+
+#+begin_src sh :tangle no
+make tangle-init
+make build-init
+#+end_src
+
+If you'd like to use a byte-compiled init, it's important that it be
+recompiled whenever =init.el= is generated from an updated =init.org=.
+Not only does my setup automatically and asynchronously tangle
+=init.org= to =init.el= every time you edit and save =init.org= in GNU
+Emacs, it will also invoke =make build-init= if you set
+=a/byte-compiled-init= to =t= above, so you wouldn't have to worry
+about manually tangling and compiling your init file whenever you
+change it.  The output of the last byte-compilation in the current
+session is kept in a =*compilation*= buffer, which will automatically
+be displayed if compilation fails.
+
 * Contents                                                   :toc_1:noexport:
 
 - [[#about][About]]
@@ -83,7 +105,7 @@ file.
 ** License
 
 #+begin_src emacs-lisp :comments none
-;; Copyright (C) 2018  Amin Bandali <bandali@gnu.org>
+;; Copyright (C) 2018-2019  Amin Bandali <bandali@gnu.org>
 
 ;; This program is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -115,6 +137,21 @@ file.
 :CUSTOM_ID: initial-setup
 :END:
 
+** Byte-compiled init preference
+:PROPERTIES:
+:CUSTOM_ID: byte-compiled-init
+:END:
+
+If you would like a byte-compiled init file, set the following
+variable to ~t~, otherwise set it to ~nil~.
+
+#+begin_src emacs-lisp
+(defvar a/byte-compiled-init t
+  "If non-nil, byte-(re)compile init.el on successful tangles.")
+#+end_src
+
+You can click on [[#installation][Installation]] to jump back up there if you like :)
+
 ** Emacs initialization
 
 I'd like to do a couple of measurements of Emacs' startup time. First,
@@ -177,7 +214,7 @@ but for now I've decided to keep them enabled. See documentation for
 
 #+begin_src emacs-lisp
 (setq user-full-name "Amin Bandali"
-      user-mail-address "amin@aminb.org")
+      user-mail-address "amin@bndl.org")
 #+end_src
 
 ** Package management
@@ -215,20 +252,34 @@ hacker.
 =straight.el= allows me to have a fully reproducible Emacs setup.
 
 #+begin_src emacs-lisp
-(setq straight-repository-branch "develop")
+;; Main engine start...
+
+(setq straight-repository-branch "develop"
+      straight-check-for-modifications '(check-on-save find-when-checking))
+
+(defun a/bootstrap-straight ()
+  (defvar bootstrap-version)
+  (let ((bootstrap-file
+         (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
+        (bootstrap-version 5))
+    (unless (file-exists-p bootstrap-file)
+      (with-current-buffer
+          (url-retrieve-synchronously
+           "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
+           'silent 'inhibit-cookies)
+        (goto-char (point-max))
+        (eval-print-last-sexp)))
+    (load bootstrap-file nil 'nomessage)))
 
-(defvar bootstrap-version)
-(let ((bootstrap-file
-       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
-      (bootstrap-version 5))
-  (unless (file-exists-p bootstrap-file)
-    (with-current-buffer
-        (url-retrieve-synchronously
-         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
-         'silent 'inhibit-cookies)
-      (goto-char (point-max))
-      (eval-print-last-sexp)))
-  (load bootstrap-file nil 'nomessage))
+;; Solid rocket booster ignition...
+
+(defun a/build-init ()
+  (a/bootstrap-straight)
+  (byte-compile-file "init.el"))
+
+(a/bootstrap-straight)
+
+;; We have lift off!
 
 (setq straight-use-package-by-default t)
 #+end_src
@@ -243,38 +294,21 @@ integration, we will define a =use-feature= for plain ole
   (declare (indent defun))
   `(use-package ,name
      :straight nil
-,@args))
+     ,@args))
 #+end_src
 
-*** COMMENT Borg
-
-#+begin_quote
-Assimilate Emacs packages as Git submodules
-#+end_quote
-
-[[https://github.com/emacscollective/borg][Borg]] is at the heart of package management of my Emacs setup. In
-short, it creates a git submodule in =lib/= for each package, which
-can then be managed with the help of Magit or other tools.
+Also, here's a useful function for reloading the init file (useful
+after running =straight-check-all=:
 
 #+begin_src emacs-lisp
-(setq user-init-file (or load-file-name buffer-file-name)
-      user-emacs-directory (file-name-directory user-init-file))
-(add-to-list 'load-path
-             (expand-file-name "lib/borg" user-emacs-directory))
-(require 'borg)
-(borg-initialize)
-
-;; (require 'borg-nix-shell)
-;; (setq borg-build-shell-command 'borg-nix-shell-build-command)
-
-(with-eval-after-load 'bind-key
-  (bind-keys
-   :package borg
-   ("C-c b A" . borg-activate)
-   ("C-c b a" . borg-assimilate)
-   ("C-c b b" . borg-build)
-   ("C-c b c" . borg-clone)
-   ("C-c b r" . borg-remove)))
+(defun a/reload-init ()
+  "Reload init.el."
+  (interactive)
+  (straight-transaction
+    (straight-mark-transaction-as-init)
+    (load (if a/byte-compiled-init
+              (concat (file-name-sans-extension user-init-file) ".elc")
+            user-init-file))))
 #+end_src
 
 *** =use-package=
@@ -289,13 +323,18 @@ and without compromising on performance.
 
 #+begin_src emacs-lisp
 (straight-use-package 'use-package)
-(if nil  ; set to t when need to debug init
-    (setq use-package-verbose t
-          use-package-expand-minimally nil
-          use-package-compute-statistics t
-          debug-on-error t)
+(if nil                             ; set to t when need to debug init
+    (progn
+      (setq use-package-verbose t
+            use-package-expand-minimally nil
+            use-package-compute-statistics t
+            debug-on-error t)
+      (require 'use-package))
   (setq use-package-verbose nil
         use-package-expand-minimally t))
+
+(setq use-package-always-defer t)
+(require 'bind-key)
 #+end_src
 
 *** COMMENT Epkg
@@ -310,12 +349,12 @@ database, low-level functions for querying the database, and a
 
 #+begin_src emacs-lisp
 (use-package epkg
-  :defer t
+  :commands (epkg-list-packages epkg-describe-package)
   :bind
-  (("C-c b d" . epkg-describe-package)
-   ("C-c b p" . epkg-list-packages)
-   ("C-c b u" . epkg-update))
+  (("C-c p e d" . epkg-describe-package)
+   ("C-c p e p" . epkg-list-packages))
   :config
+  (setq epkg-repository "~/.emacs.d/straight/repos/epkgs/")
   (eval-when-compile (defvar ivy-initial-inputs-alist))
   (with-eval-after-load 'ivy
     (add-to-list
@@ -375,9 +414,10 @@ in my shell.
 
 #+begin_src emacs-lisp
 (use-package exec-path-from-shell
-  :defer 1
+  :defer 0.4
   :init
-  (setq exec-path-from-shell-check-startup-files nil)
+  (setq exec-path-from-shell-arguments           nil
+        exec-path-from-shell-check-startup-files nil)
   :config
   (exec-path-from-shell-initialize)
   ;; while we're at it, let's fix access to our running ssh-agent
@@ -405,7 +445,7 @@ See [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Emacs-Server.htm
 
 #+begin_src emacs-lisp
 (use-feature server
-  :defer 1
+  :defer 0.4
   :config (or (server-running-p) (server-mode)))
 #+end_src
 
@@ -471,6 +511,33 @@ buffers and/or modes.
   (setq mouse-autoselect-window nil))
 #+end_src
 
+** Better scrolling (arguably)
+
+#+begin_src emacs-lisp
+(setq ;; scroll-margin 1
+      ;; scroll-conservatively 10000
+      scroll-step 1
+      scroll-conservatively 10
+      scroll-preserve-screen-position 1)
+
+(use-feature mwheel
+  :defer 0.4
+  :config
+  (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; one line at a time
+        mouse-wheel-progressive-speed nil            ; don't accelerate scrolling
+        mouse-wheel-follow-mouse t))                 ; scroll window under mouse
+
+(use-feature pixel-scroll
+  :defer 0.4
+  :config (pixel-scroll-mode 1))
+#+end_src
+
+** Ask for GPG passphrase in minibuffer
+
+#+begin_src emacs-lisp
+(setq epg-pinentry-mode 'loopback)
+#+end_src
+
 ** Libraries
 
 #+begin_src emacs-lisp
@@ -726,6 +793,8 @@ for this.
 
 ** Bindings
 
+Some bindings for functions from built-in GNU Emacs packages:
+
 #+begin_src emacs-lisp
 (bind-keys
  ("C-c a i" . ielm)
@@ -733,21 +802,56 @@ for this.
  ("C-c e b" . eval-buffer)
  ("C-c e r" . eval-region)
 
+ ("C-c e i" . emacs-init-time)
+ ("C-c e u" . emacs-uptime)
+
  ("C-c F m" . make-frame-command)
  ("C-c F d" . delete-frame)
  ("C-c F D" . delete-other-frames)
 
  ("C-c o"   . other-window)
 
- ("C-c Q"   . save-buffers-kill-terminal)
-
  ("C-S-h C" . describe-char)
  ("C-S-h F" . describe-face)
 
- ("C-x K"   . kill-this-buffer)
+ ("C-x k"   . kill-this-buffer)
+ ("C-x K"   . kill-buffer)
 
  ("s-p"     . beginning-of-buffer)
  ("s-n"     . end-of-buffer))
+
+(when (display-graphic-p)
+  (unbind-key "C-z" global-map))
+#+end_src
+
+While at it, let's bind a few for some =straight-*= functions too:
+
+#+begin_src emacs-lisp
+(bind-keys
+ :prefix-map a/straight-prefix-map
+ :prefix "C-c p s"
+ ("u" . straight-use-package)
+ ("f" . straight-freeze-versions)
+ ("t" . straight-thaw-versions)
+ ("P" . straight-prune-build)
+ ("g" . straight-get-recipe)
+ ("r" . a/reload-init)
+ ;; M-x ^straight-.*-all$
+ ("a c" . straight-check-all)
+ ("a f" . straight-fetch-all)
+ ("a m" . straight-merge-all)
+ ("a n" . straight-normalize-all)
+ ("a F" . straight-pull-all)
+ ("a P" . straight-push-all)
+ ("a r" . straight-rebuild-all)
+ ;; M-x ^straight-.*-package$
+ ("p c" . straight-check-package)
+ ("p f" . straight-fetch-package)
+ ("p m" . straight-merge-package)
+ ("p n" . straight-normalize-package)
+ ("p F" . straight-pull-package)
+ ("p P" . straight-push-package)
+ ("p r" . straight-rebuild-package))
 #+end_src
 
 ** Packages
@@ -784,41 +888,6 @@ system.
 
 In short, my favourite way of life.
 
-First, we have to resort to a [[https://github.com/raxod502/straight.el#installing-org-with-straightel][hack]] to be able to use the correct
-latest version of Org from upstream.
-
-#+begin_src emacs-lisp
-  (use-package git)
-
-  (defun org-git-version ()
-    "The Git version of org-mode.
-  Inserted by installing org-mode or when a release is made."
-    (require 'git)
-    (let ((git-repo (expand-file-name
-                     "straight/repos/org/" user-emacs-directory)))
-      (string-trim
-       (git-run "describe"
-                "--match=release\*"
-                "--abbrev=6"
-                "HEAD"))))
-
-  (defun org-release ()
-    "The release version of org-mode.
-  Inserted by installing org-mode or when a release is made."
-    (require 'git)
-    (let ((git-repo (expand-file-name
-                     "straight/repos/org/" user-emacs-directory)))
-      (string-trim
-       (string-remove-prefix
-        "release_"
-        (git-run "describe"
-                 "--match=release\*"
-                 "--abbrev=0"
-                 "HEAD")))))
-
-(provide 'org-version)
-#+end_src
-
 We will use the =org-plus-contrib= package to get the whole deal:
 
 #+begin_src emacs-lisp
@@ -834,25 +903,24 @@ And here's where my actual Org configurations begin:
   (setq org-src-tab-acts-natively t
         org-src-preserve-indentation nil
         org-edit-src-content-indentation 0
-        org-email-link-description-format "Email %c: %s" ; %.30s
+        org-link-email-description-format "Email %c: %s" ; %.30s
         org-highlight-latex-and-related '(entities)
         org-use-speed-commands t
         org-startup-folded 'content
         org-catch-invisible-edits 'show-and-error
         org-log-done 'time)
   (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t)
-  (font-lock-add-keywords
-   'org-mode
-   '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
-      (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
-      (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
-      (4 '(:foreground "#c5c8c6") t))) ; title
-   t)
-  :bind (:map org-mode-map ("M-L" . org-insert-last-stored-link))
+  :bind
+  (("C-c a o a" . org-agenda)
+   :map org-mode-map
+   ("M-L" . org-insert-last-stored-link))
   :hook ((org-mode . org-indent-mode)
          (org-mode . auto-fill-mode)
          (org-mode . flyspell-mode))
   :custom
+  (org-agenda-files '("~/usr/org/todos/personal.org"
+                      "~/usr/org/todos/masters.org"))
+  (org-agenda-start-on-weekday 0)
   (org-latex-packages-alist '(("" "listings") ("" "color")))
   :custom-face
   '(org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21"))))
@@ -865,19 +933,15 @@ And here's where my actual Org configurations begin:
   (setq org-latex-listings 'listings
         ;; org-latex-prefer-user-labels t
         )
-  (add-to-list 'org-latex-packages-alist '("" "listings"))
-  (add-to-list 'org-latex-packages-alist '("" "color"))
   (add-to-list 'org-latex-classes
                '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
-                 ("\\section{%s}" . "\\section*{%s}")
-                 ("\\subsection{%s}" . "\\subsection*{%s}")
+                 ("\\section{%s}"       . "\\section*{%s}")
+                 ("\\subsection{%s}"    . "\\subsection*{%s}")
                  ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
-                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
-                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
-               t))
-
-(use-feature ox-beamer
-  :after ox)
+                 ("\\paragraph{%s}"     . "\\paragraph*{%s}")
+                 ("\\subparagraph{%s}"  . "\\subparagraph*{%s}"))
+               t)
+  (require 'ox-beamer))
 #+end_src
 
 **** asynchronous tangle
@@ -894,9 +958,16 @@ file.
   (defvar a/show-async-tangle-time nil
     "Show the time spent tangling the file.")
 
-  (defvar a/async-tangle-post-compile "make ti"
+  (defvar a/async-tangle-post-compile
+    (when a/byte-compiled-init "make build-init")
     "If non-nil, pass to `compile' after successful tangle.")
 
+  ;; TODO: look into why directly byte-compiling init.el causes a
+  ;; number of problems, including magit-status not loading (busy
+  ;; waiting).
+  (defvar a/async-tangle-byte-recompile nil
+    "If non-nil, byte-recompile the file on successful tangle.")
+
   (defun a/async-babel-tangle ()
     "Tangle org file asynchronously."
     (interactive)
@@ -904,7 +975,7 @@ file.
            (file (buffer-file-name))
            (file-nodir (file-name-nondirectory file))
            ;; (async-quiet-switch "-q")
-           )
+           (file-noext (file-name-sans-extension file)))
       (async-start
        `(lambda ()
           (require 'org)
@@ -913,6 +984,7 @@ file.
          `(lambda (result)
             (if result
                 (progn
+                  ;; (setq byte-compile-warnings '(not noruntime unresolved))
                   (message "Tangled %s%s"
                            ,file-nodir
                            (if a/show-async-tangle-time
@@ -921,7 +993,9 @@ file.
                                                                   ',file-tangle-start-time)))
                              ""))
                   (when a/async-tangle-post-compile
-                    (compile a/async-tangle-post-compile)))
+                    (compile a/async-tangle-post-compile))
+                  (when a/async-tangle-byte-recompile
+                    (byte-recompile-file (concat ,file-noext ".el"))))
               (message "Tangling %s failed" ,file-nodir))))))))
 
 (add-to-list
@@ -939,7 +1013,7 @@ Not just how I do git, but /the/ way to do git.
 
 #+begin_src emacs-lisp
 (use-package magit
-  :defer 1
+  :defer 0.5
   :bind (("C-x g" . magit-status)
          ("s-g s" . magit-status)
          ("s-g l" . magit-log-buffer-file))
@@ -963,12 +1037,24 @@ Recently opened files.
 
 #+begin_src emacs-lisp
 (use-feature recentf
-  :defer 0.5
+  :defer 0.2
   :config
   (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:")
   (setq recentf-max-saved-items 40))
 #+end_src
 
+*** smex
+
+#+begin_quote
+A smart M-x enhancement for Emacs.
+#+end_quote
+
+Mostly because =counsel= needs it to remember history.
+
+#+begin_src emacs-lisp
+(use-package smex)
+#+end_src
+
 *** [[https://github.com/abo-abo/swiper][Ivy]] (and friends)
 
 #+begin_quote
@@ -982,7 +1068,7 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-package ivy
-  :defer 0.6
+  :defer 0.3
   :bind
   (:map ivy-minibuffer-map
    ([escape] . keyboard-escape-quit)
@@ -1030,7 +1116,7 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-feature eshell
-  :defer 1
+  :defer 0.5
   :commands eshell
   :bind ("C-c a s e" . eshell)
   :config
@@ -1067,7 +1153,6 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-feature ibuffer
-  :defer t
   :bind
   (("C-x C-b" . ibuffer-other-window)
    :map ibuffer-mode-map
@@ -1112,6 +1197,7 @@ There's no way I could top that, so I won't attempt to.
         (mode . python-mode)
         (mode . c-mode)
         (mode . c++-mode)
+        (mode . java-mode)
         (mode . emacs-lisp-mode)
         (mode . scheme-mode)
         (mode . haskell-mode)
@@ -1119,7 +1205,8 @@ There's no way I could top that, so I won't attempt to.
       ("emacs"
        (or
         (name . "^\\*scratch\\*$")
-        (name . "^\\*Messages\\*$"))))))
+        (name . "^\\*Messages\\*$")))
+      ("erc" (mode . erc-mode)))))
   (ibuffer-formats
    '((mark modified read-only locked " "
            (name 18 18 :left :elide)
@@ -1138,7 +1225,6 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-feature outline
-  :defer t
   :hook (prog-mode . outline-minor-mode)
   :bind
   (:map
@@ -1163,7 +1249,6 @@ There's no way I could top that, so I won't attempt to.
   :custom (ls-lisp-dirs-first t))
 
 (use-feature dired
-  :defer t
   :config
   (setq dired-listing-switches "-alh"
         ls-lisp-use-insert-directory-program nil)
@@ -1172,6 +1257,7 @@ There's no way I could top that, so I won't attempt to.
   ;; https://oremacs.com/2017/03/18/dired-ediff/
   (defun dired-ediff-files ()
     (interactive)
+    (require 'dired-aux)
     (defvar ediff-after-quit-hook-internal)
     (let ((files (dired-get-marked-files))
           (wnd (current-window-configuration)))
@@ -1191,6 +1277,7 @@ There's no way I could top that, so I won't attempt to.
                         (set-window-configuration wnd))))
         (error "no more than 2 files should be marked"))))
   :bind (:map dired-mode-map
+              ("b"  . dired-up-directory)
               ("e"  . dired-ediff-files)
               ("E"  . dired-toggle-read-only)
               ("\\" . dired-hide-details-mode)
@@ -1204,7 +1291,6 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-feature help
-  :defer t
   :config
   (temp-buffer-resize-mode)
   (setq help-window-select t))
@@ -1214,7 +1300,6 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-feature tramp
-  :defer t
   :config
   (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
   (add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
@@ -1226,7 +1311,6 @@ There's no way I could top that, so I won't attempt to.
 
 #+begin_src emacs-lisp
 (use-package dash
-  :defer t
   :config (dash-enable-font-lock))
 #+end_src
 
@@ -1263,9 +1347,17 @@ Highlight matching parens.
 
 #+begin_src emacs-lisp
 (use-feature paren
+  :demand
   :config (show-paren-mode))
 #+end_src
 
+** simple (for column numbers)
+
+#+begin_src emacs-lisp
+(use-feature simple
+  :config (column-number-mode))
+#+end_src
+
 ** =savehist=
 
 Save minibuffer history.
@@ -1303,23 +1395,11 @@ Automatically save place in each file.
          (text-mode . abbrev-mode)))
 #+end_src
 
-** =lisp-mode=
-
-#+begin_src emacs-lisp
-(use-feature lisp-mode
-  :config
-  (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
-  (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
-  (defun indent-spaces-mode ()
-    (setq indent-tabs-mode nil))
-  (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
-#+end_src
-
-** COMMENT Company
+** Company
 
 #+begin_src emacs-lisp
 (use-package company
-  :defer 1
+  :defer 0.6
   :bind
   (:map company-active-map
         ([tab]    . company-complete-common-or-cycle)
@@ -1334,14 +1414,11 @@ Automatically save place in each file.
   (global-company-mode t))
 #+end_src
 
-* COMMENT Syntax and spell checking
-:PROPERTIES:
-:CUSTOM_ID: syntax-spell-checking
-:END:
+** Flycheck
 
 #+begin_src emacs-lisp
 (use-package flycheck
-  :defer 3
+  :defer 0.6
   :hook (prog-mode . flycheck-mode)
   :bind
   (:map flycheck-mode-map
@@ -1356,7 +1433,7 @@ Automatically save place in each file.
 
 ;; http://endlessparentheses.com/ispell-and-apostrophes.html
 (use-package ispell
-  :defer 3
+  :defer 0.6
   :config
   ;; ’ can be part of a word
   (setq ispell-local-dictionary-alist
@@ -1381,16 +1458,28 @@ Automatically save place in each file.
               #'endless/replace-quote))
 #+end_src
 
-* COMMENT Programming modes
+* Programming modes
 :PROPERTIES:
 :CUSTOM_ID: programming-modes
 :END:
 
+** Lisp
+
+#+begin_src emacs-lisp
+(use-feature lisp-mode
+  :config
+  (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
+  (add-hook 'emacs-lisp-mode-hook 'reveal-mode)
+  (defun indent-spaces-mode ()
+    (setq indent-tabs-mode nil))
+  (add-hook 'lisp-interaction-mode-hook #'indent-spaces-mode))
+#+end_src
+
 ** [[http://alloytools.org][Alloy]] (with [[https://github.com/dwwmmn/alloy-mode][alloy-mode]])
 
 #+begin_src emacs-lisp
 (use-package alloy-mode
-  :defer t
+  :straight (:host github :repo "dwwmmn/alloy-mode")
   :config (setq alloy-basic-offset 2))
 #+end_src
 
@@ -1398,8 +1487,7 @@ Automatically save place in each file.
 
 #+begin_src emacs-lisp
 (use-package proof-site  ; Proof General
-  :defer t
-  :load-path "lib/proof-site/generic/")
+  :straight proof-general)
 #+end_src
 
 ** [[https://leanprover.github.io][Lean]] (with [[https://github.com/leanprover/lean-mode][lean-mode]])
@@ -1407,7 +1495,7 @@ Automatically save place in each file.
 #+begin_src emacs-lisp
 (eval-when-compile (defvar lean-mode-map))
 (use-package lean-mode
-  :defer 1
+  :defer 0.4
   :bind (:map lean-mode-map
               ("S-SPC" . company-complete))
   :config
@@ -1426,7 +1514,6 @@ Automatically save place in each file.
 
 #+begin_src emacs-lisp
 (use-package haskell-mode
-  :defer t
   :config
   (setq haskell-indentation-layout-offset 4
         haskell-indentation-left-offset 4
@@ -1609,13 +1696,12 @@ instead.
               ("C-c l l" . hs-lint)))
 #+end_src
 
-** Web dev
+** Web
 
 *** SGML and HTML
 
 #+begin_src emacs-lisp
 (use-package sgml-mode
-  :defer t
   :config
   (setq sgml-basic-offset 2))
 #+end_src
@@ -1624,7 +1710,6 @@ instead.
 
 #+begin_src emacs-lisp
 (use-package css-mode
-  :defer t
   :config
   (setq css-indent-offset 2))
 #+end_src
@@ -1633,7 +1718,6 @@ instead.
 
 #+begin_src emacs-lisp
 (use-package web-mode
-  :defer t
   :mode "\\.html\\'"
   :config
   (a/setq-every 2
@@ -1655,9 +1739,9 @@ instead.
   :hook (web-mode css-mode html-mode sgml-mode))
 #+end_src
 
-** COMMENT Java
+** Java
 
-*** meghanada
+*** COMMENT meghanada
 
 #+begin_src emacs-lisp
 (use-package meghanada
@@ -1668,7 +1752,7 @@ instead.
   :hook (java-mode . meghanada-mode))
 #+end_src
 
-*** lsp-java
+*** COMMENT lsp-java
 
 #+begin_comment
 dependencies:
@@ -1736,12 +1820,30 @@ treemacs
   :after (treemacs))
 #+end_src
 
+*** COMMENT eclim
+
+#+begin_src emacs-lisp
+(use-package eclim
+  :bind (:map eclim-mode-map ("S-SPC" . company-complete))
+  :hook ((java-mode . eclim-mode)
+         (eclim-mode . (lambda ()
+                         (make-local-variable 'company-idle-delay)
+                         (defvar company-idle-delay)
+                         ;; (setq company-idle-delay 0.7)
+                         (setq company-idle-delay nil))))
+  :custom
+  (eclim-auto-save nil)
+  ;; (eclimd-default-workspace "~/src/eclipse-workspace-exp")
+  (eclim-executable "~/.p2/pool/plugins/org.eclim_2.8.0/bin/eclim")
+  (eclim-eclipse-dirs '("~/usr/eclipse/dsl-2018-09/eclipse")))
+#+end_src
+
 ** geiser
 
 #+begin_src emacs-lisp
 (use-package geiser)
 
-(use-package geiser-guile
+(use-feature geiser-guile
   :config
   (setq geiser-guile-load-path "~/src/git/guix"))
 #+end_src
@@ -1749,11 +1851,10 @@ treemacs
 ** guix
 
 #+begin_src emacs-lisp
-(use-package guix
-  :load-path "lib/guix/elisp")
+(use-package guix)
 #+end_src
 
-* COMMENT Emacs enhancements
+* Emacs enhancements
 :PROPERTIES:
 :CUSTOM_ID: emacs-enhancements
 :END:
@@ -1762,7 +1863,6 @@ treemacs
 
 #+begin_src emacs-lisp
 (use-feature man
-  :defer t
   :config (setq Man-width 80))
 #+end_src
 
@@ -1774,7 +1874,7 @@ Emacs package that displays available keybindings in popup
 
 #+begin_src emacs-lisp
 (use-package which-key
-  :defer 1
+  :defer 0.4
   :config
   (which-key-add-key-based-replacements
     ;; prefixes for global prefixes and minor modes
@@ -1790,18 +1890,24 @@ Emacs package that displays available keybindings in popup
     "C-x v"   "version control"
     ;; prefixes for my personal bindings
     "C-c a"   "applications"
+    "C-c a e" "erc"
+    "C-c a o" "org"
     "C-c a s" "shells"
-    "C-c b"   "borg"
+    "C-c p"   "package-management"
+    ;; "C-c p e" "package-management/epkg"
+    "C-c p s" "straight.el"
+    "C-c psa" "all"
+    "C-c psp" "package"
     "C-c c"   "compile-and-comments"
     "C-c e"   "eval"
     "C-c f"   "files"
     "C-c F"   "frames"
     "C-S-h"   "help(ful)"
     "C-c m"   "multiple-cursors"
-    "C-c p"   "projectile"
-    "C-c p s" "projectile/search"
-    "C-c p x" "projectile/execute"
-    "C-c p 4" "projectile/other-window"
+    "C-c P"   "projectile"
+    "C-c P s" "projectile/search"
+    "C-c P x" "projectile/execute"
+    "C-c P 4" "projectile/other-window"
     "C-c q"   "boxquote"
     "s-g"     "magit"
     "s-o"     "outline"
@@ -1819,7 +1925,10 @@ Emacs package that displays available keybindings in popup
     "C-c C-e" "web/element"
     "C-c C-t" "web/tags")
 
-  (which-key-mode))
+  (which-key-mode)
+  :custom
+  (which-key-add-column-padding 5)
+  (which-key-max-description-length 32))
 #+end_src
 
 ** theme
@@ -1833,6 +1942,8 @@ Emacs package that displays available keybindings in popup
 
 #+begin_src emacs-lisp
 (use-package smart-mode-line
+  :commands (sml/apply-theme)
+  :demand
   :config
   (sml/setup))
 #+end_src
@@ -1846,19 +1957,29 @@ Emacs package that displays available keybindings in popup
 ** theme helper functions
 
 #+begin_src emacs-lisp
+(defvar a/org-mode-font-lock-keywords
+  '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
+      (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
+      (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
+      (4 '(:foreground "#c5c8c6") t))))                    ; title
+
 (defun a/lights-on ()
   "Enable my favourite light theme."
   (interactive)
   (mapc #'disable-theme custom-enabled-themes)
   (load-theme 'tangomod t)
-  (sml/apply-theme 'automatic))
+  (sml/apply-theme 'automatic)
+  (font-lock-remove-keywords
+   'org-mode a/org-mode-font-lock-keywords))
 
 (defun a/lights-off ()
   "Go dark."
   (interactive)
   (mapc #'disable-theme custom-enabled-themes)
   (load-theme 'doom-tomorrow-night t)
-  (sml/apply-theme 'automatic))
+  (sml/apply-theme 'automatic)
+  (font-lock-add-keywords
+   'org-mode a/org-mode-font-lock-keywords t))
 
 (bind-keys
  ("s-t d" . a/lights-off)
@@ -1868,8 +1989,8 @@ Emacs package that displays available keybindings in popup
 ** [[https://github.com/bbatsov/crux][crux]]
 
 #+begin_src emacs-lisp
-(use-package crux
-  :defer 1
+(use-package crux                       ; results in Waiting for git... [2 times]
+  :defer 0.4
   :bind (("C-c b k" . crux-kill-other-buffers)
          ("C-c d"   . crux-duplicate-current-line-or-region)
          ("C-c D"   . crux-duplicate-and-comment-current-line-or-region)
@@ -1894,8 +2015,7 @@ Emacs package that displays available keybindings in popup
 
 #+begin_src emacs-lisp
 (use-package projectile
-  :defer t
-  :bind-keymap ("C-c p" . projectile-command-map)
+  :bind-keymap ("C-c P" . projectile-command-map)
   :config
   (projectile-mode)
 
@@ -1916,7 +2036,7 @@ Emacs package that displays available keybindings in popup
 
 #+begin_src emacs-lisp
 (use-package helpful
-  :defer 1
+  :defer 0.6
   :bind
   (("C-S-h c" . helpful-command)
    ("C-S-h f" . helpful-callable)        ; helpful-function
@@ -1931,11 +2051,10 @@ Make =*scratch*= and =*Messages*= unkillable.
 
 #+begin_src emacs-lisp
 (use-package unkillable-scratch
-  :defer 3
+  :defer 0.6
   :config
   (unkillable-scratch 1)
   :custom
-  (unkillable-scratch-behavior 'do-nothing)
   (unkillable-buffers '("^\\*scratch\\*$" "^\\*Messages\\*$")))
 #+end_src
 
@@ -1949,7 +2068,7 @@ Make =*scratch*= and =*Messages*= unkillable.
 
 #+begin_src emacs-lisp
 (use-package boxquote
-  :defer 3
+  :defer 0.6
   :bind
   (:prefix-map a/boxquote-prefix-map
    :prefix "C-c q"
@@ -1989,7 +2108,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
 
 #+begin_src emacs-lisp
 (use-package typo
-  :defer 2
+  :defer 0.5
   :config
   (typo-global-mode 1)
   :hook (text-mode . typo-mode))
@@ -1999,7 +2118,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
 
 #+begin_src emacs-lisp
 (use-package hl-todo
-  :defer 4
+  :defer 0.5
   :config
   (global-hl-todo-mode))
 #+end_src
@@ -2008,11 +2127,9 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
 
 #+begin_src emacs-lisp
 (use-package shrink-path
+  :defer 0.5
   :after eshell
   :config
-  (setq eshell-prompt-regexp "\\(.*\n\\)*λ "
-        eshell-prompt-function #'+eshell/prompt)
-
   (defun +eshell/prompt ()
     (let ((base/dir (shrink-path-prompt default-directory)))
       (concat (propertize (car base/dir)
@@ -2022,9 +2139,10 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
               (propertize (+eshell--current-git-branch)
                           'face 'font-lock-function-name-face)
               "\n"
-              (propertize "λ" 'face 'eshell-prompt-face)
+              ;; "λ"
+              ;; (propertize "λ" 'face 'eshell-prompt)
               ;; needed for the input text to not have prompt face
-              (propertize " " 'face 'default))))
+              (propertize "λ " 'face 'default))))
 
   (defun +eshell--current-git-branch ()
     (let ((branch (car (loop for match in (split-string (shell-command-to-string "git branch") "\n")
@@ -2032,21 +2150,24 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
                              collect match))))
       (if (not (eq branch nil))
           (concat " " (substring branch 2))
-        ""))))
+        "")))
+  (setq eshell-prompt-regexp "\\(.*\n\\)*λ "
+                         eshell-prompt-function #'+eshell/prompt))
 #+end_src
 
 ** [[https://github.com/peterwvj/eshell-up][eshell-up]]
 
 #+begin_src emacs-lisp
 (use-package eshell-up
-  :after eshell)
+  :after eshell
+  :commands eshell-up)
 #+end_src
 
 ** multi-term
 
 #+begin_src emacs-lisp
 (use-package multi-term
-  :defer 1
+  :defer 0.6
   :bind (("C-c a s m" . multi-term-dedicated-toggle)
          :map term-mode-map
          ("C-c C-j" . term-char-mode)
@@ -2106,7 +2227,30 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
                ("a" . mc/mark-all-like-this))))
 #+end_src
 
-* COMMENT Email
+** forge
+
+#+begin_src emacs-lisp
+(use-package forge
+  :after magit
+  :demand)
+#+end_src
+
+** yasnippet
+
+#+begin_src emacs-lisp
+(use-package yasnippet
+  :defer 0.6
+  :config
+  (defconst yas-verbosity-cur yas-verbosity)
+  (setq yas-verbosity 2)
+  (add-to-list 'yas-snippet-dirs "~/src/git/guix/etc/snippets")
+  (yas-reload-all)
+  (setq yas-verbosity yas-verbosity-cur)
+  :hook
+  (text-mode . yas-minor-mode))
+#+end_src
+
+* Email
 :PROPERTIES:
 :CUSTOM_ID: email
 :END:
@@ -2125,7 +2269,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
  mail-user-agent   'gnus-user-agent
  read-mail-command 'gnus)
 
-(use-package gnus
+(use-feature gnus
   :bind (("s-m"   . gnus)
          ("s-M"   . gnus-unplugged))
   :init
@@ -2137,17 +2281,94 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
             (nnimap-address "127.0.0.1")
             (nnimap-server-port 143)
             (nnimap-authenticator plain)
-            (nnimap-user "amin@aminb.org"))
+            (nnimap-user "amin@bndl.org"))
      (nnimap "uwaterloo"
              (nnimap-stream plain)
              (nnimap-address "127.0.0.1")
              (nnimap-server-port 143)
              (nnimap-authenticator plain)
-             (nnimap-user "abandali@uwaterloo.ca")))
+             (nnimap-user "abandali@uwaterloo.ca"))
+     (nnimap "csclub"
+             (nnimap-stream plain)
+             (nnimap-address "127.0.0.1")
+             (nnimap-server-port 143)
+             (nnimap-authenticator plain)
+             (nnimap-user "abandali@csclub.uw")))
    gnus-message-archive-group "nnimap+amin:Sent"
    gnus-parameters
-   '(("gnu.*"
-      (gcc-self . t)))
+   '(("gnu\\.deepspec"
+      (to-address . "deepspec@lists.cs.princeton.edu")
+      (to-list    . "deepspec@lists.cs.princeton.edu"))
+     ("gnu\\.emacs-devel"
+      (to-address . "emacs-devel@gnu.org")
+      (to-list    . "emacs-devel@gnu.org"))
+     ("gnu\\.emacs-orgmode"
+      (to-address . "emacs-orgmode@gnu.org")
+      (to-list    . "emacs-orgmode@gnu.org"))
+     ("gnu\\.emacsconf-discuss"
+      (to-address . "emacsconf-discuss@gnu.org")
+      (to-list    . "emacsconf-discuss@gnu.org"))
+     ("gnu\\.fencepost-users"
+      (to-address . "fencepost-users@gnu.org")
+      (to-list    . "fencepost-users@gnu.org"))
+     ("gnu\\.gnunet-developers"
+      (to-address . "gnunet-developers@gnu.org")
+      (to-list    . "gnunet-developers@gnu.org"))
+     ("gnu\\.guile-devel"
+      (to-address . "guile-devel@gnu.org")
+      (to-list    . "guile-devel@gnu.org"))
+     ("gnu\\.guix-devel"
+      (to-address . "guix-devel@gnu.org")
+      (to-list    . "guix-devel@gnu.org"))
+     ("gnu\\.haskell-art"
+      (to-address . "haskell-art@we.lurk.org")
+      (to-list    . "haskell-art@we.lurk.org"))
+     ("gnu\\.haskell-cafe"
+      (to-address . "haskell-cafe@haskell.org")
+      (to-list    . "haskell-cafe@haskell.org"))
+     ("gnu\\.help-gnu-emacs"
+      (to-address . "help-gnu-emacs@gnu.org")
+      (to-list    . "help-gnu-emacs@gnu.org"))
+     ("gnu\\.info-gnu-emacs"
+      (to-address . "info-gnu-emacs@gnu.org")
+      (to-list    . "info-gnu-emacs@gnu.org"))
+     ("gnu\\.info-guix"
+      (to-address . "info-guix@gnu.org")
+      (to-list    . "info-guix@gnu.org"))
+     ("gnu\\.notmuch"
+      (to-address . "notmuch@notmuchmail.org")
+      (to-list    . "notmuch@notmuchmail.org"))
+     ("gnu\\.parabola-dev"
+      (to-address . "dev@lists.parabola.nu")
+      (to-list    . "dev@lists.parabola.nu"))
+     ("gnu\\.webmasters"
+      (to-address . "webmasters@gnu.org")
+      (to-list    . "webmasters@gnu.org"))
+     ("gnu\\.www-commits"
+      (to-address . "www-commits@gnu.org")
+      (to-list    . "www-commits@gnu.org"))
+     ("gnu\\.www-discuss"
+      (to-address . "www-discuss@gnu.org")
+      (to-list    . "www-discuss@gnu.org"))
+     ("gnu\\.~bandali\\.public-inbox"
+      (to-address . "~bandali/public-inbox@lists.sr.ht")
+      (to-list    . "~bandali/public-inbox@lists.sr.ht"))
+     ("gnu\\.~sircmpwn\\.srht-admins"
+      (to-address . "~sircmpwn/sr.ht-admins@lists.sr.ht")
+      (to-list    . "~sircmpwn/sr.ht-admins@lists.sr.ht"))
+     ("gnu\\.~sircmpwn\\.srht-announce"
+      (to-address . "~sircmpwn/sr.ht-announce@lists.sr.ht")
+      (to-list    . "~sircmpwn/sr.ht-announce@lists.sr.ht"))
+     ("gnu\\.~sircmpwn\\.srht-dev"
+      (to-address . "~sircmpwn/sr.ht-dev@lists.sr.ht")
+      (to-list    . "~sircmpwn/sr.ht-dev@lists.sr.ht"))
+     ("gnu\\.~sircmpwn\\.srht-discuss"
+      (to-address . "~sircmpwn/sr.ht-discuss@lists.sr.ht")
+      (to-list    . "~sircmpwn/sr.ht-discuss@lists.sr.ht"))
+     ("gnu.*"
+      (gcc-self . t))
+     ("gnu\\."
+      (subscribed . t)))
    gnus-large-newsgroup  50
    gnus-home-directory   (no-littering-expand-var-file-name "gnus/")
    gnus-directory        (concat gnus-home-directory "news/")
@@ -2156,9 +2377,13 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
    gnus-save-newsrc-file nil
    gnus-read-newsrc-file nil
    gnus-interactive-exit nil
-   gnus-gcc-mark-as-read t))
+   gnus-gcc-mark-as-read t)
+  :config
+  (require 'ebdb)
+  (require 'ebdb-mua)
+  (require 'ebdb-gnus))
 
-(use-package gnus-art
+(use-feature gnus-art
   :config
   (setq
    gnus-visible-headers
@@ -2183,11 +2408,9 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
       (concat local lapsed))))
   (bind-keys
    :map gnus-article-mode-map
-   ("r"   . gnus-article-reply-with-original)
-   ("R"   . gnus-article-wide-reply-with-original)
    ("M-L" . org-store-link)))
 
-(use-package gnus-sum
+(use-feature gnus-sum
   :bind (:map gnus-summary-mode-map
               :prefix-map a/gnus-summary-prefix-map
               :prefix "v"
@@ -2197,41 +2420,44 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
   :config
   (bind-keys
    :map gnus-summary-mode-map
-   ("r"   . gnus-summary-reply-with-original)
-   ("R"   . gnus-summary-wide-reply-with-original)
    ("M-L" . org-store-link))
   :hook (gnus-summary-mode . a/no-mouse-autoselect-window))
 
-(use-package gnus-msg
+(use-feature gnus-msg
   :config
   (setq gnus-posting-styles
         '((".*"
-           (address "amin@aminb.org")
-           (body "\nBest,\namin\n")
+           (address "amin@bndl.org")
+           (body "\nBest,\n")
            (eval (setq a/message-cite-say-hi t)))
           ("gnu.*"
-           (address "bandali@gnu.org"))
+           (address "bandali@gnu.org")
+           (eval (set (make-local-variable 'message-user-fqdn) "fencepost.gnu.org")))
           ((header "subject" "ThankCRM")
            (to "webmasters-comment@gnu.org")
-           (body "\nAdded  to 2018supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
+           (body "Added  to 2019supporters.html.\n\nMoving to campaigns.\n\n-amin\n")
            (eval (setq a/message-cite-say-hi nil)))
           ("nnimap\\+uwaterloo:.*"
            (address "abandali@uwaterloo.ca")
-           (gcc "\"nnimap+uwaterloo:Sent Items\"")))))
+           (gcc "\"nnimap+uwaterloo:Sent Items\""))
+          ("nnimap\\+csclub:.*"
+           (address "abandali@csclub.uwaterloo.ca")
+           (gcc "nnimap+csclub:Sent")))))
 
-(use-package gnus-topic
-  :hook (gnus-group-mode . gnus-topic-mode))
+(use-feature gnus-topic
+  :hook (gnus-group-mode . gnus-topic-mode)
+  :config (setq gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n"))
 
-(use-package gnus-agent
+(use-feature gnus-agent
   :config
   (setq gnus-agent-synchronize-flags 'ask)
   :hook (gnus-group-mode . gnus-agent-mode))
 
-(use-package gnus-group
+(use-feature gnus-group
   :config
-  (setq gnus-permanently-visible-groups "\\((INBOX\\|gnu$\\)"))
+  (setq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)"))
 
-(use-package mm-decode
+(use-feature mm-decode
   :config
   (setq mm-discouraged-alternatives '("text/html" "text/richtext")))
 #+end_src
@@ -2239,7 +2465,7 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
 ** sendmail
 
 #+begin_src emacs-lisp
-(use-package sendmail
+(use-feature sendmail
   :config
   (setq sendmail-program "/usr/bin/msmtp"
         ;; message-sendmail-extra-arguments '("-v" "-d")
@@ -2250,8 +2476,18 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
 ** message
 
 #+begin_src emacs-lisp
-(use-package message
+(use-feature message
   :config
+  ;; redefine for a simplified In-Reply-To header
+  ;; (see https://todo.sr.ht/~sircmpwn/lists.sr.ht/67)
+  (defun message-make-in-reply-to ()
+    "Return the In-Reply-To header for this message."
+    (when message-reply-headers
+      (let ((from (mail-header-from message-reply-headers))
+               (msg-id (mail-header-id message-reply-headers)))
+        (when from
+          msg-id))))
+
   (defconst a/message-cite-style-format "On %Y-%m-%d %l:%M %p, %N wrote:")
   (defconst message-cite-style-bandali
     '((message-cite-function  'message-cite-original)
@@ -2269,9 +2505,11 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
         message-kill-buffer-on-exit t
         message-send-mail-function 'message-send-mail-with-sendmail
         message-sendmail-envelope-from 'header
+        message-subscribed-address-functions
+        '(gnus-find-subscribed-addresses)
         message-dont-reply-to-names
-        "\\(\\(.*@aminb\\.org\\)\\|\\(amin@bandali\\.me\\)\\|\\(\\(aminb?\\|mab\\|bandali\\)@gnu\\.org\\)\\|\\(\\(m\\|a\\(min\\.\\)?\\)bandali@uwaterloo\\.ca\\)\\)"
-        message-user-fqdn "aminb.org")
+        "\\(\\(amin@bndl\\.org\\)\\|\\(.*@\\(aminb\\|amin\\.bndl\\)\\.org\\)\\|\\(\\(bandali\\|aminb?\\|mab\\)@gnu\\.org\\)\\|\\(a\\(min\\.\\)?bandali@uwaterloo\\.ca\\)\\|\\(abandali@csclub\\.uwaterloo\\.ca\\)\\)")
+  (require 'company-ebdb)
   :hook (;; (message-setup . mml-secure-message-sign-pgpmime)
          (message-mode . flyspell-mode)
          (message-mode . (lambda ()
@@ -2295,8 +2533,12 @@ Also see [[https://www.emacswiki.org/emacs/rebox2][rebox2]].
 Convenient footnotes in =message-mode=.
 
 #+begin_src emacs-lisp
-(use-package footnote
+(use-feature footnote
   :after message
+  ;; :config
+  ;; (setq footnote-start-tag ""
+  ;;       footnote-end-tag   ""
+  ;;       footnote-style     'unicode)
   :bind
   (:map message-mode-map
         :prefix-map a/footnote-prefix-map
@@ -2307,25 +2549,22 @@ Convenient footnotes in =message-mode=.
         ("d" . footnote-delete-footnote)
         ("g" . footnote-goto-footnote)
         ("r" . footnote-renumber-footnotes)
-        ("s" . footnote-set-style))
-  :config
-  (setq footnote-start-tag ""
-        footnote-end-tag   ""
-        footnote-style     'unicode))
+        ("s" . footnote-set-style)))
 #+end_src
 
 ** ebdb
 
 #+begin_src emacs-lisp
 (use-package ebdb
-  :defer 1
+  :straight (:host github :repo "girzel/ebdb")
+  :after gnus
   :bind (:map gnus-group-mode-map ("e" . ebdb))
   :config
   (setq ebdb-sources (no-littering-expand-var-file-name "ebdb"))
   (with-eval-after-load 'swiper
     (add-to-list 'swiper-font-lock-exclude 'ebdb-mode t)))
 
-(use-package ebdb-com
+(use-feature ebdb-com
   :after ebdb)
 
 ;; (use-package ebdb-complete
@@ -2334,15 +2573,10 @@ Convenient footnotes in =message-mode=.
 ;;   (ebdb-complete-enable))
 
 (use-package company-ebdb
-  :after (:all company message)
   :config
-  (defun company-ebdb--post-complete (_) nil)
-  :hook
-  (message-mode . (lambda ()
-                    (add-to-list (make-local-variable 'company-backends)
-                                 'company-ebdb))))
+  (defun company-ebdb--post-complete (_) nil))
 
-(use-package ebdb-gnus
+(use-feature ebdb-gnus
   :after ebdb
   :custom
   (ebdb-gnus-window-configuration
@@ -2353,7 +2587,7 @@ Convenient footnotes in =message-mode=.
                            (article 1.0)
                            (ebdb-gnus 0.3))))))
 
-(use-package ebdb-mua
+(use-feature ebdb-mua
   :after ebdb
   ;; :custom (ebdb-mua-pop-up nil)
   )
@@ -2366,9 +2600,13 @@ Convenient footnotes in =message-mode=.
 ;;   :after ebdb)
 #+end_src
 
-** COMMENT message-x
+** message-x
 
 #+begin_src emacs-lisp
+(use-package message-x)
+#+end_src
+
+#+begin_src emacs-lisp :tangle no
 (use-package message-x
   :custom
   (message-x-completion-alist
@@ -2393,19 +2631,28 @@ Convenient footnotes in =message-mode=.
     (gnus-harvest-install)))
 #+end_src
 
-* COMMENT Blogging
+* IRC
 :PROPERTIES:
-:CUSTOM_ID: blogging
+:CUSTOM_ID: irc
 :END:
 
-** [[https://ox-hugo.scripter.co][ox-hugo]]
+Now with ERC!
 
 #+begin_src emacs-lisp
-(use-package ox-hugo
-  :after ox)
-
-(use-package ox-hugo-auto-export
-  :load-path "lib/ox-hugo")
+(use-package znc
+  :straight (:host nil :repo "https://git.bndl.org/amin/znc.el")
+  :bind (("C-c a e e" . znc-erc)
+         ("C-c a e a" . znc-all))
+  :config
+  (let ((pwd (let ((auth (auth-source-search :host "znca")))
+               (cond
+                ((null auth) (error "Couldn't find znca's authinfo"))
+                (t (funcall (plist-get (car auth) :secret)))))))
+    (setq znc-servers
+          `(("znc.bndl.org" 1337 t
+             ((freenode "amin/freenode" ,pwd)))
+            ("znc.bndl.org" 1337 t
+             ((moznet "amin/moznet" ,pwd)))))))
 #+end_src
 
 * Post initialization
@@ -2432,6 +2679,6 @@ Display how long it took to load the init file.
 
 * COMMENT Local Variables                                           :ARCHIVE:
 # Local Variables:
-# eval: ;; (add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)
-# eval: (typo-mode -1)
+# eval: (add-hook 'after-save-hook #'a/async-babel-tangle 'append 'local)
+# eval: (when (featurep 'typo (typo-mode -1)))
 # End: