about summary refs log tree commit diff
path: root/users/wpcarro/emacs
diff options
context:
space:
mode:
Diffstat (limited to 'users/wpcarro/emacs')
-rw-r--r--users/wpcarro/emacs/.emacs.d/init.el1
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/cache.el88
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el85
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/constants.el5
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/device.el62
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/dotted.el57
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/fonts.el92
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/graph.el94
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/irc.el170
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/keybindings.el33
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/keyboard.el29
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el63
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/number.el142
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/random.el80
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/scope.el106
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/sequence.el108
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/series.el92
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/stack.el101
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/timestring.el77
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/tree.el199
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/window.el40
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el16
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el5
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el2
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el15
-rw-r--r--users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el42
-rw-r--r--users/wpcarro/emacs/AppIcon.icnsbin0 -> 449758 bytes
-rw-r--r--users/wpcarro/emacs/default.nix212
-rw-r--r--users/wpcarro/emacs/pkgs/bookmark/bookmark.el (renamed from users/wpcarro/emacs/.emacs.d/wpc/bookmark.el)0
-rw-r--r--users/wpcarro/emacs/pkgs/bookmark/default.nix13
-rw-r--r--users/wpcarro/emacs/pkgs/bytes/bytes.el (renamed from users/wpcarro/emacs/.emacs.d/wpc/bytes.el)56
-rw-r--r--users/wpcarro/emacs/pkgs/bytes/default.nix25
-rw-r--r--users/wpcarro/emacs/pkgs/bytes/tests.el18
-rw-r--r--users/wpcarro/emacs/pkgs/macros/default.nix10
-rw-r--r--users/wpcarro/emacs/pkgs/macros/macros.el (renamed from users/wpcarro/emacs/.emacs.d/wpc/macros.el)20
-rw-r--r--users/wpcarro/emacs/pkgs/passage/README.md12
-rw-r--r--users/wpcarro/emacs/pkgs/passage/default.nix12
-rw-r--r--users/wpcarro/emacs/pkgs/passage/passage.el65
-rw-r--r--users/wpcarro/emacs/pkgs/theme/default.nix14
-rw-r--r--users/wpcarro/emacs/pkgs/theme/theme.el78
-rw-r--r--users/wpcarro/emacs/pkgs/tuple/default.nix10
-rw-r--r--users/wpcarro/emacs/pkgs/tuple/tuple.el (renamed from users/wpcarro/emacs/.emacs.d/wpc/tuple.el)0
-rw-r--r--users/wpcarro/emacs/pkgs/vector/default.nix21
-rw-r--r--users/wpcarro/emacs/pkgs/vector/tests.el20
-rw-r--r--users/wpcarro/emacs/pkgs/vector/vector.el (renamed from users/wpcarro/emacs/.emacs.d/wpc/vector.el)26
45 files changed, 559 insertions, 1857 deletions
diff --git a/users/wpcarro/emacs/.emacs.d/init.el b/users/wpcarro/emacs/.emacs.d/init.el
index 9554147fe7..5db74d36c7 100644
--- a/users/wpcarro/emacs/.emacs.d/init.el
+++ b/users/wpcarro/emacs/.emacs.d/init.el
@@ -4,7 +4,6 @@
 (require 'wpc-misc)
 (require 'ssh)
 (require 'keyboard)
-(require 'irc)
 (require 'email)
 (require 'keybindings)
 (require 'window-manager)
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/cache.el b/users/wpcarro/emacs/.emacs.d/wpc/cache.el
deleted file mode 100644
index 70ebdb71ef..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/cache.el
+++ /dev/null
@@ -1,88 +0,0 @@
-;;; cache.el --- Caching things -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24.3"))
-
-;;; Commentary:
-;; An immutable cache data structure.
-;;
-;; This is like a sideways stack, that you can pull values out from and re-push
-;; to the top.  It'd be like a stack supporting push, pop, pull.
-;;
-;; This isn't a key-value data-structure like you might expect from a
-;; traditional cache.  The name is subject to change, but the underlying idea of
-;; a cache remains the same.
-;;
-;; Think about prescient.el, which uses essentially an LRU cache integrated into
-;; counsel to help create a "clairovoyant", self-organizing list.
-;;
-;; Use-cases:
-;; - Keeps an cache of workspaces sorted as MRU with an LRU eviction strategy.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-(require 'struct)
-(require '>)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(cl-defstruct cache xs)
-
-;; TODO: Prefer another KBD for yasnippet form completion than company-mode's
-;; current KBD.
-
-(defun cache-from-list (xs)
-  "Turn list, XS, into a cache."
-  (make-cache :xs xs))
-
-(defun cache-contains? (x xs)
-  "Return t if X in XS."
-  (->> xs
-       cache-xs
-       (list-contains? x)))
-
-(defun cache-touch (x xs)
-  "Ensure value X in cache, XS, is front of the list.
-If X isn't in XS (using `equal'), insert it at the front."
-  (struct-update
-   cache
-   xs
-   (>-> (list-reject (lambda (y) (equal x y)))
-       (list-cons x))
-   xs))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tests
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(progn
-  (let ((cache (cache-from-list '("chicken" "nugget"))))
-    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-    ;; contains?/2
-    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-    (prelude-refute
-     (cache-contains? "turkey" cache))
-    (prelude-assert
-     (cache-contains? "chicken" cache))
-    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-    ;; touch/2
-    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-    (prelude-assert
-     (equal
-      (cache-touch "nugget" cache)
-      (cache-from-list '("nugget" "chicken"))))
-    (prelude-assert
-     (equal
-      (cache-touch "spicy" cache)
-      (cache-from-list '("spicy" "chicken" "nugget"))))))
-
-(provide 'cache)
-;;; cache.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el b/users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el
deleted file mode 100644
index 20d209f895..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/colorscheme.el
+++ /dev/null
@@ -1,85 +0,0 @@
-;;; colorscheme.el --- Syntax highlight and friends -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24.3"))
-
-;;; Commentary:
-;;
-;; TODO: Clarify this.
-;; Since I have my own definition of "theme", which couples wallpaper, font,
-;; with Emacs's traditional notion of the word "theme", I'm choosing to use
-;; "colorscheme" to refer to *just* the notion of syntax highlight etc.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'cycle)
-(require '>)
-(require 'cl-lib)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defcustom colorscheme-whitelist
-  (cycle-from-list
-   (->> (custom-available-themes)
-        (list-map #'symbol-name)
-        (list-filter (>-> (s-starts-with? "doom-")))
-        (list-map #'intern)))
-  "The whitelist of colorschemes through which to cycle.")
-
-(defun colorscheme-current ()
-  "Return the currently enabled colorscheme."
-  (cycle-current colorscheme-whitelist))
-
-(defun colorscheme-disable-all ()
-  "Disable all currently enabled colorschemes."
-  (interactive)
-  (->> custom-enabled-themes
-       (list-map #'disable-theme)))
-
-(defun colorscheme-set (theme)
-    "Call `load-theme' with `THEME', ensuring that the line numbers are bright.
-There is no hook that I'm aware of to handle this more elegantly."
-    (load-theme theme t)
-    (prelude-set-line-number-color "#da5468"))
-
-(defun colorscheme-whitelist-set (colorscheme)
-  "Focus the COLORSCHEME in the `colorscheme-whitelist' cycle."
-  (cycle-focus! (lambda (x) (equal x colorscheme)) colorscheme-whitelist)
-  (colorscheme-set (colorscheme-current)))
-
-(defun colorscheme-ivy-select ()
-  "Load a colorscheme using ivy."
-  (interactive)
-  (let ((theme (ivy-read "Theme: " (cycle-to-list colorscheme-whitelist))))
-    (colorscheme-disable-all)
-    (colorscheme-set (intern theme))))
-
-(cl-defun colorscheme-cycle (&key forward?)
-  "Cycle next if `FORWARD?' is non-nil.
-Cycle prev otherwise."
-  (disable-theme (cycle-current colorscheme-whitelist))
-  (let ((theme (if forward?
-                   (cycle-next! colorscheme-whitelist)
-                 (cycle-prev! colorscheme-whitelist))))
-    (colorscheme-set theme)
-    (message (s-concat "Active theme: " (symbol-to-string theme)))))
-
-(defun colorscheme-next ()
-  "Disable the currently active theme and load the next theme."
-  (interactive)
-  (colorscheme-cycle :forward? t))
-
-(defun colorscheme-prev ()
-  "Disable the currently active theme and load the previous theme."
-  (interactive)
-  (colorscheme-cycle :forward? nil))
-
-(provide 'colorscheme)
-;;; colorscheme.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/constants.el b/users/wpcarro/emacs/.emacs.d/wpc/constants.el
index 69003f5955..48bcd9042f 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/constants.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/constants.el
@@ -20,7 +20,10 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defconst constants-ci? (maybe-some? (getenv "CI"))
-  "Encoded as t when Emacs is running in CI.")
+  "Defined as t when Emacs is running in CI.")
+
+(defconst constants-osx? (eq system-type 'darwin)
+  "Defined as t when OSX is running.")
 
 (provide 'constants)
 ;;; constants.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/device.el b/users/wpcarro/emacs/.emacs.d/wpc/device.el
deleted file mode 100644
index 09819ad748..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/device.el
+++ /dev/null
@@ -1,62 +0,0 @@
-;;; device.el --- Physical device information -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Functions for querying device information.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'dash)
-(require 'al)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; TODO(wpcarro): Consider integrating this with Nix and depot instead of
-;; denormalizing the state.
-(defconst device-hostname->device
-  '(("zeno.lon.corp.google.com" . work-desktop-lon)
-    ("wpcarro.svl.corp.google.com" . work-desktop-svl)
-    ("seneca" . work-laptop)
-    ("marcus" . personal-laptop)
-    ("diogenes" . personal-vm))
-  "Mapping hostname to a device symbol.")
-
-;; TODO: Should I generate these predicates?
-
-(defun device-classify ()
-  "Return the device symbol for the current host or nil if not supported."
-  (al-get system-name device-hostname->device))
-
-(defun device-work-laptop? ()
-  "Return t if current device is work laptop."
-  (equal 'work-laptop
-         (device-classify)))
-
-(defun device-work-desktop? ()
-  "Return t if current device is work desktop."
-  (-contains? '(work-desktop-lon
-                work-desktop-svl)
-              (device-classify)))
-
-(defun device-corporate? ()
-  "Return t if the current device is owned by my company."
-  (-contains? '(work-desktop-lon
-                work-desktop-svl
-                work-laptop)
-              (device-classify)))
-
-(defun device-laptop? ()
-  "Return t if the current device is a laptop."
-  (-contains? '(work-laptop personal-laptop) (device-classify)))
-
-(provide 'device)
-;;; device.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/dotted.el b/users/wpcarro/emacs/.emacs.d/wpc/dotted.el
deleted file mode 100644
index b824ddbda7..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/dotted.el
+++ /dev/null
@@ -1,57 +0,0 @@
-;;; dotted.el --- Working with dotted pairs in Elisp -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24.3"))
-
-;;; Commentary:
-;; Part of my primitives library extensions in Elisp.  Contrast my primitives
-;; with the wrapper extensions that I provide, which expose immutable variants
-;; of data structures like an list, alist, tuple, as well as quasi-typeclasses
-;; like sequence, etc.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-(require 'macros)
-(require 'cl-lib)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(cl-defun dotted-new (&optional a b)
-  "Create a new dotted pair of A and B."
-  (cons a b))
-
-(defun dotted-instance? (x)
-  "Return t if X is a dotted pair."
-  (let ((b (cdr x)))
-    (and b (atom b))))
-
-(defun dotted-first (x)
-  "Return the first element of X."
-  (car x))
-
-(defun dotted-second (x)
-  "Return the second element of X."
-  (cdr x))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tests
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(progn
-  (prelude-assert
-   (equal '(fname . "Bob") (dotted-new 'fname "Bob")))
-  (prelude-assert
-   (dotted-instance? '(one . two)))
-  (prelude-refute
-   (dotted-instance? '(1 2 3))))
-
-(provide 'dotted)
-;;; dotted.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/fonts.el b/users/wpcarro/emacs/.emacs.d/wpc/fonts.el
index 9490896ae7..0f70f69c2b 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/fonts.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/fonts.el
@@ -9,15 +9,10 @@
 
 ;;; Code:
 
-;; TODO: `defcustom' font-size.
-;; TODO: `defcustom' fonts.
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Dependencies
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(require 'prelude)
-(require 'cycle)
 (require 'maybe)
 (require 'cl-lib)
 
@@ -25,93 +20,30 @@
 ;; Constants
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;; TODO: Troubleshoot why "8" appears so large on my desktop.
-
-;; TODO: Consider having a different font size when I'm using my 4K monitor.
-
-(defconst fonts-size "10"
-  "My preferred default font-size.")
-
-(defconst fonts-size-step 10
-  "The amount (%) by which to increase or decrease a font.")
-
-(defconst fonts-hacker-news-recommendations
-  '("APL385 Unicode"
-    "Go Mono"
-    "Sudo"
-    "Monoid"
-    "Input Mono Medium" ;; NOTE: Also "Input Mono Thin" is nice.
-    )
-  "List of fonts optimized for programming I found in a HN article.")
-
-(defconst fonts-whitelist
-  (cycle-from-list
-   (list-concat
-    fonts-hacker-news-recommendations
-    '("JetBrainsMono"
-      "Mononoki Medium"
-      "Monospace"
-      "Operator Mono Light"
-      "Courier"
-      "Andale Mono"
-      "Source Code Pro"
-      "Terminus")))
-  "This is a list of my preferred fonts.")
+(defgroup fonts nil
+  "Customize group for fonts configuration.")
+
+(defcustom fonts-size "10"
+  "My preferred default font-size."
+  :group 'fonts)
+
+(defcustom fonts-size-step 10
+  "The amount (%) by which to increase or decrease a font."
+  :group 'fonts)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Functions
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;; TODO: fonts and fonts-whitelist make it difficult to name functions like
-;; fonts-set as a generic Emacs function vs choosing a font from the whitelist.
-
-(cl-defun fonts-cycle (&key forward?)
-  "Cycle forwards when `FORWARD?' non-nil."
-  (let ((font (if forward?
-                  (cycle-next! fonts-whitelist)
-                (cycle-prev! fonts-whitelist))))
-    (message (s-concat "Active font: " font))
-    (fonts-set font)))
-
-(defun fonts-next ()
-  "Quickly cycle through preferred fonts."
-  (interactive)
-  (fonts-cycle :forward? t))
-
-(defun fonts-prev ()
-  "Quickly cycle through preferred fonts."
-  (interactive)
-  (fonts-cycle :forward? nil))
-
 (defun fonts-set (font &optional size)
   "Change the font to `FONT' with option integer, SIZE, in pixels."
   (if (maybe-some? size)
       (set-frame-font (string-format "%s %s" font size) nil t)
     (set-frame-font font nil t)))
 
-(defun fonts-whitelist-set (font)
-  "Focuses the FONT in the `fonts-whitelist' cycle.
-The size of the font is determined by `fonts-size'."
-  (prelude-assert (cycle-contains? font fonts-whitelist))
-  (cycle-focus! (lambda (x) (equal x font)) fonts-whitelist)
-  (fonts-set (fonts-current) fonts-size))
-
-(defun fonts-ivy-select ()
-  "Select a font from an ivy prompt."
-  (interactive)
-  (fonts-whitelist-set
-   (ivy-read "Font: " (cycle-to-list fonts-whitelist))))
-
-(defun fonts-print-current ()
-  "Message the currently enabled font."
-  (interactive)
-  (message
-   (string-format "[fonts] Current font: \"%s\""
-                  (fonts-current))))
-
 (defun fonts-current ()
   "Return the currently enabled font."
-  (cycle-current fonts-whitelist))
+  (symbol-name (font-get (face-attribute 'default :font) :family)))
 
 (defun fonts-increase-size ()
   "Increase font size."
@@ -130,7 +62,7 @@ The size of the font is determined by `fonts-size'."
 (defun fonts-reset-size ()
   "Restore font size to its default value."
   (interactive)
-  (fonts-whitelist-set (fonts-current)))
+  (fonts-set (fonts-current) fonts-size))
 
 (defun fonts-enable-ligatures ()
   "Call this function to enable ligatures."
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/graph.el b/users/wpcarro/emacs/.emacs.d/wpc/graph.el
deleted file mode 100644
index 1d2f67a4dd..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/graph.el
+++ /dev/null
@@ -1,94 +0,0 @@
-;;; graph.el --- Working with in-memory graphs -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24.3"))
-
-;;; Commentary:
-;;
-;; Remember that there are optimal three ways to model a graph:
-;; 1. Edge List
-;; 2. Vertex Table (a.k.a. Neighbors Table)
-;; 3. Adjacency Matrix
-;;
-;; I may call these "Edges", "Neighbors", "Adjacencies" to avoid verbose naming.
-;; For now, I'm avoiding dealing with Adjacency Matrices as I don't have an
-;; immediate use-case for them.  This is subject to change.
-;;
-;; There are also hybrid representations of graphs that combine the three
-;; aforementioned models.  I believe Erlang's digraph module models graphs in
-;; Erlang Term Storage (i.e. ETS) this way.
-;; TODO: Verify this claim.
-;;
-;; Graphs can be weighted or unweighted.  They can also be directed or
-;; undirected.
-;; TODO: Create a table explaining all graph variants.
-;;
-;; TODO: Figure out the relationship of this module and tree.el, which should in
-;; principle overlap.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; For now, I'll support storing *either* neighbors or edges in the graph struct
-;; as long as both aren't set, since that introduces consistency issues.  I may
-;; want to handle that use-case in the future, but not now.
-(cl-defstruct graph neighbors edges)
-
-;; TODO: How do you find the starting point for a topo sort?
-(defun graph-sort (xs)
-  "Return a topological sort of XS.")
-
-(defun graph-from-edges (xs)
-  "Create a graph struct from the Edge List, XS.
-The user must pass in a valid Edge List since asserting on the shape of XS might
-  be expensive."
-  (make-graph :edges xs))
-
-(defun graph-from-neighbors (xs)
-  "Create a graph struct from a Neighbors Table, XS.
-The user must pass in a valid Neighbors Table since asserting on the shape of
-  XS might be expensive."
-  (make-graph :neighbors xs))
-
-(defun graph-instance? (xs)
-  "Return t if XS is a graph struct."
-  (graph-p xs))
-
-;; TODO: Model each of the mapping functions into an isomorphism.
-(defun graph-edges->neighbors (xs)
-  "Map Edge List, XS, into a Neighbors Table."
-  (prelude-assert (graph-instance? xs)))
-
-(defun graph-neighbors->edges (xs)
-  "Map Neighbors Table, XS, into an Edge List."
-  (prelude-assert (graph-instance? xs)))
-
-;; Below are three different models of the same unweighted, directed graph.
-
-(defvar graph-edges
-  '((a . b) (a . c) (a . e)
-    (b . c) (b . d)
-    (c . e)
-    (d . f)
-    (e . d) (e . f)))
-
-(defvar graph-neighbors
-  ((a b c e)
-   (b c d)
-   (c e)
-   (d f)
-   (e d g)
-   (f)))
-
-(provide 'graph)
-;;; graph.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/irc.el b/users/wpcarro/emacs/.emacs.d/wpc/irc.el
deleted file mode 100644
index 4ae50b4b1b..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/irc.el
+++ /dev/null
@@ -1,170 +0,0 @@
-;;; irc.el --- Configuration for IRC chat -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Need to decide which client I will use for IRC.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'erc)
-(require 'cycle)
-(require 'string)
-(require 'prelude)
-(require 'al)
-(require 'set)
-(require 'maybe)
-(require 'macros)
-(require '>)
-(require 'password-store)
-(require 'general)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Configuration
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defcustom irc-install-kbds? t
-  "When t, install the keybindings defined herein.")
-
-(setq erc-rename-buffers t)
-
-;; Setting `erc-join-buffer' to 'bury prevents erc from stealing focus of the
-;; current buffer when it connects to IRC servers.
-(setq erc-join-buffer 'bury)
-
-;; TODO: Find a way to avoid putting "freenode" and "#freenode" as channels
-;; here.  I'm doing it because when erc first connects, it's `(buffer-name)' is
-;; "freenode", so when `irc-next-channel' is called, it 404s on the
-;; `cycle-contains?' call in `irc-channel->cycle" unless "freenode" is there. To
-;; make matters even uglier, when `erc-join-channel' is called with "freenode"
-;; as the value, it connects to the "#freenode" channel, so unless "#freenode"
-;; exists in this cycle also, `irc-next-channel' breaks again.
-(defconst irc-server->channels
-  `(("irc.freenode.net"    . ,(cycle-new "freenode" "#freenode" "#nixos" "#emacs" "#pass"))
-    ("irc.corp.google.com" . ,(cycle-new "#drive-prod")))
-  "Mapping of IRC servers to a cycle of my preferred channels.")
-
-;; TODO: Here is another horrible hack that should be revisted.
-(setq erc-autojoin-channels-alist
-      (->> irc-server->channels
-           (al-map-values #'cycle-to-list)
-           (al-map-keys (>-> (s-chop-prefix "irc.")
-                             (s-chop-suffix ".net")))))
-
-;; TODO: Assert that no two servers have a channel with the same name. We need
-;; this because that's the assumption that underpins the `irc-channel->server'
-;; function. This will probably be an O(n^2) operation.
-(prelude-assert
- (set-distinct? (set-from-list
-                 (cycle-to-list
-                  (al-get "irc.freenode.net"
-                          irc-server->channels)))
-                (set-from-list
-                 (cycle-to-list
-                  (al-get "irc.corp.google.com"
-                          irc-server->channels)))))
-
-(defun irc-channel->server (server->channels channel)
-  "Using SERVER->CHANNELS, resolve an IRC server from a given CHANNEL."
-  (let ((result (al-find (lambda (k v) (cycle-contains? channel v))
-                         server->channels)))
-    (prelude-assert (maybe-some? result))
-    result))
-
-(defun irc-channel->cycle (server->channels channel)
-  "Using SERVER->CHANNELS, resolve an IRC's channels cycle from CHANNEL."
-  (al-get (irc-channel->server server->channels channel)
-          server->channels))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun irc-message (x)
-  "Print message X in a structured way."
-  (message (string-format "[irc.el] %s" x)))
-
-;; TODO: Integrate Google setup with Freenode setup.
-
-;; TODO: Support function or KBD for switching to an ERC buffer.
-
-(defun irc-kill-all-erc-processes ()
-  "Kill all ERC buffers and processes."
-  (interactive)
-  (->> (erc-buffer-list)
-       (-map #'kill-buffer)))
-
-(defun irc-switch-to-erc-buffer ()
-  "Switch to an ERC buffer."
-  (interactive)
-  (let ((buffers (erc-buffer-list)))
-    (if (list-empty? buffers)
-        (error "[irc.el] No ERC buffers available")
-      (switch-to-buffer (list-first (erc-buffer-list))))))
-
-(defun irc-connect-to-freenode ()
-  "Connect to Freenode IRC."
-  (interactive)
-  (erc-ssl :server "irc.freenode.net"
-           :port 6697
-           :nick "wpcarro"
-           :password (password-store-get "programming/irc/freenode")
-           :full-name "William Carroll"))
-
-;; TODO: Handle failed connections.
-(defun irc-connect-to-google ()
-  "Connect to Google's Corp IRC using ERC."
-  (interactive)
-  (erc-ssl :server "irc.corp.google.com"
-           :port 6697
-           :nick "wpcarro"
-           :full-name "William Carroll"))
-
-;; TODO: Prefer defining these with a less homespun solution. There is a
-;; function call `erc-buffer-filter' that would be more appropriate for the
-;; implementation of `irc-next-channel' and `irc-prev-channel'.
-(defun irc-next-channel ()
-  "Join the next channel for the active server."
-  (interactive)
-  (with-current-buffer (current-buffer)
-    (let ((cycle (irc-channel->cycle irc-server->channels (buffer-name))))
-      (erc-join-channel
-       (cycle-next! cycle))
-      (irc-message
-       (string-format "Current IRC channel: %s" (cycle-current cycle))))))
-
-(defun irc-prev-channel ()
-  "Join the previous channel for the active server."
-  (interactive)
-  (with-current-buffer (current-buffer)
-    (let ((cycle (irc-channel->cycle irc-server->channels (buffer-name))))
-      (erc-join-channel
-       (cycle-prev! cycle))
-      (irc-message
-       (string-format "Current IRC channel: %s" (cycle-current cycle))))))
-
-(add-hook 'erc-mode-hook (macros-disable auto-fill-mode))
-(add-hook 'erc-mode-hook (macros-disable company-mode))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Keybindings
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(when irc-install-kbds?
-  (general-define-key
-   :keymaps 'erc-mode-map
-   "<C-tab>" #'irc-next-channel
-   "<C-S-iso-lefttab>" #'irc-prev-channel))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tests
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'irc)
-;;; irc.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el b/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el
index 16b3d6c8f3..a55bf27330 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/keybindings.el
@@ -31,12 +31,10 @@
 (require 'exwm)
 (require 'vterm-mgt)
 (require 'buffer)
-(require 'device)
 (require 'fonts)
 (require 'bookmark)
 (require 'tvl)
 (require 'window-manager)
-(require 'wpc-misc)
 
 ;; Note: The following lines must be sorted this way.
 (setq evil-want-integration t)
@@ -49,6 +47,7 @@
 (require 'key-chord)
 (require 'edebug)
 (require 'avy)
+(require 'passage)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Helper Functions
@@ -156,6 +155,20 @@
         (after advice-for-evil-search-previous activate)
       (evil-scroll-line-to-center (line-number-at-pos)))))
 
+(general-define-key
+ :keymaps '(isearch-mode-map)
+ "C-p" #'isearch-ring-retreat
+ "C-n" #'isearch-ring-advance
+ "<up>" #'isearch-ring-retreat
+ "<down>" #'isearch-ring-advance)
+
+(general-define-key
+ :keymaps '(minibuffer-local-isearch-map)
+ "C-p" #'previous-line-or-history-element
+ "C-n" #'next-line-or-history-element
+ "<up>" #'previous-line-or-history-element
+ "<down>" #'next-line-or-history-element)
+
 (key-chord-mode 1)
 (key-chord-define evil-insert-state-map "jk" 'evil-normal-state)
 
@@ -209,8 +222,14 @@
 (keybindings-exwm "<M-tab>" #'window-manager-next-workspace)
 (keybindings-exwm "<M-S-iso-lefttab>" #'window-manager-prev-workspace)
 (keybindings-exwm "C-S-f" #'window-manager-toggle-previous)
-(keybindings-exwm "C-M-\\" #'ivy-pass)
-(keybindings-exwm "s-e" #'wpc-misc-copy-emoji)
+(keybindings-exwm "C-M-\\" #'passage-select)
+
+(defun keybindings-copy-emoji ()
+  "Select an emoji from the completing-read menu."
+  (interactive)
+  (clipboard-copy (emojify-completing-read "Copy: ")))
+
+(keybindings-exwm "s-e" #'keybindings-copy-emoji)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Workspaces
@@ -295,7 +314,9 @@
  "<s-backspace>" #'vterm-mgt-rename-buffer
  ;; Without this, typing "+" is effectively no-op. Try for yourself:
  ;; (vterm-send-key "<kp-add>")
- "<kp-add>" "+")
+ "<kp-add>" "+"
+ "M--" #'evil-window-split
+ "M-\\" #'evil-window-vsplit)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; notmuch
@@ -451,6 +472,8 @@
 ;; restore the ability to paste in ivy
 (general-define-key
  :keymaps '(ivy-minibuffer-map)
+ "C-k" #'kill-line
+ "C-u" (lambda () (interactive) (kill-line 0))
  "C-v" #'clipboard-yank
  "C-S-v" #'clipboard-yank)
 
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el b/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el
index 03fb9e3f35..0ee00e1b84 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/keyboard.el
@@ -15,9 +15,8 @@
 ;; Dependencies
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(require 'string)
-(require 'number)
 (require 'cl-lib)
+(require 'prelude)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Constants
@@ -46,7 +45,7 @@
 
 (defun keyboard-message (x)
   "Message X in a structured way."
-  (message (string-format "[keyboard.el] %s" x)))
+  (message (format "[keyboard.el] %s" x)))
 
 (cl-defun keyboard-set-key-repeat (&key
                                    (rate keyboard-repeat-rate)
@@ -54,7 +53,7 @@
   "Use xset to set the key-repeat RATE and DELAY."
   (prelude-start-process
    :name "keyboard-set-key-repeat"
-   :command (string-format "xset r rate %s %s" delay rate)))
+   :command (format "xset r rate %s %s" delay rate)))
 
 ;; NOTE: Settings like this are machine-dependent. For instance I only need to
 ;; do this on my laptop and other devices where I don't have access to my split
@@ -76,42 +75,42 @@
 (defun keyboard-inc-repeat-rate ()
   "Increment `keyboard-repeat-rate'."
   (interactive)
-  (setq keyboard-repeat-rate (number-inc keyboard-repeat-rate))
+  (setq keyboard-repeat-rate (1+ keyboard-repeat-rate))
   (keyboard-set-key-repeat :rate keyboard-repeat-rate)
   (keyboard-message
-   (string-format "Rate: %s" keyboard-repeat-rate)))
+   (format "Rate: %s" keyboard-repeat-rate)))
 
 (defun keyboard-dec-repeat-rate ()
   "Decrement `keyboard-repeat-rate'."
   (interactive)
-  (setq keyboard-repeat-rate (number-dec keyboard-repeat-rate))
+  (setq keyboard-repeat-rate (1- keyboard-repeat-rate))
   (keyboard-set-key-repeat :rate keyboard-repeat-rate)
   (keyboard-message
-   (string-format "Rate: %s" keyboard-repeat-rate)))
+   (format "Rate: %s" keyboard-repeat-rate)))
 
 (defun keyboard-inc-repeat-delay ()
   "Increment `keyboard-repeat-delay'."
   (interactive)
-  (setq keyboard-repeat-delay (number-inc keyboard-repeat-delay))
+  (setq keyboard-repeat-delay (1+ keyboard-repeat-delay))
   (keyboard-set-key-repeat :delay keyboard-repeat-delay)
   (keyboard-message
-   (string-format "Delay: %s" keyboard-repeat-delay)))
+   (format "Delay: %s" keyboard-repeat-delay)))
 
 (defun keyboard-dec-repeat-delay ()
   "Decrement `keyboard-repeat-delay'."
   (interactive)
-  (setq keyboard-repeat-delay (number-dec keyboard-repeat-delay))
+  (setq keyboard-repeat-delay (1- keyboard-repeat-delay))
   (keyboard-set-key-repeat :delay keyboard-repeat-delay)
   (keyboard-message
-   (string-format "Delay: %s" keyboard-repeat-delay)))
+   (format "Delay: %s" keyboard-repeat-delay)))
 
 (defun keyboard-print-key-repeat ()
   "Print the currently set values for key repeat."
   (interactive)
   (keyboard-message
-   (string-format "Rate: %s. Delay: %s"
-                  keyboard-repeat-rate
-                  keyboard-repeat-delay)))
+   (format "Rate: %s. Delay: %s"
+           keyboard-repeat-rate
+           keyboard-repeat-delay)))
 
 (defun keyboard-set-preferences ()
   "Reset the keyboard preferences to their default values.
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el b/users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el
deleted file mode 100644
index 80dc96ebeb..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/laptop-battery.el
+++ /dev/null
@@ -1,63 +0,0 @@
-;;; laptop-battery.el --- Display laptop battery information -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Some wrappers to obtain battery information.
-;;
-;; To troubleshoot battery consumpton look into the CLI `powertop`.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Roadmap
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; TODO: Support functions that work with reporting battery stats.
-;; TODO: low-battery-reporting-threshold
-;; TODO: charged-battery-reporting-threshold
-;; TODO: Format modeline battery information.
-;; TODO: Provide better time information in the modeline.
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'battery)
-(require 'al)
-(require 'maybe)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun laptop-battery-available? ()
-  "Return t if battery information is available."
-  (maybe-some? battery-status-function))
-
-(defun laptop-battery-percentage ()
-  "Return the current percentage of the battery."
-  (->> battery-status-function
-       funcall
-       (al-get 112)))
-
-(defun laptop-battery-print-percentage ()
-  "Return the current percentage of the battery."
-  (interactive)
-  (->> (laptop-battery-percentage)
-       message))
-
-(defun laptop-battery-display ()
-  "Display laptop battery percentage in the modeline."
-  (interactive)
-  (display-battery-mode 1))
-
-(defun laptop-battery-hide ()
-  "Hide laptop battery percentage in the modeline."
-  (interactive)
-  (display-battery-mode -1))
-
-(provide 'laptop-battery)
-;;; laptop-battery.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/number.el b/users/wpcarro/emacs/.emacs.d/wpc/number.el
deleted file mode 100644
index c8ed665b30..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/number.el
+++ /dev/null
@@ -1,142 +0,0 @@
-;;; number.el --- Functions for working with numbers -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24"))
-;; Homepage: https://user.git.corp.google.com/wpcarro/briefcase
-
-;;; Commentary:
-;;
-;; Classifications of numbers:
-;; - Natural: (a.k.a positive integers, counting numbers); {1, 2, 3, ... }
-;;
-;; - Whole: Natural Numbers, plus zero; {0, 1, 2, 3, ...}
-;;
-;; - Integers: Whole numbers plus all the negatives of the natural numbers;
-;;   {... , -2, -1, 0, 1, 2, ...}
-;;
-;; - Rational numbers: (a.k.a. fractions) where the top and bottom numbers are
-;;   integers; e.g., 1/2, 3/4, 7/2, ⁻4/3, 4/1.  Note: The denominator cannot be
-;;   0, but the numerator can be.
-;;
-;; - Real numbers: All numbers that can be written as a decimal.  This includes
-;;   fractions written in decimal form e.g., 0.5, 0.75 2.35, ⁻0.073, 0.3333, or
-;;   2.142857. It also includes all the irrational numbers such as π, √2 etc.
-;;   Every real number corresponds to a point on the number line.
-;;
-;; The functions defined herein attempt to capture the mathematical definitions
-;; of numbers and their classifications as defined above.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-(require 'dash)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defconst number-test? t
-  "When t, run the test suite defined herein.")
-
-;; TODO: What about int.el?
-
-;; TODO: How do we handle a number typeclass?
-
-(defun number-positive? (x)
-  "Return t if `X' is a positive number."
-  (> x 0))
-
-(defun number-negative? (x)
-  "Return t if `X' is a positive number."
-  (< x 0))
-
-;; TODO: Don't rely on this. Need to have 10.0 and 10 behave similarly.
-(defun number-float? (x)
-  "Return t if `X' is a floating point number."
-  (floatp x))
-
-(defun number-natural? (x)
-  "Return t if `X' is a natural number."
-  (and (number-positive? x)
-       (not (number-float? x))))
-
-(defun number-whole? (x)
-  "Return t if `X' is a whole number."
-  (or (= 0 x)
-      (number-natural? x)))
-
-(defun number-integer? (x)
-  "Return t if `X' is an integer."
-  (or (number-whole? x)
-      (number-natural? (- x))))
-
-;; TODO: How defensive should these guards be?  Should we assert that the inputs
-;; are integers before checking evenness or oddness?
-
-;; TODO: Look up Runar (from Unison) definition of handling zero as even or odd.
-
-;; TODO: How should rational numbers be handled? Lisp is supposedly famous for
-;; its handling of rational numbers.
-;; TODO: `calc-mode' supports rational numbers as "1:2" meaning "1/2"
-;; (defun number-rational? (x))
-
-;; TODO: Can or should I support real numbers?
-;; (defun number-real? (x))
-
-(defun number-even? (x)
-  "Return t if `X' is an even number."
-  (or (= 0 x)
-      (= 0 (mod x 2))))
-
-(defun number-odd? (x)
-  "Return t if `X' is an odd number."
-  (not (number-even? x)))
-
-(defun number-dec (x)
-  "Subtract one from `X'.
-While this function is undeniably trivial, I have unintentionally done (- 1 x)
-  when in fact I meant to do (- x 1) that I figure it's better for this function
-  to exist, and for me to train myself to reach for it and its inc counterpart."
-  (- x 1))
-
-(defun number-inc (x)
-  "Add one to `X'."
-  (+ x 1))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tests
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(when number-test?
-  (prelude-assert
-   (number-positive? 10))
-  (prelude-assert
-   (number-natural? 10))
-  (prelude-assert
-   (number-whole? 10))
-  (prelude-assert
-   (number-whole? 0))
-  (prelude-assert
-   (number-integer? 10))
-  ;; (prelude-assert
-  ;;  (= 120 (number-factorial 5)))
-  (prelude-assert
-   (number-even? 6))
-  (prelude-refute
-   (number-odd? 6))
-  (prelude-refute
-   (number-positive? -10))
-  (prelude-refute
-   (number-natural? 10.0))
-  (prelude-refute
-   (number-natural? -10))
-  (prelude-refute
-   (number-natural? -10.0)))
-
-(provide 'number)
-;;; number.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/random.el b/users/wpcarro/emacs/.emacs.d/wpc/random.el
deleted file mode 100644
index dfe10b6d47..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/random.el
+++ /dev/null
@@ -1,80 +0,0 @@
-;;; random.el --- Functions for working with randomness -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24"))
-
-;;; Commentary:
-;; Functions for working with randomness.  Some of this code is not as
-;; functional as I'd like from.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-(require 'number)
-(require 'math)
-(require 'series)
-(require 'list)
-(require 'set)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun random-int (x)
-  "Return a random integer from 0 to `X'."
-  (random x))
-
-;; TODO: Make this work with sequences instead of lists.
-(defun random-choice (xs)
-  "Return a random element of `XS'."
-  (let ((ct (list-length xs)))
-    (list-get
-     (random-int ct)
-     xs)))
-
-(defun random-boolean? ()
-  "Randonly return t or nil."
-  (random-choice (list t nil)))
-
-;; TODO: This may not work if any of these generate numbers like 0, 1, etc.
-(defun random-uuid ()
-  "Return a generated UUID string."
-  (let ((eight  (number-dec (math-triangle-of-power :base 16 :power 8)))
-        (four   (number-dec (math-triangle-of-power :base 16 :power 4)))
-        (twelve (number-dec (math-triangle-of-power :base 16 :power 12))))
-    (format "%x-%x-%x-%x-%x"
-            (random-int eight)
-            (random-int four)
-            (random-int four)
-            (random-int four)
-            (random-int twelve))))
-
-(defun random-token (length)
-  "Return a randomly generated hexadecimal string of LENGTH."
-  (->> (series/range 0 (number-dec length))
-       (list-map (lambda (_) (format "%x" (random-int 15))))
-       (list-join "")))
-
-;; TODO: Support random-sample
-;; (defun random-sample (n xs)
-;;   "Return a randomly sample of list XS of size N."
-;;   (prelude-assert (and (>= n 0) (< n (list-length xs))))
-;;   (cl-labels ((do-sample
-;;                (n xs y ys)
-;;                (if (= n (set-count ys))
-;;                    (->> ys
-;;                         set-to-list
-;;                         (list-map (lambda (i)
-;;                                     (list-get i xs))))
-;;                  (if (set-contains? y ys)
-;;                      (do-sample n xs (random-int (list-length xs)) ys)
-;;                    (do-sample n xs y (set-add y ys))))))
-;;     (do-sample n xs (random-int (list-length xs)) (set-new))))
-
-(provide 'random)
-;;; random.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/scope.el b/users/wpcarro/emacs/.emacs.d/wpc/scope.el
deleted file mode 100644
index 99cdbd2b5e..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/scope.el
+++ /dev/null
@@ -1,106 +0,0 @@
-;;; scope.el --- Work with a scope data structure -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Exposing an API for working with a scope data structure in a non-mutative
-;; way.
-;;
-;; What's a scope?  Think of a scope as a stack of key-value bindings.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'al)
-(require 'stack)
-(require 'struct)
-(require '>)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Create
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(cl-defstruct scope scopes)
-
-(defun scope-new ()
-  "Return an empty scope."
-  (make-scope :scopes (->> (stack-new)
-                           (stack-push (al-new)))))
-
-(defun scope-flatten (xs)
-  "Return a flattened representation of the scope, XS.
-The newest bindings eclipse the oldest."
-  (->> xs
-       scope-scopes
-       stack-to-list
-       (list-reduce (al-new)
-                    (lambda (scope acc)
-                      (al-merge acc scope)))))
-
-(defun scope-push-new (xs)
-  "Push a new, empty scope onto XS."
-  (struct-update scope
-                 scopes
-                 (>-> (stack-push (al-new)))
-                 xs))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Read
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun scope-get (k xs)
-  "Return K from XS if it's in scope."
-  (->> xs
-       scope-flatten
-       (al-get k)))
-
-(defun scope-current (xs)
-  "Return the newest scope from XS."
-  (let ((xs-copy (copy-scope xs)))
-    (->> xs-copy
-         scope-scopes
-         stack-peek)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Update
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun scope-set (k v xs)
-  "Set value, V, at key, K, in XS for the current scope."
-  (struct-update scope
-                 scopes
-                 (>-> (stack-map-top (>-> (al-set k v))))
-                 xs))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Delete
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun scope-pop (xs)
-  "Return a new scope without the top element from XS."
-  (->> xs
-       scope-scopes
-       stack-pop))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Predicates
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun scope-defined? (k xs)
-  "Return t if K is in scope of XS."
-  (->> xs
-       scope-flatten
-       (al-has-key? k)))
-
-;; TODO: Find a faster way to write aliases like this.
-(defun scope-instance? (xs)
-  "Return t if XS is a scope struct."
-  (scope-p xs))
-
-(provide 'scope)
-;;; scope.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/sequence.el b/users/wpcarro/emacs/.emacs.d/wpc/sequence.el
deleted file mode 100644
index 204a72c5b0..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/sequence.el
+++ /dev/null
@@ -1,108 +0,0 @@
-;;; sequence.el --- Working with the "sequence" types -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Elisp supports a typeclass none as "sequence" which covers the following
-;; types:
-;; - list: '(1 2 3 4 5)
-;; - vector: ["John" 27 :blue]
-;; - string: "To be or not to be..."
-
-;; TODO: Document the difference between a "reduce" and a "fold".  I.e. - reduce
-;; has an initial value whereas fold uses the first element in the sequence as
-;; the initial value.
-;;
-;; Note: This should be an approximation of Elixir's Enum protocol albeit
-;; without streams.
-;;
-;; Elisp has done a lot of this work already and these are mostly wrapper
-;; functions.
-;; See the following list for reference:
-;; - sequencep
-;; - elt
-;; - copy-sequence
-;; - reverse
-;; - nreverse
-;; - sort
-;; - seq-elt
-;; - seq-length
-;; - seqp
-;; - seq-drop
-;; - seq-take
-;; - seq-take-while
-;; - seq-drop-while
-;; - seq-do
-;; - seq-map
-;; - seq-mapn
-;; - seq-filter
-;; - seq-remove
-;; - seq-reduce
-;; - seq-some
-;; - seq-find
-;; - seq-every-p
-;; - seq-empty-p
-;; - seq-count
-;; - seq-sort
-;; - seq-contains
-;; - seq-position
-;; - seq-uniq
-;; - seq-subseq
-;; - seq-concatenate
-;; - seq-mapcat
-;; - seq-partition
-;; - seq-intersection
-;; - seq-difference
-;; - seq-group-by
-;; - seq-into
-;; - seq-min
-;; - seq-max
-;; - seq-doseq
-;; - seq-let
-
-;;; Code:
-
-;; Perhaps we can provide default implementations for `filter' and `map' derived
-;; from the `reduce' implementation.
-;; (defprotocol sequence
-;;   :functions (reduce))
-;; (definstance sequence list
-;;   :reduce #'list-reduce
-;;   :filter #'list-filter
-;;   :map    #'list-map)
-;; (definstance sequence vector
-;;   :reduce #'vector/reduce)
-;; (definstance sequence string
-;;   :reduce #'string)
-
-(defun sequence-classify (xs)
-  "Return the type of `XS'."
-  (cond
-   ((listp xs) 'list)
-   ((vectorp xs) 'vector)
-   ((stringp xs) 'string)))
-
-(defun sequence-reduce (acc f xs)
-  "Reduce of `XS' calling `F' on x and `ACC'."
-  (seq-reduce
-   (lambda (acc x)
-     (funcall f x acc))
-   xs
-   acc))
-
-;; Elixir also turned everything into a list for efficiecy reasons.
-
-(defun sequence-filter (p xs)
-  "Filter `XS' with predicate, `P'.
-Returns a list regardless of the type of `XS'."
-  (seq-filter p xs))
-
-(defun sequence-map (f xs)
-  "Maps `XS' calling `F' on each element.
-Returns a list regardless of the type of `XS'."
-  (seq-map f xs))
-
-(provide 'sequence)
-;;; sequence.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/series.el b/users/wpcarro/emacs/.emacs.d/wpc/series.el
deleted file mode 100644
index d890038839..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/series.el
+++ /dev/null
@@ -1,92 +0,0 @@
-;;; series.el --- Hosting common series of numbers -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "24"))
-
-;;; Commentary:
-;; Encoding number series as I learn about them.
-;;
-;; These are the following series I'm interested in supporting:
-;; - Fibonacci
-;; - Catalan numbers
-;; - Figurate number series
-;;   - Triangular
-;;   - Square
-;;   - Pentagonal
-;;   - Hexagonal
-;;   - Lazy-caterer
-;; - Magic square
-;; - Look-and-say
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'number)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun series-range (beg end)
-  "Create a list of numbers from `BEG' to `END'.
-This is an inclusive number range."
-  (if (< end beg)
-      (list-reverse
-       (number-sequence end beg))
-    (number-sequence beg end)))
-
-(defun series-fibonacci-number (i)
-  "Return the number in the fibonacci series at `I'."
-  (cond
-   ((= 0 i) 0)
-   ((= 1 i) 1)
-   (t (+ (series-fibonacci-number (- i 1))
-         (series-fibonacci-number (- i 2))))))
-
-(defun series-fibonacci (n)
-  "Return the first `N' numbers of the fibonaccci series starting at zero."
-  (if (= 0 n)
-      '()
-    (list-reverse
-     (list-cons (series-fibonacci-number (number-dec n))
-                (list-reverse
-                 (series-fibonacci (number-dec n)))))))
-
-;; TODO: Consider memoization.
-(defun series-triangular-number (i)
-  "Return the number in the triangular series at `I'."
-  (if (= 0 i)
-      0
-    (+ i (series-triangular-number (number-dec i)))))
-
-;; TODO: Improve performance.
-;; TODO: Consider creating a stream protocol with `stream/next' and implement
-;; this using that.
-(defun series-triangular (n)
-  "Return the first `N' numbers of a triangular series starting at 0."
-  (if (= 0 n)
-      '()
-    (list-reverse
-     (list-cons (series-triangular-number (number-dec n))
-                (list-reverse
-                 (series-triangular (number-dec n)))))))
-
-(defun series-catalan-number (i)
-  "Return the catalan number in the series at `I'."
-  (if (= 0 i)
-      1
-    (/ (number-factorial (* 2 i))
-       (* (number-factorial (number-inc i))
-          (number-factorial i)))))
-
-(defun series-catalan (n)
-  "Return the first `N' numbers in a catalan series."
-  (->> (series-range 0 (number-dec n))
-       (list-map #'series-catalan-number)))
-
-(provide 'series)
-;;; series.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/stack.el b/users/wpcarro/emacs/.emacs.d/wpc/stack.el
deleted file mode 100644
index e81cec6a45..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/stack.el
+++ /dev/null
@@ -1,101 +0,0 @@
-;;; stack.el --- Working with stacks in Elisp -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; A stack is a LIFO queue.
-;; The design goal here is to expose an intuitive API for working with stacks in
-;; non-mutative way.
-;;
-;; TODO: Consider naming a Functor instance "Mappable."
-;; TODO: Consider naming a Foldable instance "Reduceable."
-;;
-;; TODO: Consider implementing an instance for Mappable.
-;; TODO: Consider implementing an instance for Reduceable.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'list)
-(require '>)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Create
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(cl-defstruct stack xs)
-
-(defun stack-new ()
-  "Create an empty stack."
-  (make-stack :xs '()))
-
-(defun stack-from-list (xs)
-  "Create a new stack from the list, `XS'."
-  (list-reduce (stack-new) #'stack-push xs))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Read
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun stack-peek (xs)
-  "Look at the top element of `XS' without popping it off."
-  (->> xs
-       stack-xs
-       list-first))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Update
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun stack-push (x xs)
-  "Push `X' on `XS'."
-  (struct-update stack
-                 xs
-                 (>-> (list-cons x))
-                 xs))
-
-;; TODO: How to return something like {(list-head xs), (list-tail xs)} in Elixir
-;; TODO: How to handle popping from empty stacks?
-(defun stack-pop (xs)
-  "Return the stack, `XS', without the top element.
-Since I cannot figure out a nice way of return tuples in Elisp, if you want to
-look at the first element, use `stack-peek' before running `stack-pop'."
-  (struct-update stack
-                 xs
-                 (>-> list-tail)
-                 xs))
-
-(defun stack-map-top (f xs)
-  "Apply F to the top element of XS."
-  (->> xs
-       stack-pop
-       (stack-push (funcall f (stack-peek xs)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Miscellaneous
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun stack-to-list (xs)
-  "Return XS as a list.
-The round-trip property of `stack-from-list' and `stack-to-list' should hold."
-  (->> xs
-       stack-xs
-       list-reverse))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Predicates
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; TODO: Create a macro that wraps `cl-defstruct' that automatically creates
-;; things like `new', `instance?'.
-(defun stack-instance? (xs)
-  "Return t if XS is a stack."
-  (stack-p xs))
-
-(provide 'stack)
-;;; stack.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/timestring.el b/users/wpcarro/emacs/.emacs.d/wpc/timestring.el
deleted file mode 100644
index 245ace49e7..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/timestring.el
+++ /dev/null
@@ -1,77 +0,0 @@
-;;; timestring.el --- Quickly access timestamps in different formats -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-
-;; I was making some API calls where a URL needed a `since` parameter that of an
-;; RFC 3339 encoded string.
-;;
-;; Because I didn't know what a RFC 3339 encoded
-;; string was at the time, and because I didn't know what its format was
-;; according to strftime, and because I'm most likely to forget both of these
-;; things by the next time that I need something similar, I decided to write
-;; this package so that I can accumulate a list of common time encodings.
-;;
-;; Thank you, Emacs.
-;;
-;; p.s. - I may turn this into a proper module and publish it.  But not today.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'ts)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defgroup timestring nil
-  "Customize group for timestring configuration.")
-
-(defcustom timestring-supported-encodings
-  '(("RFC 3339" . "%Y-%m-%dT%H:%M:%SZ")
-    ;; Does anyone recognize this format?
-    ("IDK" . "%Y-%m-%d %H:%M:%S %z"))
-  "Mapping of encoding names to their format strings."
-  :group 'timestring)
-
-(defcustom timestring-supported-times
-  '(("yesterday" . timestring--yesterday)
-    ("now" . ts-now)
-    ("tomorrow" . timestring--tomorrow))
-  "Mapping of a labels to the functions that create those time objects."
-  :group 'timestring)
-
-(defun timestring--yesterday ()
-  "Return a time object for yesterday."
-  (ts-adjust 'day -1 (ts-now)))
-
-(defun timestring--tomorrow ()
-  "Return a time object for yesterday."
-  (ts-adjust 'day +1 (ts-now)))
-
-(defun timestring--completing-read (label xs)
-  "Call `completing-read' with LABEL over the collection XS."
-  (alist-get (completing-read label xs) xs nil nil #'equal))
-
-(defun timestring-copy-encoded-time ()
-  "Select a common time and an encoding.
-
-The selected time will be encoded using the selected encoding and copied onto
-your clipboard."
-  (interactive)
-  (let ((time (funcall (timestring--completing-read
-                        "Time: " timestring-supported-times)))
-        (fmt (timestring--completing-read
-              "Encoding: " timestring-supported-encodings)))
-    (kill-new (ts-format fmt time))
-    (message "Copied!")))
-
-(provide 'timestring)
-;;; timestring.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/tree.el b/users/wpcarro/emacs/.emacs.d/wpc/tree.el
deleted file mode 100644
index 332e6c8d25..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/tree.el
+++ /dev/null
@@ -1,199 +0,0 @@
-;;; tree.el --- Working with Trees -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Some friendly functions that hopefully will make working with trees cheaper
-;; and therefore more appealing!
-;;
-;; Tree terminology:
-;; - leaf: node with zero children.
-;; - root: node with zero parents.
-;; - depth: measures a node's distance from the root node.  This implies the
-;;   root node has a depth of zero.
-;; - height: measures the longest traversal from a node to a leaf.  This implies
-;;   that a leaf node has a height of zero.
-;; - balanced?
-;;
-;; Tree variants:
-;; - binary: the maximum number of children is two.
-;; - binary search: the maximum number of children is two and left sub-trees are
-;;   lower in value than right sub-trees.
-;; - rose: the number of children is variable.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-(require 'list)
-(require 'set)
-(require 'tuple)
-(require 'series)
-(require 'random)
-(require 'maybe)
-(require 'cl-lib)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(cl-defstruct tree xs)
-
-(cl-defstruct node value children)
-
-(cl-defun tree-node (value &optional children)
-  "Create a node struct of VALUE with CHILDREN."
-  (make-node :value value
-             :children children))
-
-(defun tree-reduce-breadth (acc f xs)
-  "Reduce over XS breadth-first applying F to each x and ACC (in that order).
-Breadth-first traversals guarantee to find the shortest path in a graph.
-  They're typically more difficult to implement than DFTs and may also incur
-  higher memory costs on average than their depth-first counterparts.")
-
-;; TODO: Support :order as 'pre | 'in | 'post.
-;; TODO: Troubleshoot why I need defensive (nil? node) check.
-(defun tree-reduce-depth (acc f node)
-  "Reduce over NODE depth-first applying F to each NODE and ACC.
-F is called with each NODE, ACC, and the current depth.
-Depth-first traversals have the advantage of typically consuming less memory
-  than their breadth-first equivalents would have.  They're also typically
-  easier to implement using recursion.  This comes at the cost of not
-  guaranteeing to be able to find the shortest path in a graph."
-  (cl-labels ((do-reduce-depth
-               (acc f node depth)
-               (let ((acc-new (funcall f node acc depth)))
-                 (if (or (maybe-nil? node)
-                         (tree-leaf? node))
-                     acc-new
-                   (list-reduce
-                    acc-new
-                    (lambda (node acc)
-                      (tree-do-reduce-depth
-                       acc
-                       f
-                       node
-                       (number-inc depth)))
-                    (node-children node))))))
-    (do-reduce-depth acc f node 0)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Helpers
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun tree-height (xs)
-  "Return the height of tree XS.")
-
-;; TODO: Troubleshoot why need for (nil? node).  Similar misgiving
-;; above.
-(defun tree-leaf-depths (xs)
-  "Return a list of all of the depths of the leaf nodes in XS."
-  (list-reverse
-   (tree-reduce-depth
-    '()
-    (lambda (node acc depth)
-      (if (or (maybe-nil? node)
-              (tree-leaf? node))
-          (list-cons depth acc)
-        acc))
-    xs)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Generators
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; TODO: Consider parameterizing height, forced min-max branching, random
-;; distributions, etc.
-
-;; TODO: Bail out before stack overflowing by consider branching, current-depth.
-
-(cl-defun tree-random (&optional (value-fn (lambda (_) nil))
-                                 (branching-factor 2))
-  "Randomly generate a tree with BRANCHING-FACTOR.
-
-This uses VALUE-FN to compute the node values.  VALUE-FN is called with the
-current-depth of the node.  Useful for generating test data.  Warning this
-function can overflow the stack."
-  (cl-labels ((do-random
-               (d vf bf)
-               (make-node
-                :value (funcall vf d)
-                :children (->> (series/range 0 (number-dec bf))
-                               (list-map
-                                (lambda (_)
-                                  (when (random-boolean?)
-                                    (do-random d vf bf))))))))
-    (do-random 0 value-fn branching-factor)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Predicates
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun tree-instance? (tree)
-  "Return t if TREE is a tree struct."
-  (node-p tree))
-
-(defun tree-leaf? (node)
-  "Return t if NODE has no children."
-  (maybe-nil? (node-children node)))
-
-(defun tree-balanced? (n xs)
-  "Return t if the tree, XS, is balanced.
-A tree is balanced if none of the differences between any two depths of two leaf
-  nodes in XS is greater than N."
-  (> n (->> xs
-            tree-leaf-depths
-            set-from-list
-            set-count
-            number-dec)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tests
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defconst tree-enable-testing? t
-  "When t, test suite runs.")
-
-;; TODO: Create set of macros for a proper test suite including:
-;; - describe (arbitrarily nestable)
-;; - it (arbitrarily nestable)
-;; - line numbers for errors
-;; - accumulated output for synopsis
-;; - do we want describe *and* it? Why not a generic label that works for both?
-(when tree-enable-testing?
-  (let ((tree-a (tree-node 1
-                           (list (tree-node 2
-                                            (list (tree-node 5)
-                                                  (tree-node 6)))
-                                 (tree-node 3
-                                            (list (tree-node 7)
-                                                  (tree-node 8)))
-                                 (tree-node 4
-                                            (list (tree-node 9)
-                                                  (tree-node 10))))))
-        (tree-b (tree-node 1
-                           (list (tree-node 2
-                                            (list (tree-node 5)
-                                                  (tree-node 6)))
-                                 (tree-node 3)
-                                 (tree-node 4
-                                            (list (tree-node 9)
-                                                  (tree-node 10)))))))
-    ;; instance?
-    (prelude-assert (tree-instance? tree-a))
-    (prelude-assert (tree-instance? tree-b))
-    (prelude-refute (tree-instance? '(1 2 3)))
-    (prelude-refute (tree-instance? "oak"))
-    ;; balanced?
-    (prelude-assert (tree-balanced? 1 tree-a))
-    (prelude-refute (tree-balanced? 1 tree-b))
-    (message "Tests pass!")))
-
-(provide 'tree)
-;;; tree.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/window.el b/users/wpcarro/emacs/.emacs.d/wpc/window.el
deleted file mode 100644
index aec3c7012f..0000000000
--- a/users/wpcarro/emacs/.emacs.d/wpc/window.el
+++ /dev/null
@@ -1,40 +0,0 @@
-;;; window.el --- Working with windows -*- lexical-binding: t -*-
-
-;; Author: William Carroll <wpcarro@gmail.com>
-;; Version: 0.0.1
-;; Package-Requires: ((emacs "25.1"))
-
-;;; Commentary:
-;; Utilities to make CRUDing windows in Emacs easier.
-
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'prelude)
-(require 'macros)
-(require 'maybe)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Library
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun window-find (name)
-  "Find a window by the NAME of the buffer it's hosting."
-  (let ((buffer (get-buffer name)))
-    (if (maybe-some? buffer)
-        (get-buffer-window buffer)
-      nil)))
-
-;; TODO: Find a way to incorporate these into function documentation.
-(macros-comment
- (window-find "*scratch*"))
-
-(defun window-delete (window)
-  "Delete the WINDOW reference."
-  (delete-window window))
-
-(provide 'window)
-;;; window.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el
new file mode 100644
index 0000000000..03fc430e48
--- /dev/null
+++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-dotnet.el
@@ -0,0 +1,16 @@
+;;; wpc-dotnet.el --- C# and company -*- lexical-binding: t -*-
+
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Windows things v0v.
+
+;;; Code:
+
+(require 'macros)
+
+(use-package csharp-mode)
+(macros-support-file-extension "csproj" xml-mode)
+
+(provide 'wpc-dotnet)
+;;; wpc-dotnet.el ends here
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el
index 7c1816c561..9e137ad880 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-javascript.el
@@ -42,11 +42,6 @@
       js-indent-level 2
       css-indent-offset 2)
 
-;; Flow for Javascript
-(use-package add-node-modules-path
-  :config
-  (general-add-hook wpc-javascript--js-hooks #'add-node-modules-path))
-
 (use-package web-mode
   :mode "\\.html\\'"
   :config
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el
index 1fe3509559..8363e3c08e 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-language-support.el
@@ -24,12 +24,12 @@
 (require 'wpc-rust)
 (require 'wpc-clojure)
 (require 'wpc-prolog)
+(require 'wpc-dotnet)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Miscellaneous Configuration
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(use-package csharp-mode)
 (use-package terraform-mode)
 
 (provide 'wpc-language-support)
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el
index cac16d26bd..36fbf8b12c 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-misc.el
@@ -68,9 +68,6 @@
 (setq sh-basic-offset 2)
 (setq sh-indentation 2)
 
-;; Emacs library that interfaces with my Linux password manager.
-(use-package password-store)
-
 (use-package vterm
   :config
   (general-define-key
@@ -180,12 +177,6 @@
 ;; configure ibuffer
 (setq ibuffer-default-sorting-mode 'major-mode)
 
-;; config Emacs to use $PATH values
-(use-package exec-path-from-shell
-  :if (memq window-system '(mac ns))
-  :config
-  (exec-path-from-shell-initialize))
-
 ;; Emacs autosave, backup, interlocking files
 (setq auto-save-default nil
       make-backup-files nil
@@ -326,11 +317,7 @@
   ;; Disable the default styles of:
   ;; - ascii  :P (When this is enabled, the vim command, :x, renders as 😶)
   ;; - github :smile:
-  (setq emojify-emoji-styles '(unicode))
-  (defun wpc-misc-copy-emoji ()
-    "Select an emoji from the completing-read menu."
-    (interactive)
-    (clipboard-copy (emojify-completing-read "Copy: "))))
+  (setq emojify-emoji-styles '(unicode)))
 
 ;; Always auto-close parantheses and other pairs
 (electric-pair-mode)
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el b/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el
index b39a82ad9f..a2f533cec0 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el
+++ b/users/wpcarro/emacs/.emacs.d/wpc/wpc-ui.el
@@ -13,15 +13,15 @@
 ;; Dependencies
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(require 'constants)
-(require 'prelude)
+(require '>)
 (require 'al)
+(require 'constants)
+(require 'dash)
 (require 'fonts)
-(require 'colorscheme)
-(require 'device)
-(require 'laptop-battery)
-(require 'modeline)
 (require 'general)
+(require 'modeline)
+(require 'prelude)
+(require 'theme)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Configuration
@@ -109,13 +109,12 @@
   (unless constants-ci?
     (prescient-persist-mode 1)))
 
-(use-package ivy-pass)
-
 ;; all-the-icons
 (use-package all-the-icons
   :config
   (unless (or constants-ci?
-              (f-exists? "~/.local/share/fonts/all-the-icons.ttf"))
+              (f-exists? "~/.local/share/fonts/all-the-icons.ttf")
+              (f-exists? "~/Library/Fonts/all-the-icons.ttf"))
     (all-the-icons-install-fonts t)))
 
 ;; icons for Ivy
@@ -137,8 +136,8 @@
   ;; example, Google Java projects prefer 100 character width instead of 80
   ;; character width.
   (setq whitespace-line-column 80)
-  (setq whitespace-style '(face lines-tail))
-  (add-hook 'prog-mode-hook #'whitespace-mode))
+  (setq whitespace-style '(face lines-tail tabs))
+  (global-whitespace-mode t))
 
 ;; dirname/filename instead of filename<dirname>
 (setq uniquify-buffer-name-style 'forward)
@@ -157,15 +156,24 @@
   :config
   (setq alert-default-style 'notifier))
 
-;; TODO: Should `device-laptop?' be a function or a constant that gets set
-;; during initialization?
-(when (device-laptop?) (laptop-battery-display))
+(display-battery-mode 1)
 
-(colorscheme-whitelist-set 'doom-peacock)
+(setq theme-whitelist
+      (->> (custom-available-themes)
+           (list-map #'symbol-name)
+           (list-filter (>-> (s-starts-with? "doom-")))
+           (list-map #'intern)
+           cycle-from-list))
+(setq theme-linum-color-override "da5478")
+(add-hook 'theme-after-change
+          (lambda () (prelude-set-line-number-color "#da5478")))
+(theme-whitelist-set 'doom-flatwhite)
 
 (when window-system
-  (let ((font "Monospace"))
-    (fonts-whitelist-set font)
+  ;; On OSX, JetBrainsMono is installed as "JetBrains Mono", and I'm
+  ;; not sure how to change that.
+  (let ((font (if constants-osx? "JetBrains Mono" "JetBrainsMono")))
+    (fonts-set font)
     ;; Some themes (e.g. doom-acario-*) change the font for comments. This
     ;; should prevent that.
     (set-face-attribute font-lock-comment-face nil
diff --git a/users/wpcarro/emacs/AppIcon.icns b/users/wpcarro/emacs/AppIcon.icns
new file mode 100644
index 0000000000..b3be251ccf
--- /dev/null
+++ b/users/wpcarro/emacs/AppIcon.icns
Binary files differdiff --git a/users/wpcarro/emacs/default.nix b/users/wpcarro/emacs/default.nix
index 3ca65c292e..0b3c5a6e73 100644
--- a/users/wpcarro/emacs/default.nix
+++ b/users/wpcarro/emacs/default.nix
@@ -1,3 +1,9 @@
+# My Emacs distribution, which is supporting the following platforms:
+# - Linux
+# - Darwin
+#
+# USAGE:
+#   $ nix-build -A users.wpcarro.emacs.osx -o /Applications/BillsEmacs.app
 { depot, pkgs, lib, ... }:
 
 # TODO(wpcarro): See if it's possible to expose emacsclient on PATH, so that I
@@ -22,13 +28,14 @@ let
     (with pkgs; [
       ispell
       nix
-      pass
       rust-analyzer
       rustc
       rustfmt
-      scrot
       xorg.xset
-    ])
+    ] ++
+    (if pkgs.stdenv.isLinux then [
+      scrot
+    ] else [ ]))
   );
 
   emacsWithPackages = (emacsPackagesFor emacs28).emacsWithPackages;
@@ -36,13 +43,18 @@ let
   wpcarrosEmacs = emacsWithPackages (epkgs:
     (with wpcarro.emacs.pkgs; [
       al
+      bookmark
       cycle
       list
+      macros
       maybe
+      passage
       set
       string
       struct
       symbol
+      theme
+      tuple
       vterm-mgt
       zle
     ]) ++
@@ -56,94 +68,88 @@ let
     ]) ++
 
     (with epkgs.melpaPackages; [
+      alert
+      all-the-icons
+      all-the-icons-ivy
       avy
-      org-bullets
-      sly
-      notmuch
-      elm-mode
-      ts
-      vterm
       base16-theme
-      password-store
+      cider
+      clojure-mode
+      company
+      counsel
+      counsel-projectile
       csharp-mode
+      dap-mode
+      dash
+      deadgrep
+      deferred
+      diminish
+      direnv
       dockerfile-mode
+      # TODO(wpcarro): broken since channel bump cl/10204
+      # doom-themes
+      elisp-slime-nav
+      elixir-mode
+      elm-mode
+      emojify
+      engine-mode
       evil
       evil-collection
       evil-commentary
       evil-surround
-      key-chord
-      # TODO(wpcarro): Assess whether or not I need this with Nix.
-      add-node-modules-path
-      web-mode
-      rjsx-mode
-      tide
-      prettier-js
+      f
+      fish-mode
       flycheck
-      diminish
-      doom-themes
-      telephone-line
-      which-key
-      all-the-icons
-      all-the-icons-ivy
+      flymake-shellcheck
+      general
+      go-mode
+      haskell-mode
+      helpful
       ivy
       ivy-clipmenu
-      ivy-pass
       ivy-prescient
-      restclient
-      package-lint
-      parsec
+      key-chord
+      lispyville
+      lsp-ui
+      magit
       magit-popup
-      direnv
-      alert
+      markdown-mode
       nix-mode
-      rust-mode
-      rainbow-delimiters
-      racket-mode
-      lispyville
-      elisp-slime-nav
+      notmuch
+      org-bullets
+      package-lint
+      paradox
+      parsec
+      pcre2el
+      prettier-js
+      projectile
       py-yapf
+      racket-mode
+      rainbow-delimiters
       reason-mode
-      terraform-mode
-      elixir-mode
-      go-mode
-      company
-      markdown-mode
       refine
-      deferred
-      magit
       request
-      pcre2el
-      helpful
-      # TODO(wpcarro): Determine if Nix solves this problem.
-      exec-path-from-shell
-      yasnippet
-      projectile
-      deadgrep
-      counsel
-      counsel-projectile
-      # TODO(wpcarro): Learn what this is.
-      engine-mode
-      eglot
-      dap-mode
-      lsp-ui
+      restclient
+      rjsx-mode
+      rust-mode
+      sly
       suggest
-      paradox
-      flymake-shellcheck
-      fish-mode
+      telephone-line
+      terraform-mode
+      tide
+      ts
       tuareg
-      haskell-mode
       use-package
-      general
-      clojure-mode
-      cider
-      f
-      dash
-      company
-      counsel
-      flycheck
-      emojify
+      vterm
+      web-mode
+      which-key
       yaml-mode
-    ]));
+      yasnippet
+    ]) ++
+
+    [
+      epkgs.eglot # from elpa devel
+    ]);
 
   loadPath = concatStringsSep ":" [
     ./.emacs.d/wpc
@@ -170,15 +176,76 @@ let
         ${concatStringsSep "\n  " (map (el: "--load ${el} \\") load)}
         "$@"
     '';
+
+  # I can't figure out how to augment LSEnvironment.PATH such that it inherits
+  # the default $PATH and adds the things that I need as well, so let's
+  # hardcode the desired outcome in the meantime.
+  osxDefaultPath = builtins.concatStringsSep ":" [
+    "/Users/bill/.nix-profile/bin"
+    "/nix/var/nix/profiles/default/bin"
+    "/opt/homebrew/bin"
+    "/opt/homebrew/sbin"
+    "/usr/local/bin"
+    "/usr/bin"
+    "/bin"
+    "/usr/sbin"
+    "/sbin"
+    "/opt/X11/bin"
+  ];
+
+  infoPlist = pkgs.writeText "Info.plist" (pkgs.lib.generators.toPlist { } {
+    LSEnvironment = {
+      PATH = "${emacsBinPath}:${osxDefaultPath}";
+    };
+    CFBundleExecutable = "BillsEmacs";
+    CFBundleDisplayName = "BillsEmacs";
+    CFBundleIconFile = "AppIcon";
+    CFBundleIconName = "AppIcon";
+  });
+
+  versionPlist = pkgs.writeText "version.plist" (pkgs.lib.generators.toPlist { } {
+    ProjectName = "OSXPlatformSupport";
+  });
 in
 {
-  inherit withEmacsPath;
-
+  # TODO(wpcarro): Support this with base.overrideAttrs or something similar.
   nixos = { load ? [ ] }: withEmacsPath {
     inherit load;
     emacsBin = "${wpcarrosEmacs}/bin/emacs";
   };
 
+  # To install GUI:
+  # $ nix-build -A users.wpcarro.emacs.osx -o /Applications/BillsEmacs.app
+  osx = pkgs.stdenv.mkDerivation {
+    pname = "bills-emacs";
+    version = "0.0.1";
+    src = ./.;
+    dontFixup = true;
+    installPhase = ''
+      runHook preInstall
+      APP="$out"
+      mkdir -p "$APP/Contents/MacOS"
+      mkdir -p "$APP/Contents/Resources"
+      cp ${infoPlist}      "$APP/Contents/Info.plist"
+      cp ${versionPlist}   "$APP/Contents/version.plist"
+      cp ${./AppIcon.icns} "$APP/Contents/Resources/AppIcon.icns"
+      echo "APPL????"  > "$APP/Contents/PkgInfo"
+      cat << EOF > "$APP/Contents/MacOS/BillsEmacs"
+      #!${pkgs.stdenvNoCC.shell}
+      export EMACSLOADPATH="${loadPath}"
+      exec ${wpcarrosEmacs}/bin/emacs \
+        --debug-init \
+        --no-init-file \
+        --no-site-file \
+        --no-site-lisp \
+        --load ${./.emacs.d/init.el}
+      EOF
+      chmod +x "$APP/Contents/MacOS/BillsEmacs"
+      runHook postInstall
+    '';
+    meta.platforms = [ "aarch64-darwin" ];
+  };
+
   # Script that asserts my Emacs can initialize without warnings or errors.
   check = runCommand "check-emacs" { } ''
     # Even though Buildkite defines this, I'd still like still be able to test
@@ -195,5 +262,6 @@ in
     touch $out
   '';
 
-  meta.ci.targets = [ "check" ];
+  # TODO(wpcarro): commented out because of doom-themes breakage; cl/10204
+  # meta.ci.targets = [ "check" ];
 }
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/bookmark.el b/users/wpcarro/emacs/pkgs/bookmark/bookmark.el
index ab9169a078..ab9169a078 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/bookmark.el
+++ b/users/wpcarro/emacs/pkgs/bookmark/bookmark.el
diff --git a/users/wpcarro/emacs/pkgs/bookmark/default.nix b/users/wpcarro/emacs/pkgs/bookmark/default.nix
new file mode 100644
index 0000000000..882481701f
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/bookmark/default.nix
@@ -0,0 +1,13 @@
+{ pkgs, depot, ... }:
+
+pkgs.callPackage
+  ({ emacsPackages }:
+  emacsPackages.trivialBuild {
+    pname = "bookmark";
+    version = "1.0.0";
+    src = ./bookmark.el;
+    packageRequires = (with pkgs.emacsPackages; [
+      general
+    ]);
+  })
+{ }
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/bytes.el b/users/wpcarro/emacs/pkgs/bytes/bytes.el
index b76921d3c7..b0d64795a0 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/bytes.el
+++ b/users/wpcarro/emacs/pkgs/bytes/bytes.el
@@ -34,31 +34,32 @@
 ;;  overflow.  I imagine a larger integer type may exist, but for now, I'll
 ;;  treat this as a YAGNI.
 
-(require 'prelude)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dependencies
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 (require 'tuple)
-(require 'math)
-(require 'number)
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Constants
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defconst bytes-kb (math-exp 2 10)
+(defconst bytes-kb (expt 2 10)
   "Number of bytes in a kilobyte.")
 
-(defconst bytes-mb (math-exp 2 20)
+(defconst bytes-mb (expt 2 20)
   "Number of bytes in a megabytes.")
 
-(defconst bytes-gb (math-exp 2 30)
+(defconst bytes-gb (expt 2 30)
   "Number of bytes in a gigabyte.")
 
-(defconst bytes-tb (math-exp 2 40)
+(defconst bytes-tb (expt 2 40)
   "Number of bytes in a terabyte.")
 
-(defconst bytes-pb (math-exp 2 50)
+(defconst bytes-pb (expt 2 50)
   "Number of bytes in a petabyte.")
 
-(defconst bytes-eb (math-exp 2 60)
+(defconst bytes-eb (expt 2 60)
   "Number of bytes in an exabyte.")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -67,7 +68,6 @@
 
 (defun bytes-classify (x)
   "Return unit that closest fits byte count, X."
-  (prelude-assert (number-whole? x))
   (cond
    ((and (>= x 0)        (< x bytes-kb))     'byte)
    ((and (>= x bytes-kb) (< x bytes-mb)) 'kilobyte)
@@ -80,33 +80,15 @@
   "Convert integer X into a human-readable string."
   (let ((base-and-unit
          (pcase (bytes-classify x)
-           ('byte     (tuple/from        1 "B"))
-           ('kilobyte (tuple/from bytes-kb "KB"))
-           ('megabyte (tuple/from bytes-mb "MB"))
-           ('gigabyte (tuple/from bytes-gb "GB"))
-           ('terabyte (tuple/from bytes-tb "TB"))
-           ('petabyte (tuple/from bytes-pb "PB")))))
-    (string-format "%d%s"
-                   (round x (tuple/first base-and-unit))
-                   (tuple/second base-and-unit))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Tests
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(progn
-  (prelude-assert
-   (equal "1000B" (bytes-to-string 1000)))
-  (prelude-assert
-   (equal "2KB" (bytes-to-string (* 2 bytes-kb))))
-  (prelude-assert
-   (equal "17MB" (bytes-to-string (* 17 bytes-mb))))
-  (prelude-assert
-   (equal "419GB" (bytes-to-string (* 419 bytes-gb))))
-  (prelude-assert
-   (equal "999TB" (bytes-to-string (* 999 bytes-tb))))
-  (prelude-assert
-   (equal "2PB" (bytes-to-string (* 2 bytes-pb)))))
+           ('byte     (tuple-from        1 "B"))
+           ('kilobyte (tuple-from bytes-kb "KB"))
+           ('megabyte (tuple-from bytes-mb "MB"))
+           ('gigabyte (tuple-from bytes-gb "GB"))
+           ('terabyte (tuple-from bytes-tb "TB"))
+           ('petabyte (tuple-from bytes-pb "PB")))))
+    (format "%d%s"
+            (round x (tuple-first base-and-unit))
+            (tuple-second base-and-unit))))
 
 (provide 'bytes)
 ;;; bytes.el ends here
diff --git a/users/wpcarro/emacs/pkgs/bytes/default.nix b/users/wpcarro/emacs/pkgs/bytes/default.nix
new file mode 100644
index 0000000000..4e9f52d9b9
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/bytes/default.nix
@@ -0,0 +1,25 @@
+{ pkgs, depot, ... }:
+
+let
+  bytes = pkgs.callPackage
+    ({ emacsPackages }:
+      emacsPackages.trivialBuild {
+        pname = "bytes";
+        version = "1.0.0";
+        src = ./bytes.el;
+        packageRequires =
+          (with depot.users.wpcarro.emacs.pkgs; [
+            tuple
+          ]);
+      })
+    { };
+
+  emacs = (pkgs.emacsPackagesFor pkgs.emacs28).emacsWithPackages (epkgs: [ bytes ]);
+in
+bytes.overrideAttrs (_old: {
+  doCheck = true;
+  checkPhase = ''
+    ${emacs}/bin/emacs -batch \
+      -l ert -l ${./tests.el} -f ert-run-tests-batch-and-exit
+  '';
+})
diff --git a/users/wpcarro/emacs/pkgs/bytes/tests.el b/users/wpcarro/emacs/pkgs/bytes/tests.el
new file mode 100644
index 0000000000..9b71a466c7
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/bytes/tests.el
@@ -0,0 +1,18 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dependencies
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'ert)
+(require 'bytes)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Tests
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(ert-deftest bytes-to-string ()
+  (should (equal "1000B" (bytes-to-string 1000)))
+  (should (equal "2KB" (bytes-to-string (* 2 bytes-kb))))
+  (should (equal "17MB" (bytes-to-string (* 17 bytes-mb))))
+  (should (equal "419GB" (bytes-to-string (* 419 bytes-gb))))
+  (should (equal "999TB" (bytes-to-string (* 999 bytes-tb))))
+  (should (equal "2PB" (bytes-to-string (* 2 bytes-pb)))))
diff --git a/users/wpcarro/emacs/pkgs/macros/default.nix b/users/wpcarro/emacs/pkgs/macros/default.nix
new file mode 100644
index 0000000000..d2811ed39f
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/macros/default.nix
@@ -0,0 +1,10 @@
+{ pkgs, depot, ... }:
+
+pkgs.callPackage
+  ({ emacsPackages }:
+  emacsPackages.trivialBuild {
+    pname = "macros";
+    version = "1.0.0";
+    src = ./macros.el;
+  })
+{ }
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/macros.el b/users/wpcarro/emacs/pkgs/macros/macros.el
index 32c9b59dcd..3642686eeb 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/macros.el
+++ b/users/wpcarro/emacs/pkgs/macros/macros.el
@@ -7,20 +7,9 @@
 ;;; Commentary:
 ;; This file contains helpful variables that I use in my ELisp development.
 
-;; TODO: Consider a macro solution for mimmicking OCaml's auto resolution of
-;; dependencies using `load-path' and friends.
-
 ;;; Code:
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Dependencies
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'f)
-(require 'string)
-(require 'symbol)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Library
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -42,13 +31,6 @@ Usage: (macros-add-hook-before-save 'reason-mode-hook #'refmt-before-save)"
              (lambda ()
                (add-hook 'before-save-hook ,f))))
 
-;; TODO: Privatize?
-(defun macros--namespace ()
-  "Return the namespace for a function based on the filename."
-  (->> (buffer-file-name)
-       f-filename
-       f-base))
-
 (defmacro macros-comment (&rest _)
   "Empty comment s-expresion where `BODY' is ignored."
   `nil)
@@ -56,7 +38,7 @@ Usage: (macros-add-hook-before-save 'reason-mode-hook #'refmt-before-save)"
 (defmacro macros-support-file-extension (ext mode)
   "Register MODE to automatically load with files ending with EXT extension.
 Usage: (macros-support-file-extension \"pb\" protobuf-mode)"
-  (let ((extension (string-format "\\.%s\\'" ext)))
+  (let ((extension (format "\\.%s\\'" ext)))
     `(add-to-list 'auto-mode-alist '(,extension . ,mode))))
 
 (provide 'macros)
diff --git a/users/wpcarro/emacs/pkgs/passage/README.md b/users/wpcarro/emacs/pkgs/passage/README.md
new file mode 100644
index 0000000000..51f7bd6efd
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/passage/README.md
@@ -0,0 +1,12 @@
+# passage.el
+
+Emacs support for `passage`.
+
+## Alternative Packages
+
+If you're looking for more feature-complete, configurable alternatives,
+check-out the following packages:
+
+- `ivy-pass.el`
+- `password-store.el`
+- `pass.el`
diff --git a/users/wpcarro/emacs/pkgs/passage/default.nix b/users/wpcarro/emacs/pkgs/passage/default.nix
new file mode 100644
index 0000000000..ac87f193b4
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/passage/default.nix
@@ -0,0 +1,12 @@
+{ pkgs, depot, ... }:
+
+pkgs.callPackage
+  ({ emacsPackages }:
+  emacsPackages.trivialBuild {
+    pname = "passage";
+    version = "1.0.0";
+    src = ./passage.el;
+    packageRequires = (with emacsPackages; [ dash f s ]);
+  }
+  )
+{ }
diff --git a/users/wpcarro/emacs/pkgs/passage/passage.el b/users/wpcarro/emacs/pkgs/passage/passage.el
new file mode 100644
index 0000000000..4a43920e0b
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/passage/passage.el
@@ -0,0 +1,65 @@
+;;; passage.el --- Emacs passage support -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022-2023 William Carroll <wpcarro@gmail.com>
+
+;; Author: William Carroll <wpcarro@gmail.com>
+;; Version: 1.0.0
+
+;; This file is not part of GNU Emacs.
+
+;; 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
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides functions for working with passage.
+
+;;; Code:
+
+(require 'dash)
+(require 'f)
+(require 's)
+
+(defgroup passage nil
+  "Customization options for `passage'."
+  :prefix "passage-"
+  :group 'vterm)
+
+(defcustom passage-store
+  "~/.passage/store"
+  "Path to the passage store directory."
+  :type 'string
+  :group 'passage)
+
+(defcustom passage-executable
+  (or (executable-find "passage")
+      "/nix/store/jgffkfdiiwiqa4zqpxn3691mx9xc6axa-passage-unstable-2022-05-01/bin/passage")
+  "Path to passage executable."
+  :type 'string
+  :group 'passage)
+
+(defun passage-select ()
+  "Select an entry and copy its password to the kill ring."
+  (interactive)
+  (let ((key (completing-read "Copy password of entry: "
+                              (-map (lambda (x)
+                                      (f-no-ext (f-relative x passage-store)))
+                                    (f-files passage-store nil t)))))
+    (kill-new
+     (s-trim-right
+      (shell-command-to-string
+       (format "%s show %s | head -1" passage-executable key))))
+    (message "[passage.el] Copied \"%s\"!" key)))
+
+(provide 'passage)
+;;; passage.el ends here
diff --git a/users/wpcarro/emacs/pkgs/theme/default.nix b/users/wpcarro/emacs/pkgs/theme/default.nix
new file mode 100644
index 0000000000..aea6394369
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/theme/default.nix
@@ -0,0 +1,14 @@
+{ pkgs, depot, ... }:
+
+pkgs.callPackage
+  ({ emacsPackages }:
+  emacsPackages.trivialBuild {
+    pname = "theme";
+    version = "1.0.0";
+    src = ./theme.el;
+    packageRequires =
+      (with depot.users.wpcarro.emacs.pkgs; [
+        cycle
+      ]);
+  })
+{ }
diff --git a/users/wpcarro/emacs/pkgs/theme/theme.el b/users/wpcarro/emacs/pkgs/theme/theme.el
new file mode 100644
index 0000000000..32f2c89a4d
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/theme/theme.el
@@ -0,0 +1,78 @@
+;;; theme.el --- Colors and stuff -*- lexical-binding: t -*-
+
+;; Author: William Carroll <wpcarro@gmail.com>
+;; Version: 0.0.1
+;; Package-Requires: ((emacs "24.3"))
+
+;;; Commentary:
+;;
+;; Cycle through a whitelist of themes.
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dependencies
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'cycle)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Library
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defgroup theme nil
+  "Customization options for `theme'."
+  :group 'theme)
+
+(defcustom theme-whitelist
+  (cycle-from-list (custom-available-themes))
+  "The whitelist of themes through which to cycle."
+  :type '(cycle symbol)
+  :group 'theme)
+
+(defcustom theme-after-change
+  nil
+  "Hook invoked after a new theme is loaded"
+  :type 'hook
+  :group 'theme)
+
+(defun theme-whitelist-set (theme)
+  "Focus the THEME in the `theme-whitelist' cycle."
+  (cycle-focus! (lambda (x) (equal x theme)) theme-whitelist)
+  (theme--set (cycle-current theme-whitelist)))
+
+(defun theme-select ()
+  "Load a theme using `completing-read'."
+  (interactive)
+  (let ((theme (completing-read "Theme: " (cycle-to-list theme-whitelist))))
+    (theme--disable-all)
+    (theme--set (intern theme))))
+
+(defun theme-next ()
+  "Disable the currently active theme and load the next theme."
+  (interactive)
+  (disable-theme (cycle-current theme-whitelist))
+  (theme--set (cycle-next! theme-whitelist))
+  (message (format "Active theme: %s" (cycle-current theme-whitelist))))
+
+(defun theme-prev ()
+  "Disable the currently active theme and load the previous theme."
+  (interactive)
+  (disable-theme (cycle-current theme-whitelist))
+  (theme--set (cycle-prev! theme-whitelist))
+  (message (format "Active theme: %s" (cycle-current theme-whitelist))))
+
+(defun theme--disable-all ()
+  "Disable all currently enabled themes."
+  (interactive)
+  (dolist (x custom-enabled-themes)
+    (disable-theme x)))
+
+(defun theme--set (theme)
+    "Call `load-theme' with `THEME', ensuring that the line numbers are bright.
+There is no hook that I'm aware of to handle this more elegantly."
+    (load-theme theme t)
+    (run-hooks 'theme-after-change))
+
+(provide 'theme)
+;;; theme.el ends here
diff --git a/users/wpcarro/emacs/pkgs/tuple/default.nix b/users/wpcarro/emacs/pkgs/tuple/default.nix
new file mode 100644
index 0000000000..0626370e47
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/tuple/default.nix
@@ -0,0 +1,10 @@
+{ pkgs, depot, ... }:
+
+pkgs.callPackage
+  ({ emacsPackages }:
+  emacsPackages.trivialBuild {
+    pname = "tuple";
+    version = "1.0.0";
+    src = ./tuple.el;
+  })
+{ }
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/tuple.el b/users/wpcarro/emacs/pkgs/tuple/tuple.el
index 848c6fa48b..848c6fa48b 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/tuple.el
+++ b/users/wpcarro/emacs/pkgs/tuple/tuple.el
diff --git a/users/wpcarro/emacs/pkgs/vector/default.nix b/users/wpcarro/emacs/pkgs/vector/default.nix
new file mode 100644
index 0000000000..c0a475aaaa
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/vector/default.nix
@@ -0,0 +1,21 @@
+{ pkgs, depot, ... }:
+
+let
+  vector = pkgs.callPackage
+    ({ emacsPackages }:
+      emacsPackages.trivialBuild {
+        pname = "vector";
+        version = "1.0.0";
+        src = ./vector.el;
+      })
+    { };
+
+  emacs = (pkgs.emacsPackagesFor pkgs.emacs28).emacsWithPackages (epkgs: [ vector ]);
+in
+vector.overrideAttrs (_old: {
+  doCheck = true;
+  checkPhase = ''
+    ${emacs}/bin/emacs -batch \
+      -l ert -l ${./tests.el} -f ert-run-tests-batch-and-exit
+  '';
+})
diff --git a/users/wpcarro/emacs/pkgs/vector/tests.el b/users/wpcarro/emacs/pkgs/vector/tests.el
new file mode 100644
index 0000000000..ffa9831882
--- /dev/null
+++ b/users/wpcarro/emacs/pkgs/vector/tests.el
@@ -0,0 +1,20 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dependencies
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'ert)
+(require 'vector)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Tests
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(ert-deftest vector-misc-tests ()
+  (let ((xs [1 2 3])
+        (ys [1 2 3]))
+    (should (= 1 (vector-get 0 ys)))
+    (vector-set 0 4 ys)
+    (should (= 1 (vector-get 0 ys)))
+    (should (= 1 (vector-get 0 xs)))
+    (vector-set! 0 4 xs)
+    (should (= 4 (vector-get 0 xs)))))
diff --git a/users/wpcarro/emacs/.emacs.d/wpc/vector.el b/users/wpcarro/emacs/pkgs/vector/vector.el
index 6b89708cef..87f38d7d93 100644
--- a/users/wpcarro/emacs/.emacs.d/wpc/vector.el
+++ b/users/wpcarro/emacs/pkgs/vector/vector.el
@@ -22,25 +22,14 @@
 
 ;;; Code:
 
-;; TODO: Consider supporting an alias named tuple for vector.
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Library
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defconst vector-enable-tests? t
-  "When t, run the tests defined herein.")
-
-;; TODO: Consider labelling variadic functions like `vector-concat*'
-;; vs. `vector-concat'.
 (defun vector-concat (&rest args)
   "Return a new vector composed of all vectors in `ARGS'."
   (apply #'vconcat args))
 
-;; TODO: Here's a sketch of a protocol macro being consumed.
-;; (definstance monoid vector
-;;   :empty (lambda () []))
-
 (defun vector-prepend (x xs)
   "Add `X' to the beginning of `XS'."
   (vector-concat `[,x] xs))
@@ -65,20 +54,5 @@ Returns a copy of `XS' with the updates."
 This function mutates XS."
   (aset xs i v))
 
-(when vector-enable-tests?
-  (let ((xs [1 2 3])
-        (ys [1 2 3]))
-    (prelude-assert (= 1 (vector-get 0 ys)))
-    (vector-set 0 4 ys)
-    (prelude-assert (= 1 (vector-get 0 ys)))
-    (prelude-assert (= 1 (vector-get 0 xs)))
-    (vector-set! 0 4 xs)
-    (prelude-assert (= 4 (vector-get 0 xs)))))
-
-;; TODO: Decide between "remove" and "delete" as the appropriate verbs.
-;; TODO: Implement this.
-;; (defun vector/delete (i xs)
-;;   "Remove the element at `I' in `XS'.")
-
 (provide 'vector)
 ;;; vector.el ends here