Configure package sources
Add repositories we'll load packages from. I prefer to live on the bleeding edge so have only enabled melpa. Setting
nil prevents a second package load and slightly improves startup time.
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (setq package-enable-at-startup nil)
use-package is not installed, install it.
(unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package))
Set custom settings to load in own file
This stops emacs adding customised settings to
init.el. I try to avoid using customize anyway, preferring programmatic control of variables. Creating it as a temporary file effectively disables it (i.e. any changes are session local).
(setq custom-file (make-temp-file "emacs-custom"))
Add custom packages to load path
By default Emacs only includes files directly under
~/.emacs.d/), so we need to add any folders containing custom packages.
I put my scripts under
~/dotfiles/lisp/ and symlink it with
ln -s ~/dotfiles/lisp ~/.emacs.d/lisp.
(add-to-list 'load-path "~/.emacs.d/lisp/")
Don't display the help screen on startup.
(setq inhibit-startup-screen t)
On I use ⌘ as
meta and prefer ⌥ to do nothing so I can still insert special characters like easily.
(setq mac-command-modifier 'meta mac-option-modifier 'none)
I prefer lines to wrap.
Let's turn off unwanted window decoration.
(tool-bar-mode -1) (scroll-bar-mode -1)
I don't want the error bell.
(setq ring-bell-function 'ignore)
yes or no prompts shorter.
(defalias 'yes-or-no-p 'y-or-n-p)
A common frustration with new Emacs users is the
filename# files created. This centralises the backup files created as you edit.
(setq backup-directory-alist '(("." . "~/.emacs.d/backup")) backup-by-copying t ; Don't delink hardlinks version-control t ; Use version numbers on backups delete-old-versions t ; Automatically delete excess backups kept-new-versions 20 ; how many of the newest versions to keep kept-old-versions 5 ; and how many of the old )
crux has useful functions extracted from Emacs Prelude. Set
C-a to move to the first non-whitespace character on a line, and then to toggle between that and the beginning of the line.
(use-package crux :ensure t :bind (("C-a" . crux-move-beginning-of-line)))
Key chords let us bind functions to sequential key presses like
jj. It makes evil mode being turned off much more palatable.
(use-package use-package-chords :ensure t :config (key-chord-mode 1))
We bind individual mode chords via
use-package but some globals are useful like
JJ to jump to the previous buffer.
(defun jc/switch-to-previous-buffer () "Switch to previously open buffer. Repeated invocations toggle between the two most recently open buffers." (interactive) (switch-to-buffer (other-buffer (current-buffer) 1))) (key-chord-define-global "JJ" 'jc/switch-to-previous-buffer)
smart M-x suggests
M-x commands based on recency and frequency. I don't tend to use it directly but
counsel uses it to order suggestions.
(use-package smex :ensure t)
ivy is a generic completion framework which uses the minibuffer. Turning on
ivy-mode enables replacement of lots of built in
(use-package ivy :ensure t :diminish ivy-mode :config (ivy-mode t))
ivy starts filters with
^. I don't normally want that and can easily type it manually when I do.
(setq ivy-initial-inputs-alist nil)
counsel is a collection of
ivy enhanced versions of common Emacs commands. I haven't bound much as
ivy-mode takes care of most things.
(use-package counsel :ensure t :bind (("M-x" . counsel-M-x)) :chords (("yy" . counsel-yank-pop)))
swiper is an
ivy enhanced version of isearch.
(use-package swiper :ensure t :bind (("M-s" . swiper)))
hydra presents menus for
(use-package ivy-hydra :ensure t)
Suggest next key
Suggest next keys to me based on currently entered key combination.
(use-package which-key :ensure t :diminish which-key-mode :config (add-hook 'after-init-hook 'which-key-mode))
undo-tree visualises undo history as a tree for easy navigation.
(use-package undo-tree :ensure t :chords (("uu" . undo-tree-visualize)) :diminish undo-tree-mode)
One of the most important features of an advanced editor is quick text navigation.
avy let's us jump to any character or line quickly.
(use-package avy :ensure t :chords (("jj" . avy-goto-char-2) ("jl" . avy-goto-line)))
ace-window lets us navigate between windows in the same way as
avy. Once activated it has useful sub-modes like
x to switch into window deletion mode.
(use-package ace-window :ensure t :chords ("jk" . ace-window) :config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))
expand-region expands the region around the cursor semantically depending on mode. Hard to describe but a killer feature.
(use-package expand-region :ensure t :bind ("C-=" . er/expand-region))
I don't use this a whole lot, preferring to navigate via searches such as
counsel-find-file, but it's occasionally useful to have a file tree.
(use-package neotree :ensure t :config (global-set-key (kbd "C-c t") 'neotree-toggle))
When I open the tree try to jump to current file.
(setq neo-smart-open t)
Use a simple theme for the file tree.
(setq neo-theme 'arrow)
I'm trying out solarized. Not sure I'll be able to get used to a light theme, but worth a try.
(use-package solarized-theme :ensure t :config (setq solarized-emphasize-indicators nil))
(load-theme 'solarized-light t)
Set a nice font.
(set-frame-font "FuraCode Nerd Font 12" nil t)
Set a preferred unicode font.
(set-fontset-font t 'unicode "STIXGeneral" nil 'prepend)
Display pretty symbols for things like lambda.
(setq prettify-symbols-unprettify-at-point 'right-edge) (global-prettify-symbols-mode 0) (add-hook 'python-mode-hook (lambda () (mapc (lambda (pair) (push pair prettify-symbols-alist)) '(("def" . "𝒇") ("class" . "𝑪") ("and" . "∧") ("or" . "∨") ("not" . "￢") ("in" . "∈") ("not in" . "∉") ("return" . "⟼") ("yield" . "⟻") ("for" . "∀") ("!=" . "≠") ("==" . "＝") (">=" . "≥") ("<=" . "≤") ("" . "⃞") ("=" . "≝")))))
Powerline is a port from vim, and improves the modeline. Without specifying
powerline-default-separator the separators don't show correctly for me.
(use-package powerline :ensure t :config (setq powerline-default-separator 'utf-8))
Add emoji support. This is useful when working with html.
(use-package emojify :ensure t)
Sometimes it helps to focus on the thing currently under the cursor. This turns off syntax highlighting for everything but the current thing. It's useful sometimes but a bit buggy in certain modes. I wonder if I could improve the config / find a better alternative?
(use-package focus :ensure t)
Sometimes I like to use a nyan cat to indicate progress through the buffer.
(use-package nyan-mode :ensure t)
Highlight the current line.
Programming specific interface improvements
When programming I like my editor to try to help me with keeping parentheses balanced.
(use-package smartparens :ensure t :diminish smartparens-mode :config (add-hook 'prog-mode-hook 'smartparens-mode))
Highlight parens etc. for improved readability.
(use-package rainbow-delimiters :ensure t :config (add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
Highlight strings which represent colours.
(use-package rainbow-mode :ensure t :config (add-hook 'prog-mode-hook 'rainbow-mode))
Keep things indented correctly for me.
(use-package aggressive-indent :ensure t)
Expand parentheses for me.
(add-hook 'prog-mode-hook 'electric-pair-mode)
Smart dash guesses _ vs - depending on context.
(use-package smart-dash :ensure t :config (add-hook 'python-mode-hook 'smart-dash-mode))
Projectile handles folders which are in version control.
(use-package projectile :ensure t :config (projectile-mode))
Tell projectile to integrate with
ivy for completion.
(setq projectile-completion-system 'ivy)
Add some extra completion options via integration with
counsel. In particular this enables
C-c p SPC for smart buffer / file search, and
C-c p s s for search via
There is no function for projectile-grep, but we could use
counsel-git-grep which is similar. Should I bind that to
C-c p s g?
(use-package counsel-projectile :ensure t :config (add-hook 'after-init-hook 'counsel-projectile-on))
fzf is a fuzzy file finder which is very quick.
(use-package fzf :ensure t)
By default Emacs doesn't read from the same environment variables set in your terminal. This package fixes that.
(use-package exec-path-from-shell :ensure t :config (exec-path-from-shell-initialize))
Jump to source
Individual language packages often support IDE features like jump to source, but
dumb-jump attempts to support many languages by simple searching. It's quite effective even with dynamic libraries like JS and Python.
(use-package dumb-jump :ensure t :diminish dumb-jump-mode :bind (("C-M-g" . dumb-jump-go) ("C-M-p" . dumb-jump-back) ("C-M-q" . dumb-jump-quick-look)))
Magit is an awesome interface to git. Summon it with `C-x g`.
(use-package magit :ensure t :bind ("C-x g" . magit-status))
Display line changes in gutter based on git history. Enable it everywhere.
(use-package git-gutter :ensure t :config (global-git-gutter-mode 't) :diminish git-gutter-mode)
TimeMachine lets us step through the history of a file as recorded in git.
(use-package git-timemachine :ensure t)
Flycheck is a general syntax highlighting framework which other packages hook into. It's an improvment on the built in
Setup is pretty simple - we just enable globally and turn on a custom eslint function, and also add a custom checker for proselint.
(use-package flycheck :ensure t :config (add-hook 'after-init-hook 'global-flycheck-mode) (add-hook 'flycheck-mode-hook 'jc/use-eslint-from-node-modules) (add-to-list 'flycheck-checkers 'proselint))
Proselint is a syntax checker for English language. This defines a custom checker which will run in texty modes.
Proselint is an external program, install it with
pip install proselint for this to work.
(flycheck-define-checker proselint "A linter for prose." :command ("proselint" source-inplace) :error-patterns ((warning line-start (file-name) ":" line ":" column ": " (id (one-or-more (not (any " ")))) (message (one-or-more not-newline) (zero-or-more "\n" (any " ") (one-or-more not-newline))) line-end)) :modes (text-mode markdown-mode gfm-mode org-mode))
Company mode provides good autocomplete options. Perhaps I should add company-quickhelp for documentation (https://github.com/expez/company-quickhelp)?
It would also be good to improve integration with yasnippet as I don't feel I'm making the best use there.
(use-package company :ensure t :diminish :config (add-hook 'after-init-hook 'global-company-mode) (setq company-idle-delay t) (use-package company-go :ensure t :config (add-to-list 'company-backends 'company-go)) (use-package company-anaconda :ensure t :config (add-to-list 'company-backends 'company-anaconda)))
Unlike autocomplete which suggests words / symbols, snippets are pre-prepared templates which you fill in.
I'm using a community library (
[[https://github.com/AndreaCrotti/yasnippet-snippets]]) with lots of ready made options, and have my own directory of custom snippets I've added. Not sure if I should unify these by forking
Type the shortcut and press
TAB to complete, or
M-/ to autosuggest a snippet.
(use-package yasnippet :ensure t :diminish yas-minor-mode :config (add-to-list 'yas-snippet-dirs "~/.emacs.d/yasnippet-snippets") (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets") (yas-global-mode) (global-set-key (kbd "M-/") 'company-yasnippet))
In JS indent to 2 spaces.
(setq-default js-indent-level 2)
JS2 mode improves on the built in JS mode.
(use-package js2-mode :ensure t :mode "\\.js\\'" :config (setq-default js2-ignored-warnings '("msg.extra.trailing.comma")))
js2-refactor supports some useful refactoring options and builds on top of
(use-package js2-refactor :ensure t :config (js2r-add-keybindings-with-prefix "C-c C-m") (add-hook 'js2-mode-hook 'js2-refactor-mode))
RJSX mode makes JSX work well.
(use-package rjsx-mode :ensure t)
Prettier-js autoformats JS code - much like `gofmt` - and we hook it into JS2 and RJSX modes.
(use-package prettier-js :ensure t :config (setq prettier-js-args '( "--trailing-comma" "es5" "--single-quote" "true" "--print-width" "100" )) (add-hook 'js2-mode-hook 'prettier-js-mode) (add-hook 'rjsx-mode-hook 'prettier-js-mode))
Sometimes it's useful to use the local eslint provided by a project's node_modules directory. We call this function from a flycheck hook to enable it automatically.
Web mode handles html/css/js.
(use-package web-mode :ensure t)
Markdown support isn't built into Emacs, add it with
(use-package markdown-mode :ensure t :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :init (setq markdown-command "multimarkdown"))
Go-mode provides basic language support, we call
gofmt on each save to keep code tidy, use eldoc to display documentation and add guru / doctor for IDE functionality.
(use-package go-mode :ensure t :config (add-hook 'before-save-hook 'gofmt-before-save) (use-package go-eldoc :ensure t :config (add-hook 'go-mode-hook 'go-eldoc-setup)) (use-package godoctor :ensure t) (use-package go-guru :ensure t))
Go guru needs a scope to look at, this function sets it to the current package.
(defun jc/go-guru-set-current-package-as-main () "GoGuru requires the scope to be set to a go package which contains a main, this function will make the current package the active go guru scope, assuming it contains a main" (interactive) (let* ((filename (buffer-file-name)) (gopath-src-path (concat (file-name-as-directory (go-guess-gopath)) "src")) (relative-package-path (directory-file-name (file-name-directory (file-relative-name filename gopath-src-path))))) (setq go-guru-scope relative-package-path)))
Install haskell mode.
(use-package haskell-mode :ensure t)
Emacs handles python quite well, but we can improve things with anaconda mode.
(use-package anaconda-mode :ensure t :config (add-hook 'python-mode-hook 'anaconda-mode) (add-hook 'python-mode-hook 'anaconda-eldoc-mode))
Sometimes I use kivy.
(use-package kivy-mode :ensure t :mode ("\\.kv\\'" . kivy-mode))
Elixir highlighting is not built into emacs at present. Elixir-mode gives all the usual niceties, and alchemist improves interaction with tools like
(use-package elixir-mode :ensure t :config (use-package alchemist :ensure t))
Cucumber (gherkin) is a syntax for specifying behaviour driven development tests.
(use-package feature-mode :ensure t)
Rebol / Red
Red is an updated open source implementation of Rebol.
(use-package idris-mode :ensure t)
I should comment on these more...
(setq org-startup-indented 'f) (setq org-directory "~/org") (setq org-special-ctrl-a/e 't) (setq org-default-notes-file (concat org-directory "/notes.org")) (define-key global-map "\C-cc" 'org-capture) (setq org-mobile-directory "~/Dropbox/Apps/MobileOrg") (setq org-src-fontify-natively 't) (setq org-src-tab-acts-natively t)
Improve the display of bullet points.
(use-package org-bullets :ensure t :config (setq org-bullets-bullet-list '("∙")) (add-hook 'org-mode-hook 'org-bullets-mode))
(let* ((variable-tuple (cond ((x-list-fonts "Source Sans Pro") '(:font "Source Sans Pro")) ((x-list-fonts "Lucida Grande") '(:font "Lucida Grande")) ((x-list-fonts "Verdana") '(:font "Verdana")) ((x-family-fonts "Sans Serif") '(:family "Sans Serif")) (nil (warn "Cannot find a Sans Serif Font. Install Source Sans Pro.")))) (base-font-color (face-foreground 'default nil 'default)) (headline `(:inherit default :weight normal :foreground ,base-font-color))) (custom-theme-set-faces 'user `(org-level-8 ((t (,@headline ,@variable-tuple)))) `(org-level-7 ((t (,@headline ,@variable-tuple)))) `(org-level-6 ((t (,@headline ,@variable-tuple)))) `(org-level-5 ((t (,@headline ,@variable-tuple)))) `(org-level-4 ((t (,@headline ,@variable-tuple)))) `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.33)))) `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.33)))) `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.33)))) `(org-document-title ((t (,@headline ,@variable-tuple :height 1.33 :underline nil))))))
Add bootstrap styled export.
(use-package ox-twbs :ensure t)
writegood-mode highlights bad word choices and has functions for calculating readability.
(use-package writegood-mode :ensure t :bind ("C-c g" . writegood-mode) :config (add-to-list 'writegood-weasel-words "actionable"))
w3m is a terminal based browser. Emacs now has
eww built in, but I prefer
w3m. It needs to be installed separately, e.g. with
brew install w3m.
There's an emacs package to interface with it.
(use-package w3m :ensure t)
notmuch is a fast mail client. It needs to be installed externally, e.g. with
brew install notmuch but can then be used within emacs.
(use-package notmuch :ensure t)
Sometimes I need to explore REST services. Why not Emacs?
(use-package restclient :ensure t)