about summary refs log tree commit diff
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
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!
-rw-r--r--emacs.d/bookmarks15
-rw-r--r--emacs.d/custom.el52
l---------emacs.d/init.el1
-rw-r--r--emacs.d/network-security.data4
-rw-r--r--emacs.d/projectile-bookmarks.eld1
-rw-r--r--emacs.d/smex-items160
-rw-r--r--emacs.d/snippets/emacs-lisp-mode/elisp-module-docs11
-rw-r--r--emacs.d/snippets/emacs-lisp-mode/provide-footer6
-rw-r--r--emacs.d/snippets/org-mode/code-snippet7
-rw-r--r--emacs.d/snippets/org-mode/href5
-rw-r--r--emacs.d/snippets/rjsx-mode/console-log5
-rw-r--r--emacs.d/snippets/rjsx-mode/const-defn5
-rw-r--r--emacs.d/snippets/rjsx-mode/const-function7
-rw-r--r--emacs.d/snippets/rjsx-mode/destructure-const5
-rw-r--r--emacs.d/snippets/rjsx-mode/fat-arrow5
-rw-r--r--emacs.d/snippets/rjsx-mode/fat-arrow-function7
-rw-r--r--emacs.d/snippets/rjsx-mode/import-destructured5
-rw-r--r--emacs.d/snippets/rjsx-mode/import-react5
-rw-r--r--emacs.d/snippets/rjsx-mode/import-type5
-rw-r--r--emacs.d/snippets/rjsx-mode/import-x-from-y5
-rw-r--r--emacs.d/snippets/rjsx-mode/import-y5
-rw-r--r--emacs.d/snippets/rjsx-mode/jest-describe-test10
-rw-r--r--emacs.d/snippets/rjsx-mode/jest-test7
-rw-r--r--emacs.d/snippets/rjsx-mode/react-class-component11
-rw-r--r--emacs.d/vendor/org-clubhouse.el365
-rw-r--r--emacs.d/vendor/reason-indent.el304
-rw-r--r--emacs.d/vendor/reason-interaction.el216
-rw-r--r--emacs.d/vendor/reason-mode.el242
-rw-r--r--emacs.d/vendor/refmt.el231
-rw-r--r--emacs.d/vendor/slack-snippets.el228
-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
51 files changed, 3186 insertions, 0 deletions
diff --git a/emacs.d/bookmarks b/emacs.d/bookmarks
new file mode 100644
index 0000000000..a222a18de7
--- /dev/null
+++ b/emacs.d/bookmarks
@@ -0,0 +1,15 @@
+;;;; Emacs Bookmark Format Version 1 ;;;;
+;;; This format is meant to be slightly human-readable;
+;;; nevertheless, you probably don't want to edit it.
+;;; -*- End Of Bookmark File Format Version Stamp -*-
+(("org-capture-last-stored"
+ (filename . "~/org/notes.org")
+ (front-context-string . "** TODO testing ")
+ (rear-context-string)
+ (position . 9))
+("org-refile-last-stored"
+ (filename . "~/Dropbox/cryptocurrency/todo.org")
+ (front-context-string . "** TODO Maintain")
+ (rear-context-string . "h email & text)\n")
+ (position . 1465))
+)
\ No newline at end of file
diff --git a/emacs.d/custom.el b/emacs.d/custom.el
new file mode 100644
index 0000000000..88219f70cd
--- /dev/null
+++ b/emacs.d/custom.el
@@ -0,0 +1,52 @@
+(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(ansi-color-names-vector
+   ["#10151C" "#D95468" "#8BD49C" "#EBBF83" "#5EC4FF" "#E27E8D" "#70E1E8" "#9CAABB"])
+ '(custom-safe-themes
+   (quote
+    ("bd23e5e571f9b951eb79941ba3927fb493c26463654add2a53f4fb0de72ef08b" "013c62a1fcee7c8988c831027b1c38ae215f99722911b69e570f21fc19cb662e" "0b1ded82ebea8b76e3c17c628fe0d3c7aa46746c3efcf657f633d71989110585" "8ff5073d6c694a442c85505d6f885a752061b3738e2de7c2b9042ffd2c1579e5" "4f5fb2b25a9c71d584472abc5b6f850d616ac280a69e43df6e78ddf2b4aa68fa" "0a3a41085c19d8121ed0ad3eb658a475ccb948a70a83604641ee7d4c3575a4d5" "73e35ffa5ca98b57a9923954f296c3854ce6d8736b31fdbdda3d27502d4b4d69" "a7e7804313dbf827a441c86a8109ef5b64b03011383322cbdbf646eb02692f76" "77bddca0879cb3b0ecdf071d9635c818827c57d69164291cb27268ae324efa84" "3481e594ae6866d72c40ad77d86a1ffa338d01daa9eb0977e324f365cef4f47c" "6be42070d23e832a7493166f90e9bb08af348a818ec18389c1f21d33542771af" default)))
+ '(fci-rule-color "#56697A")
+ '(flycheck-javascript-flow-args nil)
+ '(jdee-db-active-breakpoint-face-colors (cons "#10151C" "#5EC4FF"))
+ '(jdee-db-requested-breakpoint-face-colors (cons "#10151C" "#8BD49C"))
+ '(jdee-db-spec-breakpoint-face-colors (cons "#10151C" "#384551"))
+ '(org-fontify-done-headline t t)
+ '(org-fontify-quote-and-verse-blocks t t)
+ '(org-fontify-whole-heading-line t t)
+ '(package-selected-packages
+   (quote
+    (writeroom-mode general rainbow-delimiters zen-mode flx-ido xterm-color evil-collection evil-text-objects-javascript evil-text-objects-haskell dired+ org-bullets slack emojify circe oauth2 engine-mode uniquify diminish elisp-slime-nav pcre2el magit-gh-pulls org-mode intero f cycle-themes ansi-term request dash-functional company-flow flycheck-flow flow-minor-mode elixir-mode oceanic-theme git-timemachine dockerfile-mode docker yaml-mode s key-chord yasnippet prettier-js rjsx-mode indium reason-mode flycheck markdown-mode smex magit all-the-icons-ivy which-key doom-themes cider hydra ace-window counsel-projectile counsel paredit projectile company evil exec-path-from-shell use-package)))
+ '(safe-local-variable-values
+   (quote
+    ((intero-targets "grid:lib" "grid:exe:grid-exe" "grid:test:doctests" "grid:test:grid-test"))))
+ '(vc-annotate-background "#10151C")
+ '(vc-annotate-color-map
+   (list
+    (cons 20 "#8BD49C")
+    (cons 40 "#abcd93")
+    (cons 60 "#cbc68b")
+    (cons 80 "#EBBF83")
+    (cons 100 "#e5ae6f")
+    (cons 120 "#df9e5b")
+    (cons 140 "#D98E48")
+    (cons 160 "#dc885f")
+    (cons 180 "#df8376")
+    (cons 200 "#E27E8D")
+    (cons 220 "#df7080")
+    (cons 240 "#dc6274")
+    (cons 260 "#D95468")
+    (cons 280 "#b05062")
+    (cons 300 "#884c5c")
+    (cons 320 "#604856")
+    (cons 340 "#56697A")
+    (cons 360 "#56697A")))
+ '(vc-annotate-very-old-color nil))
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ )
diff --git a/emacs.d/init.el b/emacs.d/init.el
new file mode 120000
index 0000000000..f5f1a3a109
--- /dev/null
+++ b/emacs.d/init.el
@@ -0,0 +1 @@
+/Users/wpcarro/dotfiles/init.el
\ No newline at end of file
diff --git a/emacs.d/network-security.data b/emacs.d/network-security.data
new file mode 100644
index 0000000000..2b0c195b21
--- /dev/null
+++ b/emacs.d/network-security.data
@@ -0,0 +1,4 @@
+(
+ (:id "sha1:88d4df3ce5800820f90edda8f27d13572234b2b9" :fingerprint "sha1:13:0e:b7:b0:c1:b7:75:40:89:0f:0b:64:20:6b:53:a5:d2:2a:a8:07" :host "api.github.com:443" :conditions (:insecure :unknown-ca :invalid))
+ (:id "sha1:85b31c268009209a8d3c5387033b219264f7e62b" :fingerprint "sha1:f8:e1:fc:e4:34:8e:19:e8:48:c1:61:fe:3d:09:dd:d4:d2:7a:cb:db" :host "melpa.org:443" :conditions (:insecure :unknown-ca :invalid))
+)
diff --git a/emacs.d/projectile-bookmarks.eld b/emacs.d/projectile-bookmarks.eld
new file mode 100644
index 0000000000..d42f6e5512
--- /dev/null
+++ b/emacs.d/projectile-bookmarks.eld
@@ -0,0 +1 @@
+("~/urbint/meta/" "~/urbint/grid-front-end/" "~/dotfiles/" "~/urbint/evil-text-objects-javascript/" "~/pc_settings/" "~/programming/doom-emacs/" "~/urbint/evil-text-objects-haskell/" "~/urbint/grid/" "~/urbint/machina/" "~/urbint/grid-front-end-reasonml/" "~/urbint/docker-images/" "~/programming/cryptocurrency/" "~/programming/a-reason-react-tutorial/")
\ No newline at end of file
diff --git a/emacs.d/smex-items b/emacs.d/smex-items
new file mode 100644
index 0000000000..c3613fa5b7
--- /dev/null
+++ b/emacs.d/smex-items
@@ -0,0 +1,160 @@
+
+;; ----- smex-history -----
+(
+ load-theme
+ disable-theme
+ cycle-themes-mode
+ cycle-themes
+ rjsx-mode
+ enable-theme
+ package-list-packages
+)
+
+;; ----- smex-data -----
+(
+ (global-company-mode . 12)
+ (global-flycheck-mode . 6)
+ (reason-mode . 1)
+ (imenu . 2)
+ (package-refresh-contents . 24)
+ (package-install . 30)
+ (indium-connect-to-chrome . 1)
+ (indium-interaction-mode . 1)
+ (rjsx-mode . 9)
+ (flycheck-info . 3)
+ (flycheck-mode . 12)
+ (flycheck-next-error . 1)
+ (flycheck-compile . 1)
+ (flycheck-select-checker . 10)
+ (yas-new-snippet . 2)
+ (yas-visit-snippet-file . 1)
+ (yas-expand . 2)
+ (yas-minor-mode . 1)
+ (describe-mode . 4)
+ (mark-defun . 5)
+ (wpc/find-or-create-js-test . 5)
+ (wpc/find-or-create-js-module . 2)
+ (wpc/toggle-between-js-test-and-module . 2)
+ (yaml-mode . 1)
+ (docker-images . 5)
+ (docker-mode . 1)
+ (dockerfile-mode . 2)
+ (snippet-mode . 2)
+ (prettier-js-mode . 23)
+ (describe-variable . 1)
+ (elixir-mode . 1)
+ (git-timemachine . 10)
+ (disable-theme . 15)
+ (load-theme . 15)
+ (xref-goto-xref . 2)
+ (flycheck-verify-setup . 7)
+ (company-flow . 15)
+ (company-mode . 8)
+ (js2-mode . 2)
+ (company-diag . 7)
+ (flow/set-flow-executable . 1)
+ (org-clubhouse-create-story . 9)
+ (org-clubhouse-mode . 1)
+ (slack-send-code-snippet . 13)
+ (indent-pp-sexp . 1)
+ (describe-personal-keybindings . 2)
+ (wpc/insert-flow-annotation . 3)
+ (ibuffer . 2)
+ (flow-minor-mode . 4)
+ (paredit-mode . 1)
+ (evil-mode . 6)
+ (global-evil-leader-mode . 9)
+ (help . 5)
+ (menu-bar-mode . 3)
+ (enable-theme . 4)
+ (ansi-term . 9)
+ (wpcarro/terminal . 17)
+ (toggle-frame-maximized . 2)
+ (previous-buffer . 1)
+ (paredit-forward-slurp-sexp . 1)
+ (paredit-raise-sexp . 1)
+ (sh-mode . 2)
+ (haskell-mode . 1)
+ (counsel-semantic-or-imenu . 1)
+ (evil-leader-mode . 9)
+ (intero-targets . 5)
+ (find-file . 1)
+ (electric-pair-mode . 8)
+ (eval-print-last-sexp . 3)
+ (evil-inner-haskell-comment-block . 5)
+ (evil-outer-haskell-comment-block . 1)
+ (elp-instrument-function . 1)
+ (elp-instrument-list . 1)
+ (magit-checkout . 2)
+ (magit-blame . 1)
+ (org-insert-link . 1)
+ (magit-mode . 2)
+ (emacs-lisp-mode . 1)
+ (magit-status . 3)
+ (magit-gh-pulls-popup . 1)
+ (magit-log . 1)
+ (org-capture . 1)
+ (flycheck-list-errors . 2)
+ (elisp-slime-nav-mode . 2)
+ (describe-font . 1)
+ (load-library . 1)
+ (diminish . 4)
+ (diminished-modes . 1)
+ (diminish-undo . 3)
+ (undo-tree-mode . 2)
+ (undo-tree-visualize . 21)
+ (undo-tree-save-state-to-register . 3)
+ (undo-tree-restore-state-from-register . 1)
+ (transpose-words . 9)
+ (downcase-dwim . 1)
+ (ffap . 2)
+ (william-carroll-kbds-minor-mode . 4)
+ (ffap-other-window . 2)
+ (eval-expression . 2)
+ (engine/search-google . 2)
+ (counsel-spotify-next . 2)
+ (counsel-spotify-search-track . 3)
+ (counsel-spotify-search-artist . 2)
+ (slack-im-select . 39)
+ (slack-start . 10)
+ (slack-group-select . 2)
+ (slack-channel-join . 1)
+ (slack-channel-select . 18)
+ (slack-select-unread-rooms . 31)
+ (slack-edit-message-mode . 1)
+ (slack-file-upload . 2)
+ (smerge-next . 3)
+ (smerge-mode . 2)
+ (smerge-keep-mine . 5)
+ (smerge-keep-other . 31)
+ (emacs-lisp-macroexpand . 43)
+ (woman . 1)
+ (package-delete . 4)
+ (ert . 12)
+ (caps->kebab . 1)
+ (text-mode . 1)
+ (org-mode . 1)
+ (dired-do-copy . 1)
+ (wpc/toggle-terminal . 1)
+ (eshell . 1)
+ (term . 1)
+ (counsel-git-grep . 12)
+ (fzf . 1)
+ (fzf-projectile . 1)
+ (fzf-git . 1)
+ (execute-extended-command . 1)
+ (package-menu-mark-upgrades . 1)
+ (package-list-packages . 7)
+ (repeat-complex-command . 1)
+ (apropos-value . 1)
+ (apropos-variable . 6)
+ (ido-find-file . 2)
+ (counsel-find-file . 1)
+ (counsel-projectile-find-file . 1)
+ (projectile-find-file . 1)
+ (zen-mode . 6)
+ (zen-mode-increase-margin-width . 1)
+ (writeroom-mode . 7)
+ (cycle-themes . 2)
+ (cycle-themes-mode . 2)
+)
diff --git a/emacs.d/snippets/emacs-lisp-mode/elisp-module-docs b/emacs.d/snippets/emacs-lisp-mode/elisp-module-docs
new file mode 100644
index 0000000000..8ea7b8f077
--- /dev/null
+++ b/emacs.d/snippets/emacs-lisp-mode/elisp-module-docs
@@ -0,0 +1,11 @@
+# -*- mode: snippet -*-
+# name: Elisp module docs
+# key: emd
+# --
+;;; `(-> (buffer-file-name) f-filename)` --- $2 -*- lexical-binding: t -*-
+;; Author: William Carroll <wpcarro@gmail.com>
+
+;;; Commentary:
+;; $3
+
+;;; Code:
\ No newline at end of file
diff --git a/emacs.d/snippets/emacs-lisp-mode/provide-footer b/emacs.d/snippets/emacs-lisp-mode/provide-footer
new file mode 100644
index 0000000000..2a0bcc33f7
--- /dev/null
+++ b/emacs.d/snippets/emacs-lisp-mode/provide-footer
@@ -0,0 +1,6 @@
+# -*- mode: snippet -*-
+# name: Provide footer
+# key: elf
+# --
+(provide '`(-> (buffer-file-name) f-filename f-no-ext)`)
+;;; `(-> (buffer-file-name) f-filename)` ends here
\ No newline at end of file
diff --git a/emacs.d/snippets/org-mode/code-snippet b/emacs.d/snippets/org-mode/code-snippet
new file mode 100644
index 0000000000..4215b15992
--- /dev/null
+++ b/emacs.d/snippets/org-mode/code-snippet
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: Code Snippet
+# key: src
+# --
+#+BEGIN_SRC $1
+$2
+#+END_SRC
\ No newline at end of file
diff --git a/emacs.d/snippets/org-mode/href b/emacs.d/snippets/org-mode/href
new file mode 100644
index 0000000000..ac65ea2e49
--- /dev/null
+++ b/emacs.d/snippets/org-mode/href
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: Org mode URL
+# key: href
+# --
+[[$1][$2]]
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/console-log b/emacs.d/snippets/rjsx-mode/console-log
new file mode 100644
index 0000000000..bc51f83133
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/console-log
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: Console.log helper
+# key: clo
+# --
+console.log($1)
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/const-defn b/emacs.d/snippets/rjsx-mode/const-defn
new file mode 100644
index 0000000000..8e35e61fc2
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/const-defn
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: const definition
+# key: cn
+# --
+const $1 = '$2'
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/const-function b/emacs.d/snippets/rjsx-mode/const-function
new file mode 100644
index 0000000000..13f2018f22
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/const-function
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: const function
+# key: cfn
+# --
+const $1 = ($2) => {
+  $3
+}
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/destructure-const b/emacs.d/snippets/rjsx-mode/destructure-const
new file mode 100644
index 0000000000..2a52c57c75
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/destructure-const
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: Destructuring a const
+# key: cds
+# --
+const { $1 } = $2
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/fat-arrow b/emacs.d/snippets/rjsx-mode/fat-arrow
new file mode 100644
index 0000000000..187a2efc5a
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/fat-arrow
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: Fat arrow function
+# key: fa
+# --
+=>
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/fat-arrow-function b/emacs.d/snippets/rjsx-mode/fat-arrow-function
new file mode 100644
index 0000000000..694914a83c
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/fat-arrow-function
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: Fat arrow function
+# key: faf
+# --
+() => {
+  $1
+}
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/import-destructured b/emacs.d/snippets/rjsx-mode/import-destructured
new file mode 100644
index 0000000000..ded3ce163a
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/import-destructured
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: Import destructured
+# key: ids
+# --
+import { $1 } from '$2'
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/import-react b/emacs.d/snippets/rjsx-mode/import-react
new file mode 100644
index 0000000000..0463f5cd55
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/import-react
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: Import React dependency (ES6)
+# key: ir
+# --
+import React from 'react'
diff --git a/emacs.d/snippets/rjsx-mode/import-type b/emacs.d/snippets/rjsx-mode/import-type
new file mode 100644
index 0000000000..fcd51f687b
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/import-type
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: import type
+# key: ixt
+# --
+import type { $1 } from '$2'
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/import-x-from-y b/emacs.d/snippets/rjsx-mode/import-x-from-y
new file mode 100644
index 0000000000..09fa6df505
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/import-x-from-y
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: import x from y
+# key: ix
+# --
+import $1 from '$2'
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/import-y b/emacs.d/snippets/rjsx-mode/import-y
new file mode 100644
index 0000000000..9f550e300d
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/import-y
@@ -0,0 +1,5 @@
+# -*- mode: snippet -*-
+# name: import y
+# key: iy
+# --
+import '$1'
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/jest-describe-test b/emacs.d/snippets/rjsx-mode/jest-describe-test
new file mode 100644
index 0000000000..ed382d4f74
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/jest-describe-test
@@ -0,0 +1,10 @@
+# -*- mode: snippet -*-
+# name: Jest describe/test block
+# key: dsc
+# --
+describe('$1', () => {
+  test('$2', () => {
+
+    expect($3).toEqual($4)
+  })
+})
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/jest-test b/emacs.d/snippets/rjsx-mode/jest-test
new file mode 100644
index 0000000000..12ca2e786d
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/jest-test
@@ -0,0 +1,7 @@
+# -*- mode: snippet -*-
+# name: Jest / Jasmine test
+# key: tst
+# --
+test('$1', () => {
+  expect($2).toBe($3)
+})
\ No newline at end of file
diff --git a/emacs.d/snippets/rjsx-mode/react-class-component b/emacs.d/snippets/rjsx-mode/react-class-component
new file mode 100644
index 0000000000..f2a93a31d9
--- /dev/null
+++ b/emacs.d/snippets/rjsx-mode/react-class-component
@@ -0,0 +1,11 @@
+# -*- mode: snippet -*-
+# name: React class extends
+# key: clz
+# --
+class $1 extends React.Component {
+  render() {
+    $2
+  }
+}
+
+export default $1
\ No newline at end of file
diff --git a/emacs.d/vendor/org-clubhouse.el b/emacs.d/vendor/org-clubhouse.el
new file mode 100644
index 0000000000..ba1f004a24
--- /dev/null
+++ b/emacs.d/vendor/org-clubhouse.el
@@ -0,0 +1,365 @@
+;;; private/grfn/org-clubhouse.el
+
+(require 'dash)
+(require 'dash-functional)
+(require 's)
+(require 'org)
+(require 'org-element)
+(require 'cl)
+
+;;;
+;;; Configuration
+;;;
+
+(defvar org-clubhouse-auth-token nil
+  "Authorization token for the Clubhouse API")
+
+(defvar org-clubhouse-team-name nil
+  "Team name to use in links to Clubhouse
+ie https://app.clubhouse.io/<TEAM_NAME>/stories")
+
+(defvar org-clubhouse-project-ids nil
+  "Specific list of project IDs to synchronize with clubhouse.
+If unset all projects will be synchronized")
+
+(defvar org-clubhouse-workflow-name "Default")
+
+(defvar org-clubhouse-state-alist
+  '(("LATER"  . "Unscheduled")
+    ("[ ]"    . "Ready for Development")
+    ("TODO"   . "Ready for Development")
+    ("OPEN"   . "Ready for Development")
+    ("ACTIVE" . "In Development")
+    ("PR"     . "Review")
+    ("DONE"   . "Merged")
+    ("[X]"    . "Merged")
+    ("CLOSED" . "Merged")))
+
+;;;
+;;; Utilities
+;;;
+
+(defun ->list (vec) (append vec nil))
+
+(defun reject-archived (item-list)
+  (-filter (lambda (item) (equal :json-false (alist-get 'archived item))) item-list))
+
+(defun alist->plist (key-map alist)
+  (->> key-map
+       (-map (lambda (key-pair)
+               (let ((alist-key (car key-pair))
+                     (plist-key (cdr key-pair)))
+                 (list plist-key (alist-get alist-key alist)))))
+       (-flatten-n 1)))
+
+(defun alist-get-equal (key alist)
+  "Like `alist-get', but uses `equal' instead of `eq' for comparing keys"
+  (->> alist
+       (-find (lambda (pair) (equal key (car pair))))
+       (cdr)))
+
+;;;
+;;; Org-element interaction
+;;;
+
+;; (defun org-element-find-headline ()
+;;   (let ((current-elt (org-element-at-point)))
+;;     (if (equal 'headline (car current-elt))
+;;         current-elt
+;;       (let* ((elt-attrs (cadr current-elt))
+;;              (parent (plist-get elt-attrs :post-affiliated)))
+;;         (goto-char parent)
+;;         (org-element-find-headline)))))
+
+(defun org-element-find-headline ()
+  (let ((current-elt (org-element-at-point)))
+    (when (equal 'headline (car current-elt))
+      (cadr current-elt))))
+
+(defun org-element-extract-clubhouse-id (elt)
+  (when-let ((clubhouse-id-link (plist-get elt :CLUBHOUSE-ID)))
+    (string-match
+     (rx "[[" (one-or-more anything) "]"
+         "[" (group (one-or-more digit)) "]]")
+     clubhouse-id-link)
+    (string-to-int (match-string 1 clubhouse-id-link))))
+
+
+
+(defun org-element-clubhouse-id ()
+  (org-element-extract-clubhouse-id
+   (org-element-find-headline)))
+
+;;;
+;;; API integration
+;;;
+
+(defvar org-clubhouse-base-url* "https://api.clubhouse.io/api/v2")
+
+(defun org-clubhouse-auth-url (url)
+  (concat url
+          "?"
+          (url-build-query-string
+           `(("token" ,org-clubhouse-auth-token)))))
+
+(defun org-clubhouse-baseify-url (url)
+  (if (s-starts-with? org-clubhouse-base-url* url) url
+    (concat org-clubhouse-base-url*
+            (if (s-starts-with? "/" url) url
+              (concat "/" url)))))
+
+(defun org-clubhouse-request (method url &optional data)
+  (message "%s %s %s" method url (prin1-to-string data))
+  (let* ((url-request-method method)
+         (url-request-extra-headers
+          '(("Content-Type" . "application/json")))
+         (url-request-data data)
+         (buf))
+
+    (setq url (-> url
+                  org-clubhouse-baseify-url
+                  org-clubhouse-auth-url))
+
+    (setq buf (url-retrieve-synchronously url))
+
+    (with-current-buffer buf
+      (goto-char url-http-end-of-headers)
+      (prog1 (json-read) (kill-buffer)))))
+
+(cl-defun to-id-name-pairs
+    (seq &optional (id-attr 'id) (name-attr 'name))
+  (->> seq
+       ->list
+       (-map (lambda (resource)
+          (cons (alist-get id-attr   resource)
+                (alist-get name-attr resource))))))
+
+(cl-defun org-clubhouse-fetch-as-id-name-pairs
+    (resource &optional
+              (id-attr 'id)
+              (name-attr 'name))
+  "Returns the given resource from clubhouse as (id . name) pairs"
+  (let ((resp-json (org-clubhouse-request "GET" resource)))
+    (-> resp-json
+        ->list
+        reject-archived
+        (to-id-name-pairs id-attr name-attr))))
+
+(defun org-clubhouse-link-to-story (story-id)
+  (format "https://app.clubhouse.io/%s/story/%d"
+          org-clubhouse-team-name
+          story-id))
+
+(defun org-clubhouse-link-to-epic (epic-id)
+  (format "https://app.clubhouse.io/%s/epic/%d"
+          org-clubhouse-team-name
+          epic-id))
+
+(defun org-clubhouse-link-to-project (project-id)
+  (format "https://app.clubhouse.io/%s/project/%d"
+          org-clubhouse-team-name
+          project-id))
+
+;;;
+;;; Caching
+;;;
+
+
+
+(defvar org-clubhouse-cache-clear-functions ())
+
+(defmacro defcache (name &optional docstring &rest body)
+  (let* ((doc (when docstring (list docstring)))
+         (cache-var-name (intern (concat (symbol-name name)
+                                         "-cache")))
+         (clear-cache-function-name
+          (intern (concat "clear-" (symbol-name cache-var-name)))))
+    `(progn
+       (defvar ,cache-var-name :no-cache)
+       (defun ,name ()
+         ,@doc
+         (when (equal :no-cache ,cache-var-name)
+           (setq ,cache-var-name (progn ,@body)))
+         ,cache-var-name)
+       (defun ,clear-cache-function-name ()
+         (interactive)
+         (setq ,cache-var-name :no-cache))
+
+       (push (quote ,clear-cache-function-name)
+             org-clubhouse-cache-clear-functions))))
+
+(defun org-clubhouse-clear-cache ()
+  (interactive)
+  (-map #'funcall org-clubhouse-cache-clear-functions))
+
+;;;
+;;; API resource functions
+;;;
+
+(defcache org-clubhouse-projects
+  "Returns projects as (project-id . name)"
+  (org-clubhouse-fetch-as-id-name-pairs "projects"))
+
+(defcache org-clubhouse-epics
+  "Returns projects as (project-id . name)"
+  (org-clubhouse-fetch-as-id-name-pairs "epics"))
+
+(defcache org-clubhouse-workflow-states
+  "Returns worflow states as (name . id) pairs"
+  (let* ((resp-json (org-clubhouse-request "GET" "workflows"))
+         (workflows (->list resp-json))
+         ;; just assume it exists, for now
+         (workflow  (-find (lambda (workflow)
+                             (equal org-clubhouse-workflow-name
+                                    (alist-get 'name workflow)))
+                           workflows))
+         (states    (->list (alist-get 'states workflow))))
+    (to-id-name-pairs states
+                      'name
+                      'id)))
+
+(defun org-clubhouse-stories-in-project (project-id)
+  "Returns the stories in the given project as org bugs"
+  (let ((resp-json (org-clubhouse-request "GET" (format "/projects/%d/stories" project-id))))
+    (->> resp-json ->list reject-archived
+         (-reject (lambda (story) (equal :json-true (alist-get 'completed story))))
+         (-map (lambda (story)
+                 (cons
+                  (cons 'status
+                        (cond
+                         ((equal :json-true (alist-get 'started story))
+                          'started)
+                         ((equal :json-true (alist-get 'completed story))
+                          'completed)
+                         ('t
+                          'open)))
+                  story)))
+         (-map (-partial #'alist->plist
+                         '((name . :title)
+                           (id . :id)
+                           (status . :status)))))))
+
+;;;
+;;; Story creation
+;;;
+
+(cl-defun org-clubhouse-create-story-internal
+    (title &key project-id epic-id)
+  (assert (and (stringp title)
+               (integerp project-id)
+               (or (null epic-id) (integerp epic-id))))
+  (org-clubhouse-request
+   "POST"
+   "stories"
+   (json-encode
+    `((name . ,title)
+      (project_id . ,project-id)
+      (epic_id . ,epic-id)))))
+
+(defun org-clubhouse-prompt-for-project (cb)
+  (ivy-read
+   "Select a project: "
+   (-map #'cdr (org-clubhouse-projects))
+   :require-match t
+   :history 'org-clubhouse-project-history
+   :action (lambda (selected)
+             (let ((project-id
+                    (->> (org-clubhouse-projects)
+                         (-find (lambda (proj)
+                                    (string-equal (cdr proj) selected)))
+                         car)))
+               (message "%d" project-id)
+               (funcall cb project-id)))))
+
+(defun org-clubhouse-prompt-for-epic (cb)
+  (ivy-read
+   "Select an epic: "
+   (-map #'cdr (org-clubhouse-epics))
+   :history 'org-clubhouse-epic-history
+   :action (lambda (selected)
+             (let ((epic-id
+                    (->> (org-clubhouse-epics)
+                         (-find (lambda (proj)
+                                    (string-equal (cdr proj) selected)))
+                         car)))
+               (message "%d" epic-id)
+               (funcall cb epic-id)))))
+
+(defun org-clubhouse-populate-created-story (story)
+  (let ((elt        (org-element-find-headline))
+        (story-id   (alist-get 'id story))
+        (epic-id    (alist-get 'epic_id story))
+        (project-id (alist-get 'project_id story)))
+
+    (org-set-property "clubhouse-id"
+                      (org-make-link-string
+                       (org-clubhouse-link-to-story story-id)
+                       (number-to-string story-id)))
+
+    (org-set-property "clubhouse-epic"
+                      (org-make-link-string
+                       (org-clubhouse-link-to-epic epic-id)
+                       (alist-get epic-id (org-clubhouse-epics))))
+
+    (org-set-property "clubhouse-project"
+                      (org-make-link-string
+                       (org-clubhouse-link-to-project project-id)
+                       (alist-get project-id (org-clubhouse-projects))))
+
+    (org-todo "TODO")))
+
+(defun org-clubhouse-create-story ()
+  (interactive)
+  ;; (message (org-element-find-headline))
+  (when-let ((elt (org-element-find-headline))
+             (title (plist-get elt :title)))
+    (if (plist-get elt :CLUBHOUSE-ID)
+        (message "This headline is already a clubhouse story!")
+      (org-clubhouse-prompt-for-project
+       (lambda (project-id)
+         (when project-id
+           (org-clubhouse-prompt-for-epic
+            (lambda (epic-id)
+              (let* ((story (org-clubhouse-create-story-internal
+                             title
+                             :project-id project-id
+                             :epic-id epic-id)))
+                (org-clubhouse-populate-created-story story))))))))))
+
+;;;
+;;; Story updates
+;;;
+
+(cl-defun org-clubhouse-update-story-internal
+    (story-id &rest attrs)
+  (assert (and (integerp story-id)
+               (listp attrs)))
+  (org-clubhouse-request
+   "PUT"
+   (format "stories/%d" story-id)
+   (json-encode attrs)))
+
+(defun org-clubhouse-update-status ()
+  (when-let (clubhouse-id (org-element-clubhouse-id))
+    (let* ((elt (org-element-find-headline))
+           (todo-keyword (-> elt (plist-get :todo-keyword) (substring-no-properties))))
+      (message todo-keyword)
+      (when-let ((clubhouse-workflow-state
+                  (alist-get-equal todo-keyword org-clubhouse-state-alist))
+                 (workflow-state-id
+                  (alist-get-equal clubhouse-workflow-state (org-clubhouse-workflow-states))))
+        (org-clubhouse-update-story-internal
+         clubhouse-id
+         :workflow_state_id workflow-state-id)
+        (message "Successfully updated clubhouse status to \"%s\""
+                 clubhouse-workflow-state)))))
+
+(define-minor-mode org-clubhouse-mode
+  :init-value nil
+  :group 'org
+  :lighter "Org-Clubhouse"
+  :keymap '()
+  (add-hook 'org-after-todo-state-change-hook
+            'org-clubhouse-update-status
+            nil
+            t))
diff --git a/emacs.d/vendor/reason-indent.el b/emacs.d/vendor/reason-indent.el
new file mode 100644
index 0000000000..8fd3c94258
--- /dev/null
+++ b/emacs.d/vendor/reason-indent.el
@@ -0,0 +1,304 @@
+;;; reason-indent.el --- Indentation functions for ReasonML -*-lexical-binding: t-*-
+
+;; Portions Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
+
+;;; Commentary:
+
+;; Indentation functions for Reason.
+
+;;; Code:
+
+(defconst reason-re-ident "[[:word:][:multibyte:]_][[:word:][:multibyte:]_[:digit:]]*")
+
+(defcustom reason-indent-offset 2
+  "Indent Reason code by this number of spaces."
+  :type 'integer
+  :group 'reason-mode
+  :safe #'integerp)
+
+(defun reason-looking-back-str (str)
+  "Like `looking-back' but for fixed strings rather than regexps.
+Works around some regexp slowness.
+Argument STR string to search for."
+  (let ((len (length str)))
+    (and (> (point) len)
+         (equal str (buffer-substring-no-properties (- (point) len) (point))))))
+
+(defun reason-paren-level ()
+  "Get the level of nesting inside parentheses."
+  (nth 0 (syntax-ppss)))
+
+(defun reason-in-str-or-cmnt ()
+  "Return whether point is currently inside a string or a comment."
+  (nth 8 (syntax-ppss)))
+
+(defun reason-rewind-past-str-cmnt ()
+  "Rewind past string or comment."
+  (goto-char (nth 8 (syntax-ppss))))
+
+(defun reason-rewind-irrelevant ()
+  "Rewind past irrelevant characters (whitespace of inside comments)."
+  (interactive)
+  (let ((starting (point)))
+    (skip-chars-backward "[:space:]\n")
+    (if (reason-looking-back-str "*/") (backward-char))
+    (if (reason-in-str-or-cmnt)
+        (reason-rewind-past-str-cmnt))
+    (if (/= starting (point))
+        (reason-rewind-irrelevant))))
+
+(defun reason-align-to-expr-after-brace ()
+  "Align the expression at point to the expression after the previous brace."
+  (save-excursion
+    (forward-char)
+    ;; We don't want to indent out to the open bracket if the
+    ;; open bracket ends the line
+    (when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$"))
+      (when (looking-at "[[:space:]]")
+        (forward-word 1)
+        (backward-word 1))
+      (current-column))))
+
+(defun reason-align-to-prev-expr ()
+  "Align the expression at point to the previous expression."
+  (let ((alignment (save-excursion
+                     (forward-char)
+                     ;; We don't want to indent out to the open bracket if the
+                     ;; open bracket ends the line
+                     (when (not (looking-at "[[:blank:]]*\\(?://.*\\)?$"))
+                       (if (looking-at "[[:space:]]")
+                           (progn
+                             (forward-word 1)
+                             (backward-word 1))
+                         (backward-char))
+                       (current-column)))))
+    (if (not alignment)
+        (save-excursion
+          (forward-char)
+          (forward-line)
+          (back-to-indentation)
+          (current-column))
+      alignment)))
+
+;;; Start of a reason binding
+(defvar reason-binding
+  (regexp-opt '("let" "type" "module" "fun")))
+
+(defun reason-beginning-of-defun (&optional arg)
+  "Move backward to the beginning of the current defun.
+
+With ARG, move backward multiple defuns.  Negative ARG means
+move forward.
+
+This is written mainly to be used as `beginning-of-defun-function'.
+Don't move to the beginning of the line.  `beginning-of-defun',
+which calls this, does that afterwards."
+  (interactive "p")
+  (re-search-backward (concat "^\\(" reason-binding "\\)\\_>")
+                      nil 'move (or arg 1)))
+
+(defun reason-end-of-defun ()
+  "Move forward to the next end of defun.
+
+With argument, do it that many times.
+Negative argument -N means move back to Nth preceding end of defun.
+
+Assume that this is called after ‘beginning-of-defun’.  So point is
+at the beginning of the defun body.
+
+This is written mainly to be used as `end-of-defun-function' for Reason."
+  (interactive)
+  ;; Find the opening brace
+  (if (re-search-forward "[{]" nil t)
+      (progn
+        (goto-char (match-beginning 0))
+        ;; Go to the closing brace
+        (condition-case nil
+            (forward-sexp)
+          (scan-error
+           ;; The parentheses are unbalanced; instead of being unable to fontify, just jump to the end of the buffer
+           (goto-char (point-max)))))
+    ;; There is no opening brace, so consider the whole buffer to be one "defun"
+    (goto-char (point-max))))
+
+(defun reason-rewind-to-beginning-of-current-level-expr ()
+  "Rewind to the beginning of the expression on the current level of nesting."
+  (interactive)
+  (let ((current-level (reason-paren-level)))
+    (back-to-indentation)
+    (when (looking-at "=>")
+      (reason-rewind-irrelevant)
+      (back-to-indentation))
+    (while (> (reason-paren-level) current-level)
+      (backward-up-list)
+      (back-to-indentation))))
+
+(defun reason-mode-indent-line ()
+  "Indent current line."
+  (interactive)
+  (let ((indent
+         (save-excursion
+           (back-to-indentation)
+           ;; Point is now at beginning of current line
+           (let* ((level (reason-paren-level))
+                  (baseline
+                   ;; Our "baseline" is one level out from the indentation of the expression
+                   ;; containing the innermost enclosing opening bracket. That
+                   ;; way if we are within a block that has a different
+                   ;; indentation than this mode would give it, we still indent
+                   ;; the inside of it correctly relative to the outside.
+                   (if (= 0 level)
+                       0
+                     (save-excursion
+                       (reason-rewind-irrelevant)
+                       (if (save-excursion
+                             (reason-rewind-to-beginning-of-current-level-expr)
+                             (looking-at "<"))
+                           (progn
+                             (reason-rewind-to-beginning-of-current-level-expr)
+                             (current-column))
+                           (progn
+                             (backward-up-list)
+                             (reason-rewind-to-beginning-of-current-level-expr)
+
+                             (cond
+                              ((looking-at "switch")
+                               (current-column))
+
+                              ((looking-at "|")
+                               (+ (current-column) (* reason-indent-offset 2)))
+
+                              (t
+                               (let ((current-level (reason-paren-level)))
+                                 (save-excursion
+                                   (while (and (= current-level (reason-paren-level))
+                                               (not (looking-at reason-binding)))
+                                     (reason-rewind-irrelevant)
+                                     (reason-rewind-to-beginning-of-current-level-expr))
+                                   (+ (current-column) reason-indent-offset)))))))))))
+             (cond
+              ;; A function return type is indented to the corresponding function arguments
+              ((looking-at "=>")
+               (+ baseline reason-indent-offset))
+
+              ((reason-in-str-or-cmnt)
+               (cond
+                ;; In the end of the block -- align with star
+                ((looking-at "*/") (+ baseline 1))
+                ;; Indent to the following shape:
+                ;; /* abcd
+                ;;  * asdf
+                ;;  */
+                ;;
+                ((looking-at "*") (+ baseline 1))
+                ;; Indent to the following shape:
+                ;; /* abcd
+                ;;    asdf
+                ;;  */
+                ;;
+                (t (+ baseline (+ reason-indent-offset 1)))))
+
+              ((looking-at "</") (- baseline reason-indent-offset))
+
+              ;; A closing brace is 1 level unindented
+              ((looking-at "}\\|)\\|\\]")
+               (save-excursion
+                 (reason-rewind-irrelevant)
+                 (let ((jsx? (reason-looking-back-str ">")))
+                   (backward-up-list)
+                   (reason-rewind-to-beginning-of-current-level-expr)
+                   (cond
+                    ((looking-at "switch") baseline)
+
+                    (jsx? (current-column))
+
+                    (t (- baseline reason-indent-offset))))))
+
+              ;; Doc comments in /** style with leading * indent to line up the *s
+              ((and (nth 4 (syntax-ppss)) (looking-at "*"))
+               (+ 1 baseline))
+
+              ;; If we're in any other token-tree / sexp, then:
+              (t
+               (or
+                ;; If we are inside a pair of braces, with something after the
+                ;; open brace on the same line and ending with a comma, treat
+                ;; it as fields and align them.
+                (when (> level 0)
+                  (save-excursion
+                    (reason-rewind-irrelevant)
+                    (backward-up-list)
+                    ;; Point is now at the beginning of the containing set of braces
+                    (reason-align-to-expr-after-brace)))
+
+                (progn
+                  (back-to-indentation)
+                  (cond ((looking-at (regexp-opt '("and" "type")))
+                         baseline)
+                        ((save-excursion
+                           (reason-rewind-irrelevant)
+                           (= (point) 1))
+                         baseline)
+                        ((save-excursion
+                           (while (looking-at "|")
+                             (reason-rewind-irrelevant)
+                             (back-to-indentation))
+                           (looking-at (regexp-opt '("type"))))
+                         (+ baseline reason-indent-offset))
+                        ((looking-at "|\\|/[/*]")
+                         baseline)
+                        ((and (> level 0)
+                              (save-excursion
+                                (reason-rewind-irrelevant)
+                                (backward-up-list)
+                                (reason-rewind-to-beginning-of-current-level-expr)
+                                (looking-at "switch")))
+                         (+ baseline reason-indent-offset))
+                        ((save-excursion
+                           (reason-rewind-irrelevant)
+                           (looking-back "[{;,\\[(]" (- (point) 2)))
+                         baseline)
+                        ((and
+                          (save-excursion
+                            (reason-rewind-irrelevant)
+                            (reason-rewind-to-beginning-of-current-level-expr)
+                            (and (looking-at reason-binding)
+                                 (not (progn
+                                        (forward-sexp)
+                                        (forward-sexp)
+                                        (skip-chars-forward "[:space:]\n")
+                                        (looking-at "=")))))
+                          (not (save-excursion
+                                 (skip-chars-backward "[:space:]\n")
+                                 (reason-looking-back-str "=>"))))
+                         (save-excursion
+                           (reason-rewind-irrelevant)
+                           (backward-sexp)
+                           (reason-align-to-prev-expr)))
+                        ((save-excursion
+                           (reason-rewind-irrelevant)
+                           (looking-back "<\/.*?>" (- (point) 30)))
+                         baseline)
+                        (t
+                         (save-excursion
+                           (reason-rewind-irrelevant)
+                           (reason-rewind-to-beginning-of-current-level-expr)
+
+                           (if (looking-at "|")
+                               baseline
+                             (+ baseline reason-indent-offset)))))
+                  ;; Point is now at the beginning of the current line
+                  ))))))))
+
+    (when indent
+      ;; If we're at the beginning of the line (before or at the current
+      ;; indentation), jump with the indentation change.  Otherwise, save the
+      ;; excursion so that adding the indentations will leave us at the
+      ;; equivalent position within the line to where we were before.
+      (if (<= (current-column) (current-indentation))
+          (indent-line-to indent)
+        (save-excursion (indent-line-to indent))))))
+
+(provide 'reason-indent)
+
+;;; reason-indent.el ends here
diff --git a/emacs.d/vendor/reason-interaction.el b/emacs.d/vendor/reason-interaction.el
new file mode 100644
index 0000000000..6ceaed1e93
--- /dev/null
+++ b/emacs.d/vendor/reason-interaction.el
@@ -0,0 +1,216 @@
+;;; reason-interaction.el --- Phrase navitagion for rtop -*-lexical-binding: t-*-
+
+;; Portions Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
+
+;;; Commentary:
+
+;; Phrase navigation for utop and maybe other REPLs.
+
+;; The utop compatibility layer for Reason was mainly taken from:
+;; https://github.com/ocaml/tuareg/blob/master/tuareg-light.el (big thanks!)
+
+;;; Code:
+
+(defun reason-backward-char (&optional step)
+  "Go back one char.
+Similar to `backward-char` but it does not signal errors
+`beginning-of-buffer` and `end-of-buffer`.  It optionally takes a
+STEP parameter for jumping back more than one character."
+  (when step (goto-char (- (point) step))
+        (goto-char (1- (point)))))
+
+(defun reason-forward-char (&optional step)
+  "Go forward one char.
+Similar to `forward-char` but it does not signal errors
+`beginning-of-buffer` and `end-of-buffer`.  It optionally takes a
+STEP parameter for jumping back more than one character."
+  (when step (goto-char (+ (point) step))
+    (goto-char (1+ (point)))))
+
+(defun reason-in-literal-p ()
+  "Return non-nil if point is inside an Reason literal."
+  (nth 3 (syntax-ppss)))
+
+(defconst reason-comment-delimiter-regexp "\\*/\\|/\\*"
+  "Regex for identify either open or close comment delimiters.")
+
+(defun reason-in-between-comment-chars-p ()
+  "Return non-nil iff point is in between the comment delimiter chars.
+It returns non-nil if point is between the chars only (*|/ or /|*
+where | is point)."
+  (and (not (bobp)) (not (eobp))
+       (or (and (char-equal ?/ (char-before)) (char-equal ?* (char-after)))
+           (and (char-equal ?* (char-before)) (char-equal ?/ (char-after))))))
+
+(defun reason-looking-at-comment-delimiters-p ()
+  "Return non-nil iff point in between comment delimiters."
+  (looking-at-p reason-comment-delimiter-regexp))
+
+(defun reason-in-between-comment-delimiters-p ()
+  "Return non-nil if inside /* and */."
+  (nth 4 (syntax-ppss)))
+
+(defun reason-in-comment-p ()
+  "Return non-nil iff point is inside or right before a comment."
+  (or (reason-in-between-comment-delimiters-p)
+      (reason-in-between-comment-chars-p)
+      (reason-looking-at-comment-delimiters-p)))
+
+(defun reason-beginning-of-literal-or-comment ()
+  "Skip to the beginning of the current literal or comment (or buffer)."
+  (interactive)
+  (goto-char (or (nth 8 (syntax-ppss)) (point))))
+
+(defun reason-inside-block-scope-p ()
+  "Skip to the beginning of the current literal or comment (or buffer)."
+  (and (> (nth 0 (syntax-ppss)) 0)
+       (let ((delim-start (nth 1 (syntax-ppss))))
+         (save-excursion
+           (goto-char delim-start)
+           (char-equal ?{ (following-char))))))
+
+(defun reason-at-phrase-break-p ()
+  "Is the underlying `;' a phrase break?"
+  ;; Difference from OCaml, the phrase separator is a single semi-colon
+  (and (not (eobp))
+       (char-equal ?\; (following-char))))
+
+(defun reason-skip-to-close-delimiter (&optional limit)
+  "Skip to the end of a Reason block.
+It basically calls `re-search-forward` in order to go to any
+closing delimiter, not concerning itself with balancing of any
+sort.  Client code needs to check that.
+LIMIT is passed to `re-search-forward` directly."
+  (re-search-forward "\\s)" limit 'move))
+
+(defun reason-skip-back-to-open-delimiter (&optional limit)
+  "Skip to the beginning of a Reason block backwards.
+It basically calls `re-search-backward` in order to go to any
+opening delimiter, not concerning itself with balancing of any
+sort.  Client code needs to check that.
+LIMIT is passed to `re-search-backward` directly."
+  (re-search-backward "\\s(" limit 'move))
+
+(defun reason-find-phrase-end ()
+  "Skip to the end of a phrase."
+  (while (and (not (eobp))
+              (not (reason-at-phrase-break-p)))
+    (if (re-search-forward ";" nil 'move)
+        (progn (when (reason-inside-block-scope-p)
+                 (reason-skip-to-close-delimiter))
+               (goto-char (1- (point))))
+      ;; avoid infinite loop at the end of the buffer
+      (re-search-forward "[[:space:]\\|\n]+" nil 'move)))
+  (min (goto-char (1+ (point))) (point-max)))
+
+(defun reason-skip-blank-and-comments ()
+  "Skip blank spaces and comments."
+  (cond
+   ((eobp) (point))
+   ((or (reason-in-between-comment-chars-p)
+        (reason-looking-at-comment-delimiters-p)) (progn
+                                                    (reason-forward-char 1)
+                                                    (reason-skip-blank-and-comments)))
+   ((reason-in-between-comment-delimiters-p) (progn
+                                               (search-forward "*/" nil t)
+                                               (reason-skip-blank-and-comments)))
+   ((eolp) (progn
+             (reason-forward-char 1)
+             (reason-skip-blank-and-comments)))
+   (t (progn (skip-syntax-forward " ")
+             (point)))))
+
+(defun reason-skip-back-blank-and-comments ()
+  "Skip blank spaces and comments backwards."
+  (cond
+   ((bobp) (point))
+   ((looking-back reason-comment-delimiter-regexp) (progn
+                                                     (reason-backward-char 1)
+                                                     (reason-skip-back-blank-and-comments)))
+   ((reason-in-between-comment-delimiters-p) (progn
+                                               (search-backward "/*" nil t)
+                                               (reason-backward-char 1)
+                                               (reason-skip-back-blank-and-comments)))
+   ((or (reason-in-between-comment-chars-p)
+        (reason-looking-at-comment-delimiters-p)) (progn
+                                                    (reason-backward-char 1)
+                                                    (reason-skip-back-blank-and-comments)))
+   ((bolp) (progn
+             (reason-backward-char 1)
+             (reason-skip-back-blank-and-comments)))
+   (t (progn (skip-syntax-backward " ")
+             (point)))))
+
+(defun reason-ro (&rest words)
+  "Build a regex matching iff at least a word in WORDS is present."
+  (concat "\\<" (regexp-opt words t) "\\>"))
+
+(defconst reason-find-phrase-beginning-regexp
+  (concat (reason-ro "end" "type" "module" "sig" "struct" "class"
+                     "exception" "open" "let")
+          "\\|^#[ \t]*[a-z][_a-z]*\\>\\|;"))
+
+(defun reason-at-phrase-start-p ()
+  "Return t if is looking at the beginning of a phrase.
+A phrase starts when a toplevel keyword is at the beginning of a line."
+  (or (looking-at "#")
+      (looking-at reason-find-phrase-beginning-regexp)))
+
+(defun reason-find-phrase-beginning-backward ()
+  "Find the beginning of a phrase and return point.
+It scans code backwards, therefore the caller can assume that the
+beginning of the phrase (if found) is always before the starting
+point.  No error is signalled and (point-min) is returned when a
+phrease cannot be found."
+  (beginning-of-line)
+  (while (and (not (bobp)) (not (reason-at-phrase-start-p)))
+    (if (reason-inside-block-scope-p)
+        (reason-skip-back-to-open-delimiter)
+      (re-search-backward reason-find-phrase-beginning-regexp nil 'move)))
+  (point))
+
+(defun reason-discover-phrase ()
+  "Discover a Reason phrase in the buffer."
+  ;; TODO reason-with-internal-syntax ;; tuareg2 modifies the syntax table (removed for now)
+  ;; TODO stop-at-and feature for phrase detection (do we need it?)
+  ;; TODO tuareg2 has some custom logic for module and class (do we need it?)
+  (save-excursion
+    (let ((case-fold-search nil))
+      (reason-skip-blank-and-comments)
+      (list (reason-find-phrase-beginning-backward) ;; beginning
+            (reason-find-phrase-end)                ;; end
+            (save-excursion                         ;; end-with-comment
+              (reason-skip-blank-and-comments)
+              (point))))))
+
+(defun reason-discover-phrase-debug ()
+  "Discover a Reason phrase in the buffer (debug mode)."
+  (let ((triple (reason-discover-phrase)))
+    (message (concat "Evaluating: \"" (reason-fetch-phrase triple) "\""))
+    triple))
+
+(defun reason-fetch-phrase (triple)
+  "Fetch the phrase text given a TRIPLE."
+  (let* ((start (nth 0 triple))
+         (end (nth 1 triple))) ;; we don't need end-with-comment
+    (buffer-substring-no-properties start end)))
+
+(defun reason-next-phrase ()
+  "Skip to the beginning of the next phrase."
+  (cond
+   ((reason-at-phrase-start-p) (point))
+   ((eolp) (progn
+             (forward-char 1)
+             (reason-skip-blank-and-comments)
+             (reason-next-phrase)))
+   ((reason-inside-block-scope-p) (progn (reason-skip-to-close-delimiter)
+                                         (reason-next-phrase)))
+   ((looking-at ";") (progn
+                       (forward-char 1)
+                       (reason-next-phrase)))
+   (t (progn (end-of-line)
+             (reason-next-phrase)))))
+
+(provide 'reason-interaction)
+
+;;; reason-interaction.el ends here
diff --git a/emacs.d/vendor/reason-mode.el b/emacs.d/vendor/reason-mode.el
new file mode 100644
index 0000000000..789735955d
--- /dev/null
+++ b/emacs.d/vendor/reason-mode.el
@@ -0,0 +1,242 @@
+;;; reason-mode.el --- A major mode for editing ReasonML -*-lexical-binding: t-*-
+;; Portions Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
+
+;; Version: 0.4.0
+;; Author: Mozilla
+;; Url: https://github.com/reasonml-editor/reason-mode
+;; Keywords: languages, ocaml
+;; Package-Requires: ((emacs "24.3"))
+
+;; This file is NOT part of GNU Emacs.
+
+;; This file is distributed under the terms of both the MIT license and the
+;; Apache License (version 2.0).
+
+;;; Commentary:
+;; This project provides useful functions and helpers for developing code
+;; using the Reason programming language (https://facebook.github.io/reason).
+;;
+;; Reason is an umbrella project that provides a curated layer for OCaml.
+;;
+;; It offers:
+;;  - A new, familiar syntax for the battle-tested language that is OCaml.
+;;  - A workflow for compiling to JavaScript and native code.
+;;  - A set of friendly documentations, libraries and utilities.
+;;
+;; See the README.md for more details.
+
+;;; Code:
+
+(require 'reason-indent)
+(require 'refmt)
+(require 'reason-interaction)
+
+(eval-when-compile (require 'rx)
+                   (require 'compile)
+                   (require 'url-vars))
+
+;; Syntax definitions and helpers
+(defvar reason-mode-syntax-table
+  (let ((table (make-syntax-table)))
+
+    ;; Operators
+    (dolist (i '(?+ ?- ?* ?/ ?& ?| ?^ ?! ?< ?> ?~ ?@))
+      (modify-syntax-entry i "." table))
+
+    ;; Strings
+    (modify-syntax-entry ?\" "\"" table)
+    (modify-syntax-entry ?\\ "\\" table)
+    (modify-syntax-entry ?\' "_"  table)
+
+    ;; Comments
+    (modify-syntax-entry ?/  ". 124b" table)
+    (modify-syntax-entry ?*  ". 23n"  table)
+    (modify-syntax-entry ?\n "> b"    table)
+    (modify-syntax-entry ?\^m "> b"   table)
+
+    table))
+
+(defgroup reason nil
+  "Support for Reason code."
+  :link '(url-link "http://facebook.github.io/reason/")
+  :group 'languages)
+
+(defcustom reason-mode-hook nil
+  "Hook called by `reason-mode'."
+  :type 'hook
+  :group 'reason)
+
+;; Font-locking definitions and helpers
+(defconst reason-mode-keywords
+  '("and" "as"
+    "else" "external"
+    "fun" "for"
+    "if" "impl" "in" "include"
+    "let"
+    "module" "match" "mod" "move" "mutable"
+    "open"
+    "priv" "pub"
+    "rec" "ref" "return"
+    "self" "static" "switch" "struct" "super"
+    "trait" "type"
+    "use"
+    "virtual"
+    "where" "when" "while"))
+
+(defconst reason-mode-consts
+  '("true" "false"))
+
+(defconst reason-special-types
+  '("int" "float" "string" "char"
+    "bool" "unit" "list" "array" "exn"
+    "option" "ref"))
+
+(defconst reason-camel-case
+  (rx symbol-start
+      (group upper (0+ (any word nonascii digit "_")))
+      symbol-end))
+
+(eval-and-compile
+  (defconst reason--char-literal-rx
+    (rx (seq (group "'")
+             (or (seq "\\" anything)
+                 (not (any "'\\")))
+             (group "'")))))
+
+(defun reason-re-word (inner)
+  "Build a word regexp given INNER."
+  (concat "\\<" inner "\\>"))
+
+(defun reason-re-grab (inner)
+  "Build a grab regexp given INNER."
+  (concat "\\(" inner "\\)"))
+
+(defun reason-regexp-opt-symbols (words)
+  "Like `(regexp-opt words 'symbols)`, but will work on Emacs 23.
+See rust-mode PR #42.
+Argument WORDS argument to pass to `regexp-opt`."
+  (concat "\\_<" (regexp-opt words t) "\\_>"))
+
+;;; Syntax highlighting for Reason
+(defvar reason-font-lock-keywords
+  `((,(reason-regexp-opt-symbols reason-mode-keywords) . font-lock-keyword-face)
+    (,(reason-regexp-opt-symbols reason-special-types) . font-lock-builtin-face)
+    (,(reason-regexp-opt-symbols reason-mode-consts) . font-lock-constant-face)
+
+    (,reason-camel-case 1 font-lock-type-face)
+
+    ;; Field names like `foo:`, highlight excluding the :
+    (,(concat (reason-re-grab reason-re-ident) ":[^:]") 1 font-lock-variable-name-face)
+    ;; Module names like `foo::`, highlight including the ::
+    (,(reason-re-grab (concat reason-re-ident "::")) 1 font-lock-type-face)
+    ;; Name punned labeled args like ::foo
+    (,(concat "[[:space:]]+" (reason-re-grab (concat "::" reason-re-ident))) 1 font-lock-type-face)
+
+    ;; TODO jsx attribs?
+    (,
+     (concat "<[/]?" (reason-re-grab reason-re-ident) "[^>]*" ">")
+     1 font-lock-type-face)))
+
+(defun reason-mode-try-find-alternate-file (mod-name extension)
+  "Switch to the file given by MOD-NAME and EXTENSION."
+  (let* ((filename (concat mod-name extension))
+         (buffer (get-file-buffer filename)))
+    (if buffer (switch-to-buffer buffer)
+      (find-file filename))))
+
+(defun reason-mode-find-alternate-file ()
+  "Switch to implementation/interface file."
+  (interactive)
+  (let ((name buffer-file-name))
+    (when (string-match "\\`\\(.*\\)\\.re\\([il]\\)?\\'" name)
+      (let ((mod-name (match-string 1 name))
+            (e (match-string 2 name)))
+        (cond
+         ((string= e "i")
+          (reason-mode-try-find-alternate-file mod-name ".re"))
+         (t
+          (reason-mode-try-find-alternate-file mod-name ".rei")))))))
+
+(defun reason--syntax-propertize-multiline-string (end)
+  "Propertize Reason multiline string.
+Argument END marks the end of the string."
+  (let ((ppss (syntax-ppss)))
+    (when (eq t (nth 3 ppss))
+      (let ((key (save-excursion
+                   (goto-char (nth 8 ppss))
+                   (and (looking-at "{\\([a-z]*\\)|")
+                        (match-string 1)))))
+        (when (search-forward (format "|%s}" key) end 'move)
+          (put-text-property (1- (match-end 0)) (match-end 0)
+                             'syntax-table (string-to-syntax "|")))))))
+
+(defun reason-syntax-propertize-function (start end)
+  "Propertize Reason function.
+Argument START marks the beginning of the function.
+Argument END marks the end of the function."
+  (goto-char start)
+  (reason--syntax-propertize-multiline-string end)
+  (funcall
+   (syntax-propertize-rules
+    (reason--char-literal-rx (1 "\"") (2 "\""))
+    ;; multi line strings
+    ("\\({\\)[a-z]*|"
+     (1 (prog1 "|"
+          (goto-char (match-end 0))
+          (reason--syntax-propertize-multiline-string end)))))
+   (point) end))
+
+(defvar reason-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-c\C-a" #'reason-mode-find-alternate-file)
+    (define-key map "\C-c\C-r" #'refmt-region-ocaml-to-reason)
+    (define-key map "\C-c\C-o" #'refmt-region-reason-to-ocaml)
+    map))
+
+;;;###autoload
+(define-derived-mode reason-mode prog-mode "Reason"
+  "Major mode for Reason code.
+
+\\{reason-mode-map}"
+  :group 'reason
+  :syntax-table reason-mode-syntax-table
+  :keymap reason-mode-map
+
+  ;; Syntax
+  (setq-local syntax-propertize-function #'reason-syntax-propertize-function)
+  ;; Indentation
+  (setq-local indent-line-function 'reason-mode-indent-line)
+  ;; Fonts
+  (setq-local font-lock-defaults '(reason-font-lock-keywords))
+  ;; Misc
+  (setq-local comment-start "/*")
+  (setq-local comment-end   "*/")
+  (setq-local indent-tabs-mode nil)
+  ;; Allow paragraph fills for comments
+  (setq-local comment-start-skip "/\\*+[ \t]*")
+  (setq-local paragraph-start
+              (concat "^[ \t]*$\\|\\*)$\\|" page-delimiter))
+  (setq-local paragraph-separate paragraph-start)
+  (setq-local require-final-newline t)
+  (setq-local normal-auto-fill-function nil)
+  (setq-local comment-multi-line t)
+
+  (setq-local beginning-of-defun-function 'reason-beginning-of-defun)
+  (setq-local end-of-defun-function 'reason-end-of-defun)
+  (setq-local parse-sexp-lookup-properties t))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.rei?\\'" . reason-mode))
+
+(defun reason-mode-reload ()
+  "Reload Reason mode."
+  (interactive)
+  (unload-feature 'reason-mode)
+  (unload-feature 'reason-indent)
+  (unload-feature 'reason-interaction)
+  (require 'reason-mode)
+  (reason-mode))
+
+(provide 'reason-mode)
+
+;;; reason-mode.el ends here
diff --git a/emacs.d/vendor/refmt.el b/emacs.d/vendor/refmt.el
new file mode 100644
index 0000000000..b9ea2b43f0
--- /dev/null
+++ b/emacs.d/vendor/refmt.el
@@ -0,0 +1,231 @@
+;;; refmt.el --- utility functions to format reason code
+
+;; Copyright (c) 2014 The go-mode Authors. All rights reserved.
+;; Portions Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
+
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are
+;; met:
+
+;; * Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;; * Redistributions in binary form must reproduce the above
+;; copyright notice, this list of conditions and the following disclaimer
+;; in the documentation and/or other materials provided with the
+;; distribution.
+;; * Neither the name of the copyright holder nor the names of its
+;; contributors may be used to endorse or promote products derived from
+;; this software without specific prior written permission.
+
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.)
+
+;;; Commentary:
+;;
+
+;;; Code:
+
+(require 'cl-lib)
+
+(defcustom refmt-command "refmt"
+  "The 'refmt' command."
+  :type 'string
+  :group 're-fmt)
+
+(defcustom refmt-show-errors 'buffer
+    "Where to display refmt error output.
+It can either be displayed in its own buffer, in the echo area, or not at all.
+Please note that Emacs outputs to the echo area when writing
+files and will overwrite refmt's echo output if used from inside
+a `before-save-hook'."
+    :type '(choice
+            (const :tag "Own buffer" buffer)
+            (const :tag "Echo area" echo)
+            (const :tag "None" nil))
+      :group 're-fmt)
+
+(defcustom refmt-width-mode nil
+  "Specify width when formatting buffer contents."
+  :type '(choice
+          (const :tag "Window width" window)
+          (const :tag "Fill column" fill)
+          (const :tag "None" nil))
+  :group 're-fmt)
+
+;;;###autoload
+(defun refmt-before-save ()
+  "Add this to .emacs to run refmt on the current buffer when saving:
+ (add-hook 'before-save-hook 'refmt-before-save)."
+    (interactive)
+      (when (eq major-mode 'reason-mode) (refmt)))
+
+(defun reason--goto-line (line)
+  (goto-char (point-min))
+    (forward-line (1- line)))
+
+(defun reason--delete-whole-line (&optional arg)
+    "Delete the current line without putting it in the `kill-ring'.
+Derived from function `kill-whole-line'.  ARG is defined as for that
+function."
+    (setq arg (or arg 1))
+    (if (and (> arg 0)
+             (eobp)
+             (save-excursion (forward-visible-line 0) (eobp)))
+        (signal 'end-of-buffer nil))
+    (if (and (< arg 0)
+             (bobp)
+             (save-excursion (end-of-visible-line) (bobp)))
+        (signal 'beginning-of-buffer nil))
+    (cond ((zerop arg)
+           (delete-region (progn (forward-visible-line 0) (point))
+                          (progn (end-of-visible-line) (point))))
+          ((< arg 0)
+           (delete-region (progn (end-of-visible-line) (point))
+                          (progn (forward-visible-line (1+ arg))
+                                 (unless (bobp)
+                                   (backward-char))
+                                 (point))))
+          (t
+           (delete-region (progn (forward-visible-line 0) (point))
+                                                  (progn (forward-visible-line arg) (point))))))
+
+(defun reason--apply-rcs-patch (patch-buffer &optional start-pos)
+  "Apply an RCS-formatted diff from PATCH-BUFFER to the current buffer."
+  (setq start-pos (or start-pos (point-min)))
+  (let ((first-line (line-number-at-pos start-pos))
+        (target-buffer (current-buffer))
+        ;; Relative offset between buffer line numbers and line numbers
+        ;; in patch.
+        ;;
+        ;; Line numbers in the patch are based on the source file, so
+        ;; we have to keep an offset when making changes to the
+        ;; buffer.
+        ;;
+        ;; Appending lines decrements the offset (possibly making it
+        ;; negative), deleting lines increments it. This order
+        ;; simplifies the forward-line invocations.
+        (line-offset 0))
+    (save-excursion
+      (with-current-buffer patch-buffer
+        (goto-char (point-min))
+        (while (not (eobp))
+          (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)")
+            (error "invalid rcs patch or internal error in reason--apply-rcs-patch"))
+          (forward-line)
+          (let ((action (match-string 1))
+                (from (string-to-number (match-string 2)))
+                (len  (string-to-number (match-string 3))))
+            (cond
+             ((equal action "a")
+              (let ((start (point)))
+                (forward-line len)
+                (let ((text (buffer-substring start (point))))
+                  (with-current-buffer target-buffer
+                    (cl-decf line-offset len)
+                    (goto-char start-pos)
+                    (forward-line (- from len line-offset))
+                    (insert text)))))
+             ((equal action "d")
+              (with-current-buffer target-buffer
+                (reason--goto-line (- (1- (+ first-line from)) line-offset))
+                (cl-incf line-offset len)
+                (reason--delete-whole-line len)))
+             (t
+              (error "invalid rcs patch or internal error in reason--apply-rcs-patch")))))))))
+
+(defun refmt--process-errors (filename tmpfile errorfile errbuf)
+  (with-current-buffer errbuf
+    (if (eq refmt-show-errors 'echo)
+        (progn
+          (message "%s" (buffer-string))
+          (refmt--kill-error-buffer errbuf))
+      (insert-file-contents errorfile nil nil nil)
+      ;; Convert the refmt stderr to something understood by the compilation mode.
+      (goto-char (point-min))
+      (insert "refmt errors:\n")
+      (while (search-forward-regexp (regexp-quote tmpfile) nil t)
+        (replace-match (file-name-nondirectory filename)))
+      (compilation-mode)
+      (display-buffer errbuf))))
+
+(defun refmt--kill-error-buffer (errbuf)
+  (let ((win (get-buffer-window errbuf)))
+    (if win
+        (quit-window t win)
+      (with-current-buffer errbuf
+        (erase-buffer))
+      (kill-buffer errbuf))))
+
+(defun apply-refmt (&optional start end from to)
+  (setq start (or start (point-min))
+        end (or end (point-max))
+        from (or from "re")
+        to (or to "re"))
+   (let* ((ext (file-name-extension buffer-file-name t))
+          (bufferfile (make-temp-file "refmt" nil ext))
+          (outputfile (make-temp-file "refmt" nil ext))
+          (errorfile (make-temp-file "refmt" nil ext))
+          (errbuf (if refmt-show-errors (get-buffer-create "*Refmt Errors*")))
+          (patchbuf (get-buffer-create "*Refmt patch*"))
+          (coding-system-for-read 'utf-8)
+          (coding-system-for-write 'utf-8)
+          (width-args
+           (cond
+            ((equal refmt-width-mode 'window)
+             (list "--print-width" (number-to-string (window-body-width))))
+            ((equal refmt-width-mode 'fill)
+             (list "--print-width" (number-to-string fill-column)))
+            (t
+             '()))))
+     (unwind-protect
+         (save-restriction
+           (widen)
+           (write-region start end bufferfile)
+           (if errbuf
+               (with-current-buffer errbuf
+                 (setq buffer-read-only nil)
+                 (erase-buffer)))
+           (with-current-buffer patchbuf
+             (erase-buffer))
+           (if (zerop (apply 'call-process
+                             refmt-command nil (list (list :file outputfile) errorfile)
+                             nil (append width-args (list "--parse" from "--print" to bufferfile))))
+               (progn
+                 (call-process-region start end "diff" nil patchbuf nil "-n" "-"
+                                      outputfile)
+                 (reason--apply-rcs-patch patchbuf start)
+                 (message "Applied refmt")
+                 (if errbuf (refmt--kill-error-buffer errbuf)))
+             (message "Could not apply refmt")
+             (if errbuf
+                 (refmt--process-errors (buffer-file-name) bufferfile errorfile errbuf)))))
+     (kill-buffer patchbuf)
+     (delete-file errorfile)
+     (delete-file bufferfile)
+     (delete-file outputfile)))
+
+(defun refmt ()
+  "Format the current buffer according to the refmt tool."
+  (interactive)
+  (apply-refmt))
+
+(defun refmt-region-ocaml-to-reason (start end)
+  (interactive "r")
+  (apply-refmt start end "ml"))
+
+(defun refmt-region-reason-to-ocaml (start end)
+  (interactive "r")
+  (apply-refmt start end "re" "ml"))
+
+(provide 'refmt)
+
+;;; refmt.el ends here
diff --git a/emacs.d/vendor/slack-snippets.el b/emacs.d/vendor/slack-snippets.el
new file mode 100644
index 0000000000..6bf933cfb8
--- /dev/null
+++ b/emacs.d/vendor/slack-snippets.el
@@ -0,0 +1,228 @@
+;;; private/grfn/slack-snippets.el -*- lexical-binding: t; -*-
+
+(require 's)
+(require 'json)
+(require 'dash)
+(require 'dash-functional)
+(require 'request)
+(require 'subr-x)
+
+;;;
+;;; Configuration
+;;;
+
+(defvar slack/token nil
+  "Legacy (https://api.slack.com/custom-integrations/legacy-tokens) access token")
+
+(defvar slack/include-public-channels 't
+  "Whether or not to inclue public channels in the list of conversations")
+
+(defvar slack/include-private-channels 't
+  "Whether or not to inclue public channels in the list of conversations")
+
+(defvar slack/include-im 't
+  "Whether or not to inclue IMs (private messages) in the list of conversations")
+
+(defvar slack/include-mpim nil
+  "Whether or not to inclue multi-person IMs (multi-person private messages) in
+  the list of conversations")
+
+;;;
+;;; Utilities
+;;;
+
+(defmacro comment (&rest _body)
+  "Comment out one or more s-expressions"
+  nil)
+
+(defun ->list (vec) (append vec nil))
+
+(defun json-truthy? (x) (and x (not (equal :json-false x))))
+
+;;;
+;;; Generic API integration
+;;;
+
+(defvar slack/base-url "https://slack.com/api")
+
+(defun slack/get (path params &optional callback)
+  "params is an alist of query parameters"
+  (let* ((params-callback (if (functionp params) `(() . ,params) (cons params callback)))
+         (params (car params-callback)) (callback (cdr params-callback))
+         (params (append `(("token" . ,slack/token)) params))
+         (url (concat (file-name-as-directory slack/base-url) path)))
+    (request url
+             :type "GET"
+             :params params
+             :parser 'json-read
+             :success (cl-function
+                       (lambda (&key data &allow-other-keys)
+                         (funcall callback data))))))
+
+(defun slack/post (path params &optional callback)
+  (let* ((params-callback (if (functionp params) `(() . ,params) (cons params callback)))
+         (params (car params-callback)) (callback (cdr params-callback))
+         (url (concat (file-name-as-directory slack/base-url) path)))
+    (request url
+             :type "POST"
+             :data (json-encode params)
+             :headers `(("Content-Type"  . "application/json")
+                        ("Authorization" . ,(format "Bearer %s" slack/token)))
+             :success (cl-function
+                       (lambda (&key data &allow-other-keys)
+                         (funcall callback data))))))
+
+
+;;;
+;;; Specific API endpoints
+;;;
+
+;; Users
+
+(defun slack/users (cb)
+  "Returns users as (id . name) pairs"
+  (slack/get
+   "users.list"
+   (lambda (data)
+     (->> data
+          (assoc-default 'members)
+          ->list
+          (-map (lambda (user)
+                  (cons (assoc-default 'id user)
+                        (assoc-default 'real_name user))))
+          (-filter #'cdr)
+          (funcall cb)))))
+
+(comment
+ (slack/get
+  "users.list"
+  (lambda (data) (setq response-data data)))
+
+ (slack/users (lambda (data) (setq --users data)))
+
+ )
+
+;; Conversations
+
+(defun slack/conversation-types ()
+  (->>
+   (list (when slack/include-public-channels  "public_channel")
+         (when slack/include-private-channels "private_channel")
+         (when slack/include-im               "im")
+         (when slack/include-mpim             "mpim"))
+   (-filter #'identity)
+   (s-join ",")))
+
+(defun channel-label (chan users-alist)
+  (cond
+   ((json-truthy? (assoc-default 'is_channel chan))
+    (format "#%s" (assoc-default 'name chan)))
+   ((json-truthy? (assoc-default 'is_im chan))
+    (let ((user-id (assoc-default 'user chan)))
+      (format "Private message with %s" (assoc-default user-id users-alist))))
+   ((json-truthy? (assoc-default 'is_mpim chan))
+    (->> chan
+         (assoc-default 'purpose)
+         (assoc-default 'value)))))
+
+(defun slack/conversations (cb)
+  "Calls `cb' with (id . '((label . \"label\") '(topic . \"topic\") '(purpose . \"purpose\"))) pairs"
+  (slack/get
+   "conversations.list"
+   `(("types"            . ,(slack/conversation-types))
+     ("exclude-archived" . "true"))
+   (lambda (data)
+     (setq --data data)
+     (slack/users
+      (lambda (users)
+        (->> data
+             (assoc-default 'channels)
+             ->list
+             (-filter
+              (lambda (chan) (channel-label chan users)))
+             (-map
+              (lambda (chan)
+                (cons (assoc-default 'id chan)
+                      `((label   . ,(channel-label chan users))
+                        (topic   . ,(->> chan
+                                         (assoc-default 'topic)
+                                         (assoc-default 'value)))
+                        (purpose . ,(->> chan
+                                         (assoc-default 'purpose)
+                                         (assoc-default 'value)))))))
+             (funcall cb)))))))
+
+(comment
+ (slack/get
+  "conversations.list"
+  '(("types" . "public_channel,private_channel,im,mpim"))
+  (lambda (data) (setq response-data data)))
+
+ (slack/get
+  "conversations.list"
+  '(("types" . "im"))
+  (lambda (data) (setq response-data data)))
+
+ (slack/conversations
+  (lambda (convos) (setq --conversations convos)))
+
+ )
+
+;; Messages
+
+(cl-defun slack/post-message
+    (&key text channel-id (on-success #'identity))
+  (slack/post "chat.postMessage"
+              `((text    . ,text)
+                (channel . ,channel-id)
+                (as_user . t))
+              on-success))
+
+(comment
+
+ (slack/post-message
+  :text "hi slackbot"
+  :channel-id slackbot-channel-id
+  :on-success (lambda (data) (setq resp data)))
+
+ (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan)))
+                            (id (car chan)))
+                        (propertize label 'channel-id id)))
+            --conversations)
+
+ )
+
+;;;
+;;; Posting code snippets to slack
+;;;
+
+(defun prompt-for-channel (cb)
+  (slack/conversations
+   (lambda (conversations)
+     (setq testing (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan)))
+                            (id (car chan)))
+                        (propertize label 'channel-id id)))
+            conversations))
+     (ivy-read
+      "Select channel: "
+      ;; TODO want to potentially use purpose / topic stuff here
+      (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan)))
+                            (id (car chan)))
+                        (propertize label 'channel-id id)))
+            conversations)
+      :history 'slack/channel-history
+      :action (lambda (selected)
+                (let ((channel-id (get-text-property 0 'channel-id selected)))
+                  (funcall cb channel-id)
+                  (message "Sent message to %s" selected))))))
+  nil)
+
+(defun slack-send-code-snippet (&optional snippet-text)
+  (interactive)
+  (when-let ((snippet-text (or snippet-text
+                               (buffer-substring-no-properties (mark) (point)))))
+    (prompt-for-channel
+     (lambda (channel-id)
+       (slack/post-message
+        :text       (format "```\n%s```" snippet-text)
+        :channel-id channel-id)))))
diff --git a/emacs.d/wpc/casing.el b/emacs.d/wpc/casing.el
new file mode 100644
index 0000000000..0592d9dddb
--- /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 0000000000..f2514a1bed
--- /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 0000000000..aedd6f5b3c
--- /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 0000000000..3644f76a70
--- /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 0000000000..ec96bdf90b
--- /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 0000000000..1c45ec35e2
--- /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 0000000000..586878fdea
--- /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 0000000000..66314af987
--- /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 0000000000..f07040fffb
--- /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 0000000000..a37a84030f
--- /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 0000000000..5dcd5937b1
--- /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 0000000000..0e74ce68ba
--- /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 0000000000..487201d476
--- /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 0000000000..d621f83d21
--- /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 0000000000..28f1f9308d
--- /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 0000000000..472f9df623
--- /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 0000000000..912cd14572
--- /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 0000000000..36a24bbb3c
--- /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 0000000000..fff2db3e11
--- /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 0000000000..91b46b5b40
--- /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 0000000000..af6bfde45a
--- /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