about summary refs log tree commit diff
path: root/emacs.d/wpc
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2018-04-25T17·26-0400
committerWilliam Carroll <wpcarro@gmail.com>2018-07-19T16·00-0400
commit3c8e6f0cc5eac51e369b8ffbd0441366cdc6da40 (patch)
treee1c98f5b22dd258e4ae331c0591e0527fe5233a1 /emacs.d/wpc
parent56a7b9fa41c6edbb960686ccffb7a8949d242eab (diff)
Support updated emacs
Finally ported my up-to-date emacs configuration here. I was putting
this off for a long while, unsure of how to handle all of the work. All
it took was my laptop being fried to force me to do this. So... voila!
Diffstat (limited to 'emacs.d/wpc')
-rw-r--r--emacs.d/wpc/casing.el39
-rw-r--r--emacs.d/wpc/functions.el227
-rw-r--r--emacs.d/wpc/macros.el33
-rw-r--r--emacs.d/wpc/packages/wpc-clojure.el63
-rw-r--r--emacs.d/wpc/packages/wpc-company.el24
-rw-r--r--emacs.d/wpc/packages/wpc-dired.el18
-rw-r--r--emacs.d/wpc/packages/wpc-docker.el18
-rw-r--r--emacs.d/wpc/packages/wpc-flycheck.el14
-rw-r--r--emacs.d/wpc/packages/wpc-git.el17
-rw-r--r--emacs.d/wpc/packages/wpc-haskell.el32
-rw-r--r--emacs.d/wpc/packages/wpc-javascript.el87
-rw-r--r--emacs.d/wpc/packages/wpc-keybindings.el131
-rw-r--r--emacs.d/wpc/packages/wpc-lisp.el37
-rw-r--r--emacs.d/wpc/packages/wpc-misc.el155
-rw-r--r--emacs.d/wpc/packages/wpc-org.el45
-rw-r--r--emacs.d/wpc/packages/wpc-package.el32
-rw-r--r--emacs.d/wpc/packages/wpc-slack.el65
-rw-r--r--emacs.d/wpc/packages/wpc-terminal.el19
-rw-r--r--emacs.d/wpc/packages/wpc-ui.el136
-rw-r--r--emacs.d/wpc/string-functions.el41
-rw-r--r--emacs.d/wpc/variables.el18
21 files changed, 1251 insertions, 0 deletions
diff --git a/emacs.d/wpc/casing.el b/emacs.d/wpc/casing.el
new file mode 100644
index 000000000000..0592d9dddb08
--- /dev/null
+++ b/emacs.d/wpc/casing.el
@@ -0,0 +1,39 @@
+;; casing.el --- Helper functions for formatting text -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; These functions are intended to be bound to KBDs for daily use and
+;; refactoring.
+
+;;; Code:
+
+(require 's)
+(require 'dash)
+
+;; todo - grab the string at point and replace it with the output of
+;; each fn
+
+(defun caps->kebab (x)
+  "Change the casing of X from CAP_CASE to kebab-case."
+  (->> x
+       s-downcase
+       (s-replace "_" "-")))
+
+(defun kebab->caps (x)
+  "Change the casing of X from CAP_CASE to kebab-case."
+  (->> x
+       s-upcase
+       (s-replace "-" "_")))
+
+;;; Tests:
+
+(ert-deftest caps->kebab-test ()
+  (should (string= (caps->kebab "CAPS_CASE_STRING")
+                   "caps-case-string")))
+
+(ert-deftest kebab->caps-test ()
+  (should (string= (kebab->caps "kebab-case-string")
+                   "KEBAB_CASE_STRING")))
+
+(provide 'casing)
+;;; casing.el ends here
diff --git a/emacs.d/wpc/functions.el b/emacs.d/wpc/functions.el
new file mode 100644
index 000000000000..f2514a1bed85
--- /dev/null
+++ b/emacs.d/wpc/functions.el
@@ -0,0 +1,227 @@
+;; functions.el --- Helper functions for my Emacs development -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This file hopefully contains friendly APIs that making ELisp development more enjoyable.
+
+;;; Code:
+
+;; TODO: clean up this file so this isn't necessary
+(setq evil-want-integration nil)
+(require 'evil)
+
+(require 'projectile)
+(require 'paredit)
+(require 'term)
+(require 'f)
+(require 'yasnippet)
+(require 'ido)
+
+(defun wpc/evil-window-vsplit-right ()
+  (interactive)
+  (evil-window-vsplit)
+  (windmove-right))
+
+(defun wpc/evil-window-split-down ()
+  (interactive)
+  (evil-window-split)
+  (windmove-down))
+
+(defun wpc/reindent-defun-and-align-clojure-map ()
+  (interactive)
+  (call-interactively #'paredit-reindent-defun)
+  (call-interactively #'clojure-align))
+
+(defun wpc/find-file ()
+  "Prefer project-based file-finding if inside of project; otherwise gracefully fallback."
+  (interactive)
+  (with-current-buffer (current-buffer)
+    (if (projectile-project-p)
+        (call-interactively #'projectile-find-file)
+      (call-interactively #'find-file))))
+
+(defun wpc/find-or-create-js-test ()
+  (->> buffer-file-name
+       (s-chop-suffix ".js")
+       (s-append ".test.js")
+       (find-file)))
+
+(defun wpc/find-or-create-js-module ()
+  (->> buffer-file-name
+       (s-chop-suffix ".test.js")
+       (s-append ".js")
+       (find-file)))
+
+(defun wpc/find-or-create-js-store ()
+  (->> buffer-file-name
+       (s-replace "index.js" "store.js")
+       (find-file)))
+
+(defun wpc/find-or-create-js-component ()
+  (->> buffer-file-name
+       (s-replace "store.js" "index.js")
+       (find-file)))
+
+(defun wpc/bind-ido-keys ()
+  "Adds custom KBDs for ido. This function is recommended in the ido source code."
+  (define-key ido-completion-map (kbd "<tab>") #'ido-next-match)
+  (define-key ido-completion-map (kbd "<backtab>") #'ido-prev-match))
+
+(defun wpc/toggle-between-js-test-and-module ()
+  "Toggle between a Javascript test or module."
+  (interactive)
+  (if (s-ends-with? ".test.js" buffer-file-name)
+      (wpc/find-or-create-js-module)
+    (if (s-ends-with? ".js" buffer-file-name)
+        (wpc/find-or-create-js-test)
+      (message "Not in a Javascript file. Exiting..."))))
+
+(defun wpc/toggle-between-js-component-and-store ()
+  "Toggle between a React component and its Redux store."
+  (interactive)
+  (if (s-ends-with? "index.js" buffer-file-name)
+      (wpc/find-or-create-js-store)
+    (if (or (s-ends-with? "store.js" buffer-file-name)
+            (s-ends-with? "store.test.js" buffer-file-name))
+        (wpc/find-or-create-js-component)
+      (message "Not in a React/Redux file. Exiting..."))))
+
+(defun wpc/read-file-as-string (filename)
+  (with-temp-buffer
+    (insert-file-contents filename)
+    (s-trim (buffer-string))))
+
+(defun wpc/create-snippet ()
+  "Creates a window split and then opens the Yasnippet editor."
+  (interactive)
+  (evil-window-vsplit)
+  (call-interactively #'yas-new-snippet))
+
+(defun wpc/edit-init-el ()
+  "Creates a window split and then edits the init.el file."
+  (interactive)
+  (evil-window-vsplit)
+  (find-file "~/.emacs.d/init.el"))
+
+(defun wpc/set-flow-executable ()
+  (interactive)
+  (let* ((root (locate-dominating-file buffer-file-name  "node_modules/flow-bin"))
+         (executable (car (file-expand-wildcards
+                           (concat root "node_modules/flow-bin/*osx*/flow")))))
+    (setq-local company-flow-executable executable)
+    ;; These are not necessary for this package, but a good idea if you use
+    ;; these other packages
+    (setq-local flow-minor-default-binary executable)
+    (setq-local flycheck-javascript-flow-executable executable)))
+
+(defun wpc/jump-to-parent-file ()
+  "Jumps to a React store or component's parent file. Useful for store or index file."
+  (interactive)
+  (-> buffer-file-name
+      f-dirname
+      (f-join "..")
+      (f-join (f-filename buffer-file-name))
+      find-file))
+
+(defun wpc/tmux-emacs-windmove (dir)
+  "Move windows in a Tmux-friendly way."
+  (let* ((dir->opts '((left . ("-L" . windmove-left))
+                      (right . ("-R" . windmove-right))
+                      (above . ("-U" . windmove-up))
+                      (below . ("-D" . windmove-down))))
+         (opts (alist-get dir dir->opts))
+         (tmux-opt (car opts))
+         (emacs-fn (cdr opts)))
+    (if (window-in-direction dir)
+        (funcall emacs-fn)
+      (shell-command (format "tmux select-pane %s" tmux-opt)))))
+
+(defun wpc/tmux-emacs-windmove-left ()
+  (interactive)
+  (wpc/tmux-emacs-windmove 'left))
+
+(defun wpc/tmux-emacs-windmove-right ()
+  (interactive)
+  (wpc/tmux-emacs-windmove 'right))
+
+(defun wpc/tmux-emacs-windmove-up ()
+  (interactive)
+  (wpc/tmux-emacs-windmove 'above))
+
+(defun wpc/tmux-emacs-windmove-down ()
+  (interactive)
+  (wpc/tmux-emacs-windmove 'below))
+
+(defun wpc/get-window-by-buffername (buffername)
+  "Finds a window by the name of the buffer it's hosting."
+  (let ((buffer (get-buffer buffername)))
+    (when buffer
+        (get-buffer-window buffer))))
+
+(defun wpc/add-earmuffs (x)
+  "Returns X surrounded by asterisks."
+  (format "*%s*" x))
+
+(defun wpc/get-default-shell ()
+  (or explicit-shell-file-name
+      (getenv "SHELL")
+      (getenv "ESHELL")))
+
+(defun wpc/find-terminal-buffer ()
+  (get-buffer (wpc/add-earmuffs wpc/terminal-name)))
+
+(defun wpc/find-terminal-window ()
+  (wpc/get-window-by-buffername (wpc/add-earmuffs wpc/terminal-name)))
+
+(defun wpc/create-terminal-session ()
+  (wpc/evil-window-vsplit-right)
+  (ansi-term (wpc/get-default-shell) wpc/terminal-name))
+
+(defun wpc/toggle-terminal ()
+  "Toggles a custom terminal session in Emacs."
+  (interactive)
+  (let ((window (wpc/find-terminal-window)))
+    (if window
+        (delete-window window)
+      (wpc/find-or-create-terminal))))
+
+(defun wpc/find-or-create-terminal ()
+  (let ((buffer (wpc/find-terminal-buffer)))
+    (if buffer
+        (display-buffer buffer)
+      (wpc/create-terminal-session))))
+
+(defun wpc/put-file-name-on-clipboard ()
+  "Put the current file name on the clipboard"
+  (interactive)
+  (let ((filename (if (equal major-mode 'dired-mode)
+                      default-directory
+                    (buffer-file-name))))
+    (when filename
+      (with-temp-buffer
+        (insert filename)
+        (clipboard-kill-region (point-min) (point-max)))
+      (message filename))))
+
+(defun wpc/evil-replace-under-point ()
+  "Faster than typing %s//thing/g"
+  (interactive)
+  (save-excursion
+    (evil-ex (concat "%s/\\b" (symbol-name (symbol-at-point)) "\\b/"))))
+
+(defun wpc/disable-linum-mode ()
+  "Convenience function defined to make adding hooks easier without a lambda."
+  (linum-mode -1))
+
+(defun wpc/disable-company-mode ()
+  "Convenience function defined to make adding hooks easier without a lambda."
+  (company-mode -1))
+
+(defun wpc/toggle-term-mode ()
+  "Toggle between term-line-mode and temr-char-mode."
+  (if (term-in-line-mode)
+      (term-char-mode)
+    (term-line-mode)))
+
+(provide 'functions)
+;;; functions.el ends here
diff --git a/emacs.d/wpc/macros.el b/emacs.d/wpc/macros.el
new file mode 100644
index 000000000000..aedd6f5b3cb9
--- /dev/null
+++ b/emacs.d/wpc/macros.el
@@ -0,0 +1,33 @@
+;;; macros.el --- Helpful variables for making my ELisp life more enjoyable -*- lexical-binding: t -*-
+;; Authpr: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This file contains helpful variables that I use in my ELisp development.
+
+;;; Code:
+
+(require 'dash)
+(require 's)
+(require 'string-functions)
+
+(defmacro xi (&rest FORMS)
+  `(lambda ,(--filter (s-contains? (symbol-name it)
+                                   (prin1-to-string FORMS))
+                      '(x1 x2 x3 x4 x5))
+     ,FORMS))
+
+(defmacro enable (mode)
+  "Helper for enabling MODE. Useful in `add-hook' calls."
+  `#'(lambda nil (,mode 1)))
+
+(defmacro disable (mode)
+  "Helper for disabling MODE. Useful in `add-hook' calls."
+  `#'(lambda nil (,mode -1)))
+
+(defmacro add-hooks (modes)
+  "Add multiple MODES for the CALLBACK."
+  `(dolist (mode ,modes)
+     (add-hook (symbol/ensure-hookified mode) ,callback)))
+
+(provide 'macros)
+;;; macros.el ends here
diff --git a/emacs.d/wpc/packages/wpc-clojure.el b/emacs.d/wpc/packages/wpc-clojure.el
new file mode 100644
index 000000000000..3644f76a70e2
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-clojure.el
@@ -0,0 +1,63 @@
+;;; clojure.el --- My Clojure preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosting my Clojure tooling preferences
+
+;;; Code:
+
+;; Helper functions
+(defun wpc/buffer-name-for-clojure-mode (mode)
+  (let* ((project-name (projectile-project-name))
+         (cljs-name (concat "*cider-repl CLJS " project-name "*"))
+         (clj-name  (concat "*cider-repl " project-name "*")))
+    (cond ((eq mode 'clojurescript-mode) cljs-name)
+          ((eq mode 'clojure-mode) clj-name)
+          ((eq mode 'clojurec-mode) cljs-name))))
+
+(defun wpc/repl-function-for-clojure-mode (mode)
+  (let ((project-name (projectile-project-name))
+        (cljs-fn #'cider-jack-in-clojurescript)
+        (clj-fn  #'cider-jack-in))
+    (cond ((eq mode 'clojurescript-mode) cljs-fn)
+          ((eq mode 'clojure-mode) clj-fn)
+          ((eq mode 'clojurec-mode) cljs-fn))))
+
+(defun wpc/find-or-create-clojure-or-clojurescript-repl ()
+  (interactive)
+  (with-current-buffer (current-buffer)
+    (let ((buffer-name   (wpc/buffer-name-for-clojure-mode major-mode))
+          (repl-function (wpc/repl-function-for-clojure-mode major-mode)))
+      (if (get-buffer buffer-name)
+          (switch-to-buffer buffer-name)
+        (funcall repl-function)))))
+
+;; (defun wpc/evil-leader/set-key-for-clojure-modes (kbd callback)
+;;   (evil-leader/set-key-for-mode 'clojure-mode kbd callback)
+;;   (evil-leader/set-key-for-mode 'clojurec-mode kbd callback)
+;;   (evil-leader/set-key-for-mode 'clojurescript-mode kbd callback))
+
+;; ;; clojure
+;; (wpc/evil-leader/set-key-for-clojure-modes "d" #'cider-doc)
+;; (wpc/evil-leader/set-key-for-clojure-modes "e" #'cider-eval-defun-at-point)
+;; (wpc/evil-leader/set-key-for-clojure-modes "r" #'wpc/find-or-create-clojure-or-clojurescript-repl)
+
+(use-package cider
+  :general
+  (cider-repl-mode-map
+   "C-l"    'cider-repl-clear-buffer
+   "C-u"    'kill-whole-line
+   "<up>"   'cider-repl-previous-input
+   "<down>" 'cider-repl-next-input
+   "C-c 'j" 'wpc/find-or-create-clojure-or-clojurescript-repl)
+  (n
+   "M-." 'cider-find-var)
+  :config
+  (setq cider-cljs-lein-repl
+        "(do (require 'figwheel-sidecar.repl-api)
+             (figwheel-sidecar.repl-api/start-figwheel!)
+             (figwheel-sidecar.repl-api/cljs-repl))"
+        cider-prompt-for-symbol nil))
+
+(provide 'wpc-clojure)
+;;; wpc-clojure.el ends here
diff --git a/emacs.d/wpc/packages/wpc-company.el b/emacs.d/wpc/packages/wpc-company.el
new file mode 100644
index 000000000000..ec96bdf90b3e
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-company.el
@@ -0,0 +1,24 @@
+;;; company.el --- Autocompletion package, company, preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosts my company mode preferences
+
+;;; Code:
+
+;; autocompletion client
+(use-package company
+  :general
+  (company-active-map
+   "C-j" 'company-select-next
+   "C-n" 'company-select-next
+   "C-k" 'company-select-previous
+   "C-p" 'company-select-previous
+   "C-d" 'company-show-doc-buffer)
+  :config
+  (setq company-idle-delay 0)
+  (setq company-minimum-prefix-length 2)
+  (global-company-mode))
+
+(provide 'wpc-company)
+;;; company.el ends here
diff --git a/emacs.d/wpc/packages/wpc-dired.el b/emacs.d/wpc/packages/wpc-dired.el
new file mode 100644
index 000000000000..1c45ec35e2b4
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-dired.el
@@ -0,0 +1,18 @@
+;;; dired.el --- My dired preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosts my attempts at configuring dired
+
+;;; Code:
+
+(require 'dired)
+(general-def 'dired-mode-map
+    "c" 'find-file
+    "f" 'wpc/find-file
+    "-" 'dired-up-directory)
+(general-add-hook 'dired-mode-hook (list (enable dired-hide-details-mode)
+                                         #'auto-revert-mode))
+
+(provide 'wpc-dired)
+;;; dired.el ends here
diff --git a/emacs.d/wpc/packages/wpc-docker.el b/emacs.d/wpc/packages/wpc-docker.el
new file mode 100644
index 000000000000..586878fdeacd
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-docker.el
@@ -0,0 +1,18 @@
+;;; docker.el --- Docker preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; My Docker preferences and configuration
+
+;;; Code:
+
+(use-package docker
+  :config
+  (setenv "DOCKER_TLS_VERIFY" "1")
+  (setenv "DOCKER_HOST" "tcp://10.11.12.13:2376")
+  (setenv "DOCKER_MACHINE_NAME" "name"))
+
+(use-package dockerfile-mode)
+
+(provide 'wpc-docker)
+;;; docker.el ends here
diff --git a/emacs.d/wpc/packages/wpc-flycheck.el b/emacs.d/wpc/packages/wpc-flycheck.el
new file mode 100644
index 000000000000..66314af9877c
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-flycheck.el
@@ -0,0 +1,14 @@
+;;; flycheck.el --- My flycheck configuration -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosts my Flycheck preferences
+
+;;; Code:
+
+(use-package flycheck
+  :config
+  (global-flycheck-mode))
+
+(provide 'wpc-flycheck)
+;;; flycheck.el ends here
diff --git a/emacs.d/wpc/packages/wpc-git.el b/emacs.d/wpc/packages/wpc-git.el
new file mode 100644
index 000000000000..f07040fffb64
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-git.el
@@ -0,0 +1,17 @@
+;;; git.el --- My version control preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Things related to git, magit, etc belong here
+
+;;; Code:
+
+(use-package git-timemachine)
+
+(use-package magit)
+
+(use-package magit-gh-pulls
+  :ghook ('magit-mode-hook #'turn-on-magit-gh-pulls))
+
+(provide 'wpc-git)
+;;; git.el ends here
diff --git a/emacs.d/wpc/packages/wpc-haskell.el b/emacs.d/wpc/packages/wpc-haskell.el
new file mode 100644
index 000000000000..a37a84030f14
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-haskell.el
@@ -0,0 +1,32 @@
+;;; haskell.el --- My Haskell preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosts my Haskell development preferences
+
+;;; Code:
+
+;; Haskell support
+(use-package intero
+  :config
+  (intero-global-mode 1))
+
+;; text objects for Haskell
+(quelpa '(evil-text-objects-haskell
+          :fetcher github
+          :repo "urbint/evil-text-objects-haskell"))
+(require 'evil-text-objects-haskell)
+
+(use-package haskell-mode
+  :gfhook #'evil-text-objects-haskell/install
+  :after (intero evil-text-objects-haskell)
+  :config
+  (flycheck-add-next-checker 'intero 'haskell-hlint)
+  (let ((m-symbols
+         '(("`mappend`" . "⊕")
+           ("<>"        . "⊕"))))
+    (dolist (item m-symbols) (add-to-list 'haskell-font-lock-symbols-alist item)))
+  (setq haskell-font-lock-symbols t))
+
+(provide 'wpc-haskell)
+;;; haskell.el ends here
diff --git a/emacs.d/wpc/packages/wpc-javascript.el b/emacs.d/wpc/packages/wpc-javascript.el
new file mode 100644
index 000000000000..5dcd5937b11d
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-javascript.el
@@ -0,0 +1,87 @@
+;;; javascript.el --- My Javascript preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This module hosts my Javascript tooling preferences
+
+;;; Code:
+
+;; Helper functions
+(defun wpc/indium-setup (url)
+  "Setup the indium environment using URL."
+  (indium-eval (format "window.dispatchEvent(new CustomEvent('patch', {detail: {url: %s}}" url)))
+
+(defun wpc/insert-flow-annotation ()
+  "Insert a flow type annotation to the beginning of a buffer."
+  (interactive)
+  (save-excursion
+    (goto-char (point-min))
+    (insert "// @flow\n")))
+
+;; ;; javascript
+;; (evil-leader/set-key-for-mode 'rjsx-mode "t" #'wpc/toggle-between-js-test-and-module)
+;; (evil-leader/set-key-for-mode 'rjsx-mode "x" #'wpc/toggle-between-js-component-and-store)
+;; (evil-leader/set-key-for-mode 'rjsx-mode "u" #'wpc/jump-to-parent-file)
+
+;; javascript setup
+(use-package indium
+  :hook (indium-update-script-source . wpc/indium-setup))
+
+;; javascript text objects
+(quelpa '(evil-text-objects-javascript
+          :fetcher github
+          :repo "urbint/evil-text-objects-javascript"))
+(require 'evil-text-objects-javascript)
+
+;; Flow for Javascript
+(use-package flow-minor-mode
+  :hook js2-mode
+  :requires evil-leader
+  :config
+  (evil-leader/set-key-for-mode 'rjsx-mode "F" #'wpc/insert-flow-annotation))
+
+(use-package company-flow
+  :after (company)
+  :hook (rjsx-mode . wpc/set-flow-executable)
+  :config
+  (add-to-list 'company-flow-modes 'rjsx-mode)
+  (add-to-list 'company-backends 'company-flow))
+
+(use-package flycheck-flow
+  :after (flycheck)
+  :config
+  (flycheck-add-mode 'javascript-flow 'rjsx-mode)
+  (flycheck-add-mode 'javascript-flow 'flow-minor-mode)
+  (flycheck-add-mode 'javascript-eslint 'flow-minor-mode)
+  (flycheck-add-next-checker 'javascript-flow 'javascript-eslint))
+
+;; front-end indentation
+(setq js-indent-level 2
+      css-indent-offset 2)
+
+;; eslint integration with flycheck
+(setq flycheck-javascript-eslint-executable "~/urbint/grid-front-end/node_modules/.bin/eslint")
+
+;; JS autoformatting
+(use-package prettier-js
+  :after (rjsx-mode)
+  :ghook ('(rjsx-mode-hook
+            js2-mode-hook
+            json-mode-hook
+            css-mode-hook)))
+
+;; JSX highlighting
+(use-package rjsx-mode
+  :after (evil-text-objects-javascript)
+  :general
+  (general-unbind rjsx-mode-map "<" ">" "C-d")
+  (n rjsx-mode-map
+     "K" 'flow-minor-type-at-pos)
+  :gfhook #'evil-text-objects-javascript/install
+  :mode "\\.js\\'"
+  :config
+  (setq js2-mode-show-parse-errors nil
+        js2-mode-show-strict-warnings nil))
+
+(provide 'wpc-javascript)
+;;; wpc-javascript.el ends here
diff --git a/emacs.d/wpc/packages/wpc-keybindings.el b/emacs.d/wpc/packages/wpc-keybindings.el
new file mode 100644
index 000000000000..0e74ce68bacb
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-keybindings.el
@@ -0,0 +1,131 @@
+;;; keybindings.el --- My Evil preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This module hosts my Evil preferences
+
+;;; Code:
+
+(quelpa
+ '(general
+   :repo "noctuid/general.el"
+   :fetcher github))
+(general-evil-setup t)
+
+;; vim...
+(use-package evil
+  :general
+  (m
+   "RET" 'evil-goto-line
+   "H"   'evil-first-non-blank
+   "L"   'evil-end-of-line
+   "-"   'dired-jump
+   "sl"  'wpc/evil-window-vsplit-right
+   "sh"  'evil-window-vsplit
+   "sk"  'evil-window-split
+   "sj"  'wpc/evil-window-split-down
+   "sj"  'wpc/evil-window-split-down)
+  (general-unbind m "M-." "C-p")
+  (general-unbind n "s" "M-.")
+  (general-unbind i "C-d" "C-a" "C-e" "C-n" "C-p" "C-k")
+  (evil-ex-map
+   "M-p" 'previous-complete-history-element
+   "M-n" 'next-complete-history-element)
+  :init
+  (setq evil-want-integration nil)
+  :config
+  (setq evil-symbol-word-search t)
+  (evil-mode 1))
+
+;; evil keybindings
+(use-package evil-collection
+  :after evil
+  :config
+  (evil-collection-init))
+
+;; expose a leader key
+(use-package evil-leader
+  :after (evil counsel)
+  :config
+  (global-evil-leader-mode)
+  (evil-leader/set-leader "<SPC>")
+  ;; global
+  (evil-leader/set-key
+    "i"  #'counsel-semantic-or-imenu
+    "j"  #'jump-to-register
+    "h"  #'help
+    "a"  #'wpc/toggle-terminal
+    "p"  #'counsel-git-grep
+    "P"  #'counsel-git-grep
+    "f"  #'wpc/find-file
+    "N"  #'smerge-next
+    "P"  #'smerge-prev
+    "s"  #'slack-send-code-snippet
+    "S"  #'slack-select-unread-rooms
+    "b"  #'ivy-switch-buffer
+    "gs" #'magit-status
+    "es" #'wpc/create-snippet
+    "ev" #'wpc/edit-init-el
+    "B"  #'magit-blame
+    "w"  #'save-buffer
+    "x"  #'evil-save-and-close
+    "W"  #'save-all-buffers
+    "r"  #'wpc/evil-replace-under-point
+    ))
+
+;; create comments easily
+(use-package evil-commentary
+  :after (evil)
+  :config
+  (evil-commentary-mode))
+
+;; evil surround
+(use-package evil-surround
+  :after (evil)
+  :config
+  (global-evil-surround-mode 1))
+
+;; Custom minor mode that ensures that my kbds are available no matter which major
+;; or minor modes are active.
+(add-hook 'after-load-functions #'ensure-william-carroll-kbds)
+
+(defun ensure-william-carroll-kbds (_ignore)
+  "Try to ensure that my keybindings retain priority over other minor modes."
+  (unless (eq (caar minor-mode-map-alist) 'wpc/kbds-minor-mode)
+    (let ((mykbds (assq 'wpc/kbds-minor-mode minor-mode-map-alist)))
+      (assq-delete-all 'wpc/kbds-minor-mode minor-mode-map-alist)
+      (add-to-list 'minor-mode-map-alist mykbds))))
+
+(defvar wpc/kbds
+  (let ((map (make-sparse-keymap)))
+    (bind-keys :map map
+               ("M-q" . delete-window)
+               ("C-x C-;" . comment-or-uncomment-region)
+               ("C-x h" . help)
+               ("<s-return>" . toggle-frame-fullscreen)
+               ("<down-mouse-1>" . ffap-other-window)
+               ("M-h"  . wpc/tmux-emacs-windmove-left)
+               ("M-l"  . wpc/tmux-emacs-windmove-right)
+               ("M-k"  . wpc/tmux-emacs-windmove-up)
+               ("M-j"  . wpc/tmux-emacs-windmove-down)
+               ("M--"  . split-window-below)
+               ("M-\\" . split-window-right)
+               ("M-q"  . delete-window))
+    map)
+  "William Carroll's keybindings that should have the highest precedence.")
+
+(define-minor-mode wpc/kbds-minor-mode
+  "A minor mode so that my key settings override annoying major modes."
+  :init-value t
+  :lighter " wpc/kbds"
+  :keymap wpc/kbds)
+
+;; allow jk to escape
+(use-package key-chord
+  :after (evil)
+  :config
+  (key-chord-mode 1)
+  (key-chord-define evil-insert-state-map "jk" 'evil-normal-state))
+
+(provide 'wpc-keybindings)
+;;; wpc-keybindings.el ends here
diff --git a/emacs.d/wpc/packages/wpc-lisp.el b/emacs.d/wpc/packages/wpc-lisp.el
new file mode 100644
index 000000000000..487201d47625
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-lisp.el
@@ -0,0 +1,37 @@
+;;; lisp.el --- Generic LISP preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This hosts things like Paredit settings
+
+;;; Code:
+
+(defconst wpc/lisp-mode-hooks
+  '(emacs-lisp-mode-hook
+    clojure-mode-hook
+    clojurescript-mode-hook))
+
+;; Elisp
+(use-package elisp-slime-nav
+  :ghook
+  'emacs-lisp-mode
+  'ielm-mode)
+
+;; paredit LISP editing
+(use-package paredit
+  :general
+  (general-unbind paredit-mode-map "C-j" "M-q")
+  (n paredit-mode-map
+     ">)" 'paredit-forward-slurp-sexp
+     "<(" 'paredit-backward-slurp-sexp
+     "<)" 'paredit-forward-barf-sexp
+     ">(" 'paredit-backward-barf-sexp
+     ">e" 'paredit-move-forward
+     "<e" 'paredit-move-backward
+     ">f" 'paredit-move-backward
+     "<f" 'paredit-move-backward
+     "go" 'paredit-raise-sexp)
+  :ghook (wpc/lisp-mode-hooks #'enable-paredit-mode))
+
+(provide 'wpc-lisp)
+;;; lisp.el ends here
diff --git a/emacs.d/wpc/packages/wpc-misc.el b/emacs.d/wpc/packages/wpc-misc.el
new file mode 100644
index 000000000000..d621f83d2101
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-misc.el
@@ -0,0 +1,155 @@
+;;; misc.el --- Hosting miscellaneous configuration -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This is the home of any configuration that couldn't find a better home.
+
+;;; Code:
+
+;; disable custom variable entries from being written to ~/.emacs.d/init.el
+(setq custom-file "~/.emacs.d/custom.el")
+(load custom-file 'noerror)
+
+;; transparently edit compressed files
+(auto-compression-mode t)
+
+;; change emacs prompts from "yes or no" -> "y or n"
+(fset 'yes-or-no-p 'y-or-n-p)
+
+;; open photos in Emacs
+(auto-image-file-mode 1)
+
+;; disable line-wrapping
+(setq-default truncate-lines 1)
+
+;; shell file indentation
+(setq sh-basic-offset 2)
+(setq sh-indentation 2)
+
+;; create file bookmarks
+(set-register ?e '(file . "~/.emacs.d/wpc/packages"))
+(set-register ?u '(file . "~/urbint"))
+(set-register ?d '(file . "~/dotfiles"))
+(set-register ?D '(file . "~/Dropbox"))
+(set-register ?o '(file . "~/Dropbox/org/"))
+(set-register ?c '(file . "~/Dropbox/org/chains.org"))
+(set-register ?b '(file . "~/Dropbox/org/backlog.org"))
+(set-register ?p '(file . "~/urbint/grid-front-end"))
+
+;; persist history etc b/w Emacs sessions
+(setq desktop-save 'if-exists)
+(desktop-save-mode 1)
+(setq desktop-globals-to-save
+      (append '((extended-command-history . 30)
+                (file-name-history        . 100)
+                (grep-history             . 30)
+                (compile-history          . 30)
+                (minibuffer-history       . 50)
+                (query-replace-history    . 60)
+                (read-expression-history  . 60)
+                (regexp-history           . 60)
+                (regexp-search-ring       . 20)
+                (search-ring              . 20)
+                (shell-command-history    . 50)
+                tags-file-name
+                register-alist)))
+
+;; 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
+      create-lockfiles nil)
+
+;; ensure code wraps at 80 characters by default
+(setq fill-column 80)
+
+(put 'narrow-to-region 'disabled nil)
+
+;; trim whitespace on save
+(add-hook 'before-save-hook #'delete-trailing-whitespace)
+
+;; use tabs instead of spaces
+(setq-default indent-tabs-mode nil)
+
+;; automatically follow symlinks
+(setq vc-follow-symlinks t)
+
+;; fullscreen settings
+(setq ns-use-native-fullscreen nil)
+
+;; auto-close parens, brackets, quotes
+(electric-pair-mode 1)
+
+(use-package oauth2
+  :init
+  ;; necessary to remove warnings: https://emacs.stackexchange.com/questions/37036/where-are-these-variables-defined-bytecomp-warnings
+  (defvar url-http-extra-headers ())
+  (defvar oauth--token-data ())
+  (defvar url-callback-function ())
+  (defvar url-callback-arguments ()))
+
+(use-package smex
+  :general
+  ("M-x" 'smex)
+  :ghook ('ido-setup-hook #'wpc/bind-ido-keys)
+  :config
+  (smex-initialize))
+
+(use-package flx-ido
+  :after (smex)
+  :config
+  (flx-ido-mode 1)
+  (setq ido-enable-flex-matching t
+        ido-use-faces nil))
+
+(use-package swiper
+  :general
+  ("C-s" 'swiper
+   "C-r" 'swiper))
+
+(use-package yasnippet
+  :config
+  (yas-global-mode 1))
+
+(use-package ace-window
+  :general
+  ("C-x o" 'ace-window)
+  :config
+  (setq aw-keys '(?a ?s ?d ?f ?j ?k ?k ?\;)))
+
+(use-package projectile
+  :config
+  (projectile-mode t))
+
+(use-package counsel
+  :config
+  (defun wpc/counsel-git-grep ()
+    (interactive)
+    (let ((maybe-symbol (wpc/string-symbol-at-point)))
+      (if (string= maybe-symbol "nil")
+          (counsel-git-grep)
+        (counsel-git-grep nil maybe-symbol)))))
+
+;; projectile intergration with ivy
+(use-package counsel-projectile)
+
+;; search Google, Stackoverflow from within Emacs
+(use-package engine-mode
+  :config
+  (defengine google
+    "http://www.google.com/search?ie=utf-8&oe=utf-8&q=%s"
+    :keybinding "g")
+  (defengine stack-overflow
+    "https://stackoverflow.com/search?q=%s"
+    :keybinding "s"))
+
+(use-package markdown-mode)
+(use-package yaml-mode)
+
+(provide 'wpc-misc)
+;;; misc.el ends here
diff --git a/emacs.d/wpc/packages/wpc-org.el b/emacs.d/wpc/packages/wpc-org.el
new file mode 100644
index 000000000000..28f1f9308dee
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-org.el
@@ -0,0 +1,45 @@
+;;; org.el --- My org preferences -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosts my org mode preferences
+
+;;; Code:
+
+;; Griffin's org clubhouse integration
+;;(load-file "~/.emacs.d/vendor/org-clubhouse.el")
+;;(setq org-clubhouse-auth-token (wpc/read-file-as-string "~/dotfiles/configs/secrets/clubhouse_token.txt")
+;;      org-clubhouse-team-name "urbint")
+;;(add-hook 'org-mode-hook #'org-clubhouse-mode)
+
+(use-package org
+  :ghook (nil (disable linum-mode))
+  :general
+  (:prefix "C-c"
+           "l" 'org-store-link
+           "a" 'org-agenda
+           "c" 'org-capture)
+  :preface
+  (defconst wpc-org-directory
+    "~/Dropbox/org")
+  (defconst ub-org-directory
+    "~/Dropbox/sprint-planning-staging")
+  (defun wpc/org-file (file)
+    (f-join wpc-org-directory (f-swap-ext file "org")))
+  (defun ub/org-file (file)
+    (f-join ub-org-directory (f-swap-ext file "org")))
+  :config
+  (setq org-default-notes-file (wpc/org-file "notes"))
+  (setq org-log-done 'time)
+  (setq org-agenda-files (list (wpc/org-file "work")
+                               (wpc/org-file "personal")))
+  (setq org-capture-templates
+        `(("t" "Todo" entry (file+heading ,(ub/org-file "index") "Ideas")
+           "* TODO %?\n  %i"))))
+
+(use-package org-bullets
+  :after (org)
+  :ghook ('org-mode-hook (enable org-bullets-mode)))
+
+(provide 'wpc-org)
+;;; org.el ends here
diff --git a/emacs.d/wpc/packages/wpc-package.el b/emacs.d/wpc/packages/wpc-package.el
new file mode 100644
index 000000000000..472f9df623a4
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-package.el
@@ -0,0 +1,32 @@
+;;; package.el --- My package configuration -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This module hosts all of the settings required to work with ELPA,
+;; MELPA, QUELPA, and co.
+
+;;; Code:
+
+(require 'package)
+(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
+(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/") t)
+(package-initialize)
+
+(if (require 'quelpa nil t)
+    (quelpa-self-upgrade)
+  (with-temp-buffer
+    (url-insert-file-contents "https://raw.github.com/quelpa/quelpa/master/bootstrap.el")
+    (eval-buffer)))
+
+(require 'use-package)
+(setq use-package-always-ensure t)
+;; Remove this line once general integration with use-package calls
+;; with-eval-after-load 'use-package-core instead of 'use-package
+(require 'general)
+
+(add-to-list 'load-path "~/.emacs.d/vendor/")
+(add-to-list 'load-path "~/.emacs.d/wpc/")
+(add-to-list 'load-path "~/.emacs.d/wpc/packages")
+
+(provide 'wpc-package)
+;;; package.el ends here
diff --git a/emacs.d/wpc/packages/wpc-slack.el b/emacs.d/wpc/packages/wpc-slack.el
new file mode 100644
index 000000000000..912cd14572b4
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-slack.el
@@ -0,0 +1,65 @@
+;;; slack.el --- Slack settings -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Wrangling the Slack client in Emacs
+
+;;; Code:
+
+;; Griffin's Slack plugin
+;;(defconst slack/token (wpc/read-file-as-string "~/dotfiles/configs/secrets/slack_token.txt"))
+;;(defconst wpc/slack-client-secret (wpc/read-file-as-string "~/dotfiles/configs/secrets/slack-client-secret"))
+(defconst wpc/slack-client-secret "uncomment above line one day")
+(load-file "~/.emacs.d/vendor/slack-snippets.el")
+
+;; Slack client
+(use-package slack
+  :general
+  (n slack-info-mode-map
+     :prefix ","
+     "u" 'slack-room-update-messages)
+  (n slack-mode-map
+     :prefix ","
+     "c"  'slack-buffer-kill
+     "ra" 'slack-message-add-reaction
+     "rr" 'slack-message-remove-reaction
+     "rs" 'slack-message-show-reaction-users
+     "pl" 'slack-room-pins-list
+     "pa" 'slack-message-pins-add
+     "pr" 'slack-message-pins-remove
+     "mm" 'slack-message-write-another-buffer
+     "me" 'slack-message-edit
+     "md" 'slack-message-delete
+     "u"  'slack-room-update-messages
+     "2"  'slack-message-embed-mention
+     "3"  'slack-message-embed-channel)
+  (n slack-mode-map
+     "C-n" 'slack-buffer-goto-next-message
+     "C-p" 'slack-buffer-goto-prev-message)
+  (n slack-edit-message-mode-map
+     :prefix ","
+     "k" 'slack-message-cancel-edit
+     "s" 'slack-message-send-from-buffer
+     "2" 'slack-message-embed-mention
+     "3" 'slack-message-embed-channel)
+  :commands (slack-start)
+  :init
+  (setq slack-buffer-emojify t) ;; if you want to enable emoji, default nil
+  (setq slack-prefer-current-team t)
+  :config
+  (add-hook 'slack-mode-hook (disable company-mode))
+  (setq slack-buffer-function #'switch-to-buffer)
+  (slack-register-team
+   :name "urbint"
+   :default t
+   :client-id "william@urbint.com"
+   :client-secret wpc/slack-client-secret
+   :token slack-token
+   :subscribed-channels '(dev dev_questions general random recruiting)
+   :full-and-display-names t))
+
+(use-package circe)
+(use-package emojify)
+
+(provide 'wpc-slack)
+;;; wpc-slack.el ends here
diff --git a/emacs.d/wpc/packages/wpc-terminal.el b/emacs.d/wpc/packages/wpc-terminal.el
new file mode 100644
index 000000000000..36a24bbb3c46
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-terminal.el
@@ -0,0 +1,19 @@
+;;; terminal.el --- My cobbled together terminal -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; My attempts at creating a sane Emacs terminal
+
+;;; Code:
+
+(setq wpc/terminal-name "wpc/terminal")
+
+;; 256 color support in term (instead of 8)
+(use-package xterm-color)
+
+(use-package term
+  :config
+  (setq explicit-shell-file-name "/bin/zsh"))
+
+(provide 'wpc-terminal)
+;;; terminal.el ends here
diff --git a/emacs.d/wpc/packages/wpc-ui.el b/emacs.d/wpc/packages/wpc-ui.el
new file mode 100644
index 000000000000..fff2db3e1160
--- /dev/null
+++ b/emacs.d/wpc/packages/wpc-ui.el
@@ -0,0 +1,136 @@
+;;; ui.el --- Any related to the UI/UX goes here -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; Hosts font settings, scrolling, color schemes.
+
+;;; Code:
+
+;; increase line height
+(setq-default line-spacing 4)
+
+;; change font
+(add-to-list 'default-frame-alist '(font . "Operator Mono-10"))
+
+;; smooth scrolling settings
+(setq scroll-step 1
+      scroll-conservatively 10000)
+
+;; theme mgt
+(use-package cycle-themes
+  :after (doom-themes)
+  :config
+  ;; NOTE: may want to use `defconst' here
+  (setq wpc/doom-themes
+        (->> (custom-available-themes)
+             (-map #'symbol-name)
+             (-filter (-partial #'s-starts-with? "doom-"))
+             (-map #'intern)))
+  (setq cycle-themes-theme-list wpc/doom-themes))
+
+;; clean up modeline
+(use-package diminish
+  :after (yasnippet ivy which-key)
+  :config
+  (diminish 'evil-commentary-mode)
+  (diminish 'flycheck-mode "Flycheck")
+  (diminish 'company-mode "Company")
+  (diminish 'auto-revert-mode)
+  (diminish 'which-key-mode)
+  (diminish 'yas-minor-mode)
+  (diminish 'ivy-mode))
+
+;; disable startup screen
+(setq inhibit-startup-screen t)
+
+;; disable toolbar
+(tool-bar-mode -1)
+
+;; enable line numbers
+(general-add-hook '(prog-mode-hook
+                    text-mode-hook
+                    conf-mode-hook)
+                  (enable linum-mode))
+;;(add-hook 'after-init-hook (lambda () (set-face-foreground 'linum "#da5468")))
+
+;; set default buffer for Emacs
+(setq initial-buffer-choice "~/urbint/grid-front-end")
+
+;; transparent Emacs
+(set-frame-parameter (selected-frame) 'alpha '(100 . 100))
+(add-to-list 'default-frame-alist '(alpha . (100 . 100)))
+
+;; premium Emacs themes
+(use-package doom-themes
+  :config
+  (setq doom-themes-enable-bold t
+        doom-themes-enable-italic t)
+  (load-theme 'doom-solarized-light t)
+  (doom-themes-visual-bell-config)
+  (doom-themes-org-config))
+
+;; kbd discovery
+(use-package which-key
+  :config
+  (setq which-key-idle-delay 0.25)
+  (which-key-mode))
+
+;; completion framework
+(use-package ivy
+  :config
+  (ivy-mode t))
+
+;; icons for Ivy
+(use-package all-the-icons-ivy
+  :after (ivy)
+  :config
+  (all-the-icons-ivy-setup))
+
+;; disable menubar
+(menu-bar-mode -1)
+(when (string-equal system-type "darwin")
+  (setq ns-auto-hide-menu-bar t))
+
+;; highlight lines that are over 100 characters long
+(use-package whitespace
+  :config
+  (setq whitespace-line-column 100)
+  (setq whitespace-style '(face lines-tail)))
+
+;; disable GUI scrollbars
+(when (display-graphic-p)
+  (scroll-bar-mode -1))
+
+;; rebalance emacs windows after splits are created
+(defadvice split-window-below (after rebalance-windows activate)
+  (balance-windows))
+
+(defadvice split-window-right (after rebalance-windows activate)
+  (balance-windows))
+
+(defadvice delete-window (after rebalance-window activate)
+  (balance-windows))
+
+;; dirname/filename instead of filename<dirname>
+(setq uniquify-buffer-name-style 'forward)
+
+;; highlight matching parens, brackets, etc
+(show-paren-mode 1)
+
+;; GUI alerts in emacs
+(use-package alert
+  :commands (alert)
+  :config
+  (setq alert-default-style 'notifier))
+
+;; focus mode
+(quelpa '(zen-mode
+          :fetcher github
+          :repo "aki237/zen-mode"))
+(require 'zen-mode)
+
+;; focus mode
+(use-package writeroom-mode)
+
+(provide 'wpc-ui)
+;;; ui.el ends here
diff --git a/emacs.d/wpc/string-functions.el b/emacs.d/wpc/string-functions.el
new file mode 100644
index 000000000000..91b46b5b409e
--- /dev/null
+++ b/emacs.d/wpc/string-functions.el
@@ -0,0 +1,41 @@
+;; functions.el --- String helper functions for my Emacs development -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; String & Symbol helpers!
+
+;;; Code:
+
+(require 'dash)
+(require 's)
+
+;; Strings
+(defun string/hookify (x)
+  "Append \"-hook\" to X."
+  (s-append "-hook" x))
+
+(defun string/ensure-hookified (x)
+  "Ensure that X has \"-hook\" appended to it."
+  (if (s-ends-with? "-hook" x)
+      x
+    (string/hookify x)))
+
+;; Symbols
+(defun symbol/as-string (callback x)
+  "Treat the symbol, X, as a string while applying CALLBACK to it.
+Coerce back to a symbol on the way out."
+  (->> x
+       symbol-name
+       callback
+       intern))
+
+(defun symbol/hookify (x)
+  "Append \"-hook\" to X when X is a symbol."
+  (symbol/as-string #'string/hookify x))
+
+(defun symbol/ensure-hookified (x)
+  "Ensure that X has \"-hook\" appended to it when X is a symbol."
+  (symbol/as-string #'string/ensure-hookified x))
+
+(provide 'string-functions)
+;;; string-functions.el ends here
diff --git a/emacs.d/wpc/variables.el b/emacs.d/wpc/variables.el
new file mode 100644
index 000000000000..af6bfde45a41
--- /dev/null
+++ b/emacs.d/wpc/variables.el
@@ -0,0 +1,18 @@
+;;; variables.el --- Helpful variables for making my ELisp life more enjoyable -*- lexical-binding: t -*-
+;; Authpr: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; This file contains helpful variables that I use in my ELisp development.
+
+;;; Code:
+
+(defvar wpc/mouse-kbds
+  '([mouse-1] [down-mouse-1] [drag-mouse-1] [double-mouse-1] [triple-mouse-1]
+    [mouse-2] [down-mouse-2] [drag-mouse-2] [double-mouse-2] [triple-mouse-2]
+    [mouse-3] [down-mouse-3] [drag-mouse-3] [double-mouse-3] [triple-mouse-3]
+    [mouse-4] [down-mouse-4] [drag-mouse-4] [double-mouse-4] [triple-mouse-4]
+    [mouse-5] [down-mouse-5] [drag-mouse-5] [double-mouse-5] [triple-mouse-5])
+  "This variable stores all of the mouse-related keybindings that Emacs recognizes.")
+
+(provide 'variables)
+;;; variables.el ends here