#+TITLE: A literate emacs configuration

* Packages
** Set up package archives: live on the bleeding edge.
#+BEGIN_SRC emacs-lisp
  (require 'package)
  (setq package-archives '(("melpa" . "http://melpa.milkbox.net/packages/")
                           ("elpa" . "http://elpa.gnu.org/packages/")
                           ("org" . "http://orgmode.org/elpa/")))
  (package-initialize)
#+END_SRC
** TODO Use use-package
List out all packages and install them if they're available.

* Customization
With some text for comparison
** Move the file out of init.el
#+BEGIN_SRC emacs-lisp
  (setq custom-file "~/.emacs.d/custom.el")
  (load custom-file 'noerror)
#+END_SRC

* UI
** Minimal UI
Do this first to try to get the flicker in the gui out of the way quickly
#+BEGIN_SRC emacs-lisp
  (tool-bar-mode -1)
  (menu-bar-mode -1)
  (if (boundp 'fringe-mode)
  (fringe-mode -1))
  (if (boundp 'scroll-bar-mode)
      (scroll-bar-mode -1))
#+END_SRC
** Mouse support
#+BEGIN_SRC emacs-lisp
  (xterm-mouse-mode)
#+END_SRC
** Improve theme loading; from reddit
#+BEGIN_SRC emacs-lisp
  (defadvice load-theme (before clear-previous-themes activate)
    "Clear existing theme settings instead of layering them"
    (mapc #'disable-theme custom-enabled-themes))
#+END_SRC
** Set up fonts
#+BEGIN_SRC emacs-lisp
(set-face-attribute 'default nil :family "Iosevka" :height 130)
(set-face-attribute 'fixed-pitch nil :family "Iosevka" :height 130)
(set-face-attribute 'variable-pitch nil :family "Baskerville")
#+END_SRC
** And a minimal startup
#+BEGIN_SRC emacs-lisp
  (setq inhibit-startup-message t)
  (setq inhibit-splash-screen t)
  (setq initial-scratch-message nil)
#+END_SRC
** Disable the bell
#+BEGIN_SRC emacs-lisp
  (setq ring-bell-function 'ignore)
#+END_SRC
** Buffer Switching
#+BEGIN_SRC emacs-lisp
  (winner-mode t)
#+END_SRC
** Display line numbers mode
*** Activate on programming modes
#+BEGIN_SRC emacs-lisp
(add-hook 'prog-mode-hook
          'display-line-numbers-mode)
#+END_SRC

** Fill column
#+BEGIN_SRC emacs-lisp
(setq fci-rule-column 80)
#+END_SRC
** Scrolling more naturally
#+BEGIN_SRC emacs-lisp
(pixel-scroll-mode)
#+END_SRC

** Compilation window output
#+BEGIN_SRC emacs-lisp
(setq compilation-window-height 15)
#+END_SRC
** Truncate lines
#+BEGIN_SRC emacs-lisp
(setq-default truncate-lines t)
#+END_SRC
** Sweet Title Bar
#+BEGIN_SRC emacs-lisp
(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
(add-to-list 'default-frame-alist '(ns-appearance . dark))
#+END_SRC
* Evil
** I can't type without vim bindings anymore.
#+BEGIN_SRC emacs-lisp
  (evil-mode t)
#+END_SRC
** Allow some common typos
#+BEGIN_SRC emacs-lisp
  (evil-ex-define-cmd "W[rite]" 'save-buffer)
  (evil-ex-define-cmd "V[split]" 'evil-window-vsplit)
#+END_SRC

* Org
** Babel
*** Better source code window editing
#+BEGIN_SRC emacs-lisp
  (setq org-src-window-setup 'other-window)
#+END_SRC
*** Highlight and indent source code blocks
#+BEGIN_SRC emacs-lisp
(setq org-src-fontify-natively t)
(setq org-src-tab-acts-natively t)
(setq org-edit-src-content-indentation 0)
#+END_SRC
*** Highlight quotes
#+BEGIN_SRC emacs-lisp
(setq org-fontify-quote-and-verse-blocks t)
#+END_SRC
*** Enable languages
#+BEGIN_SRC emacs-lisp
(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (dot . t)
   (ditaa . t)
   (python . t)
   (C . t)
   (rust . t)))
#+END_SRC
*** Prevent confirmation
#+BEGIN_SRC emacs-lisp
  (setq org-confirm-babel-evaluate nil)
#+END_SRC
*** Use Web mode for HTML
#+BEGIN_SRC emacs-lisp
  (add-to-list 'org-src-lang-modes
               '("html" . web))
#+END_SRC
** UI
*** Hide markers
#+BEGIN_SRC emacs-lisp
  (setq org-hide-emphasis-markers t)
#+END_SRC
*** Clean bullets
#+BEGIN_SRC emacs-lisp
(setq org-bullets-bullet-list
      '("◉" "○"))
(add-hook 'org-mode-hook
          (lambda ()
            (org-bullets-mode 1)
            (org-indent-mode t)))
#+END_SRC
*** Display images
#+BEGIN_SRC emacs-lisp
  (setq org-startup-with-inline-images t)
  (add-hook
   'org-babel-after-execute-hook
   (lambda ()
     (when org-inline-image-overlays
       (org-redisplay-inline-images))))
#+END_SRC
*** Enable auto-fill mode
#+BEGIN_SRC emacs-lisp
  (add-hook
   'org-mode-hook
   (lambda ()
     (auto-fill-mode)))
#+END_SRC
*** Fontify whole lines
#+BEGIN_SRC emacs-lisp
(setq org-fontify-whole-heading-line t)
#+END_SRC
** Combined with evil
#+BEGIN_SRC emacs-lisp
  (evil-define-key 'normal org-mode-map (kbd "TAB") 'org-cycle)
#+END_SRC
** Bugfixes
#+BEGIN_SRC emacs-lisp
  (defun org-font-lock-ensure ()
    (font-lock-fontify-buffer))
#+END_SRC
** Expert tagging
(Doesn't show the tag window till an extra C-c.)
#+BEGIN_SRC emacs-lisp
(setq org-fast-tag-selection-single-key 'expert)
#+END_SRC
** Tag clicks show sparse tree instead of agenda view
#+BEGIN_SRC emacs-lisp
  (defun tag-at-point-in-heading ()
    "Returns the tag at the current point in the string"
    (let ((str (buffer-string))
          (begin (point))
          (end (point)))
      (while (not (equal (aref str begin) ?:))
        (setq begin (- begin 1)))
      (while (not (equal (aref str end) ?:))
        (setq end (+ end 1)))
      (substring str (+ 1 begin) end)))

  (defun open-sparse-view ()
    "Shows a sparse tree on clicking a tag instead of org-tags-view"
    ;; From org-open-at-point, sanity checking that we're on a headline with tags
    (when (and (org-element-lineage (org-element-context)
                                    '(headline inlinetask)
                                    t)
               (progn (save-excursion (beginning-of-line)
                                      (looking-at org-complex-heading-regexp))
                      (and (match-beginning 5)
                           (> (point) (match-beginning 5)))))
      (org-match-sparse-tree nil (concat "+" (tag-at-point-in-heading)))
      't))

  (add-hook 'org-open-at-point-functions
            'open-sparse-view)
#+END_SRC
** Add support for not exporting headlines
#+BEGIN_SRC emacs-lisp
  (require 'ox-extra) ; from org-plus-contrib
  (ox-extras-activate '(ignore-headlines))
#+END_SRC
** Add support for publishing 'web' src as is
#+BEGIN_SRC emacs-lisp
  (defun org-babel-execute:web (body params)
    body)
#+END_SRC
* Emamux
** Customization
#+BEGIN_SRC emacs-lisp
  (setq emamux:use-nearest-pane t)
#+END_SRC
** Some useful shortcuts
#+BEGIN_SRC emacs-lisp
  (define-key evil-normal-state-map (kbd "C-c r") 'emamux:run-last-command)
  (define-key evil-normal-state-map (kbd "C-c x") 'emamux:run-command)
  (define-key evil-normal-state-map (kbd "C-c i") 'emamux:inspect-runner)
#+END_SRC
* Compiling
** Keyboard shortcut
#+BEGIN_SRC emacs-lisp
(define-key evil-normal-state-map (kbd "C-c c") 'recompile)
#+END_SRC
* Man Pages
#+BEGIN_SRC emacs-lisp
(setq Man-notify-method 'pushy)

#+END_SRC
* Editing
** Indentation
#+BEGIN_SRC emacs-lisp
  (setq c-basic-offset 2)
  (setq tab-width 2)
  (setq-default indent-tabs-mode nil)
#+END_SRC
** Backups & autosaves
#+BEGIN_SRC emacs-lisp
  (setq auto-save-default nil)
  (setq backup-directory-alist
        `((".*" . ,temporary-file-directory)))
  (setq auto-save-file-name-transforms
        `((".*" ,temporary-file-directory t)))
#+END_SRC
** Better braces
*** Smartparens
#+BEGIN_SRC emacs-lisp
  (require 'smartparens-config)
  (add-hook 'prog-mode-hook 'turn-on-smartparens-mode)
  (define-key smartparens-mode-map (kbd "M-f") 'sp-forward-slurp-sexp)
  (define-key smartparens-mode-map (kbd "M-b") 'sp-backward-slurp-sexp)
  (define-key smartparens-mode-map (kbd "M-F") 'sp-forward-barf-sexp)
  (define-key smartparens-mode-map (kbd "M-B") 'sp-backward-barf-sexp)
  (define-key smartparens-mode-map (kbd "M-s") 'sp-splice-sexp)
  (define-key smartparens-mode-map (kbd "C-k") 'sp-kill-sexp)
#+END_SRC
*** Highlight parenthesis
#+BEGIN_SRC emacs-lisp
  (show-paren-mode t)
#+END_SRC
** Whitespace
#+BEGIN_SRC emacs-lisp
  (add-hook 'before-save-hook 'whitespace-cleanup)
  (setq require-final-newline t)
#+END_SRC

* Menus
** Helm
#+BEGIN_SRC emacs-lisp
(require 'helm-config)
(global-set-key (kbd "M-x") #'helm-M-x)
(global-set-key (kbd "C-x C-f") #'helm-find-files)
(setq helm-M-x-fuzzy-match 't)
(setq helm-mode-fuzzy-match 't)
(setq helm-completion-in-region-fuzzy-match 't)
(helm-mode 1)
#+END_SRC
** IDO: disabled, experimenting with Helm
#+BEGIN_SRC
  (setq ido-enable-flex-matching t)
  (setq ido-everywhere t)
  (ido-mode t)
#+END_SRC
** Smex: disabled, experimenting with Helm for a bit
#+BEGIN_SRC
  (global-set-key (kbd "M-x") 'smex)
  (global-set-key (kbd "M-X") 'smex-major-mode-commands)
  (global-set-key (kbd "C-c M-x") 'execute-extended-command)
#+END_SRC

* Language/Project specific
** BUCK
*** Trigger python mode
#+BEGIN_SRC emacs-lisp
  (add-to-list 'auto-mode-alist '(".*/BUCK$" . python-mode))
#+END_SRC
** Scheme
*** Set up chicken scheme
#+BEGIN_SRC emacs-lisp
  (setq scheme-program-name "/usr/local/bin/csi -:c")
#+END_SRC
** Web Mode
#+BEGIN_SRC emacs-lisp
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-css-indent-offset 2)
  (setq web-mode-code-indent-offset 2)

  (setq web-mode-style-padding 2)
  (setq web-mode-script-padding 2)

  (setq web-mode-auto-quote-style 2) ; use single quotes
#+END_SRC

** Rust
#+BEGIN_SRC emacs-lisp
(add-hook 'rust-mode-hook #'racer-mode)
(add-hook 'rust-mode-hook
          (lambda ()
           (define-key rust-mode-map (kbd "TAB") #'company-indent-or-complete-common)))
(add-hook 'racer-mode-hook #'eldoc-mode)
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup)
#+END_SRC

* Version Control
** Disable by default
#+BEGIN_SRC emacs-lisp
  (setq vc-handled-backends ())
#+END_SRC
** Customize Monky, for when it's loaded
*** Use command server for speed
#+BEGIN_SRC emacs-lisp
  (setq monky-process-type 'cmdserver)
#+END_SRC
*** And add support for a nicer log file
#+BEGIN_SRC emacs-lisp
  (defun hg-file-history ()
    (interactive)
    (require 'monky)
    (monky-run-hg-async
     "log"
     "--template"
     "\n{rev}) {date|shortdate}/{author|user}\n{desc|fill68}\n↘\n"
     buffer-file-name))
#+END_SRC

* Utilities
** Current file name
#+BEGIN_SRC emacs-lisp
  (defun path ()
    (interactive)
    (message (buffer-file-name)))
#+END_SRC

* GDB
** Show all the windows on start
#+BEGIN_SRC emacs-lisp
  (setq gdb-many-windows 't)
#+END_SRC
* Neotree
** Simple theme
#+BEGIN_SRC emacs-lisp
(setq neo-theme 'ascii)
#+END_SRC
* Dired
** Hide permissions and owners to make file lists less noisy (from Xah Lee's blog)
#+BEGIN_SRC emacs-lisp
  (add-hook 'dired-mode-hook
            (lambda ()
              (dired-hide-details-mode 1)))
#+END_SRC
** Disable ls by default in dired
#+BEGIN_SRC emacs-lisp
   (setq dired-use-ls-dired nil)
#+END_SRC

* Browsing
** Default to mac
#+BEGIN_SRC emacs-lisp
  (setq browse-url-browser-function 'browse-url-default-macosx-browser)
#+END_SRC
** Enable cookies
#+BEGIN_SRC emacs-lisp
  (setq w3m-use-cookies t)
#+END_SRC

* Auto completion
#+BEGIN_SRC emacs-lisp
(add-hook 'prog-mode-hook 'company-mode)
(setq company-tooltip-align-annotations t)
#+END_SRC

* Buffer Management
** Close buffers
From StackOverflow
#+BEGIN_SRC emacs-lisp
(defun close-all-buffers ()
  (interactive)
  (mapc 'kill-buffer (buffer-list)))
#+END_SRC
** Reload files
#+BEGIN_SRC emacs-lisp
  (defun revert-all-buffers ()
    (interactive)
    (dolist (buf (buffer-list))
      (with-current-buffer buf
        (when (buffer-file-name)
          (revert-buffer t t t)))))
#+END_SRC

* Desaturate
#+BEGIN_SRC emacs-lisp
(defun desaturate-color (color-hex)
  "Converts a color string to its desaturated equivalent hex string"
  (require 'color)
  (apply
   'color-rgb-to-hex
   (append (apply
            'color-hsl-to-rgb
            (apply
             'color-desaturate-hsl
             `(,@(apply 'color-rgb-to-hsl (color-name-to-rgb color-hex)) 100)))
           '(2))))

(defun transform-theme-colors (fn)
  "Apply FN to the colors on every active face.

   FN should accept the face symbol and the current color,
   and return the new color to be applied."
  (interactive)
  (mapc
   (lambda (face)
     (mapc
      (lambda (attr)
        (let ((current (face-attribute face attr)))
          (unless (or (not current)
                      (listp current)
                      (string= current "unspecified")
                      (string= current "t"))
            (set-face-attribute face nil attr (funcall fn face current)))))
      '(:foreground :background :underline :overline :box :strike-through
                    :distant-foreground))
     (mapc
      (lambda (complex-attr)
        (let* ((full (copy-tree (face-attribute face complex-attr)))
               (current (if (listp full) (member :color full))))
          (unless (or (not current)
                      (not (listp full)))
            (setcar (cdr current) (funcall fn face (cadr current)))
            (set-face-attribute face nil complex-attr full))))
      '(:underline :overline :box)))
   (face-list)))

(defun desaturate-theme ()
  "As title: desaturate all currently active face colorsj."
  (interactive)
  (transform-theme-colors
   (lambda (face color)
     (desaturate-color color))))

(defun invert-theme ()
  "Take the complement of all currently active colors."
  (interactive)
  (require 'color)
  (transform-theme-colors
   (lambda (face color)
     (apply
      'color-rgb-to-hex
      (color-complement color))))
  (let ((current-ns-appearance (assoc 'ns-appearance default-frame-alist)))
    (cond ((eq (cdr current-ns-appearance) 'light)
           (setf (cdr current-ns-appearance) 'dark))
          ((eq (cdr current-ns-appearance) 'dark)
           (setf (cdr current-ns-appearance) 'light)))))
#+END_SRC

* Mode Line
#+BEGIN_SRC emacs-lisp
(setq mode-line-format
              (list
               "%& %b%n"
               " ~ "
               "%m"
               " ~ "
               "%l:%c"))
#+END_SRC