(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1))
(defun in-emacs-dir (path)
(concat user-emacs-directory path))
(defun in-org-dir (path)
(concat "~/Dropbox/org/" path))
Don’t pollute init.el
with GUI-made customizations.
This is also used for theme loading, as well. It needs to be loaded early on; otherwise loading themes via el-get mechanisms bites because you have to continually accept their loading.
(setq custom-file (in-emacs-dir "custom.el"))
(load custom-file)
Apparently we need to use --login
(instead of -i
) to also
capture any PATH
entries that OS X brings in via it’s
/usr/libexec/path_helper
utility, which is only invoked for login
shells. This will incorporate any settings from ~/.bash_profile
as well, so I just source ~/.bashrc
from there to get everything
at once.
This is needed for (among other things), making sure
ispell=/=aspell
is available for Flyspell to work properly.
As this sets `exec-path`, it needs to come early on, so we can use `executable-find` to guard el-get recipe includes.
(I swiped this code from Steve Purcell’s emacs.d)
(defun set-exec-path-from-shell-PATH ()
(let ((path-from-shell (shell-command-to-string "$SHELL --login -c 'echo $PATH'")))
(setenv "PATH" path-from-shell)
(setq exec-path (split-string path-from-shell path-separator))))
(if window-system
(set-exec-path-from-shell-PATH))
(add-to-list 'load-path (in-emacs-dir "el-get/el-get"))
(unless (require 'el-get nil 'noerror)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.github.com/dimitri/el-get/master/el-get-install.el")
(goto-char (point-max))
(eval-print-last-sexp)))
(add-to-list 'el-get-recipe-path (in-emacs-dir "recipes"))
;; (Optional) configuration for these packages is found in the
;; "init-<package>.el" files in `el-get-user-package-directory`
(setq el-get-user-package-directory (in-emacs-dir "init"))
(setq my-packages '(
diminish
flycheck
smartparens
smex
yasnippet
;; gnuplot-mode
color-theme-zenburn
js2-mode
yaml-mode
company-mode
helm
helm-ls-git
helm-git-grep
helm-company
nyan-mode
sqitch
projectile
rainbow-delimiters
rust-mode
))
(when (executable-find "git")
(add-to-list 'my-packages 'magit)
(add-to-list 'my-packages 'gist))
(when (executable-find "markdown")
(add-to-list 'my-packages 'markdown-mode))
(when (executable-find "ruby")
(add-to-list 'my-packages 'ruby-mode)
(add-to-list 'my-packages 'ruby-tools)
(add-to-list 'my-packages 'auto-complete-ruby))
(when (executable-find "elixir")
(add-to-list 'my-packages 'elixir-mode)
(add-to-list 'my-packages 'alchemist))
(el-get 'sync my-packages)
(setq initial-major-mode 'org-mode)
(set-face-attribute 'default nil :family "Anonymous Pro" :height 150)
(setq inhibit-startup-screen t ;; There's no good reason to keep the startup screen.
next-line-add-newlines t
delete-by-moving-to-trash t ;; use system trash directory
trash-directory "~/.Trash"
line-number-mode t
column-number-mode t
size-indication-mode t
require-final-newline t ;; All files end with newlines
;; Send backups and autosaves to the temp folder instead of polluting the current directory.
backup-directory-alist `((".*" . ,temporary-file-directory))
auto-save-file-name-transforms `((".*" ,temporary-file-directory t))
create-lockfiles nil
echo-keystrokes 0.1
font-lock-maximum-decoration t
visible-bell t)
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p)
(global-linum-mode 1)
(fset 'yes-or-no-p 'y-or-n-p)
(global-auto-revert-mode t)
;; http://whattheemacsd.com/sane-defaults.el-01.html
;; Auto-refresh dired buffers, too
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)
;; From http://eden.rutgers.edu/~mangesh/emacs.html
(setq-default frame-title-format
(list '((buffer-file-name " %f" (dired-directory
dired-directory
(revert-buffer-function " %b"
("%b - Dir: " default-directory)))))))
(setq 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)
(define-key global-map (kbd "C-+") 'text-scale-increase)
;; Set to = so you don't have to hold the Shift key, and
;; increase/decrease are symmetric
(define-key global-map (kbd "C-=") 'text-scale-increase)
(define-key global-map (kbd "C--") 'text-scale-decrease)
;; Also toss in OS X bindings for the hell of it
(define-key global-map (kbd "s-=") 'text-scale-increase)
(define-key global-map (kbd "s--") 'text-scale-decrease)
;; Get back to baseline quickly
;;
;; TODO: It'd be good to find a better keybinding for this, though
(define-key global-map (kbd "s-0")
(lambda ()
(interactive)
(text-scale-set 0)))
;; Apparently this RET and C-j were swapped recently
(define-key global-map (kbd "C-j") 'newline-and-indent)
Why WOULDN’T you have this?!
(nyan-mode)
(server-start)
(require 'ido)
(ido-mode t)
(setq ido-enable-flex-matching t)
;; I got this from Seth Falcon
(require 'imenu)
(defun prelude-ido-goto-symbol (&optional symbol-list)
"Refresh imenu and jump to a place in the buffer using Ido."
(interactive)
(unless (featurep 'imenu)
(require 'imenu nil t))
(cond
((not symbol-list)
(let ((ido-mode ido-mode)
(ido-enable-flex-matching
(if (boundp 'ido-enable-flex-matching)
ido-enable-flex-matching t))
name-and-pos symbol-names position)
(unless ido-mode
(ido-mode 1)
(setq ido-enable-flex-matching t))
(while (progn
(imenu--cleanup)
(setq imenu--index-alist nil)
(prelude-ido-goto-symbol (imenu--make-index-alist))
(setq selected-symbol
(ido-completing-read "Symbol? " symbol-names))
(string= (car imenu--rescan-item) selected-symbol)))
(unless (and (boundp 'mark-active) mark-active)
(push-mark nil t nil))
(setq position (cdr (assoc selected-symbol name-and-pos)))
(cond
((overlayp position)
(goto-char (overlay-start position)))
(t
(goto-char position)))))
((listp symbol-list)
(dolist (symbol symbol-list)
(let (name position)
(cond
((and (listp symbol) (imenu--subalist-p symbol))
(prelude-ido-goto-symbol symbol))
((listp symbol)
(setq name (car symbol))
(setq position (cdr symbol)))
((stringp symbol)
(setq name symbol)
(setq position
(get-text-property 1 'org-imenu-marker symbol))))
(unless (or (null position) (null name)
(string= (car imenu--rescan-item) name))
(add-to-list 'symbol-names name)
(add-to-list 'name-and-pos (cons name position))))))))
;; Jump to a definition in the current file. (This is awesome.)
(global-set-key (kbd "M-i") 'prelude-ido-goto-symbol)
(require 'saveplace)
(setq save-place-file (in-emacs-dir "saveplace"))
(setq-default save-place t)
(global-set-key "\C-xt" 'eshell)
(setq-default indent-tabs-mode nil)
(setq tab-width 4)
(global-set-key [f5] 'whitespace-mode)
(add-hook 'before-save-hook 'whitespace-cleanup)
(add-hook 'makefile-mode-hook
(lambda ()
(whitespace-mode t)))
;; http://xahlee.org/emacs/whitespace-mode.html
(setq whitespace-display-mappings
'((space-mark 32 [183] [46]) ; normal space, ·
(space-mark 160 [164] [95])
(space-mark 2208 [2212] [95])
(space-mark 2336 [2340] [95])
(space-mark 3616 [3620] [95])
(space-mark 3872 [3876] [95])
(newline-mark 10 [182 10]) ; newlne, ¶
(tab-mark 9 [9655 9] [92 9]) ; tab, ▷
))
(global-set-key (kbd "S-C-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "S-C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "S-C-<down>") 'shrink-window)
(global-set-key (kbd "S-C-<up>") 'enlarge-window)
(defun cwm-auto-fill-comments ()
(setq comment-auto-fill-only-comments t)
(auto-fill-mode))
brew install aspell --with-lang-en
(defun cwm-flyspell-comments ()
(flyspell-prog-mode))
I’m going to try replacing Emacs’ built-in file finder with Helm’s.
(global-set-key (kbd "C-x C-f") 'helm-find-files)
This is from helm-ls-git. Another fun thing is C-]
, which toggles
full paths on and off.
(global-set-key (kbd "C-x C-d") 'helm-browse-project)
This sets up Helm in the M-x
prompt! SQUEE!
(global-set-key (kbd "M-x") 'helm-M-x)
Holy crap, this is a much better way to interact with the kill ring!
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
Waaaaay better way to interact with currently-open buffers!
(global-set-key (kbd "C-x b") 'helm-mini)
Inspired by Xah Lee’s work at
http://ergoemacs.org/emacs/elisp_datetime.html, along with the
source code to calendar-day-of-year-string
(defun cwm-insert-date ()
"Insert current date string"
(interactive)
(when (use-region-p)
(delete-region (region-beginning)
(region-end)))
(let* ((today (calendar-current-date))
(year (calendar-extract-year today))
(month (calendar-extract-month today))
(date (calendar-extract-day today))
(day (calendar-day-number today))
(day-name (calendar-day-name today))
(eoy (list 12 31 year))
(num-days (calendar-day-number eoy))
(remaining (- (calendar-day-number eoy) day)))
(insert (format "%d-%02d-%02d, %s; Day %d of %d (%d remaining in %d)"
year month date day-name day num-days remaining year))))
(defun cwm-today ()
"Insert current date string"
(interactive)
(when (use-region-p)
(delete-region (region-beginning)
(region-end)))
(insert (format-time-string "%Y-%m-%d")))
(global-set-key (kbd "<f6>") 'cwm-insert-date)
(global-set-key (kbd "C-<f6>") 'cwm-today)
Adapted from a reply to an org-mode mailing list post of mine from 4 years ago (which I forgot I had even posted!)
Intended to be used as an org-mode sexp recurring date entry
(e.g., SCHEDULED: <%%(cwm-work-payday date>
)
(defun cwm-work-payday (date)
"Returns TRUE if DATE is one of my bi-monthly paydays: the
15th (or nearest preceeding workday) and the last workday of the
month. This doesn't take into account company holidays"
(let* ((dayname (calendar-day-of-week date))
(is-weekday (memq dayname '(1 2 3 4 5)))
(is-friday (= dayname 5))
(day (calendar-extract-day date))
(month (calendar-extract-month date))
(year (calendar-extract-year date))
(lastday (calendar-last-day-of-month month year))
(is-last-day (= day lastday))
(last-two-days-before-last-day (list (- lastday 2) (- lastday 1))))
(or (and (= day 15) is-weekday)
(and (memq day '(13 14)) is-friday)
(and is-last-day is-weekday)
(and (memq day last-two-days-before-last-day) is-friday))))
Based (sort of) on http://stackoverflow.com/a/7400476
This allows you to add a function as a hook to multiple modes at once. It’s handy for setting up, say, all your programming modes with flyspell and autofill enabled in comment sections.
(defun cwm-add-to-hooks (function modes)
"Adds FUNCTION to the hooks of each one of MODES"
(mapc (lambda (mode)
(add-hook (intern (concat (symbol-name mode) "-hook"))
function))
modes))
(setq erlang-root-dir "/Users/cm/src/erlang/otp_src_R16B03")
;; (setq erlang-root-dir (getenv "ERL_TOP"))
The rest of this configuration is taken from the Erlang documentation.
(add-to-list 'load-path (concat erlang-root-dir "/lib/tools/emacs"))
(add-to-list 'exec-path (concat erlang-root-dir "/bin"))
(add-to-list 'auto-mode-alist '("\\.erl?$" . erlang-mode))
(add-to-list 'auto-mode-alist '("\\.hrl?$" . erlang-mode))
(require 'erlang-start)
;; (require 'erlang-flymake)
(global-set-key "\C-cs" 'slime-selector)
Steve Purcell made this snazzy add-on for AutoComplete to use SLIME symbols.
(load-vendor-package "ac-slime")
(require 'ac-slime)
(add-hook 'slime-mode-hook 'set-up-slime-ac)
(add-hook 'slime-repl-mode-hook 'set-up-slime-ac)
It’s nice to have Paredit in Emacs Lisp, no?
(add-hook 'emacs-lisp-mode-hook
'enable-paredit-mode)
(require 'clojure-test-mode)
(require 'clojurescript-mode)
(require 'durendal)
(add-hook 'clojure-mode-hook 'durendal-enable-auto-compile)
(add-hook 'slime-repl-mode-hook 'durendal-slime-repl-paredit)
(add-hook 'sldb-mode-hook 'durendal-dim-sldb-font-lock)
;; (add-hook 'slime-compilation-finished-hook 'durendal-hide-successful-compile)
Make it pretty.
(add-hook 'slime-repl-mode-hook
'clojure-mode-font-lock-setup)
align-cljlet is a neat little package that allows you to neatly align entries in Clojure bindings and literal hashes.
(load-vendor-package "align-cljlet")
(require 'align-cljlet)
(define-key clojure-mode-map (kbd "C-c C-c a") 'align-cljlet)
Instructions for running Petite Chez Scheme through Emacs from Indiana University (and they should know!).
(I’m using Petite Chez Scheme, because that’s what Dan Friedman and William Byrd used at Clojure Conj, 2011; if it’s good enough for them, it’s good enough for me.)
(autoload 'scheme-mode "cmuscheme"
"Major mode for Scheme." t)
(autoload 'run-scheme "cmuscheme"
"Switch to interactive Scheme buffer." t)
(add-to-list 'auto-mode-alist
'("\\.ss" . scheme-mode)
'("\\.scm" . scheme-mode))
Make Emacs invoke Petite Chez Scheme when running M-x run-scheme
(assumes petite
is on your path):
(custom-set-variables '(scheme-program-name "petite"))
Add some special indentation rules for Kanren / miniKanren function calls.
(put 'fresh 'scheme-indent-function 1)
(put 'run 'scheme-indent-function 2)
Can’t forget Paredit!
(add-hook 'scheme-mode-hook
'enable-paredit-mode)
(setq my-programming-modes
'(ruby-mode
erlang-mode))
(cwm-add-to-hooks 'cwm-flyspell-comments
my-programming-modes)
(cwm-add-to-hooks 'cwm-auto-fill-comments
my-programming-modes)
(require 'org-mobile)
(require 'org-habit)
(defun org-file (filename-without-extension)
(concat org-directory "/" filename-without-extension ".org"))
;; Stole this next bit from the INFO pages
(defun org-summary-todo (n-done n-not-done)
"Switch entry to DONE when all subentries are done, to TODO otherwise."
(let (org-log-done org-log-states) ; turn off logging
(org-todo (if (= n-not-done 0) "DONE" "TODO"))))
(add-hook 'org-mode-hook 'turn-on-visual-line-mode)
(add-hook 'org-mode-hook 'turn-on-flyspell 'append)
(add-hook 'org-mode-hook (lambda ()
(auto-fill-mode 1)))
(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
(global-set-key "\C-ca" 'org-agenda)
(global-set-key "\C-cb" 'org-iswitchb)
(global-set-key "\C-cc" 'org-capture)
(global-set-key "\C-cl" 'org-store-link)
(global-set-key (kbd "<f9>") 'org-mobile-push)
(global-set-key (kbd "S-<f9>") 'org-mobile-pull)
(global-set-key (kbd "<f11>") 'org-agenda-clock-in)
(global-set-key (kbd "<f12>") 'org-agenda-clock-out)
(setq org-blank-before-new-entry nil
org-directory "~/Dropbox/org"
org-mobile-files `(,org-directory)
org-mobile-directory "~/Dropbox/MobileOrg"
org-mobile-inbox-for-pull (org-file "from-inbox")
org-agenda-files `(,org-directory)
org-agenda-span 'day
org-agenda-skip-deadline-if-done t
org-agenda-skip-scheduled-if-done t
org-agenda-skip-scheduled-if-deadline-is-shown 'not-today
org-agenda-include-diary nil
org-agenda-log-mode-items '(closed clock)
org-agenda-custom-commands '(("p" . "Priorities")
("pa" "A items" tags-todo "+PRIORITY=\"A\""
((org-agenda-todo-ignore-scheduled 'future)
(org-agenda-tags-todo-honor-ignore-options t)))
("pb" "B items" tags-todo "+PRIORITY=\"B\""
((org-agenda-todo-ignore-scheduled 'future)
(org-agenda-tags-todo-honor-ignore-options t)))
("pc" "C items" tags-todo "+PRIORITY=\"C\""
((org-agenda-todo-ignore-scheduled 'future)
(org-agenda-tags-todo-honor-ignore-options t)))
("w" "Things I'm Waiting On" todo "WAITING")
("e" "Errands" tags-todo "errands|shopping"
((org-agenda-todo-ignore-scheduled 'future)
(org-agenda-tags-todo-honor-ignore-options t)))
("r" "Refile" tags "+REFILE")
("z" "By Date"
((agenda "Dead" ((org-agenda-entry-types '(:deadline))
(org-agenda-sorting-strategy '(priority-down category-keep))))
(agenda "Do" ((org-agenda-entry-types '(:scheduled))
(org-agenda-sorting-strategy '(priority-down category-keep))))))
("f" "Financial Work" agenda ""
((org-agenda-files `(,(org-file "financial")))))
("W" . "Work Projects")
("We" "Work" agenda ""
((org-agenda-files `(,(org-file "opscode")))
(org-agenda-sorting-strategy '(priority-down effort-down)))))
org-default-notes-file (org-file "inbox")
org-capture-templates '(("s" "Shopping")
("sg" "Groceries" entry
(file+headline (org-file "shopping") "Groceries")
"* TODO %? %^G\n")
("ss" "General Shopping" entry
(file+headline (org-file "shopping") "Other Things To Buy")
"* TODO %? %^G\n")
("t" "General TODO" entry
(file org-default-notes-file)
"* TODO %?\n%U\n%a" :clock-in t :clock-resume t)
("w" "Work Tasks" entry
(file+headline (org-file "opscode") "Daily Catch-All")
"* TODO %?"))
org-enforce-todo-dependencies t
org-todo-keywords '((sequence "TODO(t)"
"STARTED(s!)"
"WAITING(w@/!)"
"APPT(a)"
"|"
"DONE(d!)"
"CANCELLED(c@)"
"DEFERRED(f@)"))
org-treat-S-cursor-todo-selection-as-state-change nil
org-use-fast-todo-selection t
org-use-property-inheritance t
org-refile-use-outline-path 'file
org-refile-allow-creating-parent-nodes 'confirm
org-refile-targets '((org-agenda-files . (:maxlevel . 5))
(nil . (:maxlevel . 5)))
org-clock-out-remove-zero-time-clocks t
org-clock-persist t
org-completion-use-ido t
org-deadline-warning-days 3
org-hide-leading-stars t
org-log-done 'note
org-log-into-drawer t
org-outline-path-complete-in-steps t
org-hierarchical-todo-statistics nil
org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-window-setup 'current-window
org-use-sub-superscripts '{}
org-habit-graph-column 60)
(org-clock-persistence-insinuate)
(defun cwm-work-tasks-done-last-workday ()
"Produces an org agenda tags view list of the work tasks
completed on the last work day (i.e., yesterday, or last Friday
if today is Monday or Sunday). Good for daily stand-up meetings."
(interactive)
(let* ((day-of-week (calendar-day-of-week (calendar-current-date)))
(start-day (calendar-current-date (cond ((= day-of-week 1) -3) ;; if Monday, go back 3 days to Friday
((= day-of-week 0) -2) ;; if Sunday, go back 2 days to Friday
(t -1)))) ;; otherwise, use yesterday
(end-day (calendar-current-date (cond ((= day-of-week 1) -2) ;; if Monday, go back 2 days to Saturday
((= day-of-week 0) -1) ;; if Sunday, go back 1 day to Saturday
(t 0))))) ;; otherwise, use today
(org-tags-view nil
(concat "CATEGORY=\"work\"+TODO=\"DONE\""
(format "+CLOSED>=\"[%d-%02d-%02d]\""
(calendar-extract-year start-day)
(calendar-extract-month start-day)
(calendar-extract-day start-day))
(format "+CLOSED<=\"[%d-%02d-%02d]\""
(calendar-extract-year end-day)
(calendar-extract-month end-day)
(calendar-extract-day end-day))))))
(org-babel-do-load-languages
'org-babel-load-languages
'((clojure . t)
(sh . t)
(dot . t)
(js . t)))
Jump to files with a simple C-x r j <register>
.
(set-register ?i `(file . ,(in-emacs-dir "emacs-init.org")))
(set-register ?z `(file . "~/.zshrc"))
(set-register ?w `(file . ,(in-org-dir "work_log.org")))
(set-register ?t `(file . ,(in-org-dir "todo.org")))
(set-register ?d `(file . ,(in-org-dir "daily.org")))