## Table of Contents

- 1. About
- 2. Highlights
  - 2.1. How I generate
    - 2.1.1. Git Hooks
    - 2.1.2. Read The Org
    - 2.1.3. Heading Links
    - 2.1.4. Set Background Color Source Blocks
  - 2.2. My functions section
  - 2.3. Configuration of My Own Packages
  - 2.4. Programming Language Configurations
  - 2.5. org-mode
- 3. HTML Headers
- 4. Early
  - 4.1. Lexical Binding
  - 4.2. Security
  - 4.3. ELPA Archive Setup
  - 4.4. Bootstrap Package Loading
  - 4.5. Setup auto-compile
  - 4.6. Prefer Newer Versions
  - 4.7. Custom Files
  - 4.8. emit
    - 4.8.1. TODO this needs to be done better, but it works for now
  - 4.9. Benchmarking
  - 4.10. GUI Disables
  - 4.11. Byte-Compiler
  - 4.12. exec-path-from-shell
  - 4.13. noflet
  - 4.14. Non-Forking Shell Command To String
  - 4.15. Set EMACS environment variable
- 5. Functions
  - 5.1. Join Paths
  - 5.2. Variables
  - 5.3. Use Package Wrapper With Local Load Path Support
  - 5.4. Required Packages
    - 5.4.1. s
    - 5.4.2. dash
    - 5.4.3. gh
    - 5.4.4. shut-up
    - 5.4.5. pcache
    - 5.4.6. parse-csv
    - 5.4.7. emit
    - 5.4.8. request
  - 5.5. Named Build
  - 5.6. Emacs Version Predicate
  - 5.7. Compose Functions
    - 5.7.1. A version supporting macros
    - 5.7.2. Arbitrary arguments at every step
    - 5.7.3. Simpler unary version
  - 5.8. With Advice
  - 5.9. Make Interactive
  - 5.10. Advice Add Around Builder
    - 5.10.1. Kill New
  - 5.11. Let Around
  - 5.12. Let Around Advice
  - 5.13. Let Advise
  - 5.14. Compose Around Builder
  - 5.15. Measure Time
  - 5.16. Add Files to `org-agenda-files`
  - 5.17. Get String From File
  - 5.18. Get Current Location
  - 5.19. Haversine distance
  - 5.20. Font Size
  - 5.21. Message Result Builder
  - 5.22. Custom `shell-command-on-region`
  - 5.23. Copy String Functions
    - 5.23.1. Copy portions of the buffer file name
    - 5.23.2. Copy the current branch using magit
  - 5.24. Named Compile
  - 5.25. Replace Escape Sequences
  - 5.26. Download a File Into a Buffer
  - 5.27. Concat With Symbols
  - 5.28. Edit a script on PATH
  - 5.29. Toggle lexical binding in the current buffer
  - 5.30. Sync kill ring with copyq
  - 5.31. helm-zsh-history
    - 5.31.1. Use projectile as default directory
  - 5.32. Other
  - 5.33. Keyboard Macros
    - 5.33.1. For editing literate config
      - 5.33.1.1. extract-current-sexp-to-src-block
      - 5.33.1.2. name-source-block-for-use-package-name
      - 5.33.1.3. extract-and-name-use-package-block
- 6. General
  - 6.1. User Info
  - 6.2. Sane Defaults
  - 6.3. Line Numbers
  - 6.4. Backups
    - 6.4.1. Put them all in one directory
    - 6.4.2. Completely disable backups
  - 6.5. Prompts
    - 6.5.1. No popup frames
    - 6.5.2. boolean (yes-or-no)
    - 6.5.3. No dialog boxes
  - 6.6. Splitting
  - 6.7. Buffer Display
    - 6.7.1. ewmctrl
    - 6.7.2. Handle xrefs annoying dedicated window garbage
    - 6.7.3. display-buffer-alist
  - 6.8. Fill Setup
  - 6.9. Show Trailing Whitespace
    - 6.9.1. Disable
  - 6.10. Encoding
  - 6.11. Visible Bell
  - 6.12. Configure `vc`
  - 6.13. Time in Mode Line
  - 6.14. Kill Ring
  - 6.15. Subword
  - 6.16. Scratch Buffer
  - 6.17. Don't prompt about local variables
  - 6.18. proced
  - 6.19. Set default browser
  - 6.20. Set epa program
  - 6.21. Make files executable
  - 6.22. Misc
  - 6.23. paradox
  - 6.24. diminish
  - 6.25. edit-server
  - 6.26. load-dir
  - 6.27. server
  - 6.28. list-environment
  - 6.29. bug-hunter
  - 6.30. shackle
  - 6.31. beacon
  - 6.32. iregister
  - 6.33. discover-my-major
  - 6.34. refine
  - 6.35. winner
  - 6.36. eyebrowse
  - 6.37. stream
  - 6.38. tile
  - 6.39. fill-column-indicator
- 7. Keybindings
  - 7.1. god-mode
  - 7.2. bind-key
  - 7.3. which-key
  - 7.4. hydra
    - 7.4.1. Font Settings
    - 7.4.2. Yanking
    - 7.4.3. Compile
  - 7.5. kill-emacs
  - 7.6. imenu
  - 7.7. undo
  - 7.8. other-window
  - 7.9. Mark ring
  - 7.10. Other bindings
  - 7.11. global-set-key-to-use-package
  - 7.12. OSX
- 8. Navigation
  - 8.1. zop-to-char
  - 8.2. helm
  - 8.3. helm-projectile
  - 8.4. projectile
  - 8.5. ido
  - 8.6. avy
  - 8.7. ace-window
  - 8.8. neotree
  - 8.9. jump-char
  - 8.10. flimenu
  - 8.11. swiper
- 9. Completion
  - 9.1. company
    - 9.1.1. company-flx
  - 9.2. auto-complete
- 10. Text Manipulation
  - 10.1. smartparens
  - 10.2. multiple-cursors
  - 10.3. expand-region
  - 10.4. multi-line
  - 10.5. comment-dwim-2
  - 10.6. unfill
  - 10.7. cliphist
  - 10.8. electric-operator-mode
  - 10.9. string-inflection
  - 10.10. yasnippet
- 11. Source Control
  - 11.1. magit
    - 11.1.1. magithub
  - 11.2. git-link
  - 11.3. magit-gitflow
  - 11.4. git-timemachine
  - 11.5. git-gutter
  - 11.6. gitolite-clone
  - 11.7. gitconfig-mode
  - 11.8. gitignore-mode
  - 11.9. github
    - 11.9.1. github-search
    - 11.9.2. github-clone
    - 11.9.3. github-notifier
    - 11.9.4. github-browse-file
    - 11.9.5. magit-gh-pulls
    - 11.9.6. gist
- 12. Major Modes
  - 12.1. Programming
    - 12.1.1. python
      - 12.1.1.1. pyimport
      - 12.1.1.2. jedi
    - 12.1.2. go
      - 12.1.2.1. Show diffs of testify output
    - 12.1.3. emacs-lisp
      - 12.1.3.1. elisp-slime-nav
      - 12.1.3.2. macrostep
      - 12.1.3.3. emr
      - 12.1.3.4. Editing configuration
      - 12.1.3.5. Checkdoc
      - 12.1.3.6. edebug
      - 12.1.3.7. overseer
      - 12.1.3.8. Misc
      - 12.1.3.9. Show result of eval-last-sexp inline
      - 12.1.3.10. Reevalute defvars when running eval-last-sexp
      - 12.1.3.11. Init hook
      - 12.1.3.12. Keybinds
    - 12.1.4. clojure
      - 12.1.4.1. cider
      - 12.1.4.2. clj-refactor
    - 12.1.5. scala
    - 12.1.6. js
    - 12.1.7. rust
    - 12.1.8. haskell
      - 12.1.8.1. intero
      - 12.1.8.2. hindent
      - 12.1.8.3. ghc-mod
      - 12.1.8.4. company-ghc
    - 12.1.9. C/C++
    - 12.1.10. C#
    - 12.1.11. racket
  - 12.2. Data/Config/Protocol
    - 12.2.1. thrift
    - 12.2.2. protobuf
    - 12.2.3. json-mode
    - 12.2.4. yaml-mode
    - 12.2.5. es-mode
  - 12.3. Document
    - 12.3.1. org
      - 12.3.1.1. config
      - 12.3.1.2. Use frames
      - 12.3.1.3. Set Background Color of Source Blocks for Export
      - 12.3.1.4. Use my own default naming scheme for org-headings
      - 12.3.1.5. org-projectile
      - 12.3.1.6. org-notify
      - 12.3.1.7. org-reveal
      - 12.3.1.8. org-caldav
    - 12.3.2. TeX
      - 12.3.2.1. latex
      - 12.3.2.2. auctex-latexmk
      - 12.3.2.3. company-auctex
    - 12.3.3. markdown-mode
    - 12.3.4. plantuml-mode
    - 12.3.5. wsd-mode
  - 12.4. Utility
    - 12.4.1. restclient
    - 12.4.2. jq-mode
- 13. Programming
  - 13.1. realgud
  - 13.2. emr
  - 13.3. semantic
- 14. Utility
  - 14.1. term
  - 14.2. term-manager
  - 14.3. term-projectile
  - 14.4. crux
  - 14.5. kde-connect
- 15. Chat
  - 15.1. erc
  - 15.2. bitlbee
  - 15.3. slack
- 16. Cooperation
  - 16.1. togetherly
  - 16.2. floobits
  - 16.3. rudel
- 17. Other
  - 17.1. anzu
  - 17.2. fontawesome
  - 17.3. shell-history
  - 17.4. iedit
  - 17.5. tramp
  - 17.6. flycheck
  - 17.7. narrow-indirect
  - 17.8. editorconfig
  - 17.9. dtrt-indent
  - 17.10. indent-guide
  - 17.11. rainbow-delimiters
  - 17.12. undo-tree
  - 17.13. recentf
  - 17.14. key-chord
  - 17.15. nodejs-repl
  - 17.16. calc-mode
  - 17.17. helm-spotify
  - 17.18. jabber
  - 17.19. htmlize
  - 17.20. calfw
  - 17.21. clocker
  - 17.22. deft
  - 17.23. epg
  - 17.24. pinentry
  - 17.25. twittering-mode
  - 17.26. matrix-client
  - 17.27. mu4e
  - 17.28. gmail-message-mode
  - 17.29. ham-mode
  - 17.30. alert
  - 17.31. sauron
  - 17.32. screenshot
  - 17.33. libmpdee
  - 17.34. flyspell
  - 17.35. web-mode
  - 17.36. helm-themes
  - 17.37. helm-swoop
  - 17.38. perspective
  - 17.39. smex
  - 17.40. java
  - 17.41. android-mode
  - 17.42. gradle-mode
  - 17.43. jsx-mode
  - 17.44. css
  - 17.45. robe
  - 17.46. rinari
  - 17.47. helm-gtags
  - 17.48. sgml-mode
  - 17.49. evil
  - 17.50. hackernews
- 18. Appearance
  - 18.1. Basic Config
  - 18.2. Themes
  - 18.3. all-the-icons
  - 18.4. spaceline
    - 18.4.1. Disable sRGB colorspace to make powerline separators work
    - 18.4.2. config
  - 18.5. page-break-lines
  - 18.6. helm-themes
  - 18.7. window-number
  - 18.8. Whitespace Setup
  - 18.9. Colorize Compliation Buffers
  - 18.10. Automatic Theme Changer
  - 18.11. Fix `ansi-term` Colors
  - 18.12. After `load-theme` hook
  - 18.13. Frame Initialization
- 19. Post Init Custom

I suggest you read this document at http://ivanmalison.github.io/dotfiles/ or, of course, in emacs, as the internal links that follow are unlikely to work anywhere else (including, for example, at https://github.com/IvanMalison/dotfiles).

## 1 About

This is my emacs configuration in literate form. It aspires to be like the incredibly well commented literate configurations of Sacha Chua and Ryan Rix, but I haven't quite gotten around to polishing it to the point that those two have. Still, there are definitely a few sections of which I am quite proud, and that others may find to be useful.

## 2 Highlights

These sections are the ones that have the most potential to be interesting to others:

### 2.1 How I generate http://ivanmalison.github.io/dotfiles/

#### 2.1.1 Git Hooks

I wrote a githook and an installer script that automatically update index.html at the root of the repository by running `org-html-export-to-html` on my README.org (essentially this document) . These should work no matter where they are placed in a repository. The org-mode file that they target is set here and should be relatively easy to change.

#### 2.1.2 Read The Org

I use fniessen's ReadTheOrg theme which can be found at https://github.com/fniessen/org-html-themes.

#### 2.1.3 Heading Links

To make it so that internal heading links have names that correspond to the heading text, and don't change when new headings are added to the document, I wrote a custom version of `org-export-get-reference`.

See how this link (which is just a normal internal link in the original document) takes you to http://ivanmalison.github.io/dotfiles/#usemyowndefaultnamingschemefororgheadings.

In case you haven't noticed, that is where you should go grab the code that does this.

I'm considering turning this snippet in to a package, so please let me know if that is something you are interested in.

#### 2.1.4 Set Background Color Source Blocks

For some reason, org-mode uses all of your currently active fontification when exporting EXCEPT for background color. This modification fixes this.

### 2.2 My functions section

…has a bunch of generally useful functions:

- emit-prefix-selector (SUPER USEFUL, moved to emit) See README for explantion
- Font Size functions and an Awesome Hydra for them
- Download a file into a buffer (curl straight into a file)
- Edit a script on $PATH
- Copy Portions of Buffer File Path Hydra and the associated Copy String Functions
- Named Build of Builder Macros (README) and A Compose Supporting Macros (README)

### 2.3 Configuration of My Own Packages

- term-projectile and term-manager
- org-projectile
- multi-line
- github-search
- flimenu
- tile

### 2.4 Programming Language Configurations

My programming language major mode configurations can all be found here.

### 2.5 org-mode

My org-mode configuration is pretty comprehensive, but not super well commented.

## 3 HTML Headers

## 4 Early

The configurations in this section need to occur early in emacs startup for some reason or another.

### 4.1 Lexical Binding

This makes it so that the file that is produced from tangling this file uses lexical scoping.

    ;;; -*- lexical-binding: t -*-
    (setq-default lexical-binding t)

### 4.2 Security

    (defvar imalison:secure t)

    (defun imalison:use-https-and-tls ()
      (setq tls-checktrust t)
      (let ((trustfile
             (replace-regexp-in-string
              "\\\\" "/"
              (replace-regexp-in-string
               "\n" ""
               (shell-command-to-string "python -m certifi")))))
        (setq tls-program
              (list
               (format "gnutls-cli%s --x509cafile %s -p %%p %%h"
                       (if (eq window-system 'w32) ".exe" "") trustfile)))))

    (defun imalison:test-security ()
      (interactive)
      (let ((bad-hosts
             (loop for bad
                   in `("https://wrong.host.badssl.com/"
                        "https://self-signed.badssl.com/")
                   if (condition-case _e
                          (url-retrieve
                           bad (lambda (_retrieved) t))
                        (error nil))
                   collect bad)))
        (if bad-hosts
            (error (format "tls misconfigured; retrieved %s ok"
                           bad-hosts))
          (url-retrieve "https://badssl.com"
                        (lambda (_retrieved) t)))))

    (when imalison:secure (imalison:use-https-and-tls))

### 4.3 ELPA Archive Setup

The org archive does not support https, so we set http as the protocol explicitly.

     1: (require 'package)
     2:
     3: (defun imalison:build-archive-uri (uri protocol)
     4:   (unless protocol (setq protocol (if imalison:secure "https" "http")))
     5:   (format "%s://%s" protocol uri))
     6:
     7: (defvar imalison:melpa-uri nil)
     8: (defvar imalison:package-archive-triples
     9:   `(("elpa" "tromey.com/elpa/" "http")
    10:     ("org" "orgmode.org/elpa/" "http")
    11:     ("melpa" ,(or imalison:melpa-uri "melpa.org/packages/") nil)
    12:     ("melpa-stable" "stable.melpa.org/packages/" nil)))
    13:
    14: (defun imalison:add-package-archive (archive-name archive-uri)
    15:   (add-to-list 'package-archives
    16:                `(,archive-name . ,archive-uri) t))
    17:
    18: (cl-loop for package-triple in imalison:package-archive-triples
    19:          do (cl-destructuring-bind (archive-name archive-uri protocol) package-triple
    20:               (imalison:add-package-archive
    21:                archive-name (imalison:build-archive-uri archive-uri protocol))))

### 4.4 Bootstrap Package Loading

Its a shame that everyone has to have some version of this function in their init.el. I use use-package's own mechanism for ensuring packages are installed so my version of `ensure-packages-installed` is really only used to download use-package itself.

    (defun ensure-packages-installed (packages)
      (unless package-archive-contents
        (package-refresh-contents))
      (mapcar
       (lambda (package)
         (if (package-installed-p package)
             package
           (progn (message (format "Installing package %s." package))
                  (package-install package))))
       packages))

Ensure that use-package is installed.

    (package-initialize t)
    (ensure-packages-installed '(use-package))

use-package is only needed at compile time.

    (eval-when-compile (require 'use-package))

Ensure by default since most of the package for which I use use-package need to be downloaded. ensure can be disabled explicitly with a `:ensure nil`.

    (setq use-package-always-ensure t)

### 4.5 Setup auto-compile

    (use-package auto-compile
      :demand t
      :ensure t
      :config
      (progn
        (auto-compile-on-load-mode)
        (auto-compile-on-save-mode)))

### 4.6 Prefer Newer Versions

To reduce the risk of loading outdated byte code files, we set load-prefer-newer and enable auto-compile-on-load-mode as early as possible.

    (setq load-prefer-newer t)

### 4.7 Custom Files

The default value of `custom-file` is just the current user's `.emacs.d/init.el` file. Emacs will add content to `custom-file` whenever a variable is customized or marked as safe. When init.el is version controlled, it is quite annoying to have random machine-generated variable settings amended to it because those changes are often not worth keeping permanently, so we set a different custom file here to avoid this situation.

custom-before.el is loaded before the rest of init.el, while custom-after.el is loaded afterwards. this-machine.el has customizations that should only apply to the current machine. custom-before and custom-after are not version controlled in the dotfiles repo but they are shared across machines elsewhere.

    (defvar machine-custom "~/.emacs.d/this-machine.el")
    (defvar custom-after-file "~/.emacs.d/custom-after.el")
    (setq custom-file "~/.emacs.d/custom-before.el")
    (when (file-exists-p custom-file) (load custom-file))

### 4.8 emit

#### 4.8.1 TODO this needs to be done better, but it works for now

    (when (file-exists-p "~/.emacs.d/load.d/emit.el")
      (load "~/.emacs.d/load.d/emit.el"))

### 4.9 Benchmarking

This appears here so that it can accurately benchmark as much of startup as possible.

    (defvar imalison:do-benchmark)
    (use-package benchmark-init
      :if (bound-and-true-p imalison:do-benchmark)
      :demand t)

### 4.10 GUI Disables

Death to any gui elements in emacs! Do this EARLY so that emacs doesn't redisplay in a way that is visually unpleasant on startup a bunch of times.

    (when (fboundp 'menu-bar-mode) (menu-bar-mode -1))
    (when (fboundp 'tool-bar-mode) (tool-bar-mode -1))
    (when (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))

Tooltips are annoying:

    (if (fboundp 'tooltip-mode) (tooltip-mode -1) (setq tooltip-use-echo-area t))'

### 4.11 Byte-Compiler

These definitions silence the byte-compiler.

    (defvar grep-find-ignored-directories nil)
    (defvar grep-find-ignored-files nil)
    (defvar ido-context-switch-command nil)
    (defvar ido-cur-item nil)
    (defvar ido-cur-list nil)
    (defvar ido-default-item nil)
    (defvar inherit-input-method nil)
    (defvar oauth--token-data nil)
    (defvar tls-checktrust nil)
    (defvar tls-program nil)
    (defvar url-callback-arguments nil)
    (defvar url-callback-function nil)
    (defvar url-http-extra-headers nil)

    ;; This variable doesn't exist in old versions of org-mode
    (defvar org-show-context-detail)

### 4.12 exec-path-from-shell

Sets environment variables by starting a shell.

    (use-package exec-path-from-shell
      :config
      (progn
        ;; For debugging
        (when nil
          (message "path: %s, setup: %s" (getenv "PATH")
                   (getenv "ENVIRONMENT_SETUP_DONE"))
          (setq exec-path-from-shell-debug t))
        (setq exec-path-from-shell-arguments (list "-l"))
        (setq exec-path-from-shell-check-startup-files nil)
        (add-to-list 'exec-path-from-shell-variables "SHELL")
        (add-to-list 'exec-path-from-shell-variables "GOPATH")
        (add-to-list 'exec-path-from-shell-variables "ENVIRONMENT_SETUP_DONE")
        (add-to-list 'exec-path-from-shell-variables "PYTHONPATH")
        (exec-path-from-shell-initialize)))

### 4.13 noflet

    (use-package noflet
      :demand t)

### 4.14 Non-Forking Shell Command To String

Emacs' built in `shell-command-to-string` function has the downside that it forks a new shell process every time it is executed. This means that any shell startup cost is incurred when this function is called.

The following implementation uses eshell's `executable-find` to find the binary (which is the only reason `shell-comand-to-string` is typically used anyway), but it avoids incurring any shell-startup cost.

This was originally inspired by this issue.

    (defun imalison:call-process-to-string (program &rest args)
      (with-temp-buffer
        (apply 'call-process program nil (current-buffer) nil args)
        (buffer-string)))

    (defun imalison:get-call-process-args-from-shell-command (command)
      (cl-destructuring-bind
          (the-command . args) (split-string command " ")
        (let ((binary-path (executable-find the-command)))
          (when binary-path
            (cons binary-path args)))))

    (defun imalison:shell-command-to-string (command)
      (let ((call-process-args
             (imalison:get-call-process-args-from-shell-command command)))
        (if call-process-args
            (apply 'imalison:call-process-to-string call-process-args)
          (shell-command-to-string command))))

This makes it so that we always try to call-process instead of shell-command-to-sting. It may cause undesireable behavior.

    (defun imalison:try-call-process (command)
      (let ((call-process-args
             (imalison:get-call-process-args-from-shell-command command)))
        (if call-process-args
            (apply 'imalison:call-process-to-string call-process-args))))

This had to be disabled because it was causing a bunch of issues with projectile.

    (advice-add 'shell-command-to-string :before-until 'imalison:try-call-process)

This solution only applies it to projectile-find-file

    (defun imalison:call-with-quick-shell-command (fn &rest args)
      (noflet ((shell-command-to-string (&rest args)
                                        (or (apply 'imalison:try-call-process args) (apply this-fn args))))
        (apply fn args)))

    (advice-add 'projectile-find-file :around 'imalison:call-with-quick-shell-command)

### 4.15 Set EMACS environment variable

Emacs cask seems to depend on the EMACS environment variable being set to the binary path of emacs. I found the method for getting the path to the emacs executable here.

    (setenv "EMACS"
            (file-truename (expand-file-name invocation-name invocation-directory)))

Update: It turns out that it is term-exec-1 that is causing this environment variable to be set to something strange. When I tried to disable it, it seemed to cause issues. Oh well…

## 5 Functions

### 5.1 Join Paths

Works in the same way as os.path.join in python

    (defun imalison:join-paths (root &rest dirs)
      (let ((result root))
        (cl-loop for dir in dirs do
                 (setq result (concat (file-name-as-directory result) dir)))
        result))

### 5.2 Variables

    (defvar imalison:projects-directory
      (imalison:join-paths (substitute-in-file-name "$HOME") "Projects"))

    (defvar imalison:gpg-key)

### 5.3 Use Package Wrapper With Local Load Path Support

    (put 'imalison:use-package 'lisp-indent-function 'defun)
    (put 'imalison:use-package* 'lisp-indent-function 'defun)

    (defmacro imalison:use-package* (package target-directory &rest forms)
      (let* ((actual-target (if (file-exists-p target-directory)
                                target-directory
                              (let ((in-projects (imalison:join-paths imalison:projects-directory
                                                                      target-directory)))
                                (when (file-exists-p in-projects)
                                  in-projects))))
             (additional-forms
              (when actual-target
                (list
                 :load-path actual-target
                 :ensure nil))))
        `(use-package ,package
           ,@additional-forms ,@forms)))

    (defmacro imalison:use-package (package &rest forms)
      `(imalison:use-package* ,package ,(symbol-name package) ,@forms))

### 5.4 Required Packages

The packages in this section provide no functionality on their own, but provide support for writing custom elisp.

#### 5.4.1 s

    (use-package s :demand t)

#### 5.4.2 dash

    (use-package dash
      :config
      (progn
        (dash-enable-font-lock)))

#### 5.4.3 gh

    (imalison:use-package* gh "gh.el"
      :demand t)

#### 5.4.4 shut-up

    (use-package shut-up
      :config
      (defun imalison:shut-up-around (function &rest args)
        (shut-up (apply function args))))

#### 5.4.5 pcache

    (use-package pcache
      :demand t)

#### 5.4.6 parse-csv

    (use-package parse-csv
      :demand t)

#### 5.4.7 emit

This is disabled for now until I figure out what to do with emit.

    (imalison:use-package emit
      :disabled t
      :demand t)
    (require 'emit)

#### 5.4.8 request

    (use-package request)

### 5.5 Named Build

imalison:named-build provides a way to invoke a macro in such a way that the lambda that it produces is given a name.

    (defmacro imalison:named-build (name builder &rest args)
      `(defalias (quote ,name) (,builder ,@args)))
    (put 'imalison:named-build 'lisp-indent-function 1)

`imalison:named-builder-builder` builds a macro from another macro that builds lambda functions. The arguments to the macro that results are exactly the same as those of the original macro, except that the first argument of the new macro is used to name the lambda produced by the original macro (which is passed as the second argument to `imalison:named-builder-builder`).

    (defmacro imalison:named-builder-builder (named-builder-name builder-name)
      `(progn
           (defmacro ,named-builder-name (function-name &rest args)
             (cons 'imalison:named-build
                   (cons function-name
                         (cons (quote ,builder-name) args))))
           (put (quote ,named-builder-name) 'lisp-indent-function 1)))

`imalison:named-builder` runs `imalison:named-builder-builder` with the convention that original macro to modify is the concatenation of the new macro name and the -fn suffix.

    (defmacro imalison:named-builder (name)
      `(imalison:named-builder-builder
        ,name ,(intern (concat (symbol-name name) "-fn"))))

### 5.6 Emacs Version Predicate

    (defmacro imalison:emacs-version-predicate-fn (major-version minor-version)
      `(lambda ()
         (or (> emacs-major-version ,major-version)
             (and (>= emacs-major-version ,major-version)
                  (>= emacs-minor-version ,minor-version)))))

    (defun imalison:check-emacs-version (major-version minor-version)
      (funcall (imalison:emacs-version-predicate-fn major-version minor-version)))

    (imalison:named-builder imalison:emacs-version-predicate)

### 5.7 Compose Functions

#### 5.7.1 A version supporting macros

    (defun imalison:help-function-arglist (fn)
      (let ((result (help-function-arglist fn)))
        (if (eq result t) '(&rest args) result)))

    (defmacro imalison:compose-fn (&rest funcs)
      (let* ((last-function (car (last funcs)))
             (arguments (imalison:help-function-arglist last-function))
             (call-arguments (delq '&optional arguments)))
        ;; When we have an &rest arguments there is no point in taking any
        ;; of the arguments by name, so we simply pass them all as an
        ;; argument list. See the comment below to understand how this
        ;; impacts the evaluation of the last function.
        (when (memq '&rest arguments)
          (setq arguments '(&rest args))
          (setq call-arguments '(args)))
        `(imalison:compose-argspec ,arguments ,call-arguments ,@funcs)))

    (defmacro imalison:compose-argspec (arguments call-arguments &rest funcs)
      "Build a new function with NAME that is the composition of FUNCS."
      `(lambda ,arguments
         (imalison:compose-helper ,funcs ,call-arguments)))

    (defmacro imalison:compose-helper (funcs arguments)
      "Builds funcalls of FUNCS applied to the arg."
      (if (equal (length funcs) 1)
          (let ((last-function (car funcs)))
            ;; This hideous clause is here because it is the only way to
            ;; handle functions that take &rest args.
            (when (memq '&rest (imalison:help-function-arglist last-function))
              (setq last-function (apply-partially 'apply last-function)))
            `(,last-function ,@arguments))
        `(,(car funcs)
          (imalison:compose-helper ,(cdr funcs) ,arguments))))

    (defmacro imalison:compose-macro-fn (&rest args)
      `(cons 'macro (imalison:compose-fn ,@args)))

    (imalison:named-builder imalison:compose)
    (imalison:named-builder imalison:compose-macro)

#### 5.7.2 Arbitrary arguments at every step

    (defun imalison:make-list (thing)
      (if (listp thing)
          thing
        (list thing)))

    (defmacro imalison:compose-with-apply (&rest funcs)
      "Build a new function with NAME that is the composition of FUNCS."
      `(lambda (&rest args)
         (imalison:compose-with-apply-helper ,funcs)))

    (defmacro imalison:compose-with-apply-helper (funcs)
      "Builds funcalls of FUNCS applied to the arg."
      (if (equal (length funcs) 0)
          (quote args)
        `(apply ,(car funcs)
                (imalison:make-list (imalison:compose-with-apply-helper ,(cdr funcs))))))

#### 5.7.3 Simpler unary version

    (defmacro imalison:compose-unary (&rest funcs)
      "Build a new function with NAME that is the composition of FUNCS."
      `(lambda (arg)
         (imalison:compose-helper-unary ,funcs)))

    (defmacro imalison:compose-helper-unary (funcs)
      "Builds funcalls of FUNCS applied to the arg."
      (if (equal (length funcs) 0)
          'arg
        `(funcall ,(car funcs) (imalison:compose-helper-unary ,(cdr funcs)))))

### 5.8 With Advice

Taken from here.

    (defmacro imalison:with-advice (args &rest body)
      (declare (indent 1))
      (let ((fun-name (car args))
            (advice   (cadr args))
            (orig-sym (make-symbol "orig")))
        `(cl-letf* ((,orig-sym  (symbol-function ',fun-name))
                    ((symbol-function ',fun-name)
                     (lambda (&rest args)
                       (apply ,advice ,orig-sym args))))
           ,@body)))

### 5.9 Make Interactive

    (defmacro imalison:make-interactive-fn (function)
      `(lambda (&rest args)
         (interactive)
         (apply ,function args)))

    (imalison:named-builder imalison:make-interactive)

### 5.10 Advice Add Around Builder

For composing functions with an apply so that they can be used with the `:around` keyword of advice-add.

    (defmacro imalison:advice-add-around-builder-fn (&rest functions)
      `(imalison:compose-argspec
        (function &rest args) (function args) ,@functions apply))

    (imalison:named-builder imalison:advice-add-around-builder)

#### 5.10.1 Kill New

    (imalison:advice-add-around-builder imalison:kill-new-around kill-new)

### 5.11 Let Around

    (defmacro imalison:let-around-fn (orig-func &rest forms)
      (let* ((orig-interactive-form (interactive-form orig-func))
             (docstring-form (format "Call `%s' with bindings: %s." orig-func forms))
             (additional-forms (list docstring-form)))
        (when orig-interactive-form
          (nconc additional-forms (list orig-interactive-form)))
        `(lambda (&rest args)
           ,@additional-forms
           (let ,forms
             (apply (quote ,orig-func) args)))))

    (imalison:named-builder imalison:let-around)

### 5.12 Let Around Advice

    (defmacro imalison:let-advise-around-fn (&rest forms)
      `(lambda (orig-func &rest args)
         (let ,forms
           (apply orig-func args))))

    (imalison:named-builder imalison:let-advise-around)

### 5.13 Let Advise

    (defmacro imalison:let-advise (advised-function &rest forms)
      (let ((advice-fn-name (imalison:concat-symbols
                             "around-advice-" advised-function)))
        `(progn
           (imalison:let-advise-around ,advice-fn-name ,@forms)
           (advice-add (quote ,advised-function) :around (quote ,advice-fn-name)))))
    (put 'imalison:let-advise 'lisp-indent-function 1)

### 5.14 Compose Around Builder

For composing functions with an apply so that they can be used with the `:around` keyword of advice-add.

    ;; TODO/XXX: Isn't this just apply? why doesn't apply work here
    (defun imalison:around-identity (fn &rest args)
      (apply fn args))

    (defmacro imalison:compose-around-builder-fn (&rest functions)
      `(imalison:compose-fn ,@functions imalison:around-identity))

    (imalison:named-builder imalison:compose-around-builder)

### 5.15 Measure Time

    (defmacro imalison:measure-time (&rest body)
      "Measure and return the running time of the code block."
      (declare (indent defun))
      (let ((start (make-symbol "start")))
        `(let ((,start (float-time)))
           ,@body
           (- (float-time) ,start))))

### 5.16 Add Files to `org-agenda-files`

    (defun imalison:add-to-org-agenda-files (incoming-files)
      (setq org-agenda-files
            (delete-dups
             (cl-loop for filepath in (append org-agenda-files incoming-files)
                      when (and filepath (file-exists-p (file-truename filepath)))
                      collect (file-truename filepath)))))

### 5.17 Get String From File

    (defun imalison:get-string-from-file (file-path)
      "Return file-path's file content."
      (with-temp-buffer
        (insert-file-contents file-path)
        (buffer-string)))

### 5.18 Get Current Location

    (defun imalison:get-lat-long ()
      (condition-case _ex
          (mapcar 'string-to-number (s-split "," (s-trim (shell-command-to-string
                                                          "whereami"))))
        (error (list 37.7879312624533 -122.402388853402))))

### 5.19 Haversine distance

    (defun imalison:sin2 (p)
      (let ((sin-p (sin p)))
        (* sin-p sin-p) ))

    (defun imalison:haversine-distance
        (left-lat-long right-lat-long &optional radius)
      ;; Default to earth radius in km
      (unless radius (setq radius 6378.1))
      (interactive)
      (cl-destructuring-bind (left-lat left-long) left-lat-long
        (cl-destructuring-bind (right-lat right-long) right-lat-long
          (let ((l1 (degrees-to-radians left-lat))
                (f1 (degrees-to-radians left-long))
                (l2 (degrees-to-radians right-lat))
                (f2 (degrees-to-radians right-long)) )
            (* 2 radius
               (asin
                (sqrt
                 (+ (imalison:sin2 (/ (- f2 f1) 2))
                    (* (cos f2) (cos f1) (imalison:sin2 (/ (- l2 l1) 2))) ))))))))

### 5.20 Font Size

This was taken from here but it has diverged significantly from the original.

    (defvar imalison:default-font-size-pt
          (cond ((eq system-type 'darwin) 120)
                ((eq system-type 'gnu/linux) 105)))

    (defvar imalison:huge-font-size 280)

    (defun imalison:current-font-size ()
      (plist-get (custom-face-attributes-get 'default nil) :height))

    (defun imalison:set-font-size (size)
      (interactive (list (string-to-number (read-string "Enter a font size: "))))
      (set-face-attribute 'default nil :height size))

    (defun imalison:set-huge-font-size ()
      (interactive)
      (imalison:set-font-size imalison:huge-font-size))

    (cl-defun imalison:modify-font-size (&optional (arg 10))
      (interactive "p")
      (imalison:set-font-size (+ (imalison:current-font-size) arg)))

    (defun imalison:font-size-incr ()
      (interactive)
      (imalison:modify-font-size +10))

    (defun imalison:font-size-decr ()
      (interactive)
      (imalison:modify-font-size -10))

    (defun imalison:font-size-reset ()
      (interactive)
      (imalison:set-font-size imalison:default-font-size-pt))

### 5.21 Message Result Builder

This macro is useful when writing emacs-lisp. It creates a new interactive command that shows you the result of evaluating a function, with optionally provided arguments.

    (defmacro imalison:message-result-builder (new-function-name function-to-call &rest args)
      `(defun ,new-function-name ()
         (interactive)
         (message "%s" (apply (quote ,function-to-call) (list ,@args)))))

This interactive functions allows the user the select a function to invoke using a freshly minted imalison:message-result-builder

    (defun imalison:message-result-builder-runtime (function &rest args)
      (lambda ()
        (interactive)
        (message "%s" (apply function-to-call args))))

    (defun imalison:message-function-result (function)
      (interactive (find-function-read))
      (message "%s" (funcall function)))

### 5.22 Custom `shell-command-on-region`

    (defun imalison:copy-shell-command-on-region (start end command)
      (interactive (list (region-beginning) (region-end)
                         (read-shell-command "Shell command on region: ")))
      (let ((original-buffer (current-buffer)))
        (with-temp-buffer
          (let ((temp-buffer (current-buffer)))
            (with-current-buffer original-buffer
              (shell-command-on-region start end command temp-buffer))
            (let ((min (point-min))
                  (max (point-max)))
              (kill-ring-save min max)
              (buffer-substring min max))))))

    (defun imalison:shell-command-on-region-replace (start end command)
      (interactive (list (region-beginning) (region-end)
                         (read-shell-command "Shell command on region: ")))
      (shell-command-on-region start end command nil t))

    (emit-prefix-selector imalison:shell-command-on-region
      imalison:copy-shell-command-on-region
      imalison:shell-command-on-region-replace)

### 5.23 Copy String Functions

A macro for composing functions together to build an interactive command to copy a string to the kill ring.

    (defmacro imalison:compose-copy-builder-fn (&rest funcs)
      `(imalison:make-interactive-fn
        (imalison:compose-fn kill-new ,@funcs)))

    (imalison:named-builder imalison:compose-copy-builder)

#### 5.23.1 Copy portions of the buffer file name

    (defmacro imalison:copy-buffer-file-path-builder (&rest args)
      `(imalison:compose-copy-builder ,@args buffer-file-name))

    (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-path-full)
    (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-name
                                            file-name-nondirectory)
    (imalison:copy-buffer-file-path-builder imalison:copy-buffer-file-path
                                            car
                                            projectile-make-relative-to-root
                                            list)

#### 5.23.2 Copy the current branch using magit

    (imalison:compose-copy-builder imalison:copy-current-git-branch
                                   magit-get-current-branch)

### 5.24 Named Compile

    (defun imalison:named-compile (command)
      (interactive
       (list
        (let ((command (eval compile-command)))
          (if (or compilation-read-command current-prefix-arg)
              (compilation-read-command command)
            command))))
      (compilation-start command nil (lambda (&rest args)
                                       (format "*compilation %s*" command))))

### 5.25 Replace Escape Sequences

    (defun imalison:replace-escape-sequences ()
      (interactive)
      (shut-up
        (let* ((delimited (and transient-mark-mode mark-active))
               (beg (when delimited (region-beginning)))
               (end (when delimited (region-end))))
          (save-excursion
            (perform-replace "\\t" "    " nil nil delimited nil nil beg end nil))
          (save-excursion
            (perform-replace "\\n" "\n" nil nil delimited nil nil beg end nil)))))

### 5.26 Download a File Into a Buffer

    (defun imalison:download-to-buffer (uri)
      (interactive (list (read-string "Enter uri: ")))
      (request uri
               :parser 'buffer-string
               :success (cl-function
                         (lambda (&key data &allow-other-keys)
                           (let ((created-buffer (get-buffer-create uri)))
                             (with-current-buffer created-buffer
                               (insert data))
                             (switch-to-buffer created-buffer))))))

### 5.27 Concat With Symbols

    (defun imalison:maybe-symbol-name (arg)
      (if (symbolp arg)
          (symbol-name arg)
        arg))

    (defun imalison:concat-symbols (&rest args)
      (intern (mapconcat 'imalison:maybe-symbol-name args "")))

### 5.28 Edit a script on PATH

Note that you'll need to make sure that emacs properly inherits the path variable for this work. Check out my exec-path-from-shell config for details.

    (defun imalison:get-executables-at-path (filepath)
      (when (and (file-exists-p filepath) (f-directory? filepath))
        (--filter (let ((fullpath (imalison:join-paths filepath it)))
                    (and (file-executable-p fullpath)
                         (not (f-directory? fullpath))))
                  (directory-files filepath))))

    (defun imalison:get-executables-on-path ()
      (mapcan 'imalison:get-executables-at-path (eshell-parse-colon-path (getenv "PATH"))))

    (defun imalison:edit-script ()
      (interactive)
      (find-file (executable-find
                  (ido-completing-read "Select a script to edit: "
                                       (imalison:get-executables-on-path)))))

### 5.29 Toggle lexical binding in the current buffer

    (defun imalison:toggle-lexical-binding ()
      (interactive)
      (let ((new-binding (not lexical-binding)))
        (message "Setting lexical-binding to: %s" new-binding)
        (setq lexical-binding new-binding)))

### 5.30 Sync kill ring with copyq

    (defun imalison:copyq-get (i)
      (imalison:shell-command-to-string (format "copyq eval read(%s)" i)))

    (defun imalison:copyq-sync ()
      (interactive)
      (let ((missing-items (cl-loop for i from 0 to (string-to-number
                             (imalison:shell-command-to-string "copyq eval size()"))
             for item = (imalison:copyq-get i)
             when (not (member item kill-ring))
             collect item)))
        (setq kill-ring (nconc kill-ring missing-items))))

    (when (executable-find "copyq")
     (run-with-idle-timer 10 nil 'imalison:copyq-sync))

### 5.31 helm-zsh-history

This was stolen from https://github.com/jwiegley/dot-emacs

    (defvar helm-c-source-zsh-history
      '((name . "Zsh History")
        (candidates . helm-c-zsh-history-set-candidates)
        (action . (("Execute Command" . helm-c-zsh-history-action)))
        (volatile)
        (requires-pattern . 3)
        (delayed)))

    (defun helm-c-zsh-history-set-candidates (&optional request-prefix)
      (let ((pattern (replace-regexp-in-string
                      " " ".*"
                      (or (and request-prefix
                               (concat request-prefix
                                       " " helm-pattern))
                          helm-pattern))))
        (with-current-buffer (find-file-noselect "~/.zsh_history" t t)
          (auto-revert-mode -1)
          (goto-char (point-max))
          (loop for pos = (re-search-backward pattern nil t)
                while pos
                collect (replace-regexp-in-string
                         "\\`:.+?;" ""
                         (buffer-substring (line-beginning-position)
                                           (line-end-position)))))))

    (defun helm-c-zsh-history-action (candidate)
      (imalison:named-compile candidate))

    (defun helm-command-from-zsh ()
      (interactive)
      (require 'helm)
      (helm-other-buffer 'helm-c-source-zsh-history "*helm zsh history*"))

#### 5.31.1 Use projectile as default directory

    (imalison:let-around imalison:projectile-helm-command-from-zsh helm-command-from-zsh
                         (default-directory (projectile-project-root)))

### 5.32 Other

The stuff in this section is pretty crusty. I don't think its used anywhere, but I keep it around just in case I need it.

    (defun random-choice (choices)
      (nth (random (length choices)) choices))

    (defun display-prefix (arg)
      "Display the value of the raw prefix arg."
      (interactive "p")
      (message "%s" arg))

    (defun imalison:uuid ()
      (interactive)
      (s-replace "\n" "" (shell-command-to-string "uuid")))

    (defun imalison:disable-linum-mode ()
      (linum-mode 0))

    (defun imalison:disable-smartparens-mode ()
      (smartparens-mode 0))

    (defun imalison:insert-uuid ()
      (interactive)
      (insert (imalison:uuid)))

    (defun imalison:compare-int-list (a b)
      (when (and a b)
        (cond ((> (car a) (car b)) 1)
              ((< (car a) (car b)) -1)
              (t (imalison:compare-int-list (cdr a) (cdr b))))))

    (defun get-date-created-from-agenda-entry (agenda-entry)
      (org-time-string-to-time
       (org-entry-get (get-text-property 1 'org-marker agenda-entry) "CREATED")))

    (defmacro defvar-setq (name value)
      `(if (boundp (quote ,name))
           (setq ,name ,value)
         (defvar ,name ,value)))

    (defun eval-region-or-last-sexp ()
      (interactive)
      (if (region-active-p) (call-interactively 'eval-region)
        (call-interactively 'eval-last-sexp)))

    (defun undo-redo (&optional arg)
      (interactive "P")
      (if arg (undo-tree-redo) (undo-tree-undo)))

    (defun up-list-region ()
      (interactive)
      (up-list) (set-mark-command nil) (backward-sexp))

    (defun up-list-back ()
      (interactive)
      (up-list) (backward-sexp))

    (defun frame-exists ()
      (cl-find-if
       (lambda (frame)
         (assoc 'display (frame-parameters frame))) (frame-list)))

    (defun make-frame-if-none-exists ()
      (let* ((existing-frame (frame-exists)))
        (if existing-frame
            existing-frame
          (make-frame-on-display (getenv "DISPLAY")))))

    (defun make-frame-if-none-exists-and-focus ()
      (make-frame-visible (select-frame (make-frame-if-none-exists))))

    (defun notification-center (title message)
      (cl-flet ((encfn (s) (encode-coding-string s (keyboard-coding-system))))
        (shell-command
         (format "osascript -e 'display notification \"%s\" with title \"%s\"'"
                 (encfn message) (encfn title)))))

    (defun growl-notify (title message)
      (shell-command (format "grownotify -t %s -m %s" title message)))

    (defun notify-send (title message)
      (shell-command (format "notify-send -u critical %s %s" title message)))

    (defvar notify-function
      (cond ((eq system-type 'darwin) 'notification-center)
            ((eq system-type 'gnu/linux) 'notify-send)))

    (emit-prefix-selector imalison:mark-ring
      helm-mark-ring
      helm-global-mark-ring)

### 5.33 Keyboard Macros

#### 5.33.1 For editing literate config

##### 5.33.1.1 extract-current-sexp-to-src-block

This keyboard macro extracts the current sexp to an emacs-lisp source block of its own

    (fset 'extract-current-sexp-to-src-block
          [?\C-a return ?\C-p ?# ?+ ?E ?N ?D ?_ ?S ?R ?C return ?# ?+ ?B ?E ?G ?I ?N ?_ ?S ?R ?C ?  ?e ?m ?a ?c ?s ?- ?l ?i ?s ?p ?\C-a ?\C-p ?\C-  ?\C-n ?\C-e ?\M-w ?\C-n ?\C-a ?\C-\M-f return ?\C-y])

##### 5.33.1.2 name-source-block-for-use-package-name

    (fset 'name-source-block-for-use-package-name
          [?\C-c ?\' ?\M-< ?\C-s ?u ?s ?e ?- ?p ?a ?c ?k return ?\C-\M-f ?\C-f ?\C-  ?\C-\M-f ?\M-w ?\C-c ?\' ?\C-r ?B ?E ?G ?I ?N return ?\C-a ?\C-p ?\C-e return ?* ?  ?\C-y])

##### 5.33.1.3 extract-and-name-use-package-block

    (fset 'extract-and-name-use-package-block
          [?\C-a return ?\C-p ?# ?+ ?E ?N ?D ?_ ?S ?R ?C return ?# ?+ ?B ?E ?G ?I ?N ?_ ?S ?R ?C ?  ?e ?m ?a ?c ?s ?- ?l ?i ?s ?p ?\C-a ?\C-p ?\C-  ?\C-n ?\C-e ?\M-w ?\C-n ?\C-a ?\C-\M-f return ?\C-y ?\C-p ?\C-p ?\C-c ?\' ?\M-< ?\C-s ?u ?s ?e ?- ?p ?a ?c ?k return ?\C-\M-f ?\C-f ?\C-  ?\C-\M-f ?\M-w ?\C-c ?\' ?\C-r ?B ?E ?G ?I ?N return ?\C-a ?\C-p ?\C-e return ?* ?  ?\C-y])

## 6 General

### 6.1 User Info

    (setq user-full-name
          (replace-regexp-in-string "\n$" "" (shell-command-to-string
                                              "git config --get user.name")))
    (setq user-mail-address
          (replace-regexp-in-string "\n$" "" (shell-command-to-string
                                              "git config --get user.email")))

### 6.2 Sane Defaults

    1: (global-auto-revert-mode)
    2: (show-paren-mode 1)
    3: (setq reb-re-syntax 'string)
    4: (setq ad-redefinition-action 'accept)
    5: (setq-default find-file-visit-truename t)
    6: (setq large-file-warning-threshold (* 25 1024 1024))
    7: (setq line-move-visual t)
    8: (setq require-final-newline t)

This is set because this alias causes annoying messaging at startup.

### 6.3 Line Numbers

    (line-number-mode t)
    (column-number-mode t)

Linum can be really slow on large files so it does not make sense to have it on by default. Its probably safe to turn it on when in a programming mode.

    (global-linum-mode -1)
    (add-hook 'prog-mode-hook (lambda () (linum-mode t)))

### 6.4 Backups

#### 6.4.1 Put them all in one directory

    (defconst emacs-tmp-dir
      (format "%s/%s%s/" temporary-file-directory "emacs" (user-uid)))
    (setq backup-directory-alist `((".*" . ,emacs-tmp-dir)))
    (setq auto-save-file-name-transforms `((".*" ,emacs-tmp-dir t)))
    (setq auto-save-list-file-prefix emacs-tmp-dir)

#### 6.4.2 Completely disable backups

    (setq backup-inhibited t)
    (setq make-backup-files nil)
    (setq auto-save-default nil)

### 6.5 Prompts

#### 6.5.1 No popup frames

    (setq ns-pop-up-frames nil)
    (setq pop-up-frames nil)

#### 6.5.2 boolean (yes-or-no)

     1: (defadvice yes-or-no-p (around prevent-dialog activate)
     2:   "Prevent yes-or-no-p from activating a dialog"
     3:   (let ((use-dialog-box nil))
     4:     ad-do-it))
     5:
     6: (defadvice y-or-n-p (around prevent-dialog-yorn activate)
     7:   "Prevent y-or-n-p from activating a dialog"
     8:   (let ((use-dialog-box nil))
     9:     ad-do-it))
    10:
    11: (defalias 'yes-or-no-p 'y-or-n-p)

#### 6.5.3 No dialog boxes

    (setq use-dialog-box nil)

### 6.6 Splitting

    (defun split-horizontally-for-temp-buffers () (split-window-horizontally))
    (add-hook 'temp-buffer-setup-hook 'split-horizontally-for-temp-buffers)
    (setq split-height-threshold nil)
    (setq split-width-threshold 160)

### 6.7 Buffer Display

#### 6.7.1 ewmctrl

    (use-package ewmctrl
      :demand t)

#### 6.7.2 Handle xrefs annoying dedicated window garbage

    (defun xref--show-pos-in-buf (pos buf select)
      (let ((xref-buf (current-buffer))
            win)
        (with-selected-window
          (display-buffer buf)
          (xref--goto-char pos)
          (run-hooks 'xref-after-jump-hook)
          (let ((buf (current-buffer)))
            (setq win (selected-window))
            (with-current-buffer xref-buf
              (setq-local other-window-scroll-buffer buf))))
        (when select
          (select-window win))))

#### 6.7.3 display-buffer-alist

    (defvar imalison:use-frames-only)

    (defvar imalison:use-frames-only nil)

    (defun imalison:use-frames-only ()
      (or imalison:use-frames-only
          (member (getenv "XDG_CURRENT_DESKTOP") '("XMonad"))))

    (defvar imalison:use-new-frame-or-window nil)

    (defvar imalison:use-new-frame-or-window-next-command nil)

    (defun imalison:other-window-or-frame-next-command ()
      (interactive)
      (setq imalison:use-new-frame-or-window-next-command t))

    (defun imalison:use-other-frame-or-window (&rest args)
      (or
       (when imalison:use-new-frame-or-window-next-command
         (setq imalison:use-new-frame-or-window-next-command nil)
         t)
       imalison:use-new-frame-or-window))

    (defun imalison:display-buffer (&rest args)
      (if (imalison:use-other-frame-or-window args)
          (apply 'imalison:display-buffer-other-frame-or-window args)
        (apply 'display-buffer-same-window args)))

    (defun imalison:display-buffer-other-frame-or-window (buffer &rest args)
      (if (imalison:use-frames-only)
          (display-buffer buffer '((display-buffer-reuse-window
                                    display-buffer-pop-up-frame)
                                   (reusable-frames . t)
                                   (inhibit-same-window . t)) t)
        (apply 'display-buffer-reuse-window args)))

    (defun imalison:split-window-right ()
      (interactive)
      (if (imalison:use-frames-only)
          (make-frame)
        (split-window-right)))

    (defun imalison:other-window (&rest args)
      (interactive
       (list 1))
      (if (imalison:use-frames-only)
          (apply 'other-frame args)
        (apply 'other-window args)))

    (when imalison:use-frames-only
      (setq pop-up-frames 'graphic-only)
      (bind-key "C-c s" 'imalison:other-window-or-frame-next-command)
      (bind-key "C-x o" 'imalison:other-window)
      (bind-key "C-x 3" 'imalison:split-window-right)
      (bind-key "C-x O" (lambda () (interactive) (imalison:other-window -1)))
      (setq display-buffer-alist
            '((".*popup\*" . (display-buffer-pop-up-window))
              ;; XXX: This was a failed attempt to get magit-commit to properly use
              ;; frames.

              (".*magit-diff.*" . ((display-buffer-pop-up-window)
                                   ((reusable-frames . 0)
                                    (inhibit-switch-frame . t)
                                    (inhibit-same-window . t))))
              ;; (".*COMMIT_.*MSG.*" . ((display-buffer-pop-up-frame)
              ;;                          ((reusable-frames . 0)
              ;;                           (inhibit-same-window . t))))
              (".*" . ((imalison:display-buffer display-buffer-same-window
                                                display-buffer-pop-up-frame)
                       ((reusable-frames . t)))))))

### 6.8 Fill Setup

Get rid of nags about requiring setences to end with two spaces.

    (setq sentence-end-double-space nil)

Set the default fill-column

    (setq-default fill-column 80)

### 6.9 Show Trailing Whitespace

Trailing whitespace is really messy and annoying, which makes this a must-have in my opinion. It's kind of crazy how often you will encounter serious codebases with random whitespace ALL over the place.

    (setq-default show-trailing-whitespace t)

#### 6.9.1 Disable

Unfortunately, this setting can get annoying in a lot of modes, which is why I use this hook to disable it in those modes

    (defun imalison:disable-show-trailing-whitespace ()
      (setq show-trailing-whitespace nil))

### 6.10 Encoding

UTF-8 everywhere

    (defun imalison:set-coding-systems ()
      (interactive)
      (set-language-environment "Latin-1")
      (set-default-coding-systems 'utf-8)
      (unless (eq system-type 'windows-nt)
        (set-selection-coding-system 'utf-8))
      (set-terminal-coding-system 'utf-8)
      (setq locale-coding-system 'utf-8)
      (prefer-coding-system 'utf-8))
    (imalison:set-coding-systems)

Disable CJK coding/encoding (Chinese/Japanese/Korean characters)

    (setq utf-translate-cjk-mode nil)

### 6.11 Visible Bell

This is set to true to disable the annoying audible bell that plays whenever there is an error.

    (setq visible-bell t)

### 6.12 Configure `vc`

    (setq vc-follow-symlinks t)

### 6.13 Time in Mode Line

    (setq display-time-default-load-average nil)
    (setq display-time-interval 1)
    (setq display-time-format "%a|%m-%d|%r")
    (display-time-mode 1)

### 6.14 Kill Ring

    (setq kill-ring-max 1000)

### 6.15 Subword

This makes `forward-word` and `backward-word` understand snake and camel case.

    (setq c-subword-mode t)
    (global-subword-mode)

### 6.16 Scratch Buffer

    (setq initial-scratch-message "")

### 6.17 Don't prompt about local variables

    (defun risky-local-variable-p (&rest args)
      nil)

### 6.18 proced

proced is an top like utility that runs inside of emacs. The following sets auto updating automatically and makes the update interval faster.

    (require 'proced)
    (setq proced-auto-update-interval 1)
    (add-hook 'proced-mode-hook (lambda () (proced-toggle-auto-update +1)))

### 6.19 Set default browser

    (when (equal system-type 'gnu/linux)
        (setq browse-url-browser-function 'browse-url-generic
              browse-url-generic-program "google-chrome-stable"))

### 6.20 Set epa program

    (setq epg-gpg-program "gpg")

### 6.21 Make files executable

    (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)

### 6.22 Misc

    (defvar iedit-toggle-key-default nil)
    (put 'set-goal-column 'disabled nil)
    (auto-fill-mode -1)
    (setq indent-tabs-mode nil)

    (setq confirm-nonexistent-file-or-buffer nil)

    ;; No prompt for killing a buffer with processes attached.
    (setq kill-buffer-query-functions
          (remq 'process-kill-buffer-query-function
                kill-buffer-query-functions))

    (setq inhibit-startup-message t
          inhibit-startup-echo-area-message t)

    ;; This makes it so that emacs --daemon puts its files in ~/.emacs.d/server
    ;; (setq server-use-tcp t)

    ;; Make buffer names unique.
    (setq uniquify-buffer-name-style 'forward)

    ;; Don't disable commands...
    (setq disabled-command-function nil)

    ;; Make forward word understand camel and snake case.

    ;; Preserve pastes from OS when saving a new item to the kill
    ;; ring. Why wouldn't this be enabled by default?

    (setq-default cursor-type 'box)
    (setq-default cursor-in-non-selected-windows 'bar)

    (when nil ;; Causing too many annoying issues
      (add-hook 'after-init-hook '(lambda () (setq debug-on-error t))))

    ;; Make mouse scrolling less jumpy.
    (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))

    (setq ediff-split-window-function 'split-window-horizontally)
    (setq ediff-window-setup-function 'ediff-setup-windows-plain)

    ;; Disable this per major mode or maybe using file size if it causes
    ;; performance issues?
    (setq imenu-auto-rescan t)
    (setq imenu-max-item-length 300)

    (put 'narrow-to-region 'disabled nil)
    (put 'narrow-to-page 'disabled nil)

    (setq echo-keystrokes 0.25)

    ;; text mode stuff:
    (remove-hook 'text-mode-hook #'turn-on-auto-fill)
    (add-hook 'text-mode-hook 'turn-on-visual-line-mode)
    (setq sentence-end-double-space nil)

    ;; y and n instead of yes and no

    (setq-default c-basic-offset 4
                  tab-width 4
                  indent-tabs-mode t)

    (add-hook 'prog-mode-hook (lambda () (auto-fill-mode -1)))
    ;; (add-hook 'prog-mode-hook 'flyspell-prog-mode)

    ;; (add-hook 'prog-mode-hook (lambda () (highlight-lines-matching-regexp
    ;;                                  ".\\{81\\}" 'hi-blue)))

### 6.23 paradox

    (use-package paradox
      :defer 10
      :commands (paradox-upgrade-packages paradox-list-packages)
      :config
      (progn
        (require 'gh)
        (setq paradox-execute-asynchronously t
              paradox-github-token (gh-auth-get-oauth-token))))

### 6.24 diminish

    (use-package diminish
      :preface
      (defvar imalison:packages-to-diminish
        '(auto-revert-mode smartparens-mode eldoc-mode tern-mode js2-refactor-mode))
      :config
      (progn
        (cl-loop for package in imalison:packages-to-diminish
                 do (diminish package))
        (eval-after-load 'subword '(diminish 'subword-mode))
        (eval-after-load 'simple '(diminish 'visual-line-mode))))

### 6.25 edit-server

    (use-package edit-server
      :commands edit-server-start
      :defer 1
      :config
      (progn
        (edit-server-start)
        (setq edit-server-new-frame nil)))

### 6.26 load-dir

    (use-package load-dir
      :config
      (progn
        (setq load-dir-debug nil)
        (add-to-list 'load-dirs "~/.emacs.d/load.d")
        (defvar site-lisp "/usr/share/emacs24/site-lisp/")
        (when (file-exists-p site-lisp) (add-to-list 'load-dirs site-lisp))))

### 6.27 server

    (use-package server
      :config
      (progn
        (unless (server-running-p) (server-start))))

### 6.28 list-environment

    (use-package list-environment)

### 6.29 bug-hunter

    (use-package bug-hunter)

### 6.30 shackle

    (use-package shackle
      :disabled t
      :config
      (progn
        (diminish 'shackle-mode)
        (when nil                           ; disabled for now
          (shackle-mode))
        (setq shackle-inhibit-window-quit-on-same-windows t)
        (setq shackle-default-rule '(:same t))))

### 6.31 beacon

    (use-package beacon
      :bind ("C-c b" . beacon-blink)
      :config
      (beacon-mode 1))

### 6.32 iregister

    (use-package iregister)

### 6.33 discover-my-major

    (use-package discover-my-major)

### 6.34 refine

    (use-package refine
      :disabled t)

### 6.35 winner

    (use-package winner
      :after hydra
      :demand t
      :commands (winner-undo winner-redo)
      :config
      (progn
        (bind-key
         "C-c q"
         (defhydra imalison:winner-hydra ()
           "Winner"
           ("p" winner-undo "back")
           ("n" winner-redo "forward" :exit t)))
        (winner-mode 1)))

### 6.36 eyebrowse

    (use-package eyebrowse
      :defer 1
      :config
      (progn (eyebrowse-mode +1)))

### 6.37 stream

    (use-package stream)

### 6.38 tile

    (imalison:use-package tile
      :after hydra
      :bind ("C-c t" . imalison:hydra-tile/body)
      :config
      (progn
        (defvar imalison:tall-tile-strategy (tile-split-n-tall 3))
        (defvar imalison:wide-tile-strategy tile-wide)
        (defvar imalison:master-tile-strategy (tile-argument-buffer-fetcher
                                               :layout tile-master-left))
        (defhydra imalison:hydra-tile
          nil
          "tile"
          ("t" (tile :strategy imalison:tall-tile-strategy))
          ("w" (tile :strategy imalison:wide-tile-strategy))
          ("m" (tile :strategy imalison:master-tile-strategy))
          ("s" tile-select)
          ("0" (tile :strategy tile-one))
          ("n" tile)
          ("l" winner-undo))
        (setq tile-cycler
              (tile-strategies :strategies
                               (list imalison:tall-tile-strategy
                                     imalison:master-tile-strategy
                                     imalison:wide-tile-strategy
                                     tile-one)))))

### 6.39 fill-column-indicator

This interferes with too many other packages. See https://github.com/alpaker/Fill-Column-Indicator/issues/21 for more details

    (use-package fill-column-indicator
      :disabled t
      :config
      (progn
        (defun fci-on-off-fci-before-company (command)
          (when (string= "show" command)
            (turn-off-fci-mode))
          (when (string= "hide" command)
            (turn-on-fci-mode)))
        (advice-add 'company-call-frontends :before #'fci-on-off-fci-before-company)
        (add-hook 'prog-mode-hook 'fci-mode)))

## 7 Keybindings

### 7.1 god-mode

    (use-package god-mode
      :demand t
      :config
      (progn
        (global-set-key (kbd "<escape>") 'god-local-mode)))

### 7.2 bind-key

    (use-package bind-key)

### 7.3 which-key

    (use-package which-key
      :config
      (progn
        (setq which-key-idle-delay .50)
        (diminish 'which-key-mode)
        (which-key-mode)))

### 7.4 hydra

    (use-package hydra
      :demand t
      :bind (("C-c f" . imalison:hydra-font/body)
             ("C-c y" . imalison:hydra-yank/body)
             ("C-c 6" . imalison:compile/body))
      :config
      (progn

#### 7.4.1 Font Settings

    (defhydra imalison:hydra-font
      nil
      "Font Settings"
      ("-" imalison:font-size-decr "Decrease")
      ("d" imalison:font-size-decr "Decrease")
      ("=" imalison:font-size-incr "Increase")
      ("+" imalison:font-size-incr "Increase")
      ("i" imalison:font-size-incr "Increase")
      ("h" imalison:set-huge-font-size "Huge")
      ("a" imalison:appearance "Set Default Appearance")
      ("f" set-frame-font "Set Frame Font")
      ("t" helm-themes "Choose Emacs Theme")
      ("0" imalison:font-size-reset "Reset to default size"))

#### 7.4.2 Yanking

    (defhydra imalison:hydra-yank
      nil
      "Yank text"
      ("p" imalison:copy-buffer-file-path "Projectile path")
      ("f" imalison:copy-buffer-file-path-full "Full path")
      ("n" imalison:copy-buffer-file-name "File name")
      ("b" imalison:copy-current-git-branch "Git Branch"))

#### 7.4.3 Compile

    (defun imalison:make-test ()
      (interactive)
      (let ((default-directory (projectile-project-root)))
        (imalison:named-compile "make test")))

    (defun imalison:glide-up ()
      (interactive)
      (imalison:named-compile "glide up"))

    (defhydra imalison:compile nil "Compile"
      ("p" imalison:projectile-helm-command-from-zsh "Run a command in projectile root")
      ("d" helm-command-from-zsh "Run a command in default directory")
      ("c" imalison:named-compile "Enter Custom Command")
      ("t" imalison:make-test "Test")
      ("u" imalison:glide-up "Update Dependencies"))
    ;; The following parens close the use-package/progn created several blocks above
    ))

### 7.5 kill-emacs

This ensures that C-x C-c will always kill emacs, even if we are running in server mode.

    (bind-key "C-x C-c" 'kill-emacs)

### 7.6 imenu

imenu is the best. This should be a default binding.

    (bind-key "C-x C-i" 'imenu)

### 7.7 undo

I can't shake the habit of using this keybinding for undo. I should really use the default of C-/.

    (bind-key "C--" 'undo)

### 7.8 other-window

Go the other way when you use capital O.

    (bind-key "C-x O" (lambda () (interactive) (other-window -1)))

### 7.9 Mark ring

    (bind-key "C-c SPC" 'imalison:mark-ring)

### 7.10 Other bindings

    (bind-key "C-x p" 'pop-to-mark-command)
    (setq set-mark-command-repeat-pop t)
    (bind-key "C-x C-b" 'buffer-menu)
    (bind-key "C-x C-r" (lambda () (interactive) (revert-buffer t t)))
    (bind-key "C-x w" 'whitespace-mode)
    (bind-key "M-n" 'forward-paragraph)
    (bind-key "M-p" 'backward-paragraph)
    (bind-key "C-M-<backspace>" 'backward-kill-sexp)
    (bind-key "s-<return>" 'toggle-frame-fullscreen)
    (bind-key "M-|" 'imalison:shell-command-on-region)
    (bind-key "C-x 9" 'previous-buffer)
    (bind-key "s-v" 'clipboard-yank)

### 7.11 global-set-key-to-use-package

This might be useless, but I believe that it is a macro that converts between bind-key and global-set-key forms.

    (fset 'global-set-key-to-use-package
          (lambda (&optional arg) "Keyboard macro." (interactive "p")
            (kmacro-exec-ring-item
             (quote ([1 67108896 19 100 6 23 40 19 41 return
                        backspace 32 46 6 4] 0 "%d")) arg)))

### 7.12 OSX

    (when (equal system-type 'darwin)
      (setq mac-option-modifier 'meta)
      (setq mac-command-modifier 'super))

## 8 Navigation

### 8.1 zop-to-char

    (use-package zop-to-char
      :bind ("M-z" . zop-to-char)
      :init
      (progn
        (setq zop-to-char-kill-keys '(?\C-k))
        (setq zop-to-char-quit-at-point-keys '(?\r))))

### 8.2 helm

I use helm for almost all emacs completion

     1: (use-package helm-config
     2:   :ensure helm
     3:   :demand t
     4:   :bind (("M-y" . helm-show-kill-ring)
     5:          ("M-x" . helm-M-x)
     6:          ("C-x C-i" . helm-imenu)
     7:          ("C-h a" . helm-apropos)
     8:          ("C-c C-h" . helm-org-agenda-files-headings)
     9:          ("C-c ;" . helm-recentf))
    10:   :diminish helm-mode
    11:   :config
    12:   (progn
    13:     (require 'helm-org)
    14:     (setq helm-split-window-default-side 'same)
    15:
    16:     (cl-defun helm-org-headings-in-buffer ()
    17:       (interactive)
    18:       (helm :sources (helm-source-org-headings-for-files
    19:                       (list (projectile-completing-read
    20:                              "File to look at headings from: "
    21:                              (projectile-all-project-files))))
    22:             :candidate-number-limit 99999
    23:             :buffer "*helm org inbuffer*"))
    24:
    25:     (use-package helm-descbinds
    26:       :demand t
    27:       :config (helm-descbinds-mode 1))
    28:
    29:     (use-package helm-ag
    30:       :bind ("C-c p 1" . imalison:set-helm-ag-extra-options)
    31:       :preface
    32:       (progn
    33:         (defun imalison:set-helm-ag-extra-options ()
    34:           (interactive)
    35:           (let ((option (read-string "Extra options: " (or helm-ag--extra-options "")
    36:                                      'helm-ag--extra-options-history)))
    37:             (setq helm-ag--extra-options option))))
    38:       :config
    39:       (progn
    40:         (setq helm-ag-always-set-extra-option nil)))
    41:     (helm-mode 1)))

Ensure that helm buffers are started in the window that currently holds the focus

### 8.3 helm-projectile

    (use-package helm-projectile
      :commands (helm-projectile-on)
      :bind (:map helm-projectile-projects-map
                  ("M-s" . imalison:switch-to-project-and-search)
                  ("M-t" . imalison:helm-term-projectile))
      :preface
      (progn
        (defun imalison:invalidate-cache-and-open-file (_dir)
          (projectile-invalidate-cache nil)
          (projectile-find-file))

        (defun imalison:switch-to-project-and-search (dir)
          (let ((default-directory dir)
                (projectile-require-project-root nil)
                (helm-action-buffer "this-buffer-should-not-exist"))
            (helm-projectile-ag)))

        (defun imalison:helm-term-projectile (dir)
          (let ((default-directory dir)
                (projectile-require-project-root nil)
                (helm-action-buffer "this-buffer-should-not-exist"))
            (term-projectile-forward))))
      :config
      (progn
        (helm-delete-action-from-source "Search in Project"
                                        helm-source-projectile-projects)
        (helm-delete-action-from-source "Open term for project"
                                        helm-source-projectile-projects)
        (helm-add-action-to-source "Search in Project"
                                   'imalison:switch-to-project-and-search
                                   helm-source-projectile-projects)
        (helm-add-action-to-source "Open term for project"
                                   'imalison:helm-term-projectile
                                   helm-source-projectile-projects)
        (helm-add-action-to-source "Invalidate Cache and Open File"
                                   'imalison:invalidate-cache-and-open-file
                                   helm-source-projectile-projects)))

### 8.4 projectile

    (use-package projectile
      :demand t
      :bind (("C-x f" . projectile-find-file-in-known-projects)
             ("C-c p f" . imalison:projectile-find-file))
      :preface
      (progn
        (defun imalison:do-ag-default-directory ()
          (interactive)
          (helm-do-ag default-directory (car (projectile-parse-dirconfig-file))))

        (emit-prefix-selector imalison:do-ag
          helm-projectile-ag
          imalison:do-ag-default-directory
          helm-do-ag)

        (emit-prefix-selector imalison:projectile-find-file
          projectile-find-file
          projectile-find-file-other-window)

        (imalison:let-around imalison:set-options-do-ag
          imalison:do-ag
          (helm-ag-always-set-extra-option t))

        (defun imalison:projectile-make-all-subdirs-projects (directory)
          (cl-loop for file-info in (directory-files-and-attributes directory)
                   do (when (nth 1 file-info)
                        (write-region "" nil
                                      (expand-file-name
                                       (concat directory "/"
                                               (nth 0 file-info) "/.projectile")))))))
      :config
      (progn
        (use-package persp-projectile
          :commands projectile-persp-switch-project)

        (projectile-global-mode)
        (setq projectile-require-project-root nil)
        (setq projectile-enable-caching nil)
        (setq projectile-completion-system 'helm)
        (add-to-list 'projectile-globally-ignored-files "Godeps")
        (shut-up (helm-projectile-on))
        (diminish 'projectile-mode)
        (bind-key* "C-c p s" 'imalison:do-ag)
        (bind-key* "C-c p S" 'imalison:set-options-do-ag)
        (bind-key* "C-c p f" 'imalison:projectile-find-file)))

### 8.5 ido

    (use-package ido
      :commands ido-mode
      :config
      (progn
        (ido-mode 1)
        (setq ido-auto-merge-work-directories-length -1
              ido-default-buffer-method 'selected-window
              ido-use-virtual-buffers t
              ido-use-filename-at-point nil
              ido-create-new-buffer 'always)
        (ido-everywhere 1)
        (setq ido-enable-flex-matching t)
        (use-package flx)
        (use-package flx-ido
          :commands flx-ido-mode
          :init (flx-ido-mode 1)
          :config
          (progn
            ;; disable ido faces to see flx highlights.
            ;; This makes flx-ido much faster.
            (setq gc-cons-threshold 20000000)
            (setq ido-use-faces nil)))
        (use-package ido-ubiquitous
          :disabled t
          :commands (ido-ubiquitous-mode))
        (use-package ido-vertical-mode
          :config
          (progn
            (ido-vertical-mode 1)
            (setq ido-vertical-define-keys 'C-n-C-p-up-and-down)))
        (use-package flx-ido)))

### 8.6 avy

    (use-package avy
      :preface
      (progn
        (emit-prefix-selector imalison:avy
          avy-goto-word-1
          avy-goto-char))
      :bind (("C-j" . imalison:avy)
             ("M-g l" . avy-goto-line)
             ("C-'" . avy-goto-char-2)))

### 8.7 ace-window

    (use-package ace-window
      :preface
      (emit-prefix-selector imalison:ace-window
        ace-select-window
        ace-swap-window)
      :config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
      :bind ("C-c w" . imalison:ace-window))

### 8.8 neotree

    (use-package neotree)

### 8.9 jump-char

    (use-package jump-char
      :bind (("C-;" . jump-char-forward)))

### 8.10 flimenu

    (imalison:use-package flimenu
      :config
      (progn
        (flimenu-global-mode)))

### 8.11 swiper

    (use-package swiper
      :disabled t
      :bind ("C-s" . swiper))

## 9 Completion

### 9.1 company

    (use-package company
      :commands company-mode imalison:company
      :bind (("C-\\" . imalison:company))
      :config
      (progn
        (emit-prefix-selector imalison:company
          company-complete
          company-yasnippet)

        (setq company-idle-delay .25)
        (global-company-mode)
        (diminish 'company-mode))
      :init
      (add-hook 'prog-mode-hook (lambda () (company-mode t))))

#### 9.1.1 company-flx

    (use-package company-flx
      :disabled t
      :after company
      :config
      (company-flx-mode +1))

### 9.2 auto-complete

I don't use auto-complete at all, so I have set up a hook to automatically disable it whenever it is enabled to avoid creating conflicting popups when company is activated.

    (use-package auto-complete
      :preface
      (progn
        (defun imalison:auto-complete-hook ()
          (debug)
          (warn "auto-complete-mode was activated, but is being automatically disabled.")
          (let ((auto-complete-mode-hook nil))
            (auto-complete-mode -1))))
      :config
      (progn
        (add-hook 'auto-complete-mode-hook 'imalison:auto-complete-hook)))

## 10 Text Manipulation

### 10.1 smartparens

    (use-package smartparens
      :demand t
      :diminish smartparens-mode
      :bind (:map smartparens-mode-map
                  ("H-z" . sp-kill-symbol)
                  ("C-)" . sp-forward-slurp-sexp)
                  ("C-}" . sp-forward-barf-sexp)
                  ("C-(" . sp-backward-slurp-sexp)
                  ("C-{" . sp-backward-barf-sexp))
      :config
      (progn
        (require 'smartparens-config)
        (smartparens-global-mode 1)
        (sp-use-smartparens-bindings)
        (unbind-key "C-M-<backspace>" smartparens-mode-map)
        (unbind-key "C-<backspace>" smartparens-mode-map)
        (unbind-key "M-<backspace>" smartparens-mode-map)))

### 10.2 multiple-cursors

    (use-package multiple-cursors
      :config
      (progn
        (use-package phi-search-mc
          :demand t
          :config
          (phi-search-mc/setup-keys))
        (use-package mc-extras
          :demand t
          :config
          (define-key mc/keymap (kbd "C-. =") 'mc/compare-chars)))
      :bind
      (("C-c m a" . mc/mark-all-like-this)
       ("C-c m m" . mc/mark-all-like-this-dwim)
       ("C-c m l" . mc/edit-lines)
       ("C-c m n" . mc/mark-next-like-this)
       ("C-c m p" . mc/mark-previous-like-this)
       ("C-c m s" . mc/mark-sgml-tag-pair)
       ("C-c m d" . mc/mark-all-like-this-in-defun)))

### 10.3 expand-region

    (use-package expand-region
      :commands er/expand-region
      :config (setq expand-region-contract-fast-key "j")
      :bind (("C-c k" . er/expand-region)))

### 10.4 multi-line

    (imalison:use-package multi-line
      :bind ("C-c d" . multi-line))

### 10.5 comment-dwim-2

    (use-package comment-dwim-2
      :bind ("M-;" . comment-dwim-2))

### 10.6 unfill

    (use-package unfill
      :bind ("M-q" . unfill-toggle))

### 10.7 cliphist

    (use-package cliphist
      :config (setq cliphist-use-ivy t))

### 10.8 electric-operator-mode

    (use-package electric-operator
      :config
      (add-hook 'python-mode-hook #'electric-operator-mode))

### 10.9 string-inflection

    (use-package string-inflection
      :commands string-inflection-toggle
      :bind ("C-c l" . string-inflection-toggle))

### 10.10 yasnippet

    (use-package yasnippet
      :defer 5
      :commands (yas-global-mode)
      :config
      (progn
        (yas-global-mode)
        (diminish 'yas-minor-mode)
        (add-hook 'term-mode-hook (lambda() (yas-minor-mode -1)))
        (setq yas-prompt-functions
              (cons 'yas-ido-prompt
                    (cl-delete 'yas-ido-prompt yas-prompt-functions)))))

## 11 Source Control

### 11.1 magit

    (use-package magit
      :commands magit-status
      :bind (("C-x g" . imalison:magit-status))
      :preface
      (progn
        (emit-let-around imalison:magit-status-traditional
                         magit-status
                         (magit-display-buffer-function
                          'magit-display-buffer-traditional))
        (emit-prefix-selector imalison:magit-status
                              magit-status
                              imalison:magit-status-traditional)
        (defun imalison:after-magit-visit-file (&rest args)
          (when (derived-mode-p 'org-mode)
            (org-show-context 'magit-goto))))
      :config
      (progn
        (when (imalison:use-frames-only)
          (setq magit-commit-show-diff t))
        (unbind-key "C-j" magit-status-mode-map)
        (unbind-key "C-j" magit-hunk-section-map)
        (unbind-key "C-j" magit-file-section-map)
        (setq magit-last-seen-setup-instructions "1.4.0"
              magit-display-buffer-function
              'magit-display-buffer-same-window-except-diff-v1)
        (magit-auto-revert-mode)
        ;; TODO: Is this necessary now that signing is a git default
        (when (bound-and-true-p imalison:gpg-key)
          (add-to-list 'magit-commit-arguments
                       (format "--gpg-sign=%s" imalison:gpg-key)))

        (add-to-list 'org-show-context-detail '(magit-goto . lineage))
        (advice-add 'magit-diff-visit-file :after 'imalison:after-magit-visit-file)
        (add-hook 'magit-popup-mode-hook 'imalison:disable-show-trailing-whitespace)))

#### 11.1.1 magithub

    (use-package magithub
      :if (executable-find "hub")
      :after magit)

### 11.2 git-link

    (use-package git-link
      :config
      (progn
        (setq git-link-use-commit t)))

### 11.3 magit-gitflow

    (use-package magit-gitflow
      :diminish magit-gitflow-mode
      :after magit
      :init
      (progn
        (setq magit-gitflow-popup-key "C-k"))
      :config
      (progn
        (add-hook 'magit-mode-hook 'turn-on-magit-gitflow)))

### 11.4 git-timemachine

    (use-package git-timemachine
      :commands git-timemachine)

### 11.5 git-gutter

    (use-package git-gutter
      :config
      (progn
        (global-git-gutter-mode -1)))

### 11.6 gitolite-clone

    (use-package gitolite-clone
      :demand t
      :preface
      (progn
        (defun gitolite-clone-force-refresh ()
          (interactive)
          (gitolite-clone-get-projects nil nil t))))

### 11.7 gitconfig-mode

    (use-package gitconfig-mode
      :mode "\\.?gitconfig.?.*\\'")

### 11.8 gitignore-mode

    (use-package gitignore-mode
      :mode "\\.?gitignore.?.*\\'")

### 11.9 github

#### 11.9.1 github-search

    (imalison:use-package github-search
      :commands (github-search-clone-repo github-search-user-clone-repo)
      :preface
      (progn
        (defun imalison:get-appropriate-path-from-gh-repo-for-go (repo)
          (require 'go-mode)
          (imalison:get-go-src "github.com" (oref (oref repo :owner) :login)
                               (oref repo :name)))

        (defun imalison:get-projects-directory-target-from-repo (repo)
          (let ((prospective-path
                 (if (equal (oref repo language) "Go")
                     (imalison:get-appropriate-path-from-gh-repo-for-go repo)
                   (imalison:join-paths imalison:projects-directory (oref repo :name)))))
            (if (file-exists-p prospective-path)
                (funcall 'github-search-prompt-for-target-directory repo)
              prospective-path))))
      :config
      (progn
        (setq github-search-get-target-directory-for-repo-function
              'imalison:get-projects-directory-target-from-repo)))

#### 11.9.2 github-clone

    (imalison:use-package* github-clone "~/Projects/github-clone.el"
                           :commands (github-clone-add-parent-remote
                                      github-clone-add-source-remote
                                      github-clone-fork-remote
                                      github-clone-add-existing-remote
                                      github-clone))

#### 11.9.3 github-notifier

This is disabled because it was causing too many issues with my modeline and with excessive http requests to github.

    (use-package github-notifier
      :disabled t
      :config
      (progn
        (advice-add 'github-notifier-update :around 'imalison:shut-up-around)
        (github-notifier-mode)))

#### 11.9.4 github-browse-file

    (use-package github-browse-file
      :commands github-browse-file)

#### 11.9.5 magit-gh-pulls

    (use-package magit-gh-pulls
      :disabled t
      :diminish magit-gh-pulls-mode
      :after magit
      :config
      (progn
        (add-hook 'magit-mode-hook 'turn-on-magit-gh-pulls)))

#### 11.9.6 gist

    (use-package gist
      :commands (gist-region gist-region-private gist-buffer gist-buffer-private
                             gist-region-or-buffer gist-region-or-buffer-private
                             gist-list-user gist-list gist-fetch gist-star
                             gist-unstar gist-list-starred gist-fork))

## 12 Major Modes

### 12.1 Programming

#### 12.1.1 python

    (use-package python
      :commands python-mode
      :mode ("\\.py\\'" . python-mode)
      :preface
      (defun imalison:python-mode ()
        (setq show-trailing-whitespace t)
        ;; TODO: This was likely fixed and can probably be removed
        ;; Somehow this is sometimes set to jedi:ac-setup which we
        ;; don't want. This binding avoids starting auto-complete mode.
        (let ((jedi:setup-function nil))
          (jedi:setup))

        ;; XXX: This has become pretty annoying
        ;; (add-hook 'before-save-hook 'pyimport-remove-unused t t)

        ;; Ensure company is active
        (company-mode +1)
        ;; Only use company-jedi for completion
        (set (make-local-variable 'company-backends) '(company-jedi))

        ;; Remove default python completion, as we are going to rely on
        ;; company-jedi.
        (remove-hook 'completion-at-point-functions
                     'python-completion-complete-at-point 'local))
      :config
      (progn
        (use-package sphinx-doc)
        (unbind-key "C-j" python-mode-map)
        (add-hook 'python-mode-hook #'imalison:python-mode)))

##### 12.1.1.1 pyimport

Pyimport is disabled because it may be causing a performance problem.

    (use-package pyimport
      :disabled t
      :bind (:map python-mode-map
                  ("C-c C-i" . pyimport-insert-missing))
      :commands pyimport-remove-unused)

##### 12.1.1.2 jedi

The accepted way to use jedi if you prefer company to auto-complete is simply to require the company jedi package, which is why we make no reference to the jedi-core package.

    (use-package company-jedi
      :after python
      :commands (jedi:goto-definition jedi-mode company-jedi)
      :bind (:map python-mode-map
                  ("M-." . jedi:goto-definition)
                  ("M-," . jedi:goto-definition-pop-marker))
      :config
      (progn
        (setq jedi:complete-on-dot t)
        (setq jedi:imenu-create-index-function 'jedi:create-flat-imenu-index)))

#### 12.1.2 go

    (use-package go-mode
      :mode (("\\.go\\'" . go-mode))
      :preface
      (progn
        (defun imalison:glide-novendor ()
          (projectile-with-default-dir (projectile-project-root)
            (shell-command-to-string "glide novendor")))

        (defun imalison:go-mode-create-imenu-index ()
          "Create and return an imenu index alist. Unlike the default
      alist created by go-mode, this method creates an alist where
      items follow a style that is consistent with other prog-modes."
          (let* ((patterns '(("type" "^type *\\([^ \t\n\r\f]*\\)" 1)))
                 (type-index (imenu--generic-function patterns))
                 (func-index))
            (save-excursion
              (goto-char (point-min))
              (while (re-search-forward go-func-meth-regexp (point-max) t)
                (let* ((var (match-string-no-properties 1))
                       (func (match-string-no-properties 2))
                       (name (if var
                                 (concat (substring var 0 -1) "." func)
                               func))
                       (beg (match-beginning 0))
                       (marker (copy-marker beg))
                       (item (cons name marker)))
                  (setq func-index (cons item func-index)))))
            (nconc type-index (list (cons "func" func-index)))))

        (defun imalison:go-workspace-path ()
          (file-relative-name (projectile-project-root)
                              (concat (file-name-as-directory
                                       (imalison:get-go-path)) "src")))

        (defun imalison:install-current-go-project ()
          (interactive)
          (start-process
           "go install" "go install log" "go" "install"
           (concat (file-name-as-directory (imalison:go-workspace-path)) "...")))

        (defun imalison:get-go-path ()
          (let ((environment-go-path (getenv "GOPATH")))
            (if environment-go-path
                (file-name-as-directory (car (s-split ":" environment-go-path)))
              "~/go")))

        (defmacro imalison:get-go-src (&rest paths)
          `(imalison:join-paths (imalison:get-go-path) "src" ,@paths))

        (imalison:let-advise-around imalison:advise-normal-go-command
                                    (go-command "go"))

        (defun imalison:go-mode-hook ()
          (go-eldoc-setup)
          (set (make-local-variable 'company-backends) '(company-go))
          (make-local-variable 'projectile-globally-ignored-files)
          (add-hook 'after-save-hook 'imalison:install-current-go-project nil
                    'yes-do-local)
          (add-to-list 'projectile-globally-ignored-files
                       "vendor")))
      :config
      (progn
        (imalison:use-package*
         gotest "~/Projects/gotest.el"
         :demand t
         :bind (:map go-mode-map
                     ("C-c t" . imalison:gotest))
         :preface
         (progn
           (emit-prefix-selector imalison:gotest
             go-test-current-test
             go-test-current-file)

           (defun imalison:add-expected-test-name-for-suite (suite-name test-name)
             (if (> (length suite-name) 0)
                 (concat " -run Test" suite-name)
               "")))
         :config
         (progn
           (setq go-test-verbose t
                 go-test-additional-arguments-function
                 'imalison:add-expected-test-name-for-suite)))
        (use-package company-go
          :config (setq company-go-show-annotation t))
        (use-package go-projectile :demand t)
        (use-package go-eldoc :demand t)
        (use-package go-guru
          :demand t
          :bind (:map go-mode-map
                      ("M-." . go-guru-definition)
                      ("M-," . pop-tag-mark))
          :preface
          (progn
            (defun imalison:set-go-guru-scope ()
              (setq go-guru-scope (go-mode-parse-glide-novendor)))
            (defun go-mode-parse-glide-novendor ()
              (s-join ","
                      (cl-loop for path in (s-split "\n" (imalison:glide-novendor))
                               collect (if (string-equal path ".")
                                           (imalison:go-workspace-path)
                                         (s-replace "\./" (imalison:go-workspace-path) path))))))
          :config
          (progn
            (advice-add 'go-guru--set-scope-if-empty :before 'imalison:set-go-guru-scope)
            (advice-add 'go-guru-start :before 'imalison:set-go-guru-scope)
            (advice-add 'go-guru-definition :around 'imalison:advise-normal-go-command)
            (advice-add 'go-guru-definition :before
                        (lambda ()
                          (with-no-warnings
                            (ring-insert find-tag-marker-ring (point-marker)))))))

        (advice-add 'go-import-add :around 'imalison:advise-normal-go-command)

        (setq gofmt-command "goimports")

        (add-hook 'go-mode-hook 'imalison:go-mode-hook)
        (add-hook 'before-save-hook 'gofmt-before-save t)))

##### 12.1.2.1 Show diffs of testify output

    (defvar imalison:testify-ediff-buffers nil)
    (defun imalison:purge-ediff-buffers (&rest args)
      (cl-loop for buffer in imalison:testify-ediff-buffers
               do (kill-buffer buffer))
      (setq imalison:testify-ediff-buffers nil))

    (add-hook 'ediff-cleanup-hook 'imalison:purge-ediff-buffers)

    (defun imalison:go-testify-show-ediff ()
      (interactive)
      (let ((buffer (get-buffer-create "*Testify JSON*"))
            json-result)
        (shell-command-on-region (point-min) (point-max) "parse_go_testify_for_emacs.py" buffer)
        (with-current-buffer buffer
          (goto-char (point-min))
          (setq json-result (json-read)))
        (let ((actual-buffer (generate-new-buffer "*Testify Actual*"))
              (expected-buffer (generate-new-buffer "*Testify Expected*")))
          (add-to-list 'imalison:testify-ediff-buffers actual-buffer)
          (add-to-list 'imalison:testify-ediff-buffers expected-buffer)
          (with-current-buffer actual-buffer
            (insert (cdr (assoc 'actual json-result)))
            (with-current-buffer expected-buffer
              (insert (cdr (assoc 'expected json-result)))
              (ediff-buffers actual-buffer expected-buffer))))))

    (defun imalison:go-testify-show-icdiff ()
      (interactive)
      (let ((buffer (get-buffer-create "*Testify Comparison*")))
        (shell-command-on-region (point-min) (point-max) "parse_go_testify_not_equal.py" buffer)
        (with-current-buffer buffer
          (fundamental-ansi-mode))
        (switch-to-buffer buffer)))

#### 12.1.3 emacs-lisp

##### 12.1.3.1 elisp-slime-nav

    (use-package elisp-slime-nav
      :commands elisp-slime-nav-mode
      :config
      (diminish 'elisp-slime-nav-mode)
      :preface
      (emit-prefix-selector imalison:elisp-slime-nav
        elisp-slime-nav-find-elisp-thing-at-point
        elisp-slime-nav-describe-elisp-thing-at-point)
      :bind (:map elisp-slime-nav-mode-map
                  ("M-." . imalison:elisp-slime-nav)))

##### 12.1.3.2 macrostep

Macrostep is an indespensible tool for writing emacs lisp macros. It lets you see pretty printed versions of the result of macro evaluation as the macro is evaluated

    (use-package macrostep
      :bind (:map lisp-mode-shared-map
                  ("C-c e" . macrostep-expand)))

##### 12.1.3.3 emr

    (use-package emr
      :bind ("M-RET" . emr-show-refactor-menu)
      :config
      (progn
        (add-hook 'prog-mode-hook 'emr-initialize)))

##### 12.1.3.4 Editing configuration

Reduce indentation for some functions

    (put 'use-package 'lisp-indent-function 1)

##### 12.1.3.5 Checkdoc

    (setq checkdoc-force-docstrings-flag nil
          checkdoc-arguments-in-order-flag nil)

##### 12.1.3.6 edebug

    (use-package edebug
      :config
      (progn (setq edebug-trace t)))

##### 12.1.3.7 overseer

    (use-package overseer)

##### 12.1.3.8 Misc

    (defun imenu-elisp-sections ()
      (setq imenu-prev-index-position-function nil)
      (setq imenu-space-replacement nil)
      (add-to-list 'imenu-generic-expression
                   `("Package"
                     ,"(use-package \\(.+\\)$" 1))
      (add-to-list 'imenu-generic-expression
                   `("Section"
                     ,(concat ";\\{1,4\\} =\\{10,80\\}\n;\\{1,4\\} \\{10,80\\}"
                              "\\(.+\\)$") 1) t))

    (defun imalison:maybe-remove-flycheck-checkdoc-checker ()
      (when (s-starts-with? "*" (buffer-name))
        (flycheck-disable-checker 'emacs-lisp-checkdoc)))

    (add-hook 'emacs-lisp-mode-hook 'imenu-elisp-sections)
    (add-hook 'emacs-lisp-mode-hook (lambda ()
                                      (setq indent-tabs-mode nil)
                                      (setq show-trailing-whitespace t)))
    (add-hook 'flycheck-mode-hook 'imalison:maybe-remove-flycheck-checkdoc-checker)

##### 12.1.3.9 Show result of eval-last-sexp inline

Taken from http://endlessparentheses.com/eval-result-overlays-in-emacs-lisp.html

    (autoload 'cider--make-result-overlay "cider-overlays")

    (defun imalison:eval-overlay (value point)
      (cider--make-result-overlay (format "%S" value)
        :where point
        :duration 'command)
      value)

    (advice-add 'eval-region :around
                (lambda (f beg end &rest r)
                  (imalison:eval-overlay
                   (apply f beg end r)
                   end)))

    (advice-add 'eval-last-sexp :filter-return
                (lambda (r)
                  (imalison:eval-overlay r (point))))

    (advice-add 'eval-defun :filter-return
                (lambda (r)
                  (imalison:eval-overlay
                   r
                   (save-excursion
                     (end-of-defun)
                     (point)))))

##### 12.1.3.10 Reevalute defvars when running eval-last-sexp

We noflet elisp–preceding-sexp to munge defvars into sexps only for eval-last-sexp.

    (defun imalison:maybe-setq-instead (fn &rest args)
      (noflet ((elisp--preceding-sexp (&rest preceding-args)
                                      (let* ((preceding-sexp (apply this-fn preceding-args)))
                                        (if (and (listp preceding-sexp) (equal (car preceding-sexp) 'defvar))
                                            `(setq ,@(cdr preceding-sexp))
                                          preceding-sexp))))
        (apply fn args)))

    (advice-add 'eval-last-sexp :around 'imalison:maybe-setq-instead)

##### 12.1.3.11 Init hook

    (defvar imalison:check-parens nil)

    (defun imalison:maybe-check-parens ()
      (if imalison:check-parens
          (check-parens)))

    (defun imalison:emacs-lisp-hook ()
      (elisp-slime-nav-mode t)
      (add-hook 'write-file-functions 'imalison:maybe-check-parens nil t))

    (add-hook 'emacs-lisp-mode-hook 'imalison:emacs-lisp-hook)

##### 12.1.3.12 Keybinds

    (emit-compose imalison:copy-eval-last-sexp
                  kill-new prin1-to-string eval-last-sexp)

    (emit-prefix-selector imalison:eval-last-sexp
                          eval-region-or-last-sexp
                          imalison:copy-eval-last-sexp)

    (define-key lisp-mode-shared-map (kbd "C-c C-c") 'eval-defun)
    (define-key lisp-mode-shared-map (kbd "C-c o r") 'up-list-region)
    (define-key lisp-mode-shared-map (kbd "C-c o o") 'up-list-back)
    (define-key lisp-mode-shared-map (kbd "C-x C-e") 'imalison:eval-last-sexp)
    (unbind-key "C-j" lisp-interaction-mode-map)

#### 12.1.4 clojure

The following is taken from spacemacs. It adds fancification to a clojure mode.

    (defun imalison:clojure-fancify-symbols (mode)
      "Pretty symbols for Clojure's anonymous functions and sets,
       like (λ [a] (+ a 5)), ƒ(+ % 5), and ∈{2 4 6}."
      (font-lock-add-keywords mode
        `(("(\\(fn\\)[\n\[[:space:]]"
           (0 (progn (compose-region (match-beginning 1)
                                     (match-end 1) "λ"))))
          ("(\\(partial\\)[\[[:space:]]"
           (0 (progn (compose-region (match-beginning 1)
                                     (match-end 1) "Ƥ"))))
          ("(\\(comp\\)[\n\[[:space:]]"
           (0 (progn (compose-region (match-beginning 1)
                                     (match-end 1) "∘"))))
          ("\\(#\\)("
           (0 (progn (compose-region (match-beginning 1)
                                     (match-end 1) "ƒ"))))
          ("\\(#\\){"
           (0 (progn (compose-region (match-beginning 1)
                                     (match-end 1) "∈")))))))

    (use-package clojure-mode
      :commands clojure-mode
      :preface
      (progn
        (add-to-list 'magic-mode-alist '("#!.*boot\\s-*$" . clojure-mode))
        (add-to-list 'auto-mode-alist '("\\.boot\\'" . clojure-mode))

        (defun imalison:clojure-mode-hook ()
          ;; (cljr-add-keybindings-with-prefix "C-c C-m")
          (clj-refactor-mode 1)
          ;;for adding require/use/import statements
          (yas-minor-mode 1))

        (defvar imalison:clojure-level-1-symobls
          '(describe it)))
      :config
      (progn
        (cl-loop for symbol in imalison:clojure-level-1-symobls
                 do (put-clojure-indent symbol 1))
        (add-hook 'clojure-mode-hook 'imalison:clojure-mode-hook)
        (dolist (m '(clojure-mode clojurescript-mode clojurec-mode clojurex-mode))
          (imalison:clojure-fancify-symbols m))))

##### 12.1.4.1 cider

    (use-package cider
      :commands (cider-jack-in)
      :config
      (progn
        (setq cider-stacktrace-default-filters '(tooling dup)
              cider-repl-pop-to-buffer-on-connect nil
              cider-prompt-save-file-on-load nil
              cider-repl-use-clojure-font-lock t
              cider-prompt-for-symbol nil
              cider-preferred-build-tool "boot")
        (add-hook 'clojure-mode-hook 'cider-mode)))

##### 12.1.4.2 clj-refactor

    (use-package clj-refactor
      :commands clj-refactor-mode)

#### 12.1.5 scala

    (use-package scala-mode
      :mode (("\\.scala\\'" . scala-mode)
             ("\\.sc\\'" . scala-mode))
      :config
      (progn
        (use-package ensime
          :pin melpa-stable
          :bind (:map ensime-mode-map
                      ("M-," . ensime-pop-find-definition-stack))
          :commands ensime-mode
          :config
          (progn
            (setq ensime-startup-snapshot-notification nil)))
        (add-hook 'scala-mode-hook 'ensime-scala-mode-hook)
        (setq scala-indent:align-parameters t)))

#### 12.1.6 js

    (defun tape-onlyify ()
      (interactive)
      (save-excursion
        (move-end-of-line nil)
        (re-search-backward "^test")
        (forward-sexp)
        (if (looking-at ".only") (progn (zap-to-char 1 (string-to-char "(")) (insert "("))
          (insert ".only"))))

    (use-package js2-mode
      :commands (js2-mode)
      :mode "\\.js\\'"
      :bind
      ;; (("C-c b" . web-beautify-js)) TODO: to make this mode specific
      ;; and change binding
      :preface
      (progn
        (defvar-setq imalison:identifier-count 0)
        (defun imalison:console-log-unique ()
          (interactive)
          (let* ((identifier-string (int-to-string imalison:identifier-count))
                 (uuid (imalison:uuid)))
            (insert (format "console.log('%s//////////%s//////////');" identifier-string uuid))
            (setq imalison:identifier-count (+ imalison:identifier-count 1))))
        (defun imalison:js2-mode-hook ()
          ;; Sensible defaults
          (setq js2-bounce-indent-p nil
                js2-indent-level 4
                js2-basic-offset 4
                js2-highlight-level 3
                js2-include-node-externs t
                js2-mode-show-parse-errors nil
                js2-mode-show-strict-warnings nil
                indent-tabs-mode nil
                js2-indent-switch-body t)
          ;; (edconf-find-file-hook) ;; Make sure that editorconfig takes precedence
          (tern-mode t)
          (when nil (skewer-mode)) ;; TODO: reenable
          (setq imenu-create-index-function
                (lambda ()
                  (imalison:flatten-imenu-index
                   (js2-mode-create-imenu-index))))))
      :init
      (progn
        (add-hook 'js2-mode-hook 'imalison:js2-mode-hook)
        (add-hook 'js2-mode-hook 'js2-imenu-extras-mode)))

    (use-package js2-refactor
      :after js2-mode
      :config
      (progn
        (js2r-add-keybindings-with-prefix "C-c C-m")
        (add-hook 'js2-mode-hook #'js2-refactor-mode)))

    (use-package skewer-mode
      :commands skewer-mode
      :config
      (progn
        (add-hook 'css-mode-hook #'skewer-css-mode)
        (add-hook 'html-mode-hook #'skewer-html-mode)))

    (use-package tern
      :commands tern-mode
      :config
      (use-package company-tern
        :config (add-to-list 'company-backends 'company-tern)))

    (defun delete-tern-process ()
      (interactive)
      (delete-process "tern"))

#### 12.1.7 rust

    (use-package rust-mode
      :mode (("\\.rs\\'" . rust-mode))
      :preface
      (progn
        (defun imalison:rust-mode-hook ()
          (racer-mode 1)))
      :config
      (progn
        (use-package flycheck-rust
          :demand t
          :config
          (progn
            (add-hook 'flycheck-mode-hook #'flycheck-rust-setup)))
        (use-package racer
          :demand t
          :config
          (progn
            (setq racer-cmd "~/.cargo/bin/racer")
            (setq racer-rust-src-path "~/Projects/rust/src")))
        (use-package cargo
          :demand t
          :config
          (progn
            (add-hook 'rust-mode-hook 'cargo-minor-mode)))
        (add-hook 'rust-mode-hook 'imalison:rust-mode-hook)))

#### 12.1.8 haskell

    (use-package haskell-mode
      :commands haskell-mode
      :bind (:map haskell-mode-map
                  ("C-c h" . haskell-hoogle))
      :config
      (progn
        (setq haskell-hoogle-command "hoogle")
        (setq
           ;; Use notify.el (if you have it installed) at the end of running
           ;; Cabal commands or generally things worth notifying.
           haskell-notify-p t
           ;; Remove annoying error popups
           haskell-interactive-popup-errors nil
           ;; Better import handling
           haskell-process-suggest-remove-import-lines t
           haskell-process-auto-import-loaded-modules t
           ;; Disable haskell-stylish-on-save, as it breaks flycheck highlighting.
           ;; NOTE: May not be true anymore - taksuyu 2015-10-06
           haskell-stylish-on-save nil)
        (require 'flycheck)
        (delq 'haskell-stack-ghc flycheck-checkers)
        (add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
        (setq haskell-tags-on-save t)))

##### 12.1.8.1 intero

Intero seems to be causing hangs, so it has been disabled

    (use-package intero
      :disabled t
      :demand t
      :after haskell-mode
      :config (add-hook 'haskell-mode-hook 'intero-mode))

##### 12.1.8.2 hindent

    (use-package hindent
      :after haskell-mode
      :config
      (progn
        (setq hindent-style "chris-done")
        (add-hook 'haskell-mode-hook 'hindent-mode)))

##### 12.1.8.3 ghc-mod

    (use-package ghc
      :after haskell-mode
      :config
      (progn
        (setq ghc-debug t)
        (add-hook 'haskell-mode-hook 'ghc-init)))

##### 12.1.8.4 company-ghc

    (use-package company-ghc
      :demand t
      :config
      (add-to-list 'company-backends 'company-ghc))

#### 12.1.9 C/C++

    (use-package cc-mode
      :disabled t
      :preface
      (defun imalison:cc-mode-hook ()
        (when (derived-mode-p 'c-mode 'c++-mode 'java-mode 'asm-mode)
          (ggtags-mode 1)))
      :config
      (progn
        (use-package ggtags
          :demand t
          :bind (:map ggtags-mode-map
                      ("C-c g s" . ggtags-find-other-symbol)
                      ("C-c g h" . ggtags-view-tag-history)
                      ("C-c g r" . ggtags-find-reference)
                      ("C-c g f" . ggtags-find-file)
                      ("C-c g c" . ggtags-create-tags)
                      ("C-c g u" . ggtags-update-tags)
                      ("M-," . pop-tag-mark)))
        (add-hook 'c-mode-common-hook 'imalison:cc-mode-hook)))

#### 12.1.10 C#

    (use-package csharp-mode
      :mode "\\.cs\\'")

#### 12.1.11 racket

    (use-package racket-mode
      :mode "\\.rkt\\'")

### 12.2 Data/Config/Protocol

#### 12.2.1 thrift

    (use-package thrift
      :commands thrift-mode
      :mode (("\\.thrift\\'" . thrift-mode)))

#### 12.2.2 protobuf

    (use-package protobuf-mode)

#### 12.2.3 json-mode

    (use-package json-mode
      :mode "\\.json\\'"
      :init
      (add-hook 'json-mode-hook
                (lambda ()
                  (setq indent-tabs-mode nil)
                  (setq js-indent-level 4))))

#### 12.2.4 yaml-mode

    (use-package yaml-mode
      :mode (("\\.yaml\\'" . yaml-mode)
             ("\\.yml\\'" . yaml-mode)))

#### 12.2.5 es-mode

    (use-package es-mode)

### 12.3 Document

#### 12.3.1 org

##### 12.3.1.1 config

    (use-package org
      :ensure org-plus-contrib
      :preface
      (progn
        ;; XXX: These should probably be moved to config, right?
        (defvar-setq org-startup-indented nil)
        (defvar-setq org-startup-folded t)
        (defvar-setq org-edit-src-content-indentation 0)
        (defvar-setq org-src-preserve-indentation t)
        (defvar-setq org-directory "~/Dropbox/org")
        (defvar-setq org-mobile-inbox-for-pull "~/Dropbox/org/flagged.org")
        (defvar-setq org-mobile-directory "~/Dropbox/Apps/MobileOrg")

        (setq org-goto-interface 'outline-path-completion
              org-goto-max-level 10
              org-export-headline-levels 3)
        (add-hook 'org-mode-hook 'imalison:disable-linum-mode)
        (add-hook 'org-mode-hook (lambda () (setq org-todo-key-trigger t)))
        (add-hook 'org-agenda-mode-hook 'imalison:disable-linum-mode)

        (defun org-archive-if (condition-function)
          (if (funcall condition-function)
              (let ((next-point-marker
                     (save-excursion (org-forward-heading-same-level 1) (point-marker))))
                (org-archive-subtree)
                (setq org-map-continue-from (marker-position next-point-marker)))))

        (defun org-archive-if-completed ()
          (interactive)
          (org-archive-if 'org-entry-is-done-p))

        (defun org-archive-completed-in-buffer ()
          (interactive)
          (org-map-entries 'org-archive-if-completed))

        (cl-defun imalison:make-org-template (&key (content "%?"))
          (with-temp-buffer
            (org-mode)
            (insert content)
            (org-set-property "CREATED"
                              (with-temp-buffer
                                (org-insert-time-stamp
                                 (org-current-effective-time) t t)))
            (buffer-substring-no-properties (point-min) (point-max))))

        (defun imalison:make-org-template-from-file (filename)
          (imalison:make-org-template (imalison:get-string-from-file filename)))

        (cl-defun imalison:make-org-todo-template
            (&key (content "%?") (creation-state "TODO"))
          (with-temp-buffer
            (org-mode)
            (org-insert-heading)
            (insert content)
            (org-todo creation-state)
            (org-set-property "CREATED"
                              (with-temp-buffer
                                (org-insert-time-stamp
                                 (org-current-effective-time) t t)))
            (remove-hook 'post-command-hook 'org-add-log-note)
            (let ((org-log-note-purpose 'state)
                  (org-log-note-return-to (point-marker))
                  (org-log-note-marker (progn (goto-char (org-log-beginning t))
                                              (point-marker)))
                  (org-log-note-state creation-state))
              (org-add-log-note))
            (buffer-substring-no-properties (point-min) (point-max))))

        (defun org-todo-force-notes ()
          (interactive)
          (let ((org-todo-log-states
                 (mapcar (lambda (state)
                           (list state 'note 'time))
                         (apply 'append org-todo-sets))))
            (cond ((eq major-mode 'org-mode)  (org-todo))
                  ((eq major-mode 'org-agenda-mode) (org-agenda-todo)))))

        (defun org-make-habit ()
          (interactive)
          (org-set-property "STYLE" "habit"))

        (defun org-insert-habit ()
          (interactive)
          (org-insert-todo-heading nil)
          (org-make-habit))

        (defun org-todo-at-date (date)
          (interactive (list (org-time-string-to-time (org-read-date))))
          (cl-flet ((org-current-effective-time (&rest r) date)
                    (org-today (&rest r) (time-to-days date)))
            (cond ((eq major-mode 'org-mode) (org-todo))
                  ((eq major-mode 'org-agenda-mode) (org-agenda-todo)))))

        (defun imalison:make-org-linked-todo-template ()
          (imalison:make-org-todo-template "%? %A"))

        (defun org-cmp-creation-times (a b)
          (let ((a-created (get-date-created-from-agenda-entry a))
                (b-created (get-date-created-from-agenda-entry b)))
            (imalison:compare-int-list a-created b-created)))

        (defun org-agenda-done (&optional arg)
          "Mark current TODO as done.
      This changes the line at point, all other lines in the agenda referring to
      the same tree node, and the headline of the tree node in the Org-mode file."
          (interactive "P")
          (org-agenda-todo "DONE")))
      :commands (org-mode org org-mobile-push org-mobile-pull org-agenda)
      :mode ("\\.org\\'" . org-mode)
      :bind (("C-c a" . org-agenda)
             ("C-c c" . org-capture)
             :map org-mode-map
             ("C-c n t" . org-insert-todo-heading)
             ("C-c n s" . org-insert-todo-subheading)
             ("C-c n h" . org-insert-habit)
             ("C-c n m" . org-make-habit)
             ("C-c n l" . org-store-link)
             ("C-c n i" . org-insert-link)
             ("C-c C-t" . org-todo)
             ("C-c C-S-t" . org-todo-force-notes)
             ("M-." . elisp-slime-nav-find-elisp-thing-at-point))
      :config
      (progn
        (setq org-global-properties
              '(quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00")
                       ("STYLE_ALL" . "habit"))))
              ;; Record changes to todo states
        (setq org-todo-keywords
              '((sequence "IDEA(i!)" "RESEARCH(r!)" "TODO(t!)" "NEXT(n!)"
                          "STARTED(s!)" "WAIT(w!)" "BACKLOG(b!)" "|"
                          "DONE(d!)" "HANDLED(h!)" "EXPIRED(e!)" "CANCELED(c!)")))

        (defvar-setq helm-org-headings-fontify t)
        (setq org-todo-repeat-to-state "TODO")

        (setq org-agenda-span 10)
        (setq org-agenda-start-day "-2d")

        (setq org-columns-default-format
              "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM")

        (add-to-list 'org-show-context-detail '(org-goto . lineage))
        (sp-local-pair 'org-mode "~" "~")

        (add-to-list
         'org-src-lang-modes '("plantuml" . plantuml))

        (org-babel-do-load-languages
         'org-babel-load-languages
         '((sh . t)
           (python . t)
           (ruby . t)
           (octave . t)
           (sqlite . t)
           (plantuml . t)))

        (setq org-log-into-drawer t
              org-log-reschedule t
              org-log-redeadline t
              org-treat-insert-todo-heading-as-state-change t)

        (when nil
          ;; Enable appointment notifications.
          (defadvice org-agenda-to-appt (before wickedcool activate)
            "Clear the appt-time-msg-list."
            (setq appt-time-msg-list nil))
          (appt-activate)
          (defun org-agenda-to-appt-no-message ()
            (shut-up (org-agenda-to-appt)))
          (run-at-time "00:00" 60 'org-agenda-to-appt-no-message))

        ;; Override the key definition for org-exit
        ;; TODO why does this cause an error
        ;; (define-key org-agenda-mode-map "x" #'org-agenda-done)

        ;; org-mode add-ons
        (use-package org-present
          :commands org-present)
        (use-package org-pomodoro
          :disabled t)

        ;; variable configuration
        (add-to-list 'org-modules 'org-habit)
        (add-to-list 'org-modules 'org-expiry)
        (add-to-list 'org-modules 'org-notify)

        (setq org-src-fontify-natively t)
        (setq org-habit-graph-column 50)
        (setq org-habit-show-habits-only-for-today t)

        ;; My priority system:

        ;; A - Absolutely MUST, at all costs, be completed by the provided
        ;;     due date. TODO: implement some type of extreme nagging
        ;;     system that alerts in an intrusive way for overdue A
        ;;     priority tasks.

        ;; B - Should be given immediate attention if the due date is any
        ;;     time in the next two days. Failure to meet due date would
        ;;     be bad but not catastrophic.

        ;; C - The highest priority to which tasks for which failure to
        ;;     complete on time would not have considerable significant
        ;;     consequences. There is still significant reason to prefer
        ;;     the completion of these tasks sooner rather than later.

        ;; D - Failure to complete within a few days (or ever) of any
        ;;     deadline would be completely okay. As such, any deadline
        ;;     present on such a task is necessarily self imposed. Still
        ;;     probably worth doing

        ;; E - Potentially not even worth doing at all, but worth taking a
        ;;     note about in case it comes up again, or becomes more
        ;;     interesting later.

        ;; F - Almost certainly not worth attempting in the immediate future.
        ;;     Just brain dump.

        ;; Priorities are somewhat contextual within each category. Things
        ;; in the gtd or work categories are generally regarded as much
        ;; more important than things with the same priority from the
        ;; dotfiles category.

        ;; Items without deadlines or scheduled times of a given priority
        ;; can be regarded as less important than items that DO have
        ;; deadlines of that same priority.

        (setq org-lowest-priority 69) ;; The character E
        (setq org-completion-use-ido t)
        (setq org-enforce-todo-dependencies t)
        (setq org-deadline-warning-days 0)
        (setq org-default-priority ?D)
        (setq org-agenda-skip-scheduled-if-done t)
        (setq org-agenda-skip-deadline-if-done t)
        ;;(add-to-list org-agenda-tag-filter-preset "+PRIORITY<\"C\"")

        (setq org-imenu-depth 10)

        ;; Stop starting agenda from deleting frame setup!
        (setq org-agenda-window-setup 'other-window)
        (define-key mode-specific-map [?a] 'org-agenda)
        (unbind-key "C-j" org-mode-map)

        (use-package org-bullets
          :config
          (progn
            (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))))

        (use-package org-ehtml
          :disabled t
          :config
          (progn
            (setq org-ehtml-docroot (expand-file-name "~/Dropbox/org"))
            (setq org-ehtml-allow-agenda t)
            (setq org-ehtml-editable-headlines t)
            (setq org-ehtml-everything-editable t)))

        ;; Agenda setup.
        (defvar imalison:org-gtd-file "~/org/gtd.org")
        (defvar imalison:org-habits-file "~/org/habits.org")
        (defvar imalison:org-calendar-file "~/org/calendar.org")
        (defvar imalison:org-inbox-file "~/org/inbox.org")

        (unless (boundp 'org-capture-templates)
          (defvar org-capture-templates nil))

        (imalison:add-to-org-agenda-files
         (list imalison:org-gtd-file imalison:org-habits-file
               imalison:org-calendar-file imalison:org-inbox-file))

        (add-to-list 'org-capture-templates
                     `("t" "GTD Todo (Linked)" entry (file ,imalison:org-gtd-file)
                       (function imalison:make-org-linked-todo-template)))

        (add-to-list 'org-capture-templates
                     `("g" "GTD Todo" entry (file ,imalison:org-gtd-file)
                       (function imalison:make-org-todo-template)))

        (add-to-list 'org-capture-templates
                     `("y" "Calendar entry (Linked)" entry
                       (file ,imalison:org-calendar-file)
                       "* %? %A
      :PROPERTIES:
      :CREATED: %U
      :END:
    %^T"))

        (add-to-list 'org-capture-templates
                     `("c" "Calendar entry" entry
                       (file ,imalison:org-calendar-file)
                       "* %?
      :PROPERTIES:
      :CREATED: %U
      :END:
    %^T"))

        (add-to-list 'org-capture-templates
                     `("h" "Habit" entry (file ,imalison:org-habits-file)
                       "* TODO
        SCHEDULED: %^t
        :PROPERTIES:
        :CREATED: %U
        :STYLE: habit
        :END:"))

        (let ((this-week-high-priority
               ;; The < in the following line works has behavior that is opposite
               ;; to what one might expect.
               '(tags-todo "+PRIORITY<\"C\"+DEADLINE<\"<+1w>\"DEADLINE>\"<+0d>\""
                           ((org-agenda-overriding-header
                             "Upcoming high priority tasks:"))))
              (due-today '(tags-todo
                           "+DEADLINE=<\"<+0d>\""
                           ((org-agenda-overriding-header
                             "Due today:"))))
              (recently-created '(tags-todo
                                  "+CREATED=>\"<-3d>\""
                                  ((org-agenda-overriding-header "Recently created:")
                                   (org-agenda-cmp-user-defined 'org-cmp-creation-times)
                                   (org-agenda-sorting-strategy '(user-defined-down)))))
              (next '(todo "NEXT"))
              (started '(todo "STARTED"))
              (missing-deadline
               '(tags-todo "-DEADLINE={.}/!"
                           ((org-agenda-overriding-header
                             "These don't have deadlines:"))))
              (missing-priority
               '(tags-todo "-PRIORITY={.}/!"
                           ((org-agenda-overriding-header
                             "These don't have priorities:")))))

          (setq org-agenda-custom-commands
                `(("M" "Main agenda view"
                   ((agenda ""
                            ((org-agenda-overriding-header "Agenda:")
                             (org-agenda-ndays 5)
                             (org-deadline-warning-days 0)))
                    ,due-today
                    ,next
                    ,started
                    ,this-week-high-priority
                    ,recently-created)
                   nil nil)
                  ,(cons "A" (cons "High priority upcoming" this-week-high-priority))
                  ,(cons "d" (cons "Overdue tasks and due today" due-today))
                  ,(cons "r" (cons "Recently created" recently-created))
                  ("h" "A, B priority:" tags-todo "+PRIORITY<\"C\""
                   ((org-agenda-overriding-header
                     "High Priority:")))
                  ("c" "At least priority C:" tags-todo "+PRIORITY<\"D\""
                   ((org-agenda-overriding-header
                     "At least priority C:"))))))

        ;; What follows is a description of the significance of each of
        ;; the values available in `org-todo-keywords'. All headings with
        ;; one of these keywords deal with the concept of the completion
        ;; of some task or collection of tasks to bring about a particular
        ;; state of affairs. In some cases, the actual tasks involved may
        ;; not be known at the time of task creation.

        ;; Incomplete States:

        ;; IDEA - This TODO exists in only the most abstract sense: it is
        ;; an imagined state of affairs that requires tasks that are
        ;; either not yet known, or have not thoroughly been considered.

        ;; RESEARCH - This TODO needs to be investigated further before
        ;; action can be taken to achieve the desired outcome. It is not
        ;; known how much time and effort will be consumed in the actual
        ;; completion of the task.

        ;; TODO - The scope and work involved in this TODO are well
        ;; understood, but for some reason or another, it is not something
        ;; that should be attempted in the immediate future. Typically
        ;; this is because the task is not considered a top priority, but
        ;; it may also be for some other reason.

        ;; NEXT - This TODO is immediately actionable and should be
        ;; started in the immediate future.

        ;; STARTED - Work on this TODO has already started, further work
        ;; is immediately actionable.

        ;; WAIT - The work involved in this TODO is well understood, but
        ;; it is blocked for the time being.

        ;; BACKLOG - While technically actionable, this task is not only
        ;; not worth pursuing in the immediate future, but the foreseable
        ;; future. It exists as a task mostly as a note/reminder, in case
        ;; it becomes higher priority in the future.

        ;; Complete States:

        ;; DONE - This TODO has been completed exactly as imagined.

        ;; HANDLED - This TODO was completed in spirit, though not by the
        ;; means that were originally imagined/outlined in the TODO.

        ;; EXPIRED - The owner of this TODO failed to take action on it
        ;; within the appropriate time period, and there is now no point in
        ;; attempting it.

        ;; CANCELED - For whatever reason, this TODO should no longer be
        ;; attempted. This TODO is typically used in contrast to the
        ;; EXPIRED TODO to indicate that the owner is not necessarily to
        ;; blame.
        ))

##### 12.3.1.2 Use frames

    (use-package org
      :config
      (progn
      (setq org-src-window-setup 'current-window)
        (when (imalison:use-frames-only)
          (progn
            (setcdr (assoc 'file org-link-frame-setup) 'find-file-other-frame)))))

##### 12.3.1.3 Set Background Color of Source Blocks for Export

This was taken from here.

    (use-package org
      :config
      (progn
        (defun imalison:org-inline-css-hook (exporter)
          "Insert custom inline css to automatically set the
    background of code to whatever theme I'm using's background"
          (when (eq exporter 'html)
            (let* ((my-pre-bg (face-background 'default))
                   (my-pre-fg (face-foreground 'default)))
              (setq
               org-html-head-extra
               (concat
                org-html-head-extra
                (format "<style type=\"text/css\">\n pre.src {background-color: %s; color: %s;}</style>\n"
                        my-pre-bg my-pre-fg))))))

        (add-hook 'org-export-before-processing-hook 'imalison:org-inline-css-hook)))

##### 12.3.1.4 Use my own default naming scheme for org-headings

First we define a function that will generate a sanitized version of the heading as its link target.

    (defun imalison:org-get-raw-value (item)
      (when (listp item)
        (let* ((property-list (cadr item)))
          (when property-list (plist-get property-list :raw-value)))))

    (defun imalison:sanitize-name (name)
      (replace-regexp-in-string "[^[:alpha:]]" "" (s-downcase name)))

    (defun imalison:generate-name (datum cache)
      (let ((raw-value (imalison:org-get-raw-value datum)))
        (if raw-value
            (imalison:sanitize-name raw-value)
          ;; This is the default implementation from org
          (let ((type (org-element-type datum)))
            (format "org%s%d"
                    (if type
                        (replace-regexp-in-string "-" "" (symbol-name type))
                        "secondarystring")
                    (incf (gethash type cache 0)))))))

This function replaces the default naming scheme with a call to `imalison:generate-name`, and uses a slightly different uniquify approach.

    (use-package ox
      :ensure nil
      :demand t
      :config
      (defun org-export-get-reference (datum info)
        "Return a unique reference for DATUM, as a string.
    DATUM is either an element or an object.  INFO is the current
    export state, as a plist.  Returned reference consists of
    alphanumeric characters only."
        (let ((type (org-element-type datum))
              (cache (or (plist-get info :internal-references)
                         (let ((h (make-hash-table :test #'eq)))
                           (plist-put info :internal-references h)
                           h)))
              (reverse-cache (or (plist-get info :taken-internal-references)
                                 (let ((h (make-hash-table :test 'equal)))
                                   (plist-put info :taken-internal-references h)
                                   h))))
          (or (gethash datum cache)
              (let* ((name (imalison:generate-name datum cache))
                     (number (+ 1 (gethash name reverse-cache -1)))
                     (new-name (format "%s%s" name (if (< 0 number) number ""))))
                (puthash name number reverse-cache)
                (puthash datum new-name cache)
                new-name)))))

##### 12.3.1.5 org-projectile

    (imalison:use-package org-projectile
      :after helm
      :bind (("C-c n p" . imalison:helm-org-todo))
      :config
      (progn
        (require 'org-projectile-helm)
        (org-projectile-prompt)
        (add-to-list 'org-capture-templates
                     (org-projectile-project-todo-entry
                      "l" "* TODO %? %a\n" "Linked Project TODO"))
        (add-to-list 'org-capture-templates (org-projectile-project-todo-entry "p"))
        (setq org-confirm-elisp-link-function nil)
        (imalison:add-to-org-agenda-files (org-projectile-todo-files))
        (require 'helm-source)
        (require 'helm-org)
        (defun imalison:helm-org-todo (&optional arg)
          (interactive "P")
          (helm :sources (list (helm-source-org-capture-templates)
                               (org-projectile-helm-source
                                (if arg (imalison:make-org-linked-todo-template)
                                  (imalison:make-org-todo-template))))
                :candidate-number-limit 99999
                :buffer "*helm org capture templates*"))))

##### 12.3.1.6 org-notify

    (use-package org-notify
      :disabled t
      :after org
      :config
      (progn
        (defun imalison:org-notify-notification-handler (plist)
          (sauron-add-event 'org-notify 4 (format "%s, %s.\n" (plist-get plist :heading)
                                                  (org-notify-body-text plist))))

        (setq org-show-notification-handler 'imalison:org-notify-notification-handler)

        (org-notify-add 'default '(:time "1h" :actions imalison:org-notify-notification-handler
                                         :period "2m" :duration 60))
        (org-notify-add 'default '(:time "100m" :actions imalison:org-notify-notification-handler
                                         :period "2m" :duration 60))
        (org-notify-add 'urgent-second '(:time "3m" :actions (-notify/window -ding)
                                               :period "15s" :duration 10))
        (org-notify-add 'minute '(:time "5m" :actions -notify/window
                                        :period "100s" :duration 70))
        (org-notify-add '12hours
                        '(:time "3m" :actions (-notify/window -ding)
                                :period "15s" :duration 10)
                        '(:time "100m" :actions -notify/window
                                :period "2m" :duration 60)
                        '(:time "12h" :actions -notify/window :audible nil
                                :period "10m" :duration 200))
        (org-notify-add '5days
                        '(:time "100m" :actions -notify/window
                                :period "2m" :duration 60)
                        '(:time "2d" :actions -notify/window
                                :period "15m" :duration 100)
                        '(:time "5d" :actions -notify/window
                                :period "2h" :duration 200))
        (org-notify-add 'long-20days
                        '(:time "2d" :actions -notify/window
                                :period "15m" :duration 60)
                        '(:time "5d" :actions -notify/window
                                :period "2h" :duration 60)
                        '(:time "20d" :actions -email :period "2d" :audible nil))
        (org-notify-add 'long-50days
                        '(:time "4d" :actions -notify/window
                                :period "30m" :duration 100)
                        '(:time "10d" :actions -notify/window
                                :period "4h" :duration 200)
                        '(:time "50d" :actions -email :period "3d" :audible nil))
        (org-notify-add 'long-100days
                        '(:time "2d" :actions -notify/window
                                :period "1h" :duration 200)
                        '(:time "10d" :actions -notify/window
                                :period "10h" :duration 300)
                        '(:time "50d" :actions -email :period "3d" :audible nil)
                        '(:time "100d" :actions -email :period "5d" :audible nil))
        (org-notify-start 10)))

##### 12.3.1.7 org-reveal

    (use-package ox-reveal
      :after org
      :config
      (setq org-reveal-root
          (imalison:join-paths "file://" imalison:projects-directory "reveal.js")))

##### 12.3.1.8 org-caldav

    (use-package org-caldav
      :defer t
      :config
      (progn
        (setq org-caldav-url "https://www.google.com/calendar/dav"
              org-caldav-inbox imalison:org-inbox-file
              org-caldav-files (list imalison:org-calendar-file)
              org-icalendar-timezone "America/Los_Angeles")))

#### 12.3.2 TeX

    (use-package tex
      :ensure auctex
      :commands TeX-mode
      :preface
      (progn
        (defun imalison:TeX-mode-hook ()
          (turn-on-reftex)
          (TeX-source-correlate-mode +1)
          (TeX-PDF-mode +1)))
      :config
      (progn
        (unbind-key "C-j" TeX-mode-map)
        (TeX-global-PDF-mode)
        (setq TeX-auto-save t
              TeX-parse-self t
              TeX-save-query nil
              TeX-PDF-mode t)
        (TeX-global-PDF-mode t)
        (add-hook 'TeX-mode-hook 'imalison:TeX-mode-hook)))

##### 12.3.2.1 latex

    (use-package latex
      :ensure auctex
      :after tex
      :config
      (progn
        (unbind-key "C-j" LaTeX-mode-map)))

##### 12.3.2.2 auctex-latexmk

    (use-package auctex-latexmk
      :after tex
      :config
      (progn
        (setq auctex-latexmk-inherit-TeX-PDF-mode t)
        (auctex-latexmk-setup)))

##### 12.3.2.3 company-auctex

    (use-package company-auctex
      :after tex
      :config
      (company-auctex-init))

#### 12.3.3 markdown-mode

    (use-package markdown-mode
      :init
      (progn
        (add-hook 'markdown-mode-hook 'imalison:disable-linum-mode)))

#### 12.3.4 plantuml-mode

    (use-package plantuml-mode
      :commands plantuml-mode
      :mode ("\\.puml\\'" "\\.plantuml\\'")
      :preface
      (progn
        (cond ((equal system-type 'darwin)
               (let* ((plantuml-dir
                       (s-trim (shell-command-to-string "brew --prefix plantuml")))
                      (filename
                       (when (file-exists-p plantuml-dir)
                         (--first (s-ends-with? ".jar" it) (directory-files plantuml-dir))))
                      (filepath (when filename
                                  (imalison:join-paths plantuml-dir filename))))
                 (setq plantuml-jar-path filepath
                       org-plantuml-jar-path filepath)))
              ((equal system-type 'gnu/linux)
               (let ((filepath "/opt/plantuml/plantuml.jar"))
                 (setq plantuml-jar-path filepath
                       org-plantuml-jar-path filepath))))
        (add-to-list
         'org-src-lang-modes '("plantuml" . plantuml))))

#### 12.3.5 wsd-mode

    (use-package wsd-mode
      :commands (wsd-mode))

### 12.4 Utility

#### 12.4.1 restclient

    (use-package restclient
      :mode (("\\.restclient\\'" . restclient-mode))
      :config
      (progn
        (use-package company-restclient)))

#### 12.4.2 jq-mode

    (use-package jq-mode
      :mode "\\.jq\\'")

## 13 Programming

### 13.1 realgud

realgud provides debugging support with many external debuggers in emacs

    (use-package realgud
      :defer 10)

### 13.2 emr

emr (emacs refactor) provides support for refactoring in many programming languages

    (use-package emr
      :bind (:map prog-mode-map
                  ("M-RET" . emr-show-refactor-menu))
      :config (emr-initialize))

### 13.3 semantic

    (use-package semantic
      :commands semantic-mode
      :disabled t
      :preface
      (progn
        (add-hook 'prog-mode-hook 'semantic-mode)))

## 14 Utility

### 14.1 term

    (use-package term
      :bind (:map term-raw-escape-map
             ("M-x" . helm-M-x)
             :map term-raw-map
             ("M-x" . helm-M-x))
      :config
      (progn
        (define-key term-raw-map (kbd "C-h") help-map)
        (add-hook 'term-mode-hook 'imalison:disable-linum-mode)
        (add-hook 'term-mode-hook 'imalison:disable-show-trailing-whitespace)
        (setq term-buffer-maximum-size 0)))

### 14.2 term-manager

    (imalison:use-package term-manager
      :defer t
      :preface
      (progn
        (defun imalison:set-escape-char (&rest _args)
          (let (term-escape-char)
            (term-set-escape-char ?\C-x))))
      :config
      (progn
        (advice-add
         'term-manager-default-build-term :after 'imalison:set-escape-char)))

### 14.3 term-projectile

    (imalison:use-package* term-projectile "term-manager"
      :bind ("C-c 7" . imalison:term-hydra-global/body)
      :commands (term-projectile-forward term-projectile-backward
                                         term-projectile-default-directory-forward
                                         term-projectile-default-directory-backward
                                         term-projectile-create-new
                                         term-projectile-create-new-default-directory)
      :config
      (progn
        (emit-prefix-selector imalison:term
                              term-projectile-forward
                              term-projectile-create-new)

        (defvar imalison:term-hydra-original-default-directory)

        (defhydra imalison:term-hydra-default-directory
          (:body-pre
           (term-projectile-default-directory-forward-restored))
          "term - default-directory"
          ("s" term-projectile-switch-to)
          ("f" term-projectile-default-directory-forward-restored)
          ("b" term-projectile-default-directory-backward-restored)
          ("c" term-projectile-default-directory-create-new-restored)
          ("d" term-projectile-default-directory-forward-restored)
          ("g" imalison:term-hydra-global/body-restored :exit t)
          ("p" imalison:term-hydra-projectile/body-restored :exit t))

        (defhydra imalison:term-hydra-projectile
          (:body-pre
           (progn
             (term-projectile-forward-restored)))
          "term - projectile"
          ("s" term-projectile-switch-to)
          ("f" term-projectile-forward-restored)
          ("b" term-projectile-backward-restored)
          ("c" term-projectile-create-new-restored)
          ("d" imalison:term-hydra-default-directory/body-restored :exit t)
          ("g" imalison:term-hydra-global/body-restored :exit t)
          ("p" term-projectile-forward-restored))

        (defhydra imalison:term-hydra-global
          (:body-pre
           (progn (setq imalison:term-hydra-original-default-directory
                        default-directory)))
          "term - global"
          ("s" term-projectile-switch-to)
          ("f" term-projectile-global-forward-restored)
          ("b" term-projectile-global-backward-restored)
          ("c" term-projectile-global-create-new-restored)
          ("d" imalison:term-hydra-default-directory/body-restored :exit t)
          ("g" term-projectile-global-forward-restored)
          ("p" imalison:term-hydra-projectile/body-restored :exit t))

        (mapcar (lambda (term-projectile-function)
                  (defalias (imalison:concat-symbols term-projectile-function '-restored)
                    (lambda (&rest args)
                      (interactive)
                      (let ((default-directory imalison:term-hydra-original-default-directory))
                        (apply term-projectile-function args)))))
                '(term-projectile-default-directory-forward
                  term-projectile-default-directory-backward
                  term-projectile-default-directory-create-new
                  term-projectile-forward
                  term-projectile-backward
                  term-projectile-create-new
                  term-projectile-global-forward
                  term-projectile-global-backward
                  term-projectile-global-create-new
                  imalison:term-hydra-global/body
                  imalison:term-hydra-projectile/body
                  imalison:term-hydra-default-directory/body))))

### 14.4 crux

crux-reopen-as-root-mode makes it so that any file owned by root will automatically be opened as the root user.

    (use-package crux
      :demand t
      :bind (("C-c C-s" . crux-sudo-edit)
             ("C-c C-r" . crux-eval-and-replace)
             ("C-c o" . crux-open-with))
      :config
      (progn
        (crux-reopen-as-root-mode)))

### 14.5 kde-connect

    (use-package kdeconnect)

## 15 Chat

### 15.1 erc

    (use-package erc
      :commands erc
      :config
      (progn
        ;; (add-to-list 'erc-modules 'notifications)
        ;; logging:
        (use-package erc-colorize
          :config
          (erc-colorize-mode 1))))

### 15.2 bitlbee

    (use-package bitlbee
      :disabled t
      :config
      (progn
        (defvar bitlbee-password "geheim")
        (add-hook 'erc-join-hook 'bitlbee-identify)
        (defun bitlbee-identify ()
          "If we're on the bitlbee server, send the identify command to the
       &bitlbee channel."
          (when (and (string= "localhost" erc-session-server)
                     (string= "&bitlbee" (buffer-name)))
            (erc-message "PRIVMSG" (format "%s identify %s"
                                           (erc-default-target)
                                           bitlbee-password))))))

### 15.3 slack

    (use-package slack)

## 16 Cooperation

### 16.1 togetherly

    (use-package togetherly)

### 16.2 floobits

    (use-package floobits)

### 16.3 rudel

    (use-package rudel
      :disabled t)

## 17 Other

### 17.1 anzu

    (use-package anzu
      :config
      (progn
        (global-anzu-mode +1)

        (custom-set-variables
         '(anzu-mode-lighter "")
         '(anzu-deactivate-region t)
         '(anzu-search-threshold 1000)
         '(anzu-replace-threshold 50)
         '(anzu-replace-to-string-separator " => "))

        (define-key isearch-mode-map [remap isearch-query-replace]
          #'anzu-isearch-query-replace)
        (define-key isearch-mode-map [remap isearch-query-replace-regexp]
          #'anzu-isearch-query-replace-regexp)))

### 17.2 fontawesome

    (use-package fontawesome
      :commands helm-fontawesome)

### 17.3 shell-history

I think that shell-history is causing projectile to be very slow so I have disabled it.

    (use-package shell-history
      :demand t
      :disabled t)

### 17.4 iedit

I don't use iedit directly, but it is used by emr and I need to disable `iedit-toggle-key-default` or else a buffer pops up complaing that the key has been bound to something else

    (use-package iedit
      :defer t)

### 17.5 tramp

    (use-package tramp
      :commands tramp
      :config
      (setq tramp-default-method "scp"))

### 17.6 flycheck

    (use-package flycheck
      :config
      (progn
        (use-package flycheck-package
          :config (flycheck-package-setup))

        (imalison:use-package flycheck-cask
          :after flycheck
          :config
          (add-hook 'flycheck-mode-hook #'flycheck-cask-setup))

        (add-to-list 'flycheck-emacs-lisp-checkdoc-variables
                     'sentence-end-double-space)
        (global-flycheck-mode))
      :diminish flycheck-mode)

### 17.7 narrow-indirect

    (use-package narrow-indirect
      :init
      (progn
        (define-key ctl-x-4-map "nd" 'ni-narrow-to-defun-indirect-other-window)
        (define-key ctl-x-4-map "nn" 'ni-narrow-to-region-indirect-other-window)
        (define-key ctl-x-4-map "np" 'ni-narrow-to-page-indirect-other-window)))

### 17.8 editorconfig

I had to disable this mode because something that it does messes with coding settings and makes it so that I have to select the appropriate encoding every time I save gpg encrypted files.

    (use-package editorconfig
      :disabled t
      :config
      (progn
        (add-to-list 'editorconfig-exclude-modes '(org-mode))
        (editorconfig-mode 1)))

### 17.9 dtrt-indent

    (use-package dtrt-indent
      :commands 'dtrt-indent-mode
      :init (add-hook 'prog-mode-hook 'dtrt-indent-mode)
      :config
      (progn
        (setq dtrt-indent-active-mode-line-info " [⟼]")))

### 17.10 indent-guide

    (use-package indent-guide
      :disabled t
      :config
      (progn
        (indent-guide-global-mode -1)
        (setq indent-guide-delay 0.1)))

### 17.11 rainbow-delimiters

    (use-package rainbow-delimiters
      :commands rainbow-delimiters-mode
      :init
      (progn
        (add-hook 'prog-mode-hook (lambda () (rainbow-delimiters-mode t)))))

### 17.12 undo-tree

    (use-package undo-tree
      :disabled t ;; this has been getting pretty annoying
      :bind (("C--" . undo-redo)
             ("C-c u" . undo-tree-visualize)
             ("C-c r" . undo-tree-redo))
      :config
      (diminish 'undo-tree-mode)
      :init
      (progn
        ;;(setq undo-tree-visualizer-diff t) ;; This causes performance problems
        (global-undo-tree-mode)
        (setq undo-tree-visualizer-timestamps t)))

### 17.13 recentf

    (use-package recentf
      :config
      (progn
        (setq recentf-max-saved-items 1000
              recentf-max-menu-items 1000)
        (advice-add 'recentf-cleanup :around 'imalison:shut-up-around)
        (recentf-mode 1)))

### 17.14 key-chord

I have currently disabled key-chord because it may cause typing lag.

    (use-package key-chord
      :disabled t
      :preface
      (defun imalison:disable-keychord-around (function &rest args)
        (let ((key-chord-mode-was-enabled (bound-and-true-p key-chord-mode)))
          (when key-chord-mode-was-enabled (key-chord-mode -1))
          (condition-case err (progn (apply function args)) (error))
          (when key-chord-mode-was-enabled (key-chord-mode 1))))
      :config
      (progn
        (advice-add 'key-chord-mode :around 'imalison:shut-up-around)
        (key-chord-mode 1)
        (advice-add 'imalison:avy :around 'imalison:disable-keychord-around)
        (key-chord-define-global "tg" 'imalison:term-hydra/body)
        (key-chord-define-global "pj" 'imalison:projectile-find-file)
        (key-chord-define-global "p[" 'projectile-switch-project)
        (key-chord-define-global "fj" 'imalison:do-ag)
        (key-chord-define-global "jh" 'imalison:avy)))

### 17.15 nodejs-repl

    (use-package nodejs-repl
      :commands nodejs-repl)

### 17.16 calc-mode

    (use-package calc-mode
      :ensure nil
      :commands calc
      :config
      (progn
        (setq calc-context-sensitive-enter t)))

### 17.17 helm-spotify

    (use-package helm-spotify
      :commands helm-spotify)

### 17.18 jabber

    (use-package jabber
      :commands jabber-connect
      :config
      (progn
        (setq jabber-alert-presence-hooks nil)
        (defun jabber-message-content-message (from buffer text)
          (when (or jabber-message-alert-same-buffer
                    (not (memq (selected-window) (get-buffer-window-list buffer))))
            (if (jabber-muc-sender-p from)
                (format "%s: %s" (jabber-jid-resource from) text)
              (format "%s: %s" (jabber-jid-displayname from) text))))
        (setq jabber-alert-message-function 'jabber-message-content-message)))

### 17.19 htmlize

    (use-package htmlize)

### 17.20 calfw

    (use-package calfw
      :config
      (progn
        (require 'calfw-org)))

### 17.21 clocker

Not really sure what this is

    (use-package clocker)

### 17.22 deft

    (use-package deft
      :commands deft
      :config
      (progn
        (setq deft-default-extension "org")
        (setq deft-extensions '("org"))
        (setq deft-use-filter-string-for-filename t)
        (setq deft-file-naming-rules '((noslash . "_")
                                       (nospace . "_")
                                       (case-fn . downcase)))
        (setq deft-directory "~/SparkleShare/org/notes")))

### 17.23 epg

    (use-package epg
      :after shut-up
      :config
      (shut-up
        (epa-file-enable)))

### 17.24 pinentry

    (use-package pinentry
      :defer 5
      :config
      (pinentry-start))

### 17.25 twittering-mode

    (use-package twittering-mode
      :commands twittering-mode)

### 17.26 matrix-client

    (use-package matrix-client
      :disabled t ;; fails to load eieio on startup
      )

### 17.27 mu4e

    (eval-when-compile
      (require 's)
      (defvar mu4e-elisp-directory
        (s-trim (shell-command-to-string "mu4e_directory"))))
    (use-package mu4e
      :load-path mu4e-elisp-directory
      :ensure nil
      :commands (mu4e mu4e-view-message-with-msgid mu4e-update-index email)
      :bind ("C-c 0" . email)
      :config
      (progn
        (defun email (&optional arg)
          (interactive "P")
          (if (string-equal (persp-name persp-curr) "email")
              (progn (delete-other-windows) (mu4e))
            (progn
              (persp-switch "email")
              (when (or (not (mu4e-running-p)) arg)
                (delete-other-windows) (mu4e)))))
        ;; enable inline images
        (setq mu4e-view-show-images t)
        ;; show images
        (setq mu4e-show-images t)
        ;; Try to display html as text
        (setq mu4e-view-prefer-html nil)

        (setq mu4e-html2text-command "html2text -width 80 -nobs -utf8")

        ;; use imagemagick, if available
        (when (fboundp 'imagemagick-register-types)
          (imagemagick-register-types))
        (setq mail-user-agent 'mu4e-user-agent)
        (require 'org-mu4e)
        (setq mu4e-compose-complete-only-after nil)
        (setq mu4e-maildir "~/Mail")

        (setq mu4e-drafts-folder "/[Gmail].Drafts")
        (setq mu4e-sent-folder   "/[Gmail].Sent Mail")
        (setq mu4e-trash-folder  "/[Gmail].Trash")

        (setq mu4e-sent-messages-behavior 'delete)
        (setq mu4e-headers-skip-duplicates t)
        (setq mu4e-update-interval (* 60 20))
        (setq message-kill-buffer-on-exit t)
        (setq mail-user-agent 'mu4e-user-agent) ;; make mu4e the default mail client

        ;; don't save message to Sent Messages, Gmail/IMAP takes care of this
        (setq mu4e-sent-messages-behavior 'delete)

        ;; allow for updating mail using 'U' in the main view:
        (setq mu4e-get-mail-command "timeout 60 offlineimap")

        (add-hook 'mu4e-compose-mode-hook
                  (defun my-do-compose-stuff () (flyspell-mode)))

        (add-to-list 'mu4e-headers-actions '("view in browser" . mu4e-action-view-in-browser))
        (add-to-list 'mu4e-view-actions '("view in browser" . mu4e-action-view-in-browser))

        (defun mu4e-view (msg headersbuf)
          "Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
      'In sync' here means that moving to the next/previous message in
      the the message view affects HDRSBUF, as does marking etc.

      As a side-effect, a message that is being viewed loses its 'unread'
      marking if it still had that."
          (let* ((embedded ;; is it as an embedded msg (ie. message/rfc822 att)?
                  (when (gethash (mu4e-message-field msg :path)
                                 mu4e~path-parent-docid-map) t))
                 (buf
                  (if embedded
                      (mu4e~view-embedded-winbuf)
                    (get-buffer-create mu4e~view-buffer-name))))
            ;; note: mu4e~view-mark-as-read will pseudo-recursively call mu4e-view again
            ;; by triggering mu4e~view again as it marks the message as read
            (with-current-buffer buf
              (switch-to-buffer buf)
              (setq mu4e~view-msg msg)
              ;;(or embedded (not (mu4e~view-mark-as-read msg)))
              (when (or (mu4e~view-mark-as-read msg) t)
                (let ((inhibit-read-only t))
                  (erase-buffer)
                  (mu4e~delete-all-overlays)
                  (insert (mu4e-view-message-text msg))
                  (goto-char (point-min))
                  (mu4e~fontify-cited)
                  (mu4e~fontify-signature)
                  (mu4e~view-make-urls-clickable)
                  (mu4e~view-show-images-maybe msg)
                  (setq
                   mu4e~view-buffer buf
                   mu4e~view-headers-buffer headersbuf)
                  (when embedded (local-set-key "q" 'kill-buffer-and-window))
                  (mu4e-view-mode))))))

        (require 'smtpmail)

        ;; alternatively, for emacs-24 you can use:
        (setq message-send-mail-function 'smtpmail-send-it
              smtpmail-stream-type 'starttls
              smtpmail-default-smtp-server "smtp.gmail.com"
              smtpmail-smtp-server "smtp.gmail.com"
              smtpmail-smtp-service 587)))

### 17.28 gmail-message-mode

This is useful with server mode when editing gmail messages. I think that it is not currently working, or it may need to be manually enabled.

    (use-package gmail-message-mode
      :demand t)

### 17.29 ham-mode

    (use-package ham-mode
      :config
      (progn
        (setq ham-mode-html-to-markdown-command '("pandoc" "--from" "html" "--to" "markdown" file))))

### 17.30 alert

    (use-package alert
      :config
      (progn
        (defun alert-notifier-notify (info)
          (if alert-notifier-command
              (let ((args
                     (list "-title"   (alert-encode-string (plist-get info :title))
                           "-activate" "org.gnu.Emacs"
                           "-message" (alert-encode-string (plist-get info :message))
                           "-execute" (format "\"%s\"" (switch-to-buffer-command (plist-get info :buffer))))))
                (apply #'call-process alert-notifier-command nil nil nil args))
            (alert-message-notify info)))

        (defun switch-to-buffer-command (buffer-name)
          (emacsclient-command (format "(switch-to-buffer \\\"%s\\\")" buffer-name)))

        (defun emacsclient-command (command)
          (format "emacsclient --server-file='%s' -e '%s'" server-name command))

        (setq alert-default-style 'notifier)))

### 17.31 sauron

    (use-package sauron
      :defer 5
      :commands (sauron-start sauron-start-hidden)
      :init
      (progn
        (when (eq system-type 'darwin)
          (setq sauron-modules '(sauron-erc sauron-org sauron-notifications
                                            sauron-twittering sauron-jabber sauron-identica))
          (defun sauron-dbus-start ()
            nil)
          (makunbound 'dbus-path-emacs)))
      :config
      (progn
        (sauron-start-hidden)
        ;; This should really check (featurep 'dbus) but for some reason
        ;; this is always true even if support is not there.
        (setq sauron-prio-sauron-started 2)
        (setq sauron-min-priority 3)
        ;; (setq sauron-dbus-cookie t) ;; linux only?
        (setq sauron-separate-frame nil)
        (setq sauron-nick-insensitivity 1)
        (defun sauron:jabber-notify (origin priority message &optional properties)
          (funcall notify-function "gtalk" message))
        (defun sauron:erc-notify (origin priority message &optional properties)
          (let ((event (plist-get properties :event)))
            (funcall notify-function "IRC" message)))
        (defun sauron:mu4e-notify (origin priority message &optional properties)
          nil)
        (defun sauron:dbus-notify (origin priority message &optional properties)
          (funcall notify-function "GMail" message))
        (defun sauron:dispatch-notify (origin priority message &optional properties)
          (let ((handler (cond ((string= origin "erc") 'sauron:erc-notify)
                               ((string= origin "jabber") 'sauron:jabber-notify)
                               ((string= origin "mu4e") 'sauron:mu4e-notify)
                               ((string= origin "dbus") 'sauron:dbus-notify)
                               (t (lambda (&rest r) nil)))))
            (funcall handler origin priority message properties)))
        ;; Prefering alert.el for now ;; (add-hook 'sauron-event-added-functions 'sauron:dispatch-notify)
        (sauron-start-hidden)
        (add-hook 'sauron-event-added-functions 'sauron-alert-el-adapter)))

### 17.32 screenshot

    (use-package screenshot)

### 17.33 libmpdee

    (use-package libmpdee)

### 17.34 flyspell

    (use-package flyspell
      :disabled t                           ; kind of annoying
      :preface (setq flyspell-issue-welcome-flag nil)
      :config
      (progn
        (diminish 'flyspell-mode)
        (bind-key "M-s" 'flyspell-correct-word-before-point flyspell-mode-map)
        (unbind-key "C-;" flyspell-mode-map)
        (defun flyspell-emacs-popup-textual (event poss word)
          "A textual flyspell popup menu."
          (let* ((corrects (if flyspell-sort-corrections
                               (sort (car (cdr (cdr poss))) 'string<)
                             (car (cdr (cdr poss)))))
                 (cor-menu (if (consp corrects)
                               (mapcar (lambda (correct)
                                         (list correct correct))
                                       corrects)
                             '()))
                 (affix (car (cdr (cdr (cdr poss)))))
                 show-affix-info
                 (base-menu  (let ((save (if (and (consp affix) show-affix-info)
                                             (list
                                              (list (concat "Save affix: "
                                                            (car affix))
                                                    'save)
                                              '("Accept (session)" session)
                                              '("Accept (buffer)" buffer))
                                           '(("Save word" save)
                                             ("Accept (session)" session)
                                             ("Accept (buffer)" buffer)))))
                               (if (consp cor-menu)
                                   (append cor-menu (cons "" save))
                                 save)))
                 (menu (mapcar
                        (lambda (arg) (if (consp arg) (car arg) arg))
                        base-menu)))
            (cadr (assoc (popup-menu* menu :scroll-bar t) base-menu))))
        (fset 'flyspell-emacs-popup 'flyspell-emacs-popup-textual)))

### 17.35 web-mode

    (use-package web-mode
      :mode (("\\.tmpl\\'" . web-mode)
             ("\\.cql\\'" . web-mode))
      :config
      (progn
        (defvar-setq web-mode-content-types-alist
          '(("gtl" . "\\.tmpl\\'")
            ("gtl" . "\\.cql\\'")))))

### 17.36 helm-themes

    (use-package helm-themes)

### 17.37 helm-swoop

    (use-package helm-swoop
      :bind ("C-S-s" . helm-swoop)
      :commands helm-swoop)

### 17.38 perspective

I've disabled perspective because I just don't use it much.

    (use-package perspective
      :disabled t
      :demand t
      :config
      (progn
        (persp-mode)
        (defun persp-get-perspectives-for-buffer (buffer)
          "Get the names of all of the perspectives of which `buffer` is a member."
          (cl-loop for perspective being the hash-value of perspectives-hash
                   if (member buffer (persp-buffers perspective))
                   collect (persp-name perspective)))

        (defun persp-pick-perspective-by-buffer (buffer)
          "Select a buffer and go to the perspective to which that buffer
        belongs. If the buffer belongs to more than one perspective
        completion will be used to pick the perspective to switch to.
        Switch the focus to the window in which said buffer is displayed
        if such a window exists. Otherwise display the buffer in whatever
        window is active in the perspective."
          (interactive (list (funcall persp-interactive-completion-function
                                      "Buffer: " (mapcar 'buffer-name (buffer-list)))))
          (let* ((perspectives (persp-get-perspectives-for-buffer (get-buffer buffer)))
                 (perspective (if (> (length perspectives) 1)
                                  (funcall persp-interactive-completion-function
                                           (format "Select the perspective in which you would like to visit %s."
                                                   buffer)
                                           perspectives)
                                (car perspectives))))
            (if (string= (persp-name persp-curr) perspective)
                ;; This allows the opening of a single buffer in more than one window
                ;; in a single perspective.
                (switch-to-buffer buffer)
              (progn
                (persp-switch perspective)
                (if (get-buffer-window buffer)
                    (set-frame-selected-window nil (get-buffer-window buffer))
                  (switch-to-buffer buffer))))))

        (defun persp-mode-switch-buffers (arg)
          (interactive "P")
          (if arg (call-interactively 'ido-switch-buffer)
            (call-interactively 'persp-pick-perspective-by-buffer)))

        (define-key persp-mode-map (kbd "C-x b") 'persp-mode-switch-buffers))
      :bind ("C-c 9" . persp-switch))

### 17.39 smex

    (use-package smex
      ;; Using helm-M-x instead
      :disabled t
      :commands smex
      ;; This is here because smex feels like part of ido
      :bind ("M-x" . smex))

### 17.40 java

    (add-hook 'java-mode-hook
              (lambda ()
                (setq c-basic-offset 4
                      tab-width 4
                      indent-tabs-mode t)))

### 17.41 android-mode

    (use-package android-mode
      :after s
      :config
      (progn
        (setq android-mode-sdk-dir
              (s-trim (shell-command-to-string "android_sdk_directory")))))

### 17.42 gradle-mode

    (use-package gradle-mode)

### 17.43 jsx-mode

    (use-package jsx-mode
      :mode "\\.jsx\\'")

### 17.44 css

    (eval-after-load 'css-mode
      '(define-key css-mode-map (kbd "C-c b") 'web-beautify-css))

### 17.45 robe

    (use-package robe
      :commands robe-mode
      :init
      (progn (add-hook 'ruby-mode-hook 'robe-mode)))

### 17.46 rinari

    (use-package rinari
      :after ruby-mode)

### 17.47 helm-gtags

    (use-package helm-gtags
      :config
      (progn
        (setq helm-gtags-ignore-case t
              helm-gtags-auto-update t
              helm-gtags-use-input-at-cursor t
              helm-gtags-pulse-at-cursor t
              helm-gtags-prefix-key "\C-cg"
              helm-gtags-suggested-key-mapping t)
        (cl-loop for hook in '(dired-mode-hook eshell-mode-hook c-mode-hook
                                               c++-mode-hook asm-mode-hook)
                 do (add-hook hook 'helm-gtags-mode)))
      :bind (:map helm-gtags-mode-map
       ("C-c g a" . helm-gtags-tags-in-this-function)
       ("C-j" . helm-gtags-select)
       ("M-." . helm-gtags-dwim)
       ("M-," . helm-gtags-pop-stack)
       ("C-c <" . helm-gtags-previous-history)
       ("C-c >" . helm-gtags-next-history)))

### 17.48 sgml-mode

    (use-package sgml-mode
      ;; :bind ("C-c b" . web-beautify-html) TODO: mode specific, change binding
      :commands sgml-mode)

### 17.49 evil

    (use-package evil :commands (evil-mode))

### 17.50 hackernews

    (use-package hackernews :commands hackernews)

## 18 Appearance

### 18.1 Basic Config

    (setq inhibit-startup-screen t)
    (blink-cursor-mode -1)

### 18.2 Themes

Ensure all themes that I use are installed:

    (use-package solarized-theme
      :init
      (progn
        (setq solarized-high-contrast-mode-line t)))

    (defvar-setq packages-appearance
      '(monokai-theme solarized-theme zenburn-theme base16-theme molokai-theme
                      tango-2-theme gotham-theme sublime-themes rainbow-delimiters waher-theme
                      ample-theme material-theme zerodark-theme color-theme-modern leuven-theme
                      spacemacs-theme gruvbox-theme forest-blue-theme flatland-theme afternoon-theme))

    (ensure-packages-installed packages-appearance)

### 18.3 all-the-icons

    (use-package all-the-icons
      :demand t)

### 18.4 spaceline

#### 18.4.1 Disable sRGB colorspace to make powerline separators work

    (setq ns-use-srgb-colorspace nil)

#### 18.4.2 config

    (use-package spaceline-config
      :ensure spaceline
      :commands spaceline-compile
      :preface
      (progn
        (defun spaceline-gh-notifier-disable-default-notifier-modeline (&rest args)
          (delq 'github-notifier-mode-line global-mode-string)))
      :config
      (progn
        (advice-add 'github-notifier-mode :after
                    'spaceline-gh-notifier-disable-default-notifier-modeline)
        (advice-add 'github-notifier-update :after
                    'spaceline-gh-notifier-disable-default-notifier-modeline)

        (setq powerline-default-separator (random-choice '(butt slant wave)))
        (setq spaceline-workspace-numbers-unicode t
              spaceline-window-numbers-unicode t)

        (if (display-graphic-p)
            (setq-default powerline-default-separator 'wave)
          (setq-default powerline-default-separator 'utf-8))

        (spaceline-define-segment imalison:muni
          "Display the number of minutes until the next muni train comes"
          (format "🚇%s" (imalison:get-cached-muni-time))
          :when active)

        (spaceline-define-segment spaceline-gh-notifier
          "Display the number of github notifications the user has"
          (format "✉%s" github-notifier-unread-count)
          :when (> github-notifier-unread-count 0))

        (advice-add 'pl/separator-height :around
                    (lambda (function &rest args)
                      (+ (apply function args) 10)))

        ;; This needs to be executed after setting the font because the separators
        ;; need to get regenerated
        (advice-add 'imalison:set-font-size :after 'spaceline-compile)

        (spaceline-helm-mode)
        ;; 'spaceline-gh-notifier and 'imalison:muni disabled for now
        (spaceline-spacemacs-theme)))

### 18.5 page-break-lines

    (use-package page-break-lines
      :defer 1
      :diminish (page-break-lines-mode)
      :config
      (progn
        (add-to-list 'page-break-lines-modes 'prog-mode)
        (global-page-break-lines-mode +1)))

### 18.6 helm-themes

helm-themes provides an easy way to switch between emacs-themes.

    (use-package helm-themes
      :after helm)

### 18.7 window-number

    (use-package window-number
      :defer t)

### 18.8 Whitespace Setup

Make whitespace-mode use just basic coloring:

    (setq whitespace-style
          '(spaces tabs newline space-mark tab-mark newline-mark))

Set the character used to represent spaces to ·, and the character used for tabs to be ▷.

    (setq whitespace-display-mappings
          '((space-mark 32 [183] [46])
            (tab-mark 9 [9655 9] [92 9])))

### 18.9 Colorize Compliation Buffers

This automatically applies ansi-color interpretation of terminal escape sequences to compilation buffers.

    (defun imalison:colorize-compilation-buffer ()
      (let ((was-read-only buffer-read-only))
        (unwind-protect
            (progn
              (when was-read-only
                (read-only-mode -1))
              (ansi-color-apply-on-region (point-min) (point-max)))
          (when was-read-only
            (read-only-mode +1)))))

    (add-hook 'compilation-filter-hook 'imalison:colorize-compilation-buffer)

### 18.10 Automatic Theme Changer

Disabled for now

    (use-package theme-changer
      :disabled t
      :config
      (progn
        (destructuring-bind (latitude longitude)
            (imalison:get-lat-long)
          (setq calendar-latitude latitude)
          (setq calendar-longitude longitude))))

### 18.11 Fix `ansi-term` Colors

For some reason, loading certain themes can cause colors in `ansi-term-color-vector` to be undefined. The following code handles restoring the original `ansi-term-color-vector` state. The code is exectued in a load-theme hook (See the heading below).

    (require 'term)
    (defvar imalison:ansi-term-color-vector ansi-term-color-vector)

    (defun imalison:ansi-term-color-vector-broken? ()
      (--some (or (eq it 'unspecified) (not (symbolp it)))
              (append ansi-term-color-vector nil)))

    (defun imalison:restore-ansi-term-color-vector (&optional force)
      (when (or force (imalison:ansi-term-color-vector-broken?))
        (setq ansi-term-color-vector imalison:ansi-term-color-vector)))

### 18.12 After `load-theme` hook

    (defvar imalison:light-theme 'solarized-light)
    (defvar imalison:dark-theme 'material)

    (defun imalison:after-load-theme (&rest _args)
      (when (fboundp 'powerline-reset)
        (powerline-reset))
      (set-face-background 'fringe (face-background 'default))
      (imalison:restore-ansi-term-color-vector))

    (advice-add 'load-theme :after #'imalison:after-load-theme)

### 18.13 Frame Initialization

    (defvar imalison:linum-format)

    (defun imalison:format-linum (line-text)
      (propertize (format imalison:linum-format line-text) 'face 'linum))

    (make-variable-buffer-local 'imalison:linum-format)
    (defun imalison:linum-before-numbering-hook ()
      (setq imalison:linum-format
            (concat "%" (number-to-string
                         (max (length
                               (number-to-string
                                (count-lines (point-min) (point-max)))) 3)) "d")))

    (defun imalison:remove-fringe-and-hl-line-mode (&rest _stuff)
      (interactive)
      (if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
      (if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
      (if (fboundp 'menu-bar-mode) (menu-bar-mode -1))
      (defvar-setq linum-format 'imalison:format-linum)
      (add-hook 'linum-before-numbering-hook 'imalison:linum-before-numbering-hook)
      (setq left-margin-width 0)
      (defvar-setq hl-line-mode nil))

    (defun imalison:appearance (&optional frame)
      (interactive (list nil))
      (if (display-graphic-p)
          (progn
            (condition-case error
                (set-face-attribute 'default nil :font "source code pro")
              ('error (message "Error: %s, when setting font" error)))
            (set-face-attribute 'default nil :weight 'semi-bold)
            (set-face-attribute
             'default nil :height imalison:default-font-size-pt))
        (progn
          (load-theme 'source-code-pro t)
          (message "not setting font")))
      (setq powerline-default-separator (if (display-graphic-p) 'wave 'utf-8))
      (load-theme imalison:dark-theme t)
      (spaceline-compile)
      (imalison:remove-fringe-and-hl-line-mode))

    ;; This is needed because you can't set the font or theme at daemon start-up.
    ;; (when (display-graphic-p) (imalison:appearance))
    (add-hook 'after-init-hook 'imalison:appearance)
    (add-hook 'after-make-frame-functions 'imalison:appearance)
    ;; TODO/XXX: why do we immediately remove this hook?
    (remove-hook 'after-make-frame-functions 'imalison:appearance)

## 19 Post Init Custom

    (when (file-exists-p custom-after-file) (load custom-after-file))
    (when (file-exists-p machine-custom) (load machine-custom))

Author: Ivan Malison

Created: 2016-11-07 Mon 16:42

Validate