This is my configuration file. It can be loaded by Emacs via org-babel.
The contents of my ~/.emacs/init.el
simplify to this, which loads it:
(add-hook 'after-init-hook
(lambda ()
(org-babel-load-file
(expand-file-name "mwestbom.org" user-emacs-directory))))
One can evaluate individual blocks of this file by putting (point)
on them
and calling org-edit-special
, which is bound by default to C-c \'
Then M-x eval-buffer
to evaluate them.
Now we’ll enable John Wiegley’s phenomenal use-package library:
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(require 'use-package)
Going to move away from customize eventually, but until then, let’s use the customizations I’ve got:
(setq custom-file
(expand-file-name "customizations.el" user-emacs-directory))
(load custom-file)
Swap super and meta for macs. This retains option being alt as in the rest of the OS.
(setq mac-command-modifier 'super
mac-option-modifier 'meta)
Seriously.
(blink-cursor-mode 0)
Emacs comes with a toolbar. It’s redundant.
(tool-bar-mode -1)
Let’s add the golden ratio addon to allow for automatically resizing windows.
(use-package golden-ratio
:ensure golden-ratio
:commands golden-ratio)
By default, files with the same name but in different folders aren’t well distinguished. Uniquify, built into Emacs, solves this.
By default, Uniquify names buffers like this:
- post.js<1>
- post.js<2>
Let’s name them like this:
- app/models/post.js
- app/controllers/post.js
(setq uniquify-buffer-name-style 'forward)
Let’s enable guide-key. This tells you what possible bindings are available based on what you’ve already pressed.
(use-package guide-key-tip
:ensure t
:diminish guide-key-mode
:init
(progn
(setq guide-key/guide-key-sequence `("C-x"
"C-c"
"C-h")
guide-key/recursive-key-sequence-flag t
guide-key/text-scale-amount 0
guide-key-tip/enabled nil)
(guide-key-mode 1)))
(add-hook 'term-mode-hook
(lambda ()
(setq show-trailing-whitespace nil)))
(add-hook 'eshell-mode-hook
(lambda ()
(setq show-trailing-whitespace nil)))
;; Add line/column numbers to modeline
(line-number-mode t)
(column-number-mode t)
linum-mode
enables gutter line numbers. Disable it for specific modes.
From emacswiki
(require 'linum)
(defcustom linum-disabled-modes-list '(eshell-mode
wl-summary-mode
compilation-mode
org-mode
text-mode
dired-mode
doc-view-mode
image-mode)
"* List of modes disabled when global linum mode is on"
:type '(repeat (sexp :tag "Major mode"))
:tag " Major modes where linum is disabled"
:group 'linum)
(defcustom linum-disable-starred-buffers 't
"* Disable buffers that have stars in them like *Gnu Emacs*"
:type 'boolean
:group 'linum)
(defun linum-on ()
"* When linum is running globally, disable line numbers in modes
defined in `linum-disabled-modes-list'. Changed by linum-off.
Also turns off numbering in starred modes like *scratch*."
(unless (or (minibufferp)
(member major-mode linum-disabled-modes-list)
(string-match "*" (buffer-name))
(> (buffer-size) 3000000)) ;; Don't number huge files
(linum-mode 1)))
(provide 'linum-off)
y is just fine, thank you.
(fset 'yes-or-no-p 'y-or-n-p)
Base16 railscast.
(defun mcw/load-theme ()
(if (package-installed-p 'base16-theme)
(load-theme 'base16-railscasts)
(progn
(package-install 'base16-theme)
(mcw/load-theme))))
(mcw/load-theme)
(use-package multiple-cursors
:ensure multiple-cursors
:commands (mc/mark-next-like-this mc/mark-previous-like-this mc/mark-all-like-this)
:init
(progn
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)))
Helm is, in my opinion, the best minibuffer completion thing. Let’s stick it just about everywhere.
Also replace the standard M-x
with helm-M-x
Still further, we’ll replace C-x b
(switch-to-buffer) with
helm-mini, which is crazy smart
(use-package helm
:ensure t
:diminish helm-mode
:init
(progn
(require 'helm-config)
(global-set-key (kbd "M-x") 'helm-M-x)
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
(global-set-key (kbd "C-x b") 'helm-mini)
(helm-mode)))
Don’t need ido-mode. Disable it.
(ido-mode -1)
helm-descbinds is pretty great. C-h b
brings up a helm-powered
list of available bindings in the current mode.
(use-package helm-descbinds
:ensure helm-descbinds
:commands helm-descbinds
:config
(helm-descbinds-mode))
Turn on a whole mess of backup/save stuff. I’ll probably cut this out eventually.
(setq
backup-by-copying t
backup-directory-alist '(("." . "~/.emacs.d/saves"))
delete-old-versions -1
version-control t)
(let
((autosave-dir (expand-file-name "autosave" user-emacs-directory)))
(unless (file-exists-p autosave-dir)
(make-directory autosave-dir))
(setq auto-save-list-file-prefix (concat autosave-dir "/")
auto-save-file-name-transforms `((".*" ,autosave-dir t))))
(setq gc-cons-threshold 200000000)
The default modeline can get unwieldy, and go wider than the frame.
Add Bruce Connor’s smart-mode-line to make for a prettier and more manageable modeline
(use-package smart-mode-line
:ensure smart-mode-line
:init
(progn
(use-package smart-mode-line-powerline-theme
:ensure smart-mode-line-powerline-theme))
:config
(progn
(setq-default mode-line-format
'("%e"
mode-line-front-space
mode-line-mule-info
mode-line-client
mode-line-modified
mode-line-remote
mode-line-frame-identification
mode-line-buffer-identification
sml/pos-id-separator
mode-line-position
(vc-mode vc-mode)
sml/pre-modes-separator
mode-line-modes
mode-line-misc-info
mode-line-end-spaces))
(sml/setup)))
Undo tree is fabulous
(use-package undo-tree
:ensure undo-tree
:diminish undo-tree-mode
:init
(progn
(global-undo-tree-mode)
(setq undo-tree-auto-save-history t)))
(delete-selection-mode 1)
Stole these from Sacha Chua
(defun vsplit-last-buffer ()
(interactive)
(split-window-vertically)
(other-window 1 nil)
(switch-to-next-buffer))
(defun hsplit-last-buffer ()
(interactive)
(split-window-horizontally)
(other-window 1 nil)
(switch-to-next-buffer))
(global-set-key (kbd "C-x 2") 'vsplit-last-buffer)
(global-set-key (kbd "C-x 3") 'hsplit-last-buffer)
Winner mode adds an undo history to window configurations.
(use-package winner
:ensure winner
:init (winner-mode 1))
Enable integration with Ag. This must happen before Projectile
(use-package helm-ag
:ensure helm-ag)
Windmove beats using C-x o
to toggle through windows
Let’s switch the binding from Super
to Meta
though
(use-package windmove
:init (progn
(windmove-default-keybindings 'meta)))
Instead of C-a
moving to column 0, go to first non-whitespace
character. THEN go to column 0. And back again.
(defun smarter-move-beginning-of-line (arg)
"Move point back to indentation of beginning of line.
Move point to the first non-whitespace character on this line.
If point is already there, move to beginning of the line.
Effectively toggle between the first non-whitespace character and
the beginning of the line.
If ARG is not nil or 1, move forward ARG - 1 lines first.
If point reaches the beginning or end of the buffer, stop there."
(interactive "^p")
(setq arg (or arg 1))
;; Move lines first
(when (/= arg 1)
(let ((line-move-visual nil))
(forward (1- arg))))
(let ((orig-point (point)))
(back-to-indentation)
(when (= orig-point (point))
(move-beginning-of-line 1))))
;; remap C-a to `smarter-move-beginning-of-line`
(global-set-key [remap move-beginning-of-line]
'smarter-move-beginning-of-line)
Experiment with keybindings for visual expand
(use-package expand-region
:ensure expand-region
:bind ("C-=" . er/expand-region))
Haven’t built this into muscle memory yet.
(bind-key "C-x p" 'pop-to-mark-command)
(setq set-mark-command-repeat-pop t)
Switch to last buffer. Absolutely essential.
(defun mcw/switch-to-previous-buffer ()
"Switch to previously open buffer.
Repeated invocations toggle between the most recently open buffers."
(interactive)
(switch-to-buffer (other-buffer (current-buffer) 1)))
(bind-key "C-c b" 'mcw/switch-to-previous-buffer)
Projectile is a fantastic tool.
(use-package projectile
:ensure projectile
:diminish projectile-mode
:init
(progn
(setq projectile-keymap-prefix (kbd "C-c p"))
(projectile-global-mode)))
Also enable helm-projectile, which teaches projectile to use helm.
(use-package helm-projectile
:ensure helm-projectile
:config
(helm-projectile-on))
Just use the same window for the source buffer.
(setq org-src-window-setup 'current-window)
(setq org-use-speed-commands t)
Let’s try to set up org-jekyll
(use-package org-jekyll
:ensure org-jekyll)
(setq org-publish-mcw "~/code/mike-blog/publish")
(setq org-publish-mcw-blog "~/code/mike-blog/org")
(setq org-publish-project-alist
`("mcw-org"
:base-directory "~/code/mike-blog/org"
:recursive t
:base-extension "org"
:publishing-directory ,org-publish-mcw
:exclude "^blog"
:jekyll-sanitize-permalinks t
:publishing-function org-html-publish-to-html
:section-numbers nil
:headline-levels 4
:table-of-contents t
:auto-index nil
:auto-preamble nil
:body-only nil
:auto-postamble nil))
(add-to-list 'org-publish-project-alist
`("mcw-img"
:base-directory "~/code/mike-blog/org"
:recursive t
:exclude "^publish"
:base-extension "jpg\\|gif\\|png"
:publishing-directory ,org-publish-mcw
:publishing-function org-html-publish-attachment))
(add-to-list 'org-publish-project-alist
'("mcw" :components ("mcw-org" "mcw-img")))
(add-to-list 'org-publish-project-alist
'("mcw-blog"
:base-directory "~/code/mike-blog/org"
:recursive t
:base-extension "org"
:publishing-directory ,org-publish-mcw
:blog-publishing-directory ,org-publish-mcw-blog
:jekyll-sanitize-permalinks t
:publishing-function org-html-publish-to-html
:section-numbers nil
:headline-levels 4
:table-of-contents nil
:auto-index nil
:auto-preamble nil
:body-only t
:auto-postamble nil))
(use-package org-page
:ensure org-page
:config
(progn
(setq op/site-domain "file:///Users/mwestbom/code/org-blog/blog")
(setq op/repository-directory "~/code/org-blog")))
Don’t bother adding section numbers.
(setq org-export-with-section-numbers nil)
(setq org-html-include-timestamps nil)
(setq org-export-with-sub-superscripts nil)
How to style stuffs for export purposes
(defun mcw/get-org-htmlize-css-string ()
"Get CSS from org-html-htmlize-generate-css buffer"
(save-current-buffer
(org-html-htmlize-generate-css)
(let ((css-tag (buffer-string)))
(kill-buffer)
css-tag)))
(setq org-html-htmlize-output-type 'css)
(setq org-src-fontify-natively t)
Publish my config file.
(defun mcw/org-share-emacs ()
"Publish emacs config"
(interactive)
(setq org-html-doctype "html5")
(setq org-html-html5-fancy t)
(with-current-buffer (find-file "~/.emacs.d/mwestbom.org")
(save-restriction
(save-excursion
(widen)
(remove-hook 'prog-mode-hook 'rainbow-identifiers-mode)
(org-html-export-to-html)
(add-hook 'prog-mode-hook 'rainbow-identifiers-mode)))))
Emacs has so many fantastic get-related tools.
Magit is 90% of why I moved over to it in the first place.
(use-package magit
:commands magit-status
:load-path "site-lisp/magit"
:init (progn
(use-package dash
:ensure t)
(bind-key "C-x g" 'magit-status))
:config
(progn
(setq magit-diff-options '("-b"))))
Here’s a handy tool for working with gists. I don’t use it very often, but I enjoy it when I do.
(use-package gist
:ensure gist
:commands (gist-buffer gist-region gist-list))
Lets you flip back and forth through a file’s VC history
(use-package git-timemachine
:ensure git-timemachine)
Shows most recent commit message for line under mark
(use-package git-messenger
:ensure t
:bind (("C-x v p" . git-messenger:popup-message)))
Lots and lots of colors…
(use-package rainbow-identifiers
:ensure rainbow-delimiters
:config (progn
(add-hook 'prog-mode-hook 'rainbow-identifiers-mode)))
Individually color delimiters, to differentiate levels of nesting.
(use-package rainbow-delimiters
:ensure rainbow-delimiters
:config (progn
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)))
Loads and loads of useful snippets. The ability to add more snippets
(use-package yasnippet
:ensure yasnippet
:config
(progn
(add-to-list 'yas-snippet-dirs "~/.emacs.d/site-lisp/yasnippet-snippets")
(yas-global-mode 1)))
Bring in company mode for autocomplete
(use-package company
:ensure company
:diminish company-mode
:config
(add-hook 'prog-mode-hook 'company-mode))
Enables support for linting in a bunch of different languages.
(use-package flycheck
:ensure t
:diminish flycheck-mode
:init
(global-flycheck-mode))
Enable automatic matching of paired syntax tokens. This is brilliant.
(defun mcw/web-mode-is-code-context (id action context)
(when (and (eq action 'insert)
(not (or (get-text-property (point) 'part-side)
(get-text-property (point) 'block-side))))
t))
(use-package smartparens
:ensure smartparens
:diminish smartparens-mode
:config
(progn
(require 'smartparens-config)
(sp-local-pair 'web-mode "<" nil :when '(sp-web-mode-is-code-context))
(smartparens-global-strict-mode)
(smartparens-global-mode 1)))
Web mode is pretty great about handling mixed-mode files like HTML pages with javascript, or handlebars template pages.
Enable it for handlebars files.
;; From faq at http://web-mode.org/ for smartparens
(defun mcw/web-mode-hook ()
(setq web-mode-enable-auto-pairing nil))
(use-package web-mode
:ensure t
:mode ("\\.hbs\\'" . web-mode)
:init
(progn
(add-to-list 'auto-mode-alist '("\\.jsx\\'" . web-mode))
(add-hook 'web-mode-hook 'mcw/web-mode-hook)))
(use-package clojure-mode
:commands clojure-mode
:mode (("\\.clj\\'" . clojure-mode)
("\\.cljs\\'" . clojure-mode)))
(use-package cider
:ensure cider
:commands cider-jack-in
:bind ("C-c M-j" . cider-jack-in))
Replace standard ruby mode with enh-ruby-mode. I like its indentation engine better.
(use-package enh-ruby-mode
:ensure t
:diminish enh-ruby-mode
:commands enh-ruby-mode
:init
(progn
(setq enh-ruby-bounce-deep-indent t)
(add-to-list 'auto-mode-alist '("\\.rb$" . enh-ruby-mode))
(add-to-list 'interpreter-mode-alist '("ruby" . enh-ruby-mode))))
Run rspec from emacs. I love this so much.
Overwrite the default predicate method for rspec mode, because it doesn’t play nicely with rbenv
(use-package rspec-mode
:ensure rspec-mode
:diminish rspec-mode
:commands rspec-mode
:init
(progn
(add-hook 'enh-ruby-mode-hook 'rspec-mode))
:config
(progn
(setq rspec-command-options "--fail-fast --format documentation")
(defun rspec-spring-p ()
(and rspec-use-spring-when-possible
(let ((root (directory-file-name (rspec-project-root))))
(or
(file-exists-p (format "%s/tmp/spring/spring.pid" root))
(file-exists-p (format "%s/spring/%s.pid" temporary-file-directory (md5 root)))
(let ((path (or (getenv "XDG_RUNTIME_DIR") temporary-file-directory))
(ruby-version (getenv "RBENV_VERSION")))
(file-exists-p (format "%s/spring/%s.pid" path (md5 (concat ruby-version root)))))))))
(inf-ruby-switch-setup)))
(use-package rbenv
:ensure t
:commands rbenv-use-global
:init
(progn
(add-hook 'enh-ruby-mode-hook 'rbenv-use-global)))
Add projectile rails for rails-specific completions, finders, commands
(use-package projectile-rails
:ensure projectile-rails
:commands projectile-rails-on
:init
(add-hook 'projectile-mode-hook 'projectile-rails-on))
(use-package elixir-mode
:ensure elixir-mode)
Add the alchemist package for mix-related stuffs
(use-package alchemist
:ensure alchemist)
Enable markdown mode
(use-package markdown-mode
:ensure t
:mode ("\\.md\\'" . markdown-mode))
(use-package dockerfile-mode
:ensure t
:mode ("Dockerfile\\'" . dockerfile-mode))
js2-mode seems to have the best indentation/linting support.
(use-package js2-mode
:commands js2-mode
:ensure t
:init
(progn
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
(add-to-list 'interpreter-mode-alist (cons "node" 'js2-mode))))
(use-package less-css-mode
:commands less-css-mode
:ensure less-css-mode
:mode ("\\.less\\'" . less-css-mode))
(use-package yaml-mode
:ensure yaml-mode
:mode "\\.yml\\'")
multi-term adds some useful features, like running multiple terminal emulators, and a dedicated term buffer.
(use-package multi-term
:ensure multi-term
:bind ("<f5>" . multi-term-dedicated-toggle))