#+BABEL: :cache yes #+PROPERTY: header-args :tangle yes :comments no #+TITLE: Emacs Configuration #+AUTHOR: Mitch Tishmack * readme This is my emacs configuration file. I don't encourage anyone to use this verbatim, but if you wanted to this is how you would do so: ** Clone this repo #+BEGIN_SRC sh :tangle no git clone https://github.com/mitchty/dotfiles #+END_SRC ** Preferably backup your emacs configuration Always good to back things up, just in case you hate how I did things. #+BEGIN_SRC sh :tangle no tar cvf ~/.emacs-backup.tar ~/.emacs.d ~/.emacs #+END_SRC ** Remove/move your old configuration This is up to you to do right, just an example. #+BEGIN_SRC sh :tangle no rm -fr ~/.emacs.d ~/.emacs #+END_SRC ** Lastly copy necessary files #+BEGIN_SRC sh :tangle no mkdir ~/.emacs.d cp dotfiles/init.el dotfiles/emacs.org ~/.emacs.d #+END_SRC * use-package-hack For some reason init.el doesn't always seem to get reflecte here. Weird reaserch later. #+BEGIN_SRC emacs-lisp (require 'use-package) #+END_SRC * prelude ** match end of string function #+BEGIN_SRC emacs-lisp (defun string/ends-with (string suffix) "Return t if STRING ends with SUFFIX." (and (string-match (rx-to-string `(: ,suffix eos) t) string) t) ) #+END_SRC ** always babel tangle and byte compile emacs.org Add a save hook to always tangle and byte compile emacs.org file when we save it. #+BEGIN_SRC emacs-lisp (defun tangle-init () "If the current buffer is 'emacs.org' the code-blocks are tangled, and the tangled file is compiled." (when (string/ends-with (buffer-file-name) ".emacs.d/emacs.org") (let ((prog-mode-hook nil)) (org-babel-tangle) (byte-compile-file (concat user-emacs-directory "emacs.el"))) ) ) (add-hook 'after-save-hook 'tangle-init) #+END_SRC ** debug on error Not having to start *emacs* with *--debug-init* is useful. #+BEGIN_SRC emacs-lisp (setq debug-on-error t) #+END_SRC ** emacs server Start up the emacs server if it isn't running. #+BEGIN_SRC emacs-lisp (load "server") (unless (server-running-p) (server-start)) #+END_SRC ** os detection Make it easier to determine what os we're running on. #+BEGIN_SRC emacs-lisp (defvar on-mswindows (string-match "windows" (symbol-name system-type)) "Am I running under windows?") (defvar on-osx (string-match "darwin" (symbol-name system-type)) "Am I running under osx?") (defvar on-linux (string-match "gnu/linux" (symbol-name system-type)) "Am I running under linux?") #+END_SRC *** Mac OS X Gui emacs PATH setup This is here because if gui emacs gets started say from Finder, one can end up with missing certain things that aren't in the default PATH. The strategy is fire off a $SHELL and have it echo the PATH it has and then parse that to setup emacs exec-path. For now we restrict this only to OSX. It may be more generally useful however. #+BEGIN_SRC emacs-lisp (defun set-exec-path-from-shell-PATH () (let ((path-from-shell (shell-command-to-string "$SHELL -i -c 'echo $PATH'"))) (setenv "PATH" path-from-shell) (setq exec-path (split-string path-from-shell path-separator)))) (if on-osx (set-exec-path-from-shell-PATH)) #+END_SRC ** disable pointless startup stuff Like the startup screen and the echo hooey. #+BEGIN_SRC emacs-lisp (customize-set-variable 'inhibit-startup-screen t) (customize-set-variable 'inhibit-startup-message t) (customize-set-variable 'inhibit-startup-echo-area-message t) #+END_SRC ** temporary files Keep temporary stuff isolated from everyone else. It infects everything otherwise. As bad as the .DS_Store files on osx. #+BEGIN_SRC emacs-lisp (customize-set-variable 'temporary-file-directory "/tmp") (customize-set-variable 'backup-directory-alist `((".*" . ,temporary-file-directory))) (customize-set-variable 'auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) (customize-set-variable 'create-lockfiles nil) (customize-set-variable 'make-backup-files nil) (customize-set-variable 'auto-save-default nil) (customize-set-variable 'backup-by-copying t) (customize-set-variable 'auto-save-list-file-prefix temporary-file-directory) (customize-set-variable 'backup-directory-alist `((".*" . ,temporary-file-directory))) (customize-set-variable 'auto-save-file-name-transforms `((".*" ,temporary-file-directory t))) #+END_SRC ** auto revert Update files in open buffers as they're changed on disk, freaking annoying without this on. #+BEGIN_SRC emacs-lisp (customize-set-variable 'global-auto-revert-mode t) #+END_SRC ** dired Use dired-x. #+BEGIN_SRC emacs-lisp (add-hook 'dired-load-hook (function (lambda () (load "dired-x")))) #+END_SRC ** ediff For those rare times I use it, make it a bit less derp on output. #+BEGIN_SRC emacs-lisp (setq ediff-window-setup-function 'ediff-setup-windows-plain) (setq ediff-split-window-function 'split-window-horizontally) #+END_SRC ** tramp Tramp configuration. Make the proxy list less weird. #+BEGIN_SRC emacs-lisp (require 'tramp) ;; FIXME ;; (customize-variable 'tramp-default-proxies-alist ;; (quote ((".*" "\\`root\\'" "/ssh:%h:")))) #+END_SRC So this was originally a way to do tramp over ssh where sudo only worked with su. Its a hack, but it work(ed). Will remove it at some date in the future. #+BEGIN_SRC emacs-lisp (add-to-list 'tramp-methods '("susudo" (tramp-login-program "sudo") (tramp-login-args (("-u" "%u") ("-H") ("-p" "Password:") ("su -c /bin/sh"))) (tramp-remote-sh "/bin/sh") (tramp-copy-program nil) (tramp-copy-args nil) (tramp-copy-keep-date nil) (tramp-password-end-of-line nil))) #+END_SRC ** always remove trailing whitespace Trailing whitespace is not normally useful. Remove it always on save in the *before-save-hook*. #+BEGIN_SRC emacs-lisp (add-hook 'before-save-hook 'delete-trailing-whitespace) #+END_SRC ** chmod u+x on save for scripts Because its derp to have to chmod 755 stuff after I save. Honestly, do it for me kthxbai. #+BEGIN_SRC emacs-lisp (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p) #+END_SRC ** misc text related Not sure what to categorize this crap as tbh. *** wtf does this do? TODO: find out why I added this ages ago. #+BEGIN_SRC emacs-lisp :tangle no (move-text-default-bindings) #+END_SRC *** default major mode So if we don't know, call it text-mode. #+BEGIN_SRC emacs-lisp (custom-set-variables '(default-major-mode 'text-mode)) #+END_SRC *** encoding utf8 is the best. Default to it. #+BEGIN_SRC emacs-lisp (custom-set-variables '(locale-coding-system 'utf-8)) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8) #+END_SRC *** text selection If I selected text, delete the selection, I probably meant it emacs. #+BEGIN_SRC emacs-lisp (delete-selection-mode 1) #+END_SRC *** line width 80 char line columns not 72. #+BEGIN_SRC emacs-lisp (custom-set-variables '(fill-column 80)) #+END_SRC *** we aren't banging rocks on typewriters anymore emacs Double spacing after a line isn't needed. #+BEGIN_SRC emacs-lisp (set-default 'sentence-end-double-space nil) #+END_SRC *** sentence end Semi related to the above, make the sentence endings a bit more code-ish. #+BEGIN_SRC emacs-lisp (custom-set-variables '(sentence-end "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*")) (custom-set-variables '(sentence-end-double-space nil)) #+END_SRC *** default tab-width Two seems sensible, cause well, tabs are evil incarnate. #+BEGIN_SRC emacs-lisp (custom-set-variables '(default-tab-width 2)) #+END_SRC ** uncategorized I have no idea how to label these. Highlight parens. #+BEGIN_SRC emacs-lisp (show-paren-mode) #+END_SRC Typing out *yes* or *no* is stupid. #+BEGIN_SRC emacs-lisp (defalias 'yes-or-no-p 'y-or-n-p) #+END_SRC * global key bindings Global key bindings. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-,") 'kill-whole-line) (global-set-key (kbd "C-]") 'er/expand-region) (global-set-key (kbd "C-x C-m") 'compile) #+END_SRC * appearance ** theme Solarized light is decent. I'll just use that. #+BEGIN_SRC emacs-lisp (use-package solarized-theme :ensure t :init (load-theme 'solarized-light 't)) #+END_SRC ** modeline Update the time every ~3 seconds in the mode line. #+BEGIN_SRC emacs-lisp (custom-set-variables '(display-time-default-load-average nil)) (custom-set-variables '(display-time-format "%T")) (custom-set-variables '(display-time-interval 3)) (display-time-mode) #+END_SRC Display line and column always in the modeline. #+BEGIN_SRC emacs-lisp (custom-set-variables '(line-number-mode t)) (custom-set-variables '(column-number-mode t)) #+END_SRC Format the mode line, I... can't decipher this anymore nor do I care to, it works eff it. #+BEGIN_SRC emacs-lisp (custom-set-variables '(mode-line-format (list '(:eval (propertize "%b " 'face 'font-lock-keyword-face 'help-echo (buffer-file-name))) (propertize "%02l" 'face 'font-lock-type-face) "," (propertize "%02c" 'face 'font-lock-type-face) " [" '(:eval (propertize "%m" 'face 'font-lock-string-face 'help-echo buffer-file-coding-system)) minor-mode-alist "] " "[" '(:eval (propertize (if overwrite-mode "Ovr" "Ins") 'face 'font-lock-preprocessor-face 'help-echo (concat "Buffer is in " (if overwrite-mode "overwrite" "insert") " mode"))) '(:eval (when (buffer-modified-p) (concat "," (propertize "Mod" 'face 'font-lock-warning-face 'help-echo "Buffer has been modified")))) '(:eval (when buffer-read-only (concat "," (propertize "RO" 'face 'font-lock-type-face 'help-echo "Buffer is read-only")))) "] " '(:eval (propertize (format-time-string "%H:%M:%S") 'help-echo (concat (format-time-string "%c; ") (emacs-uptime "Uptime:%hh") ))) " --" "%-" ))) #+END_SRC ** whitespace Customize whitespace mode to make tabs obvious as boxes, and to highlight lines over 80 characters in length. #+BEGIN_SRC emacs-lisp (require 'whitespace) (setq whitespace-style '(face tabs trailing)) (set-face-attribute 'whitespace-tab nil :foreground "#2075c7" :background "lightgrey") (set-face-attribute 'whitespace-line nil :foreground "#2075c7" :background "lightgrey") #+END_SRC ** gui chrome When i'm running in a terminal emacs, most of this junk isn't needed. For that matter gui counts for most. Basically, never show the tool bar or the scroll bar in gui or tty. In gui its ok to show the menu-bar. #+BEGIN_SRC emacs-lisp (tool-bar-mode -1) (scroll-bar-mode -1) (when (not window-system) (menu-bar-mode -1)) #+END_SRC ** gui fonts Ah Fonts. Let me specify them for gui emacs. #+BEGIN_SRC emacs-lisp (when window-system (require 'cl) (defun font-candidate (&rest fonts) "Return first font that matches list of provided fonts." (with-no-warnings (find-if (lambda (f) (find-font (font-spec :name f))) fonts))) (set-face-attribute 'default nil :font (font-candidate '"Pragmata\ Pro-13:weight=normal" "Source Code Pro-13:weight=normal" "Menlo-12:weight=normal" "Monaco-12:weight=normal" )) (cond (on-linux (setq interprogram-paste-function 'x-cut-buffer-or-selection-value) (setq x-select-enable-clipboard t) ) ) ) #+END_SRC * packages All the packages I use. ** Helm By Helms Deep use Helm to do ALL THE THINGS. IDO is ass in comparison. #+BEGIN_SRC emacs-lisp (use-package helm :ensure t :diminish helm-mode :bind (("M-x" . helm-M-x) ("M-y" . helm-show-kill-ring) ("C-x b" . helm-mini) ("C-x C-b" . helm-buffers-list) ("C-x C-f" . helm-find-files) ("C-x C-r" . helm-recentf) ("C-x c o" . helm-occur)) :init (progn (require 'helm-config) (helm-mode 1))) #+END_SRC ** helm-descbinds Its nice being able to describe helm things you know? #+BEGIN_SRC emacs-lisp (use-package helm-descbinds :ensure t :bind (("C-h b" . helm-descbinds) ("C-h w" . helm-descbinds)) ) #+END_SRC ** helm-ag Helm search plugin for Ag (The Silver Searcher) so much nicer than regular searching in helm imo. #+BEGIN_SRC emacs-lisp (use-package helm-ag :ensure t) #+END_SRC ** helm-projectile #+BEGIN_SRC emacs-lisp (use-package helm-projectile :ensure t) #+END_SRC ** magit Make git not ass to use. At least in emacs. magit is the best git interface... in the world. #+BEGIN_SRC emacs-lisp (use-package magit :ensure t :commands (magit-init magit-status magit-diff magit-commit) :bind ("C-x m" . magit-status) :config (progn (defadvice magit-status (around magit-fullscreen activate) (window-configuration-to-register :magit-fullscreen) ad-do-it (delete-other-windows)) (defadvice magit-quit-window (around magit-restore-screen activate) ad-do-it (jump-to-register :magit-fullscreen))) ) (use-package magit-blame :ensure magit :commands (magit-blame-mode) ) #+END_SRC ** workgroups2 Save workgroup layouts. Similar..ish to desktop-save. #+BEGIN_SRC emacs-lisp (use-package workgroups2 :ensure t :init (progn ;; Can't use :bind OR :config for this sadly ;; also annoying, is that I have to set this before ;; running workgroups-mode. Hokey stuff. ;; ;; Also note, use setq here not customize-set-variable ;; workgroups2 can't detect stuff thats customized. (setq wg-session-file "~/.emacs.d/workgroups") (setq wg-prefix-key (kbd "C-c C-w")) (workgroups-mode 1) ) ) #+END_SRC ** autopair Highlight matching ()'s []'s etc... #+BEGIN_SRC emacs-lisp (use-package autopair :ensure t :config (customize-set-variable 'autopair-blink 'nil) ) #+END_SRC ** org-mode Org-mode keybindings and settings, pretty sparse really. #+BEGIN_SRC emacs-lisp (use-package org :ensure t :bind (("C-c a" . org-agenda) ("C-c b" . org-iswitchb) ("C-c c" . org-capture) ("C-c l" . org-store-link) ("C-c p" . org-latex-export-to-pdf)) :config (customize-set-variable 'org-log-done t) ) #+END_SRC ** flycheck Flycheck for on the fly checking of code. #+BEGIN_SRC emacs-lisp (use-package flycheck :ensure t :config (customize-set-variable 'flycheck-indication-mode 'right-fringe) ) #+END_SRC Need to vet this, used it more when I did more c. But its handy for non standard pkg-config setups. Not tangled into the config intentionally. #+BEGIN_SRC emacs-lisp :tangle=no (defun pkg-config-add-lib-cflags (pkg-config-lib) "This function will add necessary header file path of a specified by `pkg-config-lib' to `flycheck-clang-include-path', which make it completionable by auto-complete-clang" (interactive "spkg-config lib: ") (if (executable-find "pkg-config") (if (= (shell-command (format "pkg-config %s" pkg-config-lib)) 0) (setq flycheck-clang-include-path (append flycheck-clang-include-path (split-string (shell-command-to-string (format "pkg-config --cflags-only-I %s" pkg-config-lib))))) (message "Error, pkg-config lib %s not found." pkg-config-lib)) (message "Error: pkg-config tool not found."))) #+END_SRC ** auto-complete Auto complete functionality is nice to have. #+BEGIN_SRC emacs-lisp (use-package auto-complete :ensure t :defer t :init (progn (require 'auto-complete-config) (ac-config-default) (global-auto-complete-mode t)) ) #+END_SRC ** smartparens Helpfully inserts matching parens, can be a pita too. #+BEGIN_SRC emacs-lisp (use-package smartparens :ensure t) #+END_SRC ** uniquify Make buffer names unique based on their directory and not have or other nonsense. #+BEGIN_SRC emacs-lisp (require 'uniquify) (customize-set-variable 'uniquify-buffer-name-style 'post-forward) #+END_SRC ** desktop-save Desktop saving of session information handy to keep the same buffers between sessions. #+BEGIN_SRC emacs-lisp (require 'desktop) (desktop-save-mode 1) (customize-set-variable 'desktop-restore-eager 5) (customize-set-variable 'desktop-path '("~/.emacs.d")) (customize-set-variable 'desktop-dirname "~/.emacs.d") (customize-set-variable 'desktop-base-file-name "desktop") (defun local-desktop-save () (interactive) (if (eq (desktop-owner) (emacs-pid)) (desktop-save desktop-dirname))) (add-hook 'auto-save-hook 'desktop-save-in-desktop-dir) #+END_SRC ** fic-mode Highlight TODO/FIXME type messages in comments. #+BEGIN_SRC emacs-lisp (use-package fic-mode :ensure t) #+END_SRC ** projectile #+BEGIN_SRC emacs-lisp (use-package projectile :ensure t :defer t :idle (projectile-global-mode) :config (progn (require 'helm-projectile) (helm-projectile-on)) ) #+END_SRC ** git gutter #+BEGIN_SRC emacs-lisp (use-package git-gutter :ensure t :defer t :idle (global-git-gutter-mode t) ) #+END_SRC ** clang-format #+BEGIN_SRC emacs-lisp (use-package clang-format :ensure t :bind (([C-M-tab] . clang-format-region)) ) #+END_SRC ** ggtags #+BEGIN_SRC emacs-lisp :tangle no (use-package ggtags :ensure t) #+END_SRC ** company-mode Completion tips. #+BEGIN_SRC emacs-lisp :tangle no (use-package company-mode :ensure t) #+END_SRC ** yaml-mode For.. yaml #+BEGIN_SRC emacs-lisp (use-package yaml-mode :ensure t) #+END_SRC ** writegood-mode So I write gooder. Me fail English? Thats unpossible. #+BEGIN_SRC emacs-lisp (use-package writegood-mode :ensure t :defer t) #+END_SRC ** restclient Comes in handily for those times you need it. #+BEGIN_SRC emacs-lisp (use-package restclient :ensure t :defer t) #+END_SRC ** helm-gtags #+BEGIN_SRC emacs-lisp (use-package helm-gtags :ensure t) #+END_SRC * mode related ** common defaults Common mode defaults I think are sensible. *** prog-mode hook #+BEGIN_SRC emacs-lisp (add-hook 'prog-mode-hook '(lambda () (interactive) (hl-line-mode) (auto-complete-mode) (whitespace-mode) (smartparens-mode) (visual-line-mode) (customize-set-variable 'indent-tabs-mode nil) (customize-set-variable 'tab-width 2) (flycheck-mode) (turn-on-fic-mode) ) ) #+END_SRC *** c #+BEGIN_SRC emacs-lisp (add-to-list 'auto-mode-alist '("\\.[chm]\\'" . c-mode)) (add-hook 'c-mode-common-hook '(lambda () (global-set-key "\C-x\C-m" 'compile) (setq flycheck-clang-language-standard "c11") (setq flycheck-idle-change-delay 2) (setq flycheck-highlighting-mode 'symbols) ;; later... ;; (add-hook 'before-save-hook 'clang-format-buffer nil t) (c-toggle-auto-state 1) (setq-default c-basic-offset 2 tab-width 2 indent-tabs-mode nil c-electric-flag t indent-level 2 c-default-style "bsd" backward-delete-function nil) )) #+END_SRC *** elisp TODO: fixme #+BEGIN_SRC emacs-lisp :tangle no (add-hook 'emacs-lisp-hook (lambda () (define-key emacs-lisp-map "\C-x\C-e" 'pp-eval-last-sexp) (define-key emacs-lisp-map "\r" 'reindent-then-newline-and-indent))) #+END_SRC *** python #+BEGIN_SRC emacs-lisp (add-hook 'python-mode-hook '(lambda () (flycheck-select-checker 'python-flake8))) #+END_SRC *** shell #+BEGIN_SRC emacs-lisp (autoload 'sh--mode "sh-mode" "mode for shell stuff" t) (add-to-list 'auto-mode-alist '("\\.sh$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\.[zk]sh$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\.bash$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("\\[.].*shrc$\\'" . sh-mode)) (add-to-list 'auto-mode-alist '("sourceme$\\'" . sh-mode)) (add-hook 'sh-mode-hook '(lambda () (setq sh-basic-offset 2 sh-indentation 4 sh-indent-for-case-label 0 sh-indent-for-case-alt '+))) #+END_SRC ** auto-insert-mode new file templates Use auto-insert-mode to insert in templates for blank files. So first up, add auto-insert to *find-file-hooks* so we insert straight away. Also setup the copyright bit to minimally put in name. #+BEGIN_SRC emacs-lisp (add-hook 'find-file-hooks 'auto-insert) (setq auto-insert-copyright (user-full-name)) #+END_SRC Create the *auto-insert-alist* so all the mode lists are the same #+BEGIN_SRC emacs-lisp (setq auto-insert-alist '(())) #+END_SRC *** c #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((c-mode . "c") nil "/*\n" "File: " (file-name-nondirectory buffer-file-name) "\n" "Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "Description: " _ "\n" "*/\n" "#include \n" "#include \n\n" "int main(int argc, char **argv) {\n" " return 0;\n" "}\n" ) ) auto-insert-alist) ) #+END_SRC *** elisp #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((emacs-lisp-mode . "elisp") nil ";;-*-mode: emacs-lisp; coding: utf-8;-*-\n" ";; File: " (file-name-nondirectory buffer-file-name) "\n" ";; Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" ";; Description: " _ "\n" ) ) auto-insert-alist) ) #+END_SRC *** python #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '(((python-mode . "python") nil "#!/usr/bin/env python\n" "# -*-mode: Python; coding: utf-8;-*-\n" "# File: " (file-name-nondirectory buffer-file-name) "\n" "# Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "# Description: " _ "\n\n" ) ) auto-insert-alist) ) #+END_SRC *** shell #+BEGIN_SRC emacs-lisp (setq auto-insert-alist (append '( ((sh-mode . "sh") nil "#!/usr/bin/env sh\n" "#-*-mode: Shell-script; coding: utf-8;-*-\n" "# File: " (file-name-nondirectory buffer-file-name) "\n" "# Copyright: " (substring (current-time-string) -4) " " auto-insert-copyright "\n" "# Description: " _ "\n" "export script=$(basename \"$0\")\n" "export dir=$(cd \"$(dirname \"$0\")\"; pwd)\n" "export iam=${dir}/${script}\n" ) ) auto-insert-alist) ) #+END_SRC