summary refs log tree commit diff stats
path: root/emacs/init.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/init.el')
-rw-r--r--emacs/init.el1035
1 files changed, 1035 insertions, 0 deletions
diff --git a/emacs/init.el b/emacs/init.el
new file mode 100644
index 0000000..d011945
--- /dev/null
+++ b/emacs/init.el
@@ -0,0 +1,1035 @@
+;;;; Startup
+;; Do not merge echo-area-message sexp
+(setq inhibit-startup-echo-area-message "alan")
+(setq inhibit-startup-screen t
+      initial-scratch-message ""
+      initial-major-mode 'text-mode
+      user-mail-address "alan@alanpearce.co.uk"
+      user-full-name "Alan Pearce")
+(setq custom-file "~/.emacs.d/custom.el")
+
+;;;; Package Management
+(setq *el-get-dir* (expand-file-name "el-get/" user-emacs-directory)
+      *elisp-dir*  (expand-file-name "elisp/" user-emacs-directory)
+      *custom-dir* (expand-file-name "custom/" user-emacs-directory)
+      el-get-github-default-url-type "git"
+      el-get-emacswiki-base-url "http://raw.github.com/emacsmirror/emacswiki.org/master/"
+      package-archives '(("ELPA"      . "http://tromey.com/elpa/")
+                         ("gnu"       . "http://elpa.gnu.org/packages/")
+                         ("marmalade" . "http://marmalade-repo.org/packages/")
+                         ("melpa"     . "http://melpa.milkbox.net/packages/")))
+
+(defun add-subdirs-to-load-path (path)
+  (unless (member path load-path)
+    (mapc (lambda (file)
+            (let ((full-path (concat path file)))
+              (if (and (not (string-prefix-p "." file))
+                       (file-directory-p full-path))
+                  (add-to-list 'load-path full-path))))
+          (directory-files *el-get-dir*))))
+
+(if (file-exists-p (concat *el-get-dir* "el-get"))
+    (add-subdirs-to-load-path *el-get-dir*)
+  (unless (require 'el-get nil t)
+    (with-current-buffer
+      (url-retrieve-synchronously
+       "https://raw.github.com/dimitri/el-get/master/el-get-install.el")
+      (make-local-variable 'el-get-master-branch)
+      (goto-char (point-max))
+      (eval-print-last-sexp)
+      (load (concat *elisp-dir* "el-get-setup")))))
+
+(add-to-list 'load-path *elisp-dir*)
+
+(require 'use-package)
+
+(eval-when-compile
+  (unless (fboundp 'diminish)
+    (require 'diminish nil t)))
+
+(use-package el-get
+  :commands (el-get-init
+             el-get-install
+             el-get-reinstall
+             el-get-remove
+             el-get-update
+             el-get-self-update
+             el-get-describe))
+
+;;;; Style
+
+(use-package linum
+  :commands (linum-mode)
+  :config (setq linum-format " %4d "))
+
+(use-package highlight-symbol
+  :disabled t
+  :config (setq highlight-symbol-idle-delay 0.2))
+
+(use-package whitespace
+  :defer t
+  :config (setq whitespace-style
+                '(face
+                  space
+                  tabs
+                  trailing
+                  newline
+                  empty
+                  space-after-tab
+                  tab-mark
+                  space-before-tab
+                  indentation
+                  indentation::space
+                  indentation::tabs
+                  )))
+
+(global-font-lock-mode t)
+;; Allow font-lock-mode to do background parsing
+(setq jit-lock-stealth-time 1
+      jit-lock-stealth-load 5
+      jit-lock-defer-time 0.1)
+
+(use-package solarized-theme
+  :config (load-theme 'solarized-light t))
+
+(use-package color-theme-solarized
+  :disabled t
+  :commands (color-theme-solarized-light)
+  :depends color-theme
+  :init (color-theme-solarized-light))
+
+(when (or (display-graphic-p)
+          (daemonp))
+  (use-package fringe
+    :defer t
+    :config (fringe-mode '(0 . 0)))
+
+  (defun use-variable-fonts ()
+    (interactive)
+    (variable-pitch-mode)
+    (setq cursor-type 'bar))
+
+  (add-hook 'org-mode-hook #'use-variable-fonts)
+
+  (if (eq window-system 'w32)
+      (let* ((font-size 10)
+             (mono-face (cond
+                         ((member "Liberation Mono" (font-family-list))
+                          "Liberation Mono")
+                         ((member "Liberation Sans Mono" (font-family-list))
+                          "Liberation Sans Mono")
+                         ((member "Consolas" (font-family-list))
+                          "Consolas")
+                         ))
+             (variable-face "Segoe UI")
+          (default-font (concat mono-face "-" (number-to-string font-size))))
+     (when mono-face
+       (set-face-font 'default default-font)
+       (set-face-font 'fixed-pitch default-font))
+     (when variable-face
+       (set-face-font 'variable-pitch (concat variable-face "-"
+                                              (number-to-string (1+ font-size))))))))
+
+(with-elapsed-timer "Setting up font styles"
+  (let* ((font-height (face-attribute 'default :height))
+         (small-font-height (max 1 (floor (* .917 font-height)))))
+    (mapc (lambda (item)
+            (put (car item) 'customized-face (cadr item))
+            (face-spec-set (car item) (cadr item)))
+          `((linum
+             ((t (:height ,small-font-height
+                          :foreground unspecified
+                          :inherit fringe
+                          :overline nil
+                          :slant normal))))
+            (vertical-border
+             ((t (:foreground unspecified
+                              :background unspecified
+                              :inherit file-name-shadow))))
+            (font-lock-comment-face
+             ((t (:slant normal))))
+            (font-lock-doc-face
+             ((t (:slant normal))))
+            (popup-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit linum
+                              :height ,font-height))))
+            (popup-scroll-bar-foreground-face
+             ((t (:background unspecified
+                              :inherit region))))
+            (popup-scroll-bar-background-face
+             ((t (:background unspecified
+                              :inherit popup-face))))
+            (ac-completion-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit popup-face))))
+            (ac-candidate-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit linum
+                              :height ,font-height))))
+            (ac-selection-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit font-lock-variable-name-face
+                              :inverse-video t))))
+            (ac-candidate-mouse-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit region))))
+            (ac-dabbrev-menu-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit popup-face))))
+            (ac-dabbrev-selection-face
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit ac-selection-face))))
+            (flymake-warnline
+             ((t (:background unspecified
+                              :foreground unspecified
+                              :inherit font-lock-preprocessor-face))))
+            (org-table ((t (:inherit 'fixed-pitch))))
+            (org-formula ((t (:foreground "Firebrick"
+                                          :inherit 'fixed-pitch))))
+            (org-done ((t (:weight normal
+                                   :strike-through t))))
+            (org-headline-done ((t (:strike-through t))))
+            ))))
+
+;;;; Autosaves & Backups
+(let ((backup-dir (expand-file-name "~/.emacs.d/backups/")))
+  (unless (file-directory-p backup-dir)
+    (make-directory backup-dir))
+  (setq backup-directory-alist `((".*" . ,backup-dir))
+        auto-save-file-name-transforms `((".*" ,temporary-file-directory t))
+        backup-by-copying-when-linked t
+        backup-by-copying-when-mismatch t))
+
+;;;; Buffers
+
+(use-package ibuffer
+  :disabled t
+  :commands (ibuffer)
+  :config (progn
+            (setq ibuffer-saved-filter-groups
+                  (quote (("default"
+                           ("org" (mode . org-mode))
+                           ("emacs" (mode . emacs-lisp-mode))
+                           ("zsh" (filename . "/zsh"))
+                           ("server" (filename . "/su:root@server"))
+                           ))))
+
+            ;; Human-readable base-2 size column
+            (define-ibuffer-column size-h
+              (:name "Size" :inline t)
+              (cond
+               ((> (buffer-size) 1024)
+                (format "%7.2fK" (/ (buffer-size) 1024.0)))
+               ((> (buffer-size) 1048576)
+                (format "%7.2fM" (/ (buffer-size) 1048576.0)))
+               (t
+                (format "%8d" (buffer-size)))))
+
+            (setq ibuffer-formats
+                  '((mark modified read-only " "
+                          (name 18 18 :left :elide)
+                          " "
+                          (size-h 9 -1 :right)
+                          " "
+                          (mode 16 16 :left :elide)
+                          " "
+                          filename-and-process)))))
+
+(use-package uniquify
+  :defer t
+  :idle (require 'uniquify)
+  :config (progn
+            (setq uniquify-buffer-name-style 'reverse
+                  uniquify-separator "/"
+                  uniquify-after-kill-buffer-p t
+                  uniquify-ignore-buffers-re "^\\*")))
+
+;;;; Communication
+
+(use-package erc
+  :defer t
+  :config (progn
+            (setq erc-user-full-name "Alan Pearce"
+                  erc-email-userid "alan@alanpearce.co.uk"
+                  erc-echo-notice-in-minibuffer t
+                  erc-keywords '("alanpearce" "lethalrocks")
+                  erc-autojoin-channels-alist
+                  '(("freenode.net" "#emacs" "##freebsd" "#bufferbloat" "#openwrt" "#lojban" "#zfs" "#introverts")
+                    ("what.cd" "#what.cd")
+                    ("beusergroup.co.uk" "#be")
+                    ))
+            (add-to-list 'erc-modules 'scrolltobottom)
+            (add-to-list 'erc-modules 'autojoin)
+            (add-to-list 'erc-modules 'match)))
+
+;;;; Completion
+
+(setq completion-styles '(basic initials partial-completion substring)
+      completion-ignore-case t)
+
+(use-package smart-tab
+  :commands (global-smart-tab-mode)
+  :idle (global-smart-tab-mode)
+  :config (progn
+            (nconc smart-tab-completion-functions-alist '((php-mode . php-complete-function)))
+            (diminish 'smart-tab-mode "")))
+
+;;;; Directory browsing
+(use-package dired
+  :defer t
+  :config (progn
+            (bind-key "<return>" #'dired-find-file dired-mode-map)
+            (bind-key "^" (lambda () (interactive) (find-alternate-file "..")) dired-mode-map)
+            (setq dired-dwim-target t
+                  dired-recursive-copies 'top
+                  dired-recursive-deletes 'top
+                  dired-bind-jump nil)
+            (put 'dired-find-alternate-file 'disabled nil)))
+
+(use-package dired+
+  :defer t
+  :config (diredp-toggle-find-file-reuse-dir 1))
+
+;;;; Documentation
+
+(add-to-list 'Info-default-directory-list
+             (concat user-emacs-directory
+                     "info"))
+
+(use-package eldoc
+  :commands (turn-on-eldoc-mode
+             eldoc-add-command))
+
+(use-package eldoc-context
+  :depends eldoc
+  :bind (("C-c h" . rgr/toggle-context-help)))
+
+(use-package help+
+  :bind (("<f1>" . help-on-click/key)))
+
+(use-package which-func
+  :defer t
+  :idle (which-function-mode)
+  :init (setq which-func-modes t))
+
+;;;; Files
+
+(prefer-coding-system 'utf-8-auto-unix)
+(set-default-coding-systems 'utf-8-auto-unix)
+(setq-default buffer-file-coding-system 'utf-8-auto-unix)
+(use-package autorevert
+  :defer t
+  :idle (global-auto-revert-mode 1))
+
+(add-hook 'before-save-hook #'delete-trailing-whitespace)
+
+(defun rename-current-buffer-file ()
+  "Renames current buffer and file it is visiting."
+  (interactive)
+  (let ((name (buffer-name))
+        (filename (buffer-file-name)))
+    (if (not (and filename (file-exists-p filename)))
+        (error "Buffer '%s' is not visiting a file!" name)
+      (let ((new-name (read-file-name "New name: " filename)))
+        (if (get-buffer new-name)
+            (error "A buffer named '%s' already exists!" new-name)
+          (rename-file filename new-name 1)
+          (rename-buffer new-name)
+          (set-visited-file-name new-name)
+          (set-buffer-modified-p nil)
+          (message "File '%s' successfully renamed to '%s'"
+                   name (file-name-nondirectory new-name)))))))
+
+(defun delete-current-buffer-file ()
+  "Removes file connected to current buffer and kills buffer."
+  (interactive)
+  (let ((filename (buffer-file-name))
+        (buffer (current-buffer))
+        (name (buffer-name)))
+    (if (not (and filename (file-exists-p filename)))
+        (ido-kill-buffer)
+      (when (yes-or-no-p "Are you sure you want to remove this file? ")
+        (delete-file filename)
+        (kill-buffer buffer)
+        (message "File '%s' successfully removed" filename)))))
+
+(use-package saveplace
+  :defer t
+  :idle (require 'saveplace)
+  :config (progn (setq-default save-place t)
+                 (setq save-place-file (expand-file-name ".saveplace" user-emacs-directory))
+                 ))
+
+(use-package tramp
+  :defer t
+  :config (progn
+            (setq tramp-default-method (if (eq system-type 'windows-nt) "plinkx" "ssh")
+                  tramp-default-user-alist '(("\\`su\\(do\\)?\\'" nil "root") (nil nil "alan"))
+                  tramp-backup-directory-alist backup-directory-alist
+                  backup-enable-predicate (lambda (name)
+                                            (and (normal-backup-enable-predicate name)
+                                                 (not (let ((method (file-remote-p name 'method)))
+                                                        (when (stringp method)
+                                                          (member method '("su" "sudo")))))))
+                  tramp-shell-prompt-pattern "\\(?:^\\|
\\)[^#$%>\n]*#?[#$%>›] *\\(\\[[0-9;]*[a-zA-Z] *\\)*")
+            (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" (concat "/" tramp-default-method ":%h:")))
+            (add-to-list 'tramp-default-proxies-alist '((regexp-quote (system-name)) nil nil))
+            (add-to-list 'tramp-default-proxies-alist '("router" nil nil))))
+
+(use-package tramp-sh
+  :defer t
+  :config (progn
+            (add-to-list 'tramp-remote-path "/usr/local/sbin")
+            (add-to-list 'tramp-remote-path "~/bin")))
+
+;;;; Indentation
+
+(setq-default tab-width 4
+              indent-tabs-mode t)
+(setq tab-stop-list
+      ;; (mapcar (lambda (x)
+      ;;           (* 4 x))
+      ;;         (number-sequence 1 (/ 120 4)))
+      '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120)
+      tab-always-indent 'complete)
+
+(use-package auto-indent-mode
+  :defer t
+  :commands (auto-indent-minor-mode
+             auto-indent-mode)
+  :config (progn
+            (setq auto-indent-key-for-end-of-line-then-newline "<C-return>"
+                  auto-indent-key-for-end-of-line-insert-char-then-newline "<C-S-return>"
+                  auto-indent-blank-lines-on-move nil
+                  auto-indent-assign-indent-level 4
+                  auto-indent-backward-delete-char-behavior nil
+                  auto-indent-delete-trailing-whitespace-on-save-file t
+                  auto-indent-mode-untabify-on-yank-or-paste nil
+                  )
+            (auto-indent-global-mode)))
+
+(use-package smart-tabs-mode
+  :commands (smart-tabs-mode
+             smart-tabs-mode-enable
+             smart-tabs-advice)
+  :config (progn
+            (smart-tabs-insinuate 'c 'javascript 'cperl 'python 'ruby)
+            (add-hook 'php-mode-hook #'smart-tabs-mode-enable)
+            ))
+
+;;;; Keybindings
+
+(unbind-key "<f4>")
+(bind-key "<f5>" #'compile)
+(bind-key "<f6>" #'kmacro-start-macro-or-insert-counter)
+(bind-key "<f7>" #'kmacro-end-or-call-macro)
+
+(bind-key "<apps>" #'execute-extended-command)
+
+(if (display-graphic-p)
+    (unbind-key "C-z"))
+(bind-key "C-<tab>" #'other-window)
+
+(bind-key "C-x C-r" #'revert-buffer)
+(bind-key "C-x C-j" #'delete-indentation)
+(unbind-key "C-x C-c")
+
+(bind-key "C-c i" #'ucs-insert)
+
+;; Enable narrowing functions C-x n
+(put 'narrow-to-defun  'disabled nil)
+(put 'narrow-to-page   'disabled nil)
+(put 'narrow-to-region 'disabled nil)
+
+;;;; Minibuffer
+
+(setq enable-recursive-minibuffers t)
+(use-package mb-depth
+  :defer t
+  :idle (minibuffer-depth-indicate-mode t))
+
+(defalias 'exit-emacs 'save-buffers-kill-emacs)
+
+(use-package lacarte
+  :bind (("M-`" . lacarte-execute-menu-command)))
+
+(use-package helm-config
+  :bind (("C-x i"   . helm-imenu)
+         ("C-x C-b" . helm-mini)))
+
+(use-package ido
+  :commands (ido-mode
+             ido-find-file)
+  :init (bind-key* "C-x C-f" #'ido-find-file)
+  :bind (("C-x b"   . ido-switch-buffer))
+  :config (progn
+            (ido-mode)
+            (setq ido-decorations (quote ("\n›" "" "\n " "\n …" "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")))
+            (setq ido-auto-merge-delay-time 99999
+                  ido-enable-flex-matching t)
+            (ido-init-completion-maps)
+            (defun ido-manual-merge ()
+              (interactive)
+              (ido-initiate-auto-merge (current-buffer)))
+            (bind-key "C-c C-s" #'ido-manual-merge ido-file-dir-completion-map)))
+
+(use-package smex
+  :bind (("M-x" . smex)
+         ("<apps>" . smex)
+         ("<menu>" . smex)
+         ("M-X" . smex-major-mode-commands)
+         ("C-c M-x" . execute-extended-command))
+  :config (progn
+            (setq smex-history-length 100
+                  smex-save-file (concat user-emacs-directory
+                                         "smex-items"))
+            (smex-initialize)
+            (setq smex-key-advice-ignore-menu-bar t
+                  smex-auto-update nil)
+            (defun smex-update-after-load (unused)
+              (if (boundp 'smex-cache)
+                  (smex-update)))
+            (add-hook 'after-load-functions 'smex-update-after-load)))
+
+;;;; Modeline
+
+(column-number-mode t)
+(size-indication-mode t)
+
+;;;; Modes
+
+;;;; systemd files
+(add-to-list 'auto-mode-alist '("\\.service\\'" . conf-mode))
+(add-to-list 'auto-mode-alist '("\\.target\\'" . conf-mode))
+(add-to-list 'auto-mode-alist '("\\.socket\\'" . conf-mode))
+
+(use-package xrdb-mode
+  :mode (("\\.Xdefaults\\'" . xrdb-mode)
+         ("\\.Xresources\\'" . xrdb-mode)))
+
+(use-package haskell-mode
+  :mode (("\\.hs\\'" . haskell-mode)
+         ("xmobarrc\\'" . haskell-mode)))
+
+;;;; Planning
+
+(use-package calendar
+  :defer t
+  :config (progn
+            (setq calendar-week-start-day 1)
+            (calendar-set-date-style 'iso)))
+
+(use-package org-mode
+  :bind (("C-c C-a" . org-agenda-list)
+         ("C-c a" . org-agenda)
+         ("C-c l" . org-store-list)
+         ("C-c r" . org-remember)
+         ("C-c b" . org-iswitchb))
+  :config (progn
+            (setq org-directory "~/org")
+            (setq org-agenda-files `(,org-directory)
+
+                  org-default-notes-file (concat org-directory "/notes")
+
+                  ;; Fewer asterisks, doesn't change indentation
+                  org-hide-leading-stars t
+
+                  org-startup-indented nil
+
+                  ;; ‘Remember’: new items at top
+                  org-reverse-note-order t
+
+                  org-modules '(org-habit
+                                org-checklist)
+
+                  ;; Add time done to ‘done’ tasks
+                  org-log-done 'time
+
+                  ;; Allow refiling into any org file
+                  org-refile-targets '((org-agenda-files :maxlevel . 3))
+
+                  org-alphabetical-lists t
+
+                  org-pretty-entities t
+
+                  org-table-duration-custom-format 'seconds
+
+                  org-export-have-math t
+
+                  org-blank-before-new-entry '((heading . t)
+                                               (plain-list-item . auto))
+                  org-fontify-done-headline t))
+  :init (setq org-replace-disputed-keys t
+              org-todo-keywords '((sequence "TODO" "STARTED" "|" "DONE")
+                                  (sequence "TOLEARN" "LEARNING" "LEARNED" "|" "MASTERED")
+                                  (sequence "|" "CANCELLED"))))
+
+;;;; Programming
+
+(use-package cedet
+  :defer t
+  :config (progn
+            (semantic-load-enable-code-helpers)
+            (global-semantic-idle-completions-mode t)
+            (global-semantic-highlight-func-mode t)
+            (global-semantic-show-unmatched-syntax-mode t)
+            (global-semantic-decoration-mode t)))
+
+;;;; Projects
+
+(use-package projectile
+  :bind (("C-c C-f" . projectile-find-file))
+  :commands (projectile-global-mode))
+
+(use-package project-persist
+  :commands (project-persist-mode)
+  :bind (("C-c P d" . project-persist-delete)
+         ("C-c P f" . project-persist-find)
+         ("C-c P k" . project-persist-close)
+         ("C-c P n" . project-persist-create)
+         ("C-c P s" . project-persist-save))
+  :load-path "el-get/project-persist/lib/"
+  :config (progn
+            (project-persist-mode t)
+
+            (setq project-persist-auto-save-global t)
+
+            (add-hook 'project-persist-before-load-hook #'kill-all-buffers)
+
+            (defun emacs-process-p (pid)
+              "If pid is the process ID of an emacs process, return t, else nil.
+Also returns nil if pid is nil."
+              (when pid
+                (let ((attributes (process-attributes pid)) (cmd))
+                  (dolist (attr attributes)
+                    (if (string= "comm" (car attr))
+                        (setq cmd (cdr attr))))
+                  (if (and cmd (or (string= "emacs" cmd) (string= "emacs.exe" cmd))) t))))
+
+            (defadvice desktop-owner (after pry-from-cold-dead-hands activate)
+              "Don't allow dead emacsen to own the desktop file."
+              (when (not (emacs-process-p ad-return-value))
+                (setq ad-return-value nil)))
+
+            (defun load-project-desktop ()
+              "Load the project's desktop if available"
+              (ignore-errors
+                (let ((default-directory project-persist-current-project-settings-dir))
+                  (desktop-read))))
+
+            (defun kill-all-buffers ()
+              "Kill all file-based buffers."
+              (interactive)
+              (mapc (lambda (buf)
+                      (when (buffer-file-name buf)
+                        (when (and (buffer-modified-p buf)
+                                   (y-or-n-p (format "Buffer %s is modified - save it?" (buffer-name buf))))
+                          (save-some-buffers nil buf))
+                        (set-buffer-modified-p nil)
+                        (kill-buffer buf)))
+                    (buffer-list)))
+
+            (add-hook 'project-persist-after-close-hook
+                      (lambda ()
+                        (kill-all-buffers)
+                        (projectile-global-mode -1)))
+
+            (add-hook 'project-persist-after-load-hook
+                      (lambda ()
+                        (setq default-directory (pp/settings-get 'root-dir))
+                        (load-project-desktop)
+                        (projectile-global-mode 1)))
+
+            (add-hook 'project-persist-after-save-hook
+                      (lambda ()
+                        (message (format "Saving project desktop (%s)" project-persist-current-project-settings-dir))
+                        (desktop-save project-persist-current-project-settings-dir)))
+
+            ))
+
+(use-package vc
+  :config (progn
+            (setq vc-follow-symlinks t)))
+
+(use-package magit
+  :commands (magit-status)
+  :bind (("C-x g" . magit-status)))
+
+;;;; Spelling
+(setq ispell-program-name "aspell"
+      ispell-dictionary "british")
+;; (setq ispell-process-directory (expand-file-name "~/"))
+;; If aspell is too slow
+;; If it is still too slow, use ‘ultra’ instead of ‘fast’
+;; (setq ispell-extra-args '(" --sug-mode=fast"))
+(use-package ispell
+  :bind (("<f8>" . ispell-word)))
+
+;;;; Scripting
+
+(add-hook 'after-save-hook
+          #'executable-make-buffer-file-executable-if-script-p)
+
+(use-package sh-script
+  :defer t
+  :config (setq sh-shell-file "/usr/bin/env zsh"))
+
+(use-package ntcmd
+  :mode (("\\`.cmd\\'" . ntcmd-mode)
+         ("\\`.bat\\'" . ntcmd-mode)))
+
+;;;; Shells & REPLs
+
+(use-package eshell
+  :defer t
+  :config (setq eshell-directory-name "~/.emacs.d/eshell"))
+
+(use-package shell
+  :defer t
+  :config (define-key shell-mode-map
+            (kbd "C-d") 'comint-delchar-or-eof-or-kill-buffer))
+
+(use-package multi-term
+  :if (not (eq system-type 'windows-nt))
+  :bind ("C-`" . multi-term-dedicated-toggle))
+
+(defun comint-delchar-or-eof-or-kill-buffer (arg)
+  (interactive "p")
+  (if (null (get-buffer-process (current-buffer)))
+      (kill-buffer)
+    (comint-delchar-or-maybe-eof arg)))
+
+;;;; Text editing
+
+;; Enable upcase and downcase-region
+(put 'upcase-region 'disabled nil)
+(put 'downcase-region 'disabled nil)
+(setq sentence-end-double-space nil
+      line-move-visual nil)
+
+;; replace highlighted text rather than just inserting at point
+(delete-selection-mode t)
+
+(use-package subword
+  :init (global-subword-mode t))
+
+(use-package misc
+  :bind (("M-z" . zap-up-to-char)
+         ("M-Z" . zap-to-char)))
+
+(use-package ap-functions
+  :commands (ap/remove-extra-cr
+             ap/byte-compile-get-dest)
+  :bind (("C-x r M-w" . copy-rectangle)
+         ("M-!" . shell-execute)))
+
+(when (boundp 'x-select-request-type)
+  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))
+
+(use-package ace-jump-mode
+  :bind (("C-c SPC" . ace-jump-mode))
+  :config (progn
+            (ace-jump-mode-enable-mark-sync)
+            (setq ace-jump-word-mode-use-query-char nil
+                  ace-jump-mode-scope 'window)))
+
+(use-package autopair
+  :commands (autopair-mode)
+  :init (progn
+          (add-hook 'prog-mode-hook #'autopair-mode)
+          (setq autopair-blink nil
+                autopair-skip-whitespace nil)))
+
+(use-package electric-return
+  :bind (("RET" . electrify-return-if-match)))
+
+(use-package expand-region
+  :bind ("C-M-SPC" . er/expand-region))
+
+(use-package goto-chg
+  :bind ("C-x C-SPC" . goto-last-change))
+
+(use-package multiple-cursors
+  :bind (("C-." . mc/mark-next-like-this)
+         ("C-," . mc/mark-previous-like-this)
+         ("M-<f3>" . mc/mark-all-like-this-dwim)
+         ("C-<f3>" . mc/mark-more-like-this-extended)
+         ("C-S-L" . mc/edit-lines)))
+
+(use-package paredit
+  :commands (paredit-mode)
+  :init (progn
+          (put #'paredit-forward-delete 'delete-selection 'supersede)
+          (put #'paredit-backward-delete 'delete-selection 'supersede)
+          (add-hook 'minibuffer-setup-hook #'conditionally-enable-paredit-mode)
+          (defun conditionally-enable-paredit-mode ()
+            "enable paredit-mode during eval-expression"
+            (if (eq this-command 'eval-expression)
+                (paredit-mode 1)))))
+
+(use-package shuffle-lines
+  :bind (("C-S-<up>" . move-line-up)
+         ("C-S-<down>" . move-line-down)))
+
+(use-package smart-forward
+  :bind (("C-M-u" . smart-up)
+         ("C-M-d" . smart-down)
+         ("C-M-p" . smart-backward)
+         ("C-M-n" . smart-forward)))
+
+(use-package undo-tree
+  :idle (require 'undo-tree)
+  :defer t
+  :config (progn
+            (global-undo-tree-mode)
+            ;; Keep region when undoing in region
+            (defadvice undo-tree-undo (around keep-region activate)
+              (if (use-region-p)
+                  (let ((m (set-marker (make-marker) (mark)))
+                        (p (set-marker (make-marker) (point))))
+                    ad-do-it
+                    (goto-char p)
+                    (set-mark m)
+                    (set-marker p nil)
+                    (set-marker m nil))
+                ad-do-it)))
+  :diminish undo-tree-mode)
+
+;;;; Lisps
+
+(defun ap/lisp-setup ()
+  (if (featurep 'autopair)
+      (autopair-mode -1))
+  (paredit-mode +1)
+  (eldoc-add-command 'paredit-backward-delete 'paredit-close-round)
+
+  (if (featurep 'auto-indent-mode)
+      (progn (auto-indent-mode -1)
+             (setq lisp-body-indent 2)))
+
+  (show-paren-mode t)
+  (setq indent-tabs-mode nil)
+
+  (local-set-key (kbd "RET") 'electrify-return-if-match)
+  (local-set-key (kbd "C-j") 'electrify-return-if-match))
+
+(add-hook 'emacs-lisp-mode-hook #'ap/lisp-setup)
+(add-hook 'emacs-lisp-mode-hook #'turn-on-eldoc-mode)
+
+(add-hook 'scheme-mode-hook #'ap/lisp-setup)
+
+(use-package bytecomp
+  :defer t
+  :config (setq byte-compile-dest-file-function #'ap/byte-compile-get-dest))
+
+(use-package elisp-slime-nav
+  :commands elisp-slime-nav-mode
+  :diminish elisp-slime-nav-mode)
+
+(use-package geiser
+  :defer t
+  :commands (geiser-mode
+             geiser
+             run-geiser
+             run-racket)
+  :load-path "el-get/geiser/elisp")
+
+(use-package geiser-base
+  :defer t
+  :config (use-package quack))
+
+(use-package slime
+  :commands (slime)
+  :config (progn
+            (setq inferior-lisp-program (executable-find "sbcl"))
+            (slime-setup)))
+
+(defun imenu-elisp-sections ()
+  (setq imenu-prev-index-position-function nil)
+  (add-to-list 'imenu-generic-expression '("Sections" "^;;;; \\(.+\\)$" 1) t))
+
+(defun init-narrow-to-section ()
+  (interactive)
+  (save-excursion
+	(beginning-of-line)
+	(unless (looking-at "^;;;;")
+	  (re-search-backward "^;;;;" nil t))
+	(push-mark)
+	(forward-line)
+	(re-search-forward "^;;;;" nil t)
+	(forward-line -1)
+	(narrow-to-region (region-beginning) (region-end))))
+
+(defun init-imenu (p)
+  (interactive "P")
+  (find-file-existing "~/dotfiles/emacs/init.el")
+  (widen)
+  (helm-imenu)
+  (if p (init-narrow-to-section)))
+
+(add-hook 'emacs-lisp-mode-hook 'imenu-elisp-sections)
+
+;;;; Programming
+
+(use-package auto-compile
+  :commands (auto-compile-on-save-mode)
+  :init (add-hook 'emacs-lisp-mode-hook #'auto-compile-on-save-mode))
+
+(use-package cc-mode
+  :defer t
+  :init (progn
+          (add-hook 'c-mode-common-hook (lambda ()
+                                          ;; (use-package mic-paren
+                                          ;;   :init (paren-toggle-open-paren-context 1))
+                                          (electric-indent-mode 1))))
+  :config (progn
+            (setq c-default-style '((java-mode . "java")
+                                    (awk-mode . "awk")
+                                    (other . "k&r"))
+                  c-basic-offset 4)
+            (c-set-offset 'case-label '+)
+            (c-set-offset 'arglist-cont-nonempty #'ap/c-lineup-arglist)
+            (defun ap/c-lineup-arglist (langelem)
+              "Line up the current argument line under the first argument.
+
+As a special case, if the indented line is inside a brace block
+construct, the indentation is 0 only.  This is intended
+as a \"DWIM\" measure in cases like macros that contains statement
+blocks, e.g:
+
+A_VERY_LONG_MACRO_NAME ({
+    some (code, with + long, lines * in[it]);
+});
+<--> c-basic-offset
+
+Works with: arglist-cont-nonempty, arglist-close."
+              (save-excursion
+                (let ((indent-pos (point)))
+
+                  (if (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element))
+                      0
+
+                    ;; Normal case.  Indent to the token after the arglist open paren.
+                    (goto-char (c-langelem-2nd-pos c-syntactic-element))
+                    (if (and c-special-brace-lists
+                             (c-looking-at-special-brace-list))
+                        ;; Skip a special brace list opener like "({".
+                        (progn (c-forward-token-2)
+                               (forward-char))
+                      (forward-char))
+
+                    (let ((arglist-content-start (point)))
+                      (c-forward-syntactic-ws)
+                      (when (< (point) indent-pos)
+                        (goto-char arglist-content-start)
+                        (skip-chars-forward " \t"))
+                      (vector (if (or (looking-at ",")
+                                      (looking-at ")"))
+                                  (- (current-column) 2)
+                                (current-column)
+                                )))))))))
+
+;;;; Web Development
+
+(use-package moz
+  :load-path "moz-repl"
+  :commands (moz-firefox-reload
+             moz-reload-on-save-mode
+             moz-minor-mode)
+  :config (progn
+            (define-minor-mode moz-reload-on-save-mode
+              "Moz Reload On Save Minor Mode"
+              nil " Reload" nil
+              (if moz-reload-on-save-mode
+                  ;; Edit hook buffer-locally.
+                  (add-hook 'after-save-hook 'moz-firefox-reload nil t)
+                (remove-hook 'after-save-hook 'moz-firefox-reload t)))
+
+            (defun moz-firefox-reload ()
+              "Reload Firefox"
+              (interactive)
+              (comint-send-string (inferior-moz-process)
+                                  "BrowserReload();"))))
+
+(use-package js3
+  :mode ("\\.js\\'" . js3-mode)
+  :config (progn
+            (defun ap/javascript-setup ()
+              (moz-minor-mode t)
+              (autopair-mode -1)
+              (auto-indent-mode -t))
+            (add-hook 'js3-mode-hook #'ap/javascript-setup)
+            (setq js3-indent-level 4
+                  js3-expr-indent-offset 4
+                  js3-paren-indent-offset 4
+                  js3-square-indent-offset 4
+                  js3-curly-indent-offset 4)))
+
+(use-package mustache-mode
+  :mode (("\\.mustache" . mustache-mode)
+         ("\\.mt\\'" . mustache-mode)
+         ("\\.template\\'" . mustache-mode)))
+
+(use-package nxhtml-mode
+  :defer t
+  :mode (("\\.php\\'" . html-mumamo-mode))
+  :idle (load (expand-file-name "nxhtml/autostart" *el-get-dir*))
+  :config (progn
+            (setq mumamo-chunk-coloring 4
+                  nxhtml-skip-welcome t
+                  nxhtml-autoload-web nil)
+            (nxhtml-menu-mode 0)))
+
+(use-package php-mode
+  :mode ("\\.php\\'" . php-mode)
+  :config (progn
+            (bind-key "C-h C-f" #'php-search-documentation php-mode-map)
+            (unbind-key "C-c C-f" php-mode-map)
+            (unbind-key "C-." php-mode-map)
+            (if (member system-name '("PREFECT" "prefect"))
+                (setq php-manual-url "http://docs.home/manual/en/"))
+            (add-hook 'php-mode-hook (lambda ()
+                                       (set (make-local-variable 'eldoc-documentation-function) #'my-php-eldoc-function)))
+            (use-package eldoc-php
+              :config (turn-on-eldoc-mode))))
+
+(use-package sgml-mode
+  :defer t
+  :config (setq sgml-basic-offset 4))
+
+;;;; Windows & Frames
+
+(setq frame-title-format
+      '(""
+        (:eval (capitalize invocation-name)) ": "
+        (:eval (if (buffer-file-name)
+                   (abbreviate-file-name (buffer-file-name))
+                 "%b"))))
+
+(setq scroll-conservatively 100 ; Keep the cursor position when scrolling
+      scroll-preserve-screen-position nil)
+
+(when menu-bar-mode
+  (menu-bar-mode -1))
+(when scroll-bar-mode
+  (scroll-bar-mode -1)
+  (tooltip-mode -1)
+  (tool-bar-mode -1))
+
+(use-package winner
+  :bind (("C-c <left>"  . winner-undo)
+         ("C-c <right>" . winner-redo)))
+
+(use-package windmove
+  :bind (("S-<left>"  . windmove-left)
+         ("S-<right>" . windmove-right)
+         ("S-<up>"    . windmove-up)
+         ("S-<down>"  . windmove-down)))