summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorKyle Meyer <kyle@kyleam.com>2014-01-26 01:59:44 -0500
committerKyle Meyer <kyle@kyleam.com>2014-01-26 01:59:44 -0500
commit7869360008d87ca4b459c703f4894625dd8181cc (patch)
treeb0f3f50ae2c309056883e03848abb3e1e4cb9b1e /lisp
parent47e1d90700105f6b0f0550d7632a22b3fe81acb9 (diff)
downloademacs.d-7869360008d87ca4b459c703f4894625dd8181cc.tar.gz
Follow Purcell's emacs.d structure
User init files are added using provide/require. https://github.com/purcell/emacs.d
Diffstat (limited to 'lisp')
-rw-r--r--lisp/init-babel.el27
-rw-r--r--lisp/init-bib.el14
-rw-r--r--lisp/init-dired.el27
-rw-r--r--lisp/init-elisp.el14
-rw-r--r--lisp/init-func.el236
-rw-r--r--lisp/init-general.el94
-rw-r--r--lisp/init-git.el27
-rw-r--r--lisp/init-gnus.el223
-rw-r--r--lisp/init-grep.el15
-rw-r--r--lisp/init-haskell.el3
-rw-r--r--lisp/init-ibuffer.el69
-rw-r--r--lisp/init-ido.el32
-rw-r--r--lisp/init-keybindings.el30
-rw-r--r--lisp/init-keychord.el36
-rw-r--r--lisp/init-keymaps.el18
-rw-r--r--lisp/init-modes.el15
-rw-r--r--lisp/init-org.el149
-rw-r--r--lisp/init-orgcontacts.el9
-rw-r--r--lisp/init-pkg.el53
-rw-r--r--lisp/init-projectile.el29
-rw-r--r--lisp/init-python.el45
-rw-r--r--lisp/init-smex.el9
-rw-r--r--lisp/init-tex.el20
-rw-r--r--lisp/init-yas.el13
24 files changed, 1207 insertions, 0 deletions
diff --git a/lisp/init-babel.el b/lisp/init-babel.el
new file mode 100644
index 0000000..561419d
--- /dev/null
+++ b/lisp/init-babel.el
@@ -0,0 +1,27 @@
+;; Set up babel languages.
+(org-babel-do-load-languages
+ 'org-babel-load-languages
+ '((sh . t)
+ (python . t)
+ (R . t)
+ (emacs-lisp . t)
+ (latex . t)))
+
+;; Don't ask for confirmation before running code.
+(setq org-confirm-babel-evaluate nil)
+
+;; Babel minted latex export
+;; Modified from
+;; http://orgmode.org/worg/org-tutorials/org-latex-export.html.
+(setq org-export-latex-listings 'minted)
+(setq org-export-latex-custom-lang-environments
+ '((R "rcode")
+ (sh "shcode")
+ (python "pythoncode")))
+
+(setq org-latex-to-pdf-process
+ '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
+ "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
+ "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
+
+(provide 'init-babel)
diff --git a/lisp/init-bib.el b/lisp/init-bib.el
new file mode 100644
index 0000000..7d91e93
--- /dev/null
+++ b/lisp/init-bib.el
@@ -0,0 +1,14 @@
+;; Make cite key have form <last author last name><year><first word>.
+(setq bibtex-autokey-year-length 4)
+(setq bibtex-autokey-titleword-length nil)
+(setq bibtex-autokey-titlewords-stretch 0)
+(setq bibtex-autokey-titlewords 1)
+(setq bibtex-autokey-year-title-separator "")
+
+(setq bibtex-autokey-titleword-ignore
+ '("A" "An" "On" "The" "Why" "How" "Where" "[0-9].*"))
+
+;; Used by `bibtex-fill-entry'.
+(setq bibtex-align-at-equal-sign t)
+
+(provide 'init-bib)
diff --git a/lisp/init-dired.el b/lisp/init-dired.el
new file mode 100644
index 0000000..a81f5c3
--- /dev/null
+++ b/lisp/init-dired.el
@@ -0,0 +1,27 @@
+(put 'dired-find-alternate-file 'disabled nil)
+
+(require 'dired-x)
+
+;; .git is present as part of `dired-omit-extensions', but this
+;; seems to only be taken into account if the a non-exension part
+;; exists.
+(setq dired-omit-files
+ (concat dired-omit-files "\\|\\.git$\\|\\.gitignore$\\|__pycache__"))
+
+(defvar km/latex-omit-extensions '(".aux"
+ ".fdb_latexmk"
+ ".fls"
+ ".log"
+ ".nav"
+ ".out"
+ ".snm")
+ "Intermediate LaTeX files")
+
+(setq dired-omit-extensions
+ (append dired-omit-extensions km/latex-omit-extensions))
+
+(setq-default dired-omit-files-p t)
+
+(setq dired-listing-switches "-alh")
+
+(provide 'init-dired)
diff --git a/lisp/init-elisp.el b/lisp/init-elisp.el
new file mode 100644
index 0000000..511ee4a
--- /dev/null
+++ b/lisp/init-elisp.el
@@ -0,0 +1,14 @@
+(autoload 'enable-paredit-mode "paredit"
+ "Turn on pseudo-structural editing of Lisp code."
+ t)
+
+(add-hook 'emacs-lisp-mode-hook 'enable-paredit-mode)
+
+(eval-after-load "paredit"
+ '(progn
+ (define-key paredit-mode-map (kbd "C-,") 'paredit-forward-slurp-sexp)
+ (define-key paredit-mode-map (kbd "C-.") 'paredit-forward-barf-sexp)
+ (define-key paredit-mode-map (kbd "C-M-,") 'paredit-backward-slurp-sexp)
+ (define-key paredit-mode-map (kbd "C-M-.") 'paredit-backward-barf-sexp)))
+
+(provide 'init-elisp)
diff --git a/lisp/init-func.el b/lisp/init-func.el
new file mode 100644
index 0000000..9c87ed1
--- /dev/null
+++ b/lisp/init-func.el
@@ -0,0 +1,236 @@
+;; http://whattheemacsd.com/
+;; whitespace cleanup
+
+;; Buffer-specific prevention modified from
+;; http://stackoverflow.com/questions/14913398/
+;; in-emacs-how-do-i-save-without-running-save-hooks.
+(defvar km/prevent-cleanup nil
+ "If set, `km/cleanup-buffer' does not perform clean up on save.")
+
+(defun km/toggle-prevent-cleanup ()
+ "Toggle state of `km/prevent-cleanup'"
+ (interactive)
+ (let ((state t))
+ (when km/prevent-cleanup
+ (setq state nil))
+ (set (make-local-variable 'km/prevent-cleanup) state)))
+
+(defun km/cleanup-buffer ()
+ (interactive)
+ (unless km/prevent-cleanup
+ (unless (equal major-mode 'makefile-gmake-mode)
+ (untabify (point-min) (point-max)))
+ (delete-trailing-whitespace)
+ (set-buffer-file-coding-system 'utf-8)))
+(add-hook 'before-save-hook 'km/cleanup-buffer)
+
+(defun km/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)))))))
+
+(global-set-key (kbd "C-x C-r") 'km/rename-current-buffer-file)
+
+(defun km/shebang (&optional lang)
+ (interactive "s\language (default python):")
+ (if (= (length lang) 0)
+ (setq lang "python"))
+ (insert "#!/usr/bin/env " lang "\n"))
+(define-key insert-map "s" 'km/shebang)
+
+(defun km/insert-date ()
+ (interactive)
+ (insert (format-time-string "%Y-%m-%d")))
+
+(define-key insert-map "d" 'km/insert-date)
+
+(defun km/start-ess ()
+ (interactive)
+ (require 'ess-site))
+
+;; http://emacs-fu.blogspot.com/2013/03/editing-with-root-privileges-once-more.html
+(defun km/find-file-as-root ()
+ "`ido-find-file` that automatically edits the file with
+root-privileges (using tramp/sudo) if the file is not writable by
+user."
+ (interactive)
+ (let ((file (ido-read-file-name "Edit as root: ")))
+ (unless (file-writable-p file)
+ (setq file (concat "/sudo:root@localhost:" file)))
+ (find-file file)))
+
+(global-set-key (kbd "C-x F") 'km/find-file-as-root)
+
+(defun km/save-and-kill-buffer ()
+ "Save current buffer and then kill it"
+ (interactive)
+ (save-buffer)
+ (kill-this-buffer))
+
+(defun km/toggle-line-or-region-comment ()
+ "Comment/uncomment the current line or region"
+ (interactive)
+ (let (beg end)
+ (if (region-active-p)
+ (setq beg (region-beginning) end (region-end))
+ (setq beg (line-beginning-position) end (line-end-position)))
+ (comment-or-uncomment-region beg end))
+ (forward-line))
+
+(defun km/todo-comment ()
+ "Add commented TODO"
+ (interactive)
+ (let (beg end)
+ (if (region-active-p)
+ (setq beg (region-beginning) end (region-end))
+ (setq beg (line-beginning-position) end (line-end-position)))
+ (unless (comment-only-p beg end)
+ (beginning-of-line)
+ (insert "TODO ")
+ (comment-region beg (+ end 5))
+ (forward-line))))
+
+;; Kill functions
+
+(defun km/kill-string-at-point ()
+ (interactive)
+ (let ((string-start (nth 8 (syntax-ppss))))
+ (goto-char string-start)
+ (kill-sexp)))
+
+(defun km/kill-thing-at-point (thing killthing killarg)
+ "Go to the beginning of THING and call KILLTHING with
+KILLARG."
+ (goto-char (beginning-of-thing thing))
+ (funcall killthing killarg))
+
+(defun km/kill-sentence-at-point (arg)
+ (interactive "P")
+ (km/kill-thing-at-point 'sentence 'kill-sentence arg))
+
+(defun km/kill-word-at-point (arg)
+ (interactive "P")
+ (km/kill-thing-at-point 'word 'kill-word arg))
+
+(defun km/kill-paragraph-at-point (arg)
+ (interactive "P")
+ (km/kill-thing-at-point 'paragraph 'kill-paragraph arg))
+
+(defun km/kill-line-at-point (arg)
+ (interactive "P")
+ (km/kill-thing-at-point 'line 'kill-line arg))
+
+(defun km/kill-sexp-at-point (arg)
+ (interactive "P")
+ (km/kill-thing-at-point 'sexp 'kill-sexp arg))
+
+(define-key kill-map "s" 'km/kill-string-at-point)
+(define-key kill-map "." 'km/kill-sentence-at-point)
+(define-key kill-map "w" 'km/kill-word-at-point)
+(define-key kill-map "p" 'km/kill-paragraph-at-point)
+(define-key kill-map "l" 'km/kill-line-at-point)
+
+(defun km/join-next-line-with-space ()
+ "Join current line to the next line with a space in between."
+ (interactive)
+ (move-end-of-line 1)
+ (kill-line)
+ (just-one-space))
+
+(define-key kill-map "j" 'km/join-next-line-with-space)
+
+(defadvice recompile (around restore-windows)
+ "Prevent recompiling from spawning new windows."
+ (save-window-excursion
+ ad-do-it))
+(ad-activate 'recompile)
+
+(global-set-key (kbd "C-c g") 'recompile)
+
+;; From prelude
+(defun km/swap-windows ()
+ "If you have 2 windows, it swaps them."
+ (interactive)
+ (if (/= (count-windows) 2)
+ (message "You need exactly 2 windows to do this.")
+ (let* ((w1 (car (window-list)))
+ (w2 (cadr (window-list)))
+ (b1 (window-buffer w1))
+ (b2 (window-buffer w2))
+ (s1 (window-start w1))
+ (s2 (window-start w2)))
+ (set-window-buffer w1 b2)
+ (set-window-buffer w2 b1)
+ (set-window-start w1 s2)
+ (set-window-start w2 s1)))
+ (other-window 1))
+
+(global-set-key (kbd "C-c s") 'km/swap-windows)
+
+(defvar km/terminal "urxvt")
+
+(defun km/open-external-terminal ()
+ (interactive)
+ (start-process "ext-term" nil km/terminal))
+
+(define-key external-map "t" 'km/open-external-terminal)
+
+(defun km/export-wrapped-text (arg)
+ "Export the text in current buffer as wrapped text.
+This is useful for preparing text in emacs and then exporting to
+a wrapped buffer for pasting text (e.g., into a web form).
+
+If region is active, export is restricted to the region. If ARG
+is non-nil, the region is copied with `x-select-text'."
+ (interactive "P")
+ (let ((wrapped-buffer (get-buffer-create "*Wrapped export*"))
+ beg end)
+ (if (region-active-p)
+ (progn (setq beg (region-beginning))
+ (setq end (region-end)))
+ (setq beg (point-min))
+ (setq end (point-max)))
+ (copy-to-buffer wrapped-buffer beg end)
+ (switch-to-buffer-other-window wrapped-buffer)
+ (while (not (eobp))
+ (forward-paragraph)
+ (forward-line -1)
+ (unfill-paragraph)
+ (forward-line 1))
+ (when arg
+ (x-select-text (buffer-substring-no-properties (point-min) (point-max))))))
+
+;; http://www.emacswiki.org/emacs/UnfillParagraph
+(defun unfill-paragraph ()
+ "Takes a multi-line paragraph and makes it into a single line of text."
+ (interactive)
+ (let ((fill-column (point-max)))
+ (fill-paragraph nil)))
+
+;; http://www.emacswiki.org/emacs/ToggleWindowSplit
+(defun km/switch-frame-split ()
+ "If the frame is split vertically, split it horizontally or vice versa.
+Assumes that the frame is only split into two."
+ (interactive)
+ (unless (= (length (window-list)) 2)
+ (error "Can only toggle a frame split in two"))
+ (let ((split-vertically-p (window-combined-p)))
+ (delete-window)
+ (if split-vertically-p
+ (split-window-horizontally)
+ (split-window-vertically))
+ (switch-to-buffer nil)))
+
+(provide 'init-func)
diff --git a/lisp/init-general.el b/lisp/init-general.el
new file mode 100644
index 0000000..04541b1
--- /dev/null
+++ b/lisp/init-general.el
@@ -0,0 +1,94 @@
+(setq default-frame-alist '((font . "Droid Sans Mono-9")))
+
+(setq inhibit-splash-screen t
+ initial-scratch-message nil)
+
+(scroll-bar-mode -1)
+(tool-bar-mode -1)
+(menu-bar-mode -1)
+
+(setq-default indicate-empty-lines t)
+(when (not indicate-empty-lines)
+ (toggle-indicate-empty-lines))
+
+(setq echo-keystrokes 0.1
+ use-dialog-box nil
+ visible-bell t)
+(show-paren-mode t)
+
+(defalias 'yes-or-no-p 'y-or-n-p)
+
+;; Line info
+(line-number-mode t)
+(column-number-mode t)
+(size-indication-mode t)
+
+;; Set location of custom.el.
+(setq custom-file "~/.emacs.d/custom.el")
+(load custom-file)
+
+;; Store all backup and autosave files in tmp dir.
+(setq backup-directory-alist
+ `((".*" . ,temporary-file-directory)))
+(setq auto-save-file-name-transforms
+ `((".*" ,temporary-file-directory t)))
+
+;; Revert buffers automatically when underlying files are changed
+;; externally.
+(global-auto-revert-mode t)
+
+;; Tramp
+(require 'tramp)
+(setq tramp-default-method "ssh")
+
+(setq browse-url-browser-function 'browse-url-generic
+ browse-url-generic-program "chromium")
+
+(setq x-select-enable-primary t)
+
+;; Make scripts executable at save.
+(add-hook 'after-save-hook
+ 'executable-make-buffer-file-executable-if-script-p)
+
+(setq-default fill-column 72)
+(add-hook 'text-mode-hook 'turn-on-auto-fill)
+
+;; Make whitespace-mode use just basic coloring.
+;; http://ergoemacs.org/emacs/whitespace-mode.html
+(setq whitespace-style (quote
+ (spaces tabs newline space-mark
+ tab-mark newline-mark)))
+
+(transient-mark-mode -1)
+
+;; Share clipboard with system.
+(setq x-select-enable-clipboard t)
+
+(blink-cursor-mode -1)
+
+(put 'narrow-to-region 'disabled nil)
+
+(setq ispell-program-name "aspell")
+
+(global-set-key (kbd "M-/") 'hippie-expand)
+;; http://www.emacswiki.org/emacs/HippieExpand#toc9
+(defadvice he-substitute-string (after he-paredit-fix activate)
+ "Remove extra paren when expanding line in paredit."
+ (if (and paredit-mode (equal (substring str -1) ")"))
+ (progn (backward-delete-char 1) (forward-char))))
+
+(setq sentence-end-double-space nil)
+
+(eval-after-load "view"
+ '(progn
+ (define-key view-mode-map "l" 'recenter-top-bottom)
+ (define-key view-mode-map "a" 'ace-jump-mode)))
+
+(setq shell-command-switch "-ic")
+
+;; http://irreal.org/blog/?p=1536
+(autoload 'zap-up-to-char "misc"
+ "Kill up to, but not including ARGth occurrence of CHAR.")
+(global-set-key (kbd "M-z") 'zap-up-to-char)
+
+(provide 'init-general)
diff --git a/lisp/init-git.el b/lisp/init-git.el
new file mode 100644
index 0000000..2f9316d
--- /dev/null
+++ b/lisp/init-git.el
@@ -0,0 +1,27 @@
+(require 'git-annex)
+
+(setq git-annex-commit nil)
+
+(require 'magit)
+
+(defun km/magit-auto-commit ()
+ "Commit all changes with \"auto\" commit message.
+Useful for non-source code repos (e.g., Org mode note files)."
+ (interactive)
+ (magit-run-git "commit" "--all" "--message=auto"))
+
+(magit-key-mode-insert-action 'committing
+ "u" "Auto commit" 'km/magit-auto-commit)
+
+;; http://whattheemacsd.com/setup-magit.el-01.html
+(defadvice magit-status (around magit-fullscreen activate)
+ ad-do-it
+ (delete-other-windows))
+
+(setq magit-restore-window-configuration t)
+
+(setq magit-default-tracking-name-function 'magit-default-tracking-name-branch-only)
+
+(setq magit-log-show-margin nil)
+
+(provide 'init-git)
diff --git a/lisp/init-gnus.el b/lisp/init-gnus.el
new file mode 100644
index 0000000..4021d43
--- /dev/null
+++ b/lisp/init-gnus.el
@@ -0,0 +1,223 @@
+(require 'gnus)
+
+;; Set up gnus directories before gnus is initialized.
+(setq gnus-directory "~/.gnus.d"
+ gnus-home-directory "~/.gnus.d"
+ message-directory "~/.gnus.d/mail"
+ message-auto-save-directory "~/.gnus.d/drafts"
+ nnml-directory "~/.gnus.d/nnml-mail"
+ nnfolder-directory "~/.gnus.d/mail/archive"
+ nnfolder-active-file "~/.gnus.d/mail/archive/active"
+ gnus-article-save-directory "~/.gnus.d/saved"
+ gnus-kill-files-directory "~/.gnus.d/scores"
+ gnus-cache-directory "~/.gnus.d/cache")
+
+(setq gnus-startup-file (nnheader-concat gnus-home-directory "newsrc"))
+(setq gnus-init-file (nnheader-concat gnus-home-directory "gnus"))
+
+(setq gnus-save-newsrc-file nil
+ gnus-read-newsrc-file nil)
+
+(defun km/sync-mail ()
+ (interactive)
+ (let ((bufname (get-buffer-create "*Mail sync*"))
+ (default-directory "~"))
+ (with-current-buffer bufname
+ (view-mode 1)
+ (goto-char (point-max)))
+ (display-buffer bufname)
+ (start-process "mail sync" bufname km/sync-mail-cmd)))
+
+(defvar km/sync-mail-cmd "~/bin/sync-mail.sh"
+ "Run sync mail script.")
+
+;; http://www.emacswiki.org/emacs/GnusSync
+(defun gnus-grace-exit-before-kill-emacs ()
+ (if (and (fboundp 'gnus-alive-p)
+ (gnus-alive-p))
+ (let ((noninteractive t))
+ (gnus-group-exit))))
+(add-hook 'kill-emacs-hook 'gnus-grace-exit-before-kill-emacs)
+
+(setq imap-shell-program "/usr/lib/dovecot/imap -c ~/.dovecotrc"
+ gnus-select-method '(nnimap "dov" (nnimap-stream shell))
+ gnus-secondary-select-methods '((nntp "news.gmane.org")))
+
+(setq message-send-mail-function 'message-send-mail-with-sendmail
+ sendmail-program "/usr/bin/msmtp")
+
+(setq message-sendmail-envelope-from 'header)
+
+(setq gnus-gcc-mark-as-read t)
+
+(setq message-citation-line-function 'message-insert-formatted-citation-line)
+(setq message-citation-line-format "On %D %R, %N wrote:")
+
+(setq message-kill-buffer-on-exit t)
+
+;; Use for rss too specific to add to gwene.
+(require 'nnrss)
+
+(setq gnus-group-list-inactive-groups nil)
+
+;; Start in topic mode.
+(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
+(setq gnus-topic-display-empty-topics nil)
+
+(setq gnus-visible-headers
+ '("^From" "^Subject" "^Date" "^To" "^Cc" "^User-Agent"))
+
+(add-hook 'message-mode-hook
+ '(lambda ()
+ (flyspell-mode 1)))
+
+(setq gnus-confirm-mail-reply-to-news t)
+
+(setq mm-discouraged-alternatives '("text/html" "text/richtext"))
+
+(setq gnus-summary-line-format
+ "%U%R %&user-date;%-20= %-15,15f %B %S \n")
+(setq gnus-sum-thread-tree-indent " "
+ gnus-sum-thread-tree-root "."
+ gnus-sum-thread-tree-false-root "o "
+ gnus-sum-thread-tree-single-indent ""
+ gnus-sum-thread-tree-leaf-with-other "+-> "
+ gnus-sum-thread-tree-vertical "| "
+ gnus-sum-thread-tree-single-leaf "`-> ")
+
+(setq gnus-thread-sort-functions
+ '(gnus-thread-sort-by-number
+ gnus-thread-sort-by-most-recent-date))
+
+(defun km/follow-gwene-link ()
+ "Follow link at bottom of gwene message"
+ (interactive)
+ (km/gnus-end-of-article-buffer)
+ (search-backward "Link")
+ (widget-button-press (point)))
+
+(define-key gnus-summary-mode-map
+ (kbd "C-c j") 'km/follow-gwene-link)
+(define-key gnus-article-mode-map
+ (kbd "C-c j") 'km/follow-gwene-link)
+
+(require 'url-handlers)
+
+(defun km/gnus-open-github-patch ()
+ "Open patch from github email.
+A new buffer with the patch contents is opened in another window."
+ (interactive)
+ (km/gnus-end-of-article-buffer)
+ (search-backward "patch")
+ (let ((url (thing-at-point 'url))
+ (patch-buffer (generate-new-buffer "*gnus-github-patch*")))
+ (switch-to-buffer-other-window patch-buffer)
+ (url-insert-file-contents url)
+ (diff-mode)
+ (view-mode 1)))
+
+(defun km/gnus-end-of-article-buffer ()
+ "Move point to the end of the article buffer."
+ ;; The next 3 lines are from `gnus-summary-widget-forward'.
+ (gnus-summary-select-article)
+ (gnus-configure-windows 'article)
+ (select-window (gnus-get-buffer-window gnus-article-buffer))
+ (goto-char (point-max)))
+
+(require 'notmuch)
+(require 'org-gnus)
+
+(define-key gnus-group-mode-map "GG" 'notmuch-search)
+;; http://roland.entierement.nu/blog/2010/09/08/gnus-dovecot-offlineimap-search-a-howto.html
+(defun km/notmuch-shortcut ()
+ (define-key gnus-group-mode-map "GG" 'notmuch-search))
+
+(defun km/notmuch-file-to-group (file)
+ "Calculate the Gnus group name from the given file name."
+ (let ((group (file-name-directory (directory-file-name (file-name-directory file)))))
+ (setq group (replace-regexp-in-string ".*/mail/" "nnimap+dov:" group))
+ (setq group (replace-regexp-in-string "/$" "" group))
+ (if (string-match ":$" group)
+ (concat group "INBOX")
+ (replace-regexp-in-string ":\\." ":" group))))
+
+(defun km/notmuch-goto-message-in-gnus ()
+ "Open a summary buffer containing the current notmuch article."
+ (interactive)
+ (let ((group (km/notmuch-file-to-group (notmuch-show-get-filename)))
+ (message-id (replace-regexp-in-string
+ "^id:" "" (notmuch-show-get-message-id))))
+ (setq message-id (replace-regexp-in-string "\"" "" message-id))
+ (if (and group message-id)
+ (progn
+ (switch-to-buffer "*Group*")
+ (org-gnus-follow-link group message-id))
+ (message "Couldn't get relevant infos for switching to Gnus."))))
+
+(define-key notmuch-show-mode-map (kbd "C-c C-c") 'km/notmuch-goto-message-in-gnus)
+(add-hook 'gnus-group-mode-hook 'km/notmuch-shortcut)
+
+(setq notmuch-fcc-dirs nil)
+
+(setq footnote-section-tag "")
+
+;; modified from
+;; http://emacs-fu.blogspot.com/2008/12/some-simple-tricks-boxquote-footnote.html
+(defun km/snip-mail-quote (beg end &optional quote-char no-number)
+ "Replace region lines with \"[n lines ...]\".
+
+The default QUOTE-CHAR is \">\". Text following the snipped lines
+is placed on a new line and the resulting paragraph is filled. If
+NO-NUMBER is non-nil, the number of lines is not added."
+ (interactive "r")
+ (let ((nlines (count-lines beg end))
+ (quote-char (or quote-char ">")))
+ (delete-region beg end)
+ (if no-number
+ (insert (format "[...]"))
+ (insert (format "[%d line%s ...]" nlines (if (= 1 nlines) "" "s"))))
+ (search-backward "[")
+ (unless (bolp)
+ (newline))
+ (search-forward "]")
+ (unless (eolp)
+ (newline)
+ (insert quote-char)
+ (just-one-space)
+ (fill-paragraph))))
+
+(define-key message-mode-map
+ (kbd "C-c m s") 'km/snip-mail-quote)
+
+;; Without reporting the number of lines
+(define-key message-mode-map
+ (kbd "C-c m S") '(lambda (beg end)
+ (interactive "r")
+ (km/snip-mail-quote beg end nil t)))
+
+(add-hook 'gnus-summary-mode-hook
+ (lambda ()
+ (gnus-define-keys gnus-summary-mode-map
+ "j" gnus-summary-next-unread-article
+ ";" gnus-summary-universal-argument ;; mutt's tag
+ "e" gnus-summary-scroll-up)))
+
+(add-hook 'gnus-group-mode-hook
+ (lambda ()
+ (gnus-define-keys gnus-group-mode-map
+ "e" gnus-topic-select-group)))
+
+(add-hook 'gnus-article-mode-hook
+ (lambda ()
+ (gnus-define-keys gnus-article-mode-map
+ "e" shr-browse-url)))
+
+(defadvice gnus (around gnus-fullscreen activate)
+ (window-configuration-to-register :gnus-fullscreen)
+ ad-do-it
+ (delete-other-windows))
+(defadvice gnus-group-exit (around gnus-restore-screen activate)
+ ad-do-it
+ (jump-to-register :gnus-fullscreen))
+
+(provide 'init-gnus)
diff --git a/lisp/init-grep.el b/lisp/init-grep.el
new file mode 100644
index 0000000..5a5051e
--- /dev/null
+++ b/lisp/init-grep.el
@@ -0,0 +1,15 @@
+;; http://stackoverflow.com/questions/16122801/
+;; remove-header-information-from-rgrep-grep-output-in-emacs
+(defun hide-grep-header ()
+ (save-excursion
+ (with-current-buffer grep-last-buffer
+ (goto-line 5)
+ (narrow-to-region (point) (point-max)))))
+
+(defadvice grep (after hide-grep-header activate) (hide-grep-header))
+(defadvice rgrep (after hide-grep-header activate) (hide-grep-header))
+(defadvice lgrep (after hide-grep-hxoeader activate) (hide-grep-header))
+(defadvice grep-find (after hide-grep-header activate) (hide-grep-header))
+(defadvice vc-git-grep (after hide-grep-header activate) (hide-grep-header))
+
+(provide 'init-grep)
diff --git a/lisp/init-haskell.el b/lisp/init-haskell.el
new file mode 100644
index 0000000..3be2fe8
--- /dev/null
+++ b/lisp/init-haskell.el
@@ -0,0 +1,3 @@
+(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
+
+(provide 'init-haskell)
diff --git a/lisp/init-ibuffer.el b/lisp/init-ibuffer.el
new file mode 100644
index 0000000..9131279
--- /dev/null
+++ b/lisp/init-ibuffer.el
@@ -0,0 +1,69 @@
+;; Replace buffer-menu with ibuffer.
+(global-set-key (kbd "C-x C-b") 'ibuffer)
+
+;; Modified from http://martinowen.net/blog/2010/02/tips-for-emacs-ibuffer.html
+;; and here http://www.elliotglaysher.org/emacs/.
+
+(setq ibuffer-saved-filter-groups
+ '(("home"
+ ("elisp" (mode . emacs-lisp-mode))
+ ("org" (or (mode . org-mode)
+ (name . "^\\*Org Agenda\\*$")
+ (name . "^\\*Calendar\\*$")))
+ ("web" (or (mode . html-mode)
+ (mode . nxml-mode)
+ (mode . css-mode)
+ (mode . less-css-mode)))
+ ("r" (or (mode . ess-mode)
+ (mode . inferior-ess-mode)
+ (name . "^\\*ESS\\*$")))
+ ("markup" (or (mode . markdown-mode)
+ (mode . rst-mode)))
+ ("lua" (mode . lua-mode))
+ ("perl" (mode . perl-mode))
+ ("python" (or (mode . python-mode)
+ (name . "^\\*Python")))
+ ("haskell" (mode . haskell-mode))
+ ("text" (mode . text-mode))
+ ("shell" (mode . sh-mode))
+ ("latex" (or (mode . latex-mode)
+ (mode . LaTeX-mode)
+ (mode . bibtex-mode)
+ (mode . reftex-mode)))
+ ("dir" (or (mode . dired-mode)
+ (name . "^\\*tramp")))
+ ("terminal" (or (mode . term-mode)
+ (name . "^\\*Shell Command Output*")
+ (name . "^\\*External terminal*")))
+ ("packages" (or (name . "^\\*Compile-Log\\*")
+ (name . "^\\*Packages\\*")))
+ ("magit" (name . "^\\*magit"))
+ ("emacs" (or (name . "^\\*scratch\\*$")
+ (name . "^\\*Messages\\*$")))
+ ("mail" (or (mode . message-mode)
+ (mode . mail-mode)
+ (mode . gnus-group-mode)
+ (mode . gnus-summary-mode)
+ (mode . gnus-article-mode)
+ (mode . notmuch-search-mode)
+ (mode . notmuch-show-mode)
+ (name . "^\\*Mail sync\\*$")
+ (name . "^\\*Gnus sync\\*$")
+ (name . "^\\.newsrc-dribble")))
+ ("help" (or (name . "^\\*Help\\*$")
+ (name . "^\\*Apropos\\*$")
+ (name . "^\\*info\\*$")
+ (name . "^\\*Completions\\*"))))))
+
+(add-hook 'ibuffer-mode-hook
+ '(lambda ()
+ (ibuffer-auto-mode 1) ; Keep buffer list up-to-date.
+ (ibuffer-switch-to-saved-filter-groups "home")))
+
+;; Don't prompt to delete unmodified buffers.
+(setq ibuffer-expert t)
+
+;; Don't show empty filter groups.
+(setq ibuffer-show-empty-filter-groups nil)
+
+(provide 'init-ibuffer)
diff --git a/lisp/init-ido.el b/lisp/init-ido.el
new file mode 100644
index 0000000..078107f
--- /dev/null
+++ b/lisp/init-ido.el
@@ -0,0 +1,32 @@
+(require 'flx-ido)
+(ido-mode t)
+
+(setq ido-enable-prefix nil
+ ido-everywhere t
+ ido-enable-flex-matching t
+ ido-create-new-buffer 'always
+ ido-use-filename-at-point 'guess
+ ido-max-prospects 10
+ ido-save-directory-list-file "~/.emacs.d/cache/ido.hist")
+
+(flx-ido-mode 1)
+;; Disable ido faces to see flx highlights.
+(setq ido-use-faces nil)
+
+(setq ido-max-directory-size 100000)
+
+;; Recent files
+(setq recentf-save-file "~/.emacs.d/cache/recentf"
+ recentf-max-saved-items 200
+ recentf-max-menu-items 15)
+(recentf-mode t)
+
+;; From prelude
+(defun km/recentf-ido-find-file ()
+ "Find a recent file using ido."
+ (interactive)
+ (let ((file (ido-completing-read "Choose recent file: " recentf-list nil t)))
+ (when file
+ (find-file file))))
+
+(provide 'init-ido)
diff --git a/lisp/init-keybindings.el b/lisp/init-keybindings.el
new file mode 100644
index 0000000..70ad6b3
--- /dev/null
+++ b/lisp/init-keybindings.el
@@ -0,0 +1,30 @@
+;; Keybindings that don't go with other topics
+
+(global-set-key (kbd "C-x \\") 'align-regexp)
+(global-set-key (kbd "C-x K") 'kill-buffer-and-window)
+
+;; Overrides `suspend-emacs' (which is also bound to C-x C-z).
+(global-set-key (kbd "C-z") 'zap-to-char)
+(global-unset-key (kbd "M-z"))
+
+(global-set-key (kbd "C-'") 'backward-kill-word)
+
+(define-key replace-map "s" 'query-replace)
+(define-key replace-map "S" 'replace-string)
+(define-key replace-map "r" 'query-replace-regexp)
+(define-key replace-map "R" 'replace-regexp)
+
+(define-key insert-map "t" 'km/todo-comment)
+
+(define-key insert-map "i" 'indent-relative)
+
+(define-key multiple-cursors-map "l" 'mc/edit-lines)
+(define-key multiple-cursors-map "n" 'mc/mark-next-like-this)
+(define-key multiple-cursors-map "p" 'mc/mark-previous-like-this)
+(define-key multiple-cursors-map "a" 'mc/mark-all-like-this)
+
+(global-set-key (kbd "C-;") 'er/expand-region)
+
+(define-key external-map "s" 'shell-command)
+
+(provide 'init-keybindings)
diff --git a/lisp/init-keychord.el b/lisp/init-keychord.el
new file mode 100644
index 0000000..8b1603a
--- /dev/null
+++ b/lisp/init-keychord.el
@@ -0,0 +1,36 @@
+(require 'key-chord)
+(key-chord-mode 1)
+
+(key-chord-define-global ",r" 'km/recentf-ido-find-file)
+(key-chord-define-global ",t" 'org-capture)
+;; Instead of alt-x
+(key-chord-define-global ",x" 'smex)
+(key-chord-define-global ",f" 'find-file)
+(key-chord-define-global ",g" 'magit-status)
+(key-chord-define-global ",b" 'ido-switch-buffer)
+
+(key-chord-define-global ",s" 'save-buffer)
+(key-chord-define-global ",q" 'kill-this-buffer)
+(key-chord-define-global ",d" 'km/save-and-kill-buffer)
+(key-chord-define-global ",e" '(lambda ()
+ (interactive)
+ (save-buffer)
+ (server-edit)))
+
+(key-chord-define-global ",c" 'km/toggle-line-or-region-comment)
+
+(key-chord-define-global ";a" 'ace-jump-mode)
+(key-chord-define-global ",z" 'rgrep)
+(key-chord-define-global ",v" 'view-mode)
+
+(key-chord-define-global ",a" 'org-agenda)
+
+;; Projectile key chords
+(key-chord-define-global ";s" 'projectile-switch-project)
+(key-chord-define-global ";f" 'projectile-find-file)
+(key-chord-define-global ";d" 'projectile-find-dir)
+(key-chord-define-global ";g" 'projectile-grep)
+(key-chord-define-global ";r" 'projectile-replace)
+(key-chord-define-global ";c" 'projectile-commander)
+
+(provide 'init-keychord)
diff --git a/lisp/init-keymaps.el b/lisp/init-keymaps.el
new file mode 100644
index 0000000..eb1db41
--- /dev/null
+++ b/lisp/init-keymaps.el
@@ -0,0 +1,18 @@
+(define-prefix-command 'replace-map)
+(global-set-key (kbd "C-c r") 'replace-map)
+
+(define-prefix-command 'kill-map)
+(global-set-key (kbd "C-c k") 'kill-map)
+
+(define-prefix-command 'insert-map)
+(global-set-key (kbd "C-c i") 'insert-map)
+
+;; multiple cursors
+;; Put under insert prefix.
+(define-prefix-command 'multiple-cursors-map)
+(define-key insert-map "m" 'multiple-cursors-map)
+
+(define-prefix-command 'external-map)
+(global-set-key (kbd "C-c x") 'external-map)
+
+(provide 'init-keymaps)
diff --git a/lisp/init-modes.el b/lisp/init-modes.el
new file mode 100644
index 0000000..5db7a41
--- /dev/null
+++ b/lisp/init-modes.el
@@ -0,0 +1,15 @@
+;; These could be kept alongside related topics, but for whatever reason
+;; I prefer having them together.
+
+(defvar km/modes '(("\\.zsh$" . shell-script-mode)
+ ("\\.*rc$" . conf-unix-mode)
+ ("\\.org.txt$" . org-mode)
+ ("PKGBUILD" . pkgbuild-mode))
+ "Auto mode mappings")
+
+(mapc
+ (lambda (mode) (setq auto-mode-alist
+ (cons mode auto-mode-alist)))
+ km/modes)
+
+(provide 'init-modes)
diff --git a/lisp/init-org.el b/lisp/init-org.el
new file mode 100644
index 0000000..274e673
--- /dev/null
+++ b/lisp/init-org.el
@@ -0,0 +1,149 @@
+(setq org-modules '(org-bibtex org-gnus org-info))
+
+(setq org-log-done t)
+(setq org-todo-keywords
+ '((sequence "TODO" "STARTED" "|" "DONE" "NA")))
+(setq org-use-speed-commands t)
+(setq org-fast-tag-selection-single-key 'expert)
+(setq org-catch-invisible-edits 'error)
+(setq org-goto-interface 'outline-path-completion)
+(setq org-src-fontify-natively t)
+(setq org-special-ctrl-k t)
+(setq org-blank-before-new-entry '((heading . t)
+ (plain-list-item . auto)))
+
+(setq org-capture-templates
+ '(("t" "task" entry (file+headline "~/notes/tasks.org" "Inbox")
+ "* TODO %?\n%i")
+ ("d" "date" entry (file+headline "~/notes/calendar.org" "Inbox")
+ "* %?\n%i")
+ ("m" "misc" entry (file+headline "~/notes/misc.org" "Inbox")
+ "* %?\n%i")
+ ("b" "backburner" entry (file+headline "~/notes/backburner.org" "Inbox")
+ "* TODO %?\n%i")
+ ;; Link counterparts
+ ("T" "task link" entry (file+headline "~/notes/tasks.org" "Inbox")
+ "* TODO %?\n%i\nLink: %a")
+ ("D" "date link" entry (file+headline "~/notes/calendar.org" "Inbox")
+ "* %?\n%i\nLink: %a")
+ ("M" "misc link" entry (file+headline "~/notes/misc.org" "Inbox")
+ "* %?\n%i\nLink: %a")
+ ("B" "backburner link" entry (file+headline "~/notes/backburner.org" "Inbox")
+ "* TODO %?\n%i\nLink: %a")
+ ;; Clipboard
+ ("x" "task clipboard" entry (file+headline "~/notes/tasks.org" "Inbox")
+ "* TODO %?\n%x")
+ ("X" "misc clipboard" entry (file+headline "~/notes/misc.org" "Inbox")
+ "* %?\n%x")))
+
+(defun km/open-main-orgfile ()
+ (interactive)
+ (find-file org-default-notes-file))
+
+(global-set-key (kbd "C-c o l") 'org-store-link)
+(global-set-key (kbd "C-c o a") 'org-agenda)
+(global-set-key (kbd "C-c o b") 'org-iswitchb)
+(global-set-key (kbd "C-c o m") 'km/open-main-orgfile)
+
+(setq org-structure-template-alist
+ '(("p" "#+property: " "")
+ ("o" "#+options: " "")
+ ("d" "#+date: " "")
+ ("t" "#+title: " "")
+ ("S" "#+setupfile: ?" "")
+ ("n" "#+begin_note\n ?\n#+end_note" "<note>\n?\n</note>")
+ ("w" "#+begin_note\n ?\n#+end_note" "<note>\n?\n</note>")
+ ("C" "#+caption: " "")
+ ("b" "#+label: " "")
+ ("r" "#+attr_latex: " "")
+ ("R" "#+attr_html: " "")
+ ;; Lower case versions of defaults
+ ("s" "#+begin_src ?\n \n#+end_src" "<src lang=\"?\">\n\n</src>")
+ ("e" "#+begin_example\n ?\n#+end_example" "<example>\n?\n</example>")
+ ("q" "#+begin_quote\n ?\n#+end_quote" "<quote>\n?\n</quote>")
+ ("v" "#+begin_versen ?\n#+end_verse" "<verse>\n?\n</verse>")
+ ("V" "#+begin_verbatim\n ?\n#+end_verbatim" "<verbatim>\n?\n</verbatim>")
+ ("c" "#+begin_center\n ?\n#+end_center" "<center>\n?\n</center>")
+ ("l" "#+begin_latex\n ?\n#+end_latex" "<literal style=\"latex\">\n?\n</literal>")
+ ("L" "#+latex: " "<literal style=\"latex\">?</literal>")
+ ("h" "#+begin_html\n ?\n#+end_html" "<literal style=\"html\">\n?\n</literal>")
+ ("H" "#+html: " "<literal style=\"html\">?</literal>")
+ ("a" "#+begin_ascii\n ?\n#+end_ascii" "")
+ ("A" "#+ascii: " "")
+ ("i" "#+index: ?" "#+index: ?")
+ ("I" "#+include: %file ?" "<include file=%file markup=\"?\">")))
+
+;; Don't let `org-cycle-agenda-files' binding override custom
+;; `backward-kill-word' binding (`org-cycle-agenda-files' is still bound
+;; to C-,).
+(define-key org-mode-map (kbd "C-'") nil)
+
+;;; Org in other modes
+(defun km/load-orgstruct ()
+ (turn-on-orgstruct++)
+ (turn-on-orgtbl))
+
+(add-hook 'message-mode-hook 'km/load-orgstruct)
+(add-hook 'git-commit-mode-hook 'km/load-orgstruct)
+
+;; Avoid conflict when amsmath is loaded.
+(setcar (rassoc '("wasysym" t) org-latex-default-packages-alist)
+ "nointegrals")
+(add-to-list 'org-latex-packages-alist '("" "amsmath" t))
+
+(defadvice org-agenda-list (around org-agenda-fullscreen activate)
+ "Start agenda in fullscreen.
+
+After agenda loads, delete other windows.
+`org-agenda-restore-windows-after-quit' should non-nil to restore
+the previous window configuration. If `org-agenda-sticky' is
+non-nil, configurations with more than one window do not seem to
+be restored properly."
+ ad-do-it
+ (delete-other-windows))
+
+(setq org-agenda-restore-windows-after-quit t)
+(setq org-agenda-sticky nil)
+
+;;; Agenda
+
+(setq org-agenda-files '("~/notes/calendar.org" "~/notes/tasks.org"))
+(setq org-default-notes-file "~/notes/tasks.org")
+
+(setq org-agenda-show-all-dates t)
+(setq org-agenda-skip-deadline-if-done t)
+(setq org-agenda-skip-scheduled-if-done t)
+(setq org-agenda-start-on-weekday nil)
+(setq org-reverse-note-order t)
+
+(setq org-agenda-custom-commands
+ '(("d" todo "DONE" nil)
+ ("s" todo "STARTED" nil)
+ ("u" "Unschedule TODO entries" alltodo ""
+ ((org-agenda-skip-function
+ (lambda nil
+ (org-agenda-skip-entry-if 'scheduled 'deadline
+ 'regexp "\n]+>")))
+ (org-agenda-overriding-header "Unscheduled TODO entries: ")))
+ ("p" "Past timestamps" tags "TIMESTAMP<=\"<now>\"")))
+
+;;; Refiling
+
+(defvar km/org-refiling-targets
+ (append org-agenda-files '("~/notes/backburner.org" "~/notes/misc.org"))
+ "List of refiling targets for agenda, including non-agenda
+files.")
+
+(setq org-refile-targets (quote ((nil :maxlevel . 3)
+ (km/org-refiling-targets :maxlevel . 2))))
+
+;; Use ido for refiling.
+(setq org-outline-path-complete-in-steps nil)
+(setq org-completion-use-ido t)
+
+(defun km/verify-refile-target ()
+ "Exclude DONE state from refile targets."
+ (not (member (nth 2 (org-heading-components)) org-done-keywords)))
+(setq org-refile-target-verify-function 'km/verify-refile-target)
+
+(provide 'init-org)
diff --git a/lisp/init-orgcontacts.el b/lisp/init-orgcontacts.el
new file mode 100644
index 0000000..548c146
--- /dev/null
+++ b/lisp/init-orgcontacts.el
@@ -0,0 +1,9 @@
+(require 'org-contacts)
+
+(setq org-contacts-files '("~/notes/contacts.org"))
+
+(add-to-list 'org-capture-templates
+ '("a" "email address" entry (file+headline "~/notes/contacts.org" "Inbox")
+ "** %(org-contacts-template-name)\n :PROPERTIES:\n :EMAIL: %(org-contacts-template-email)\n :END:"))
+
+(provide 'init-orgcontacts)
diff --git a/lisp/init-pkg.el b/lisp/init-pkg.el
new file mode 100644
index 0000000..0b248ef
--- /dev/null
+++ b/lisp/init-pkg.el
@@ -0,0 +1,53 @@
+;; http://www.aaronbedra.com/emacs.d/
+
+(require 'package)
+(add-to-list 'package-archives
+ '("melpa" . "http://melpa.milkbox.net/packages/") t)
+(setq package-enable-at-startup nil)
+(package-initialize)
+
+(require 'cl)
+(defvar km/packages '(ace-jump-mode
+ auctex
+ dash
+ ess
+ expand-region
+ flx
+ flx-ido
+ git-annex
+ git-commit-mode
+ haskell-mode
+ htmlize
+ key-chord
+ less-css-mode
+ lua-mode
+ magit
+ markdown-mode
+ mocker
+ multiple-cursors
+ paredit
+ pkgbuild-mode
+ projectile
+ smex
+ wrap-region
+ yasnippet)
+ "Default packages")
+
+(defun km/packages-installed-p ()
+ (loop for pkg in km/packages
+ when (not (package-installed-p pkg)) do (return nil)
+ finally (return t)))
+
+(unless (km/packages-installed-p)
+ (message "%s" "Refreshing package database...")
+ (package-refresh-contents)
+ (dolist (pkg km/packages)
+ (when (not (package-installed-p pkg))
+ (message "installing %s" pkg)
+ (package-install pkg))))
+
+(add-to-list 'load-path "~/.emacs.d/vendor/")
+(add-to-list 'load-path "~/src/emacs/org-mode/lisp")
+(add-to-list 'load-path "~/src/emacs/org-mode/contrib/lisp" t)
+
+(provide 'init-pkg)
diff --git a/lisp/init-projectile.el b/lisp/init-projectile.el
new file mode 100644
index 0000000..66da4c6
--- /dev/null
+++ b/lisp/init-projectile.el
@@ -0,0 +1,29 @@
+(projectile-global-mode)
+
+(setq projectile-switch-project-action 'projectile-commander)
+
+;; Default binding is D.
+(def-projectile-commander-method ?r
+ "Open project root in dired."
+ (projectile-dired))
+
+(def-projectile-commander-method ?c
+ "Run project compilation command."
+ (call-interactively 'projectile-compile-project))
+
+(defun km/projectile-switch-project-to-file ()
+ "Provide access to the of default `projectile-find-file'.
+
+I have set `projectile-switch-project-action' to
+`projectile-commander' but would still like quick access to
+`projectile-find-file'."
+ (interactive)
+ (let ((projectile-switch-project-action 'projectile-find-file))
+ (projectile-switch-project)))
+
+(define-key projectile-mode-map (kbd "C-c p j")
+ 'km/projectile-switch-project-to-file)
+
+(setq projectile-use-git-grep t)
+
+(provide 'init-projectile)
diff --git a/lisp/init-python.el b/lisp/init-python.el
new file mode 100644
index 0000000..ae4871b
--- /dev/null
+++ b/lisp/init-python.el
@@ -0,0 +1,45 @@
+;; http://www.emacswiki.org/emacs/PythonProgrammingInEmacs#toc5
+(defun km/setup-ipython-shell ()
+ (interactive)
+ (setq
+ python-shell-interpreter "ipython"
+ python-shell-interpreter-args ""
+ python-shell-prompt-regexp "In \\[[0-9]+\\]: "
+ python-shell-prompt-output-regexp "Out\\[[0-9]+\\]: "
+ python-shell-completion-setup-code
+ "from IPython.core.completerlib import module_completion"
+ python-shell-completion-module-string-code
+ "';'.join(module_completion('''%s'''))\n"
+ python-shell-completion-string-code
+ "';'.join(get_ipython().Completer.all_completions('''%s'''))\n"))
+
+(defun km/create-python-test-file (arg)
+ "Create a python test file from the name of the current file.
+Unless a prefix argument ARG is given, py.test is also imported."
+ (interactive "P")
+ (let* ((py-file (file-name-nondirectory buffer-file-name))
+ (test-file (concat "test_" py-file)))
+ (when (file-exists-p test-file)
+ (error "Test file %s already exists." test-file))
+ (with-current-buffer (find-file-other-window test-file)
+ (insert (format "import %s\n" (file-name-sans-extension py-file)))
+ (unless arg
+ (insert "import pytest\n")))))
+
+(defun km/python-hook ()
+ (local-set-key (kbd "C-c m c") 'km/create-python-test-file)
+ (local-set-key (kbd "C-c m t") '(lambda ()
+ (interactive)
+ (compile "py.test")))
+ (local-set-key (kbd "C-c m T") '(lambda ()
+ (interactive)
+ (compile "py.test2"))))
+
+(add-hook 'python-mode-hook 'km/python-hook)
+
+(add-to-list 'interpreter-mode-alist '("python2" . python-mode))
+(add-to-list 'interpreter-mode-alist '("python3" . python-mode))
+
+(setq python-fill-docstring-style 'pep-257-nn)
+
+(provide 'init-python)
diff --git a/lisp/init-smex.el b/lisp/init-smex.el
new file mode 100644
index 0000000..94e48b5
--- /dev/null
+++ b/lisp/init-smex.el
@@ -0,0 +1,9 @@
+;; http://www.juanrubio.me/2011/11/emacs-smex-m-x-do-not-like-typing/
+(require 'smex)
+(smex-initialize)
+;; smex bound in km-evil.ex (,x).
+(global-set-key (kbd "M-X") 'smex-major-mode-commands)
+;; Old M-x
+(global-set-key (kbd "M-x") 'execute-extended-command)
+
+(provide 'init-smex)
diff --git a/lisp/init-tex.el b/lisp/init-tex.el
new file mode 100644
index 0000000..3654a87
--- /dev/null
+++ b/lisp/init-tex.el
@@ -0,0 +1,20 @@
+(require 'tex)
+(require 'reftex)
+(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
+
+;;; Add path for pdflatex.
+(setenv "PATH"
+ (concat
+ "/usr/texbin" ":"
+ (getenv "PATH")))
+
+(defun km/org-mode-reftex-setup ()
+ (define-key org-mode-map (kbd "C-c [") 'reftex-citation))
+
+(add-hook 'org-mode-hook 'km/org-mode-reftex-setup)
+
+(setq reftex-default-bibliography
+ (quote
+ ("~/refs/refs.bib")))
+
+(provide 'init-tex)
diff --git a/lisp/init-yas.el b/lisp/init-yas.el
new file mode 100644
index 0000000..1c0c74a
--- /dev/null
+++ b/lisp/init-yas.el
@@ -0,0 +1,13 @@
+(require 'yasnippet)
+
+(yas-reload-all)
+
+(add-hook 'prog-mode-hook
+ '(lambda ()
+ (yas-minor-mode)))
+
+(add-hook 'LaTeX-mode-hook
+ '(lambda ()
+ (yas-minor-mode)))
+
+(provide 'init-yas)