about summary refs log tree commit diff
path: root/emacs/.emacs.d/wpc/themes.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/.emacs.d/wpc/themes.el')
-rw-r--r--emacs/.emacs.d/wpc/themes.el204
1 files changed, 204 insertions, 0 deletions
diff --git a/emacs/.emacs.d/wpc/themes.el b/emacs/.emacs.d/wpc/themes.el
new file mode 100644
index 0000000000..ee81d3beed
--- /dev/null
+++ b/emacs/.emacs.d/wpc/themes.el
@@ -0,0 +1,204 @@
+;;; themes.el --- Functions for working with my themes. -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+
+
+;; Because I couldn't get cycle-themes to work, I'm writing my own version.
+;;
+;; Terminology:
+;; - colorscheme: determines the colors used by syntax highlighting and other
+;;   Emacs UI elements.
+;; - theme: Structural representation of a "theme" that includes colorscheme
+;;   (see above), font, wallpaper.  "theme" is a superset of "colorscheme".
+;;
+;; Wishlist:
+;; - TODO: Find a way to update the terminal (e.g. terminator) theme.
+;; - TODO: Ensure terminal font is updated when Emacs font changes.
+;; - TODO: Support a light theme.
+;; - TODO: Support Rick & Morty theme.
+;; - TODO: Support retro/arcade/80s theme.
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Dependencies
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(require 'prelude)
+(require 'alist)
+(require 'symbol)
+(require 'f)
+(require 'wallpaper)
+(require 'fonts)
+(require 'cycle)
+(require 'symbol)
+(require 'random)
+(require 'colorscheme)
+(require 'dotted)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Library
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The theme struct couples a font, a wallpaper, and a colorschemes.
+(cl-defstruct theme
+  font
+  wallpaper
+  colorscheme)
+
+(defvar themes/current nil
+  "Store the name of the currently enabled theme.")
+
+(defconst themes/themes
+  (list (dotted/new
+         "Forest"
+         (make-theme
+          :font "Operator Mono Light"
+          :wallpaper "forest_8k.jpg"
+          :colorscheme 'doom-peacock))
+        (dotted/new
+         "Geometry"
+         (make-theme
+          :font "Input Mono Medium"
+          :wallpaper "geometric_4k.jpg"
+          :colorscheme 'doom-molokai))
+        (dotted/new
+         "Ice"
+         (make-theme
+          :font "Go Mono"
+          :wallpaper "construction_paper_iceberg_4k.jpg"
+          :colorscheme 'doom-dracula))
+        (dotted/new
+         "Lego Manhattan"
+         (make-theme
+          :font "Input Mono Medium"
+          :wallpaper "lego_manhattan.jpg"
+          :colorscheme 'base16-atelier-sulphurpool))
+        (dotted/new
+         "Shapely Patterns"
+         (make-theme
+          :font "Operator Mono Light"
+          :wallpaper "geometric_dark_4k.jpg"
+          :colorscheme 'doom-vibrant))
+        ;; TODO: Support setting backgrounds as solid colors.
+        (dotted/new
+         "Gruvbox"
+         (make-theme
+          :font "JetBrainsMono"
+          :wallpaper "geometric_dark_4k.jpg"
+          :colorscheme 'doom-gruvbox))
+        (dotted/new
+         "Solarized Light"
+         (make-theme
+          :font "JetBrainsMono"
+          :wallpaper "solarized_light_thinkpad.jpg"
+          :colorscheme 'doom-solarized-light))
+        (dotted/new
+         "Lightness"
+         (make-theme
+          :font "Input Mono Medium"
+          :wallpaper "construction_paper_iceberg_4k.jpg"
+          :colorscheme 'doom-one-light))
+        (dotted/new
+         "Edison Lightbulb"
+         (make-theme
+          :font "Mononoki Medium"
+          :wallpaper "lightbulb_4k.jpg"
+          :colorscheme 'base16-atelier-cave))
+        (dotted/new
+         "Wall-E"
+         (make-theme
+          :font "Input Mono Medium"
+          :wallpaper "walle_4k.jpg"
+          :colorscheme 'doom-material))
+        (dotted/new
+         "Galaxy"
+         (make-theme
+          :font "Source Code Pro"
+          :wallpaper "galaxy_4k.jpg"
+          :colorscheme 'doom-moonlight))
+        (dotted/new
+         "Underwater"
+         (make-theme
+          :font "Go Mono"
+          ;; TODO: Change this wallpaper to an oceanic scene.
+          :wallpaper "galaxy_4k.jpg"
+          :colorscheme 'doom-solarized-dark))
+        (dotted/new
+         "Fantasy Tree"
+         (make-theme
+          :font "Go Mono"
+          :wallpaper "fantasy_tree_4k.jpg"
+          :colorscheme 'doom-outrun-electric)))
+  "Predefined themes to suit my whims.")
+
+;; TODO: Choose between plural and singular names for Elisp modules.  For
+;; example, why have themes.el and colorscheme.el.  I think singular is
+;; preferable.
+;; TODO: Decide between "message", "show", "print", "inspect" for naming
+;; commands that output human-readable information to the "*Messages*" buffer.
+;; TODO: Is there a idiomatic CL/Elisp way to print struct information?
+(defun themes/print (name)
+  "Print a human-readable description of theme named NAME."
+  (let* ((theme (alist/get name themes/themes))
+         (f (theme-font theme))
+         (w (theme-wallpaper theme))
+         (c (theme-colorscheme theme)))
+    (message (string/format
+              "[themes] Name: %s. Font: %s. Wallpaper: %s. Colorscheme: %s"
+              name f w c))))
+
+;; TODO: Make this into a proper test.
+(defun themes/debug ()
+  "Print a human-readable description of theme named NAME."
+  (interactive)
+  (let ((theme (alist/get themes/current themes/themes)))
+    (prelude/assert (equal (theme-font theme)
+                           (fonts/current)))
+    (prelude/assert (equal (theme-wallpaper theme)
+                           (f-filename (wallpaper/current))))
+    (prelude/assert (equal (theme-colorscheme theme)
+                           (colorscheme/current)))
+    (message "[themes] Debug couldn't find any inconsistencies. All good!")))
+
+;; TODO: Assert that all of the dependencies exist before attempting to load
+;; theme.
+;; TODO: Provide a friendlier way to define themes.
+(defun themes/ivy-select ()
+  "Use ivy to interactively load a theme."
+  (interactive)
+  (let* ((name (ivy-read "Theme: " (alist/keys themes/themes))))
+    (message (string/format "name: %s" name))
+    (themes/set name)))
+
+(defun themes/load (theme)
+  "Load the struct, THEME."
+  (colorscheme/disable-all)
+  (let* ((font (theme-font theme))
+         (wallpaper (theme-wallpaper theme))
+         (colorscheme (theme-colorscheme theme)))
+    (fonts/whitelist-set font)
+    (wallpaper/whitelist-set (f-join wallpaper/path-to-dir wallpaper))
+    (colorscheme/whitelist-set colorscheme)))
+
+(defun themes/set (name)
+  "Set the currently enabled theme to the theme named NAME.
+NAME needs to a key defined in `themes/themes'."
+  (prelude/assert (alist/has-key? name themes/themes))
+  (themes/load (alist/get name themes/themes))
+  (setq themes/current name))
+
+(defun themes/print-current ()
+  "Print the currently enabled theme."
+  (interactive)
+  (themes/print themes/current))
+
+(defun themes/random ()
+  "Return the name of a randomly selected theme in `themes/themes'."
+  (->> themes/themes
+       alist/keys
+       random/choice))
+
+(provide 'themes)
+;;; themes.el ends here