belak’s Emacs Config
This config has been cobbled together from quite a few places.
Most notably, smf’s dotfiles, dakrone’s dotfiles, Spacemacs, among other sources.
Platform Specific
Helper functions and OS-specific settings should go here. Each OS is kept in a separate block even though it could easily be a case statement because it’s easier to read.
(defun osx-p ()
"Check if a system is running OSX."
(eq system-type 'darwin))
(defun linux-p ()
"Check if a system is running Linux."
(eq system-type 'gnu/linux))Linux Specific
The only current Linux specific settings are relating to opening files. Because I assume xdg-open is configured properly, we can set the URL function to just call it so we always get the right browser.
(when (linux-p)
(setq browse-url-browser-function 'browse-url-xdg-open))OSX Specific
(when (osx-p)
(setq mac-command-modifier 'super
mac-option-modifier 'meta
mac-control-modifier 'control
insert-directory-program "/usr/local/bin/gls")
(let ((default-directory "/usr/local/share/emacs/site-lisp/"))
(normal-top-level-add-subdirs-to-load-path)))XXX: There’s a strange interaction of my init.el with emacs-mac which causes the maximize button to revert to the old “vertical” maximize. For whatever reason, calling toggle-frame-fullscreen after the frame is created fixes that, so we enter then exit fullscreen to fix the state.
(when (osx-p)
(add-hook 'after-make-window-system-frame-hooks
(lambda ()
(toggle-frame-fullscreen)
(toggle-frame-fullscreen))))Package Setup
Load package.el and do our best to make sure we don’t automatically load everything we have installed.
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("gnu" . "https://elpa.gnu.org/packages/")))
(setq package-enable-at-startup nil)
(package-initialize)Firstly, we disable as many warnings as we can while installing packages. Secondly, increasing the minimum prime bits size to something larger than the default settings stops all the GnuTLS warnings from showing up. This might not be the right place, but it needs to happen before we install packages.
(setq byte-compile-warnings nil
gnutls-min-prime-bits 4096)This block simply defines a few helpers. belak/ensure-refreshed will
run a refresh if the package list hasn’t been refreshed this
session. belak/package-ensure-installed will ensure the package list
has been refreshed and try to install the package if it hasn’t been
installed already.
(defvar belak/refreshed-package-list nil
"This will be t if the package list has been refreshed.")
(defun belak/ensure-refreshed ()
"Ensure the package list has been refreshed this startup."
(unless belak/refreshed-package-list
(package-refresh-contents)
(setq belak/refreshed-package-list t)))
(defun belak/package-ensure-installed (package)
"Install a missing PACKAGE if it isn't already."
(unless (package-installed-p package)
(package-install package)))Now that we have some helpers defined, we wrap package-install to make sure that the first install of each session will refresh the package list.
(advice-add 'package-install
:before
(lambda (&rest args)
(belak/ensure-refreshed)))Core Packages
Portions of this config depend on other components, so we load the common components here. The only things which should be here are packages which are needed for the organization of the rest of the file and stuff which needs to be loaded very early.
use-package (and general)
use-package is a wrapper around package loading which makes lots of
common operations easier. We install it as early as possible so we can
use it when installing everything else.
(belak/package-ensure-installed 'use-package)
(eval-when-compile
(defvar use-package-verbose t)
(require 'use-package))
(require 'diminish)
(require 'bind-key)Always attempt to install packages unless we specify otherwise.
(setq use-package-always-ensure t)We also load general here, as this integrates with use-package for
better key bind settings.
(belak/package-ensure-installed 'general)
(require 'general)page-break-lines
Display a line as opposed to ^L. This is early in the config file so most bootstrapped package logs will take advantage of this.
(use-package page-break-lines
:diminish page-break-lines-mode
:config (global-page-break-lines-mode 1))base16-theme
Because I maintain this package, I usually have it checked out to a directory, rather than dealing with installing the package from melpa. Because of this we need to do a little bit of acrobatics to make sure all the proper directories are in the proper load paths.
We load the theme as early as humanly possible so we’re not waiting for other packages to load before fixing the colors.
(defvar belak/base16-colors nil)
(use-package base16-theme
:ensure nil
:load-path "site-lisp/base16-theme"
:init
(add-to-list 'custom-theme-load-path "~/.emacs.d/site-lisp/base16-theme/build")
:config
(setq base16-theme-256-color-source "colors")
(load-theme 'base16-tomorrow-night t)
(setq belak/base16-colors base16-tomorrow-night-colors))company
company-mode is used as a completion system.
(use-package company
:diminish company-mode
:config
(defmacro belak/register-company-backend (hook backend)
`(add-hook ,hook (lambda ()
(set (make-local-variable 'company-backends) (list ,backend)))))
(setq company-tooltip-limit 20
company-idle-delay 0
company-echo-delay 0
company-minimum-prefix-length 1
company-selection-wrap-around t
company-show-numbers t
company-tooltip-align-annotations t)
(global-company-mode))evil-mode
There’s an evil-mode killswitch here because there are so many
packages which we would have to manually add :disabled t to
otherwise.
(defvar belak/evil-enabled nil "Set to nil to disable all evil related packages")evil-mode is a vim emulation layer for Emacs. It’s currently
disabled as I’ve switched back to Emacs keybinds.
Note that it is important to load this early because of how many packages actually use it.
(defvar belak/evil-leader "," "Leader key for most vim bindings.")
(use-package evil
:demand
:if belak/evil-enabled
:general
("C-'" 'evil-toggle-key)
:config
;; We need to do the evil setup for general here, because I disable
;; evil-mode fairly frequently.
(general-evil-setup)
(evil-mode 1)
(setq evil-echo-state nil
evil-vsplit-window-right t
evil-split-window-below t)
;; Set the cursor color based on the evil state
(setq evil-emacs-state-cursor `(,(plist-get belak/base16-colors :base0D) box)
evil-insert-state-cursor `(,(plist-get belak/base16-colors :base0D) bar)
evil-motion-state-cursor `(,(plist-get belak/base16-colors :base0E) box)
evil-normal-state-cursor `(,(plist-get belak/base16-colors :base0B) box)
evil-replace-state-cursor `(,(plist-get belak/base16-colors :base08) bar)
evil-visual-state-cursor `(,(plist-get belak/base16-colors :base09) box))
;; Evil selection shouldn't update the clipboard
(fset 'evil-visual-update-x-selection 'ignore)
;; For the operator state, the only thing we want to change is the
;; size. We can keep the same color.
(setq evil-operator-state-cursor 'evil-half-cursor))I really like C-a and C-e for beginning and end of the line, so
evil-rsi is included which tries to add back useful emacs bindings.
(use-package evil-rsi
:if belak/evil-enabled
:after evil-mode
:config (evil-rsi-mode))This is a port of tpope’s vim-surround which adds text objects for surrounding characters.
(use-package evil-surround
:if belak/evil-enabled
:after evil-mode
:config
(global-evil-surround-mode 1))flycheck
flycheck-mode is used for linters and catching compilation errors.
(use-package flycheck
:diminish flycheck-mode
:config
(defalias 'flycheck-show-error-at-point-soon 'flycheck-show-error-at-point)
(global-flycheck-mode))projectile
Project based navigation is pretty much the best thing ever.
(use-package projectile
:diminish projectile-mode
:config
(projectile-global-mode))spaceline
spaceline is a better modeline with simple config. It’s up here because it needs to be loaded before persistent-scratch and anzu.
(use-package spaceline
:demand
:config
(require 'spaceline-config)
(setq powerline-default-separator 'bar
spaceline-highlight-face-func 'spaceline-highlight-face-evil-state)
(spaceline-spacemacs-theme))Utils
init-frame-hooks is a simple package which handles hooks for after
the frame has been initialized and adds convenient hooks for after
console init and GUI init.
(use-package init-frame-hooks
:ensure nil
:load-path "lisp/")diminish-major-mode is a snippet from Achint Sandhu’s dotfiles.
(defmacro diminish-major-mode (mode new-name)
`(add-hook (intern (concat (symbol-name ,mode) "-hook"))
'(lambda () (setq mode-name ,new-name))))
;; Make the lisp modes a bit shorter
(diminish-major-mode 'lisp-interaction-mode "λ»")
(diminish-major-mode 'emacs-lisp-mode "Eλ")
(diminish-major-mode 'lisp-mode "λ")Development Packages
diff-hl
diff-hl uses the emacs vcs integration to display added/modified/removed lines. This uses my own hooks which add some conveniences depending on if we’re in a terminal or gui.
(use-package diff-hl
:config
(add-hook 'after-make-console-frame-hooks
(lambda ()
(global-diff-hl-mode 0)
(diff-hl-margin-mode 1)))
(add-hook 'after-make-window-system-frame-hooks
(lambda ()
(global-diff-hl-mode 1)
(diff-hl-margin-mode 0))))editorconfig
editorconfig is a simple way to share indentation settings between editors. Because I sometimes dabble in neovim and sublime, it’s nice to not have to re-do these settings at a project level between editors.
(use-package editorconfig
:diminish editorconfig-mode
:config
(editorconfig-mode 1))exec-shell-from-path
Grab important environment variables from the shell, the most important of which is PATH. We used to also grab GOPATH here, but newer releases of go (>= 1.8) it’s set to what I use.
(use-package exec-path-from-shell
:config
(exec-path-from-shell-initialize))magit
magit is an amazing tool for working with git inside emacs.
(use-package magit
:general
("M-g M-g" 'magit-status)
;;(when (fboundp 'evil-mode)
;; (general-nmap :prefix belak/evil-leader
;; "g" 'magit-status))
:config
;;(when (fboundp 'evil-mode)
;; (add-hook 'git-commit-mode-hook 'evil-insert-state))
(setq magit-push-current-set-remote-if-missing t
magit-completing-read-function 'magit-ido-completing-read))(use-package magit-filenotify
:if (linux-p)
:after magit
:config
(add-hook 'magit-status-mode-hook 'magit-filenotify-mode))yasnippet
yasnippet adds some useful tools to make reusable code snippets.
(use-package yasnippet
:diminish yas-minor-mode
:config
(setq yas-verbosity 0)
(yas-global-mode 1))Language Packages
This section is meant for non-web languages. TODO: I’d like to eventually make this my commonly used languages rather than non-web, but it’s not a high priority.
C/C++
irony-mode is a pretty solid dev environment for C/C++/ObjC, but we
also need to load up the additional company and flycheck modules.
(use-package irony
:config
(add-hook 'c++-mode-hook 'irony-mode)
(add-hook 'c-mode-hook 'irony-mode)
(add-hook 'objc-mode-hook 'irony-mode)
;; replace the `completion-at-point' and `complete-symbol' bindings
;; in irony-mode's buffers by irony-mode's function and run the
;; autosetup function
(defun my-irony-mode-hook ()
(subword-mode 1)
(define-key irony-mode-map [remap completion-at-point]
'irony-completion-at-point-async)
(define-key irony-mode-map [remap complete-symbol]
'irony-completion-at-point-async)
(irony-cdb-autosetup-compile-options))
(add-hook 'irony-mode-hook 'my-irony-mode-hook))(use-package company-irony
:after (irony company)
:config
(add-to-list 'company-backends 'company-irony))(use-package flycheck-irony
:after (irony flycheck-mode)
:config
(add-hook 'flycheck-mode-hook #'flycheck-irony-setup))This function decides whether .h file is C or C++ header, sets C++ by default because there’s more chance of there being a .h without a .cc than a .h without a .c (ie. for C++ template files)
This comes from http://stackoverflow.com/questions/3312114/how-to-tell-emacs-to-open-h-file-in-c-mode
(defun c-c++-header ()
"sets either c-mode or c++-mode, whichever is appropriate for
header"
(interactive)
(let ((c-file (concat (substring (buffer-file-name) 0 -1) "c")))
(if (file-exists-p c-file)
(c-mode)
(c++-mode))))
(add-to-list 'auto-mode-alist '("\\.h\\'" . c-c++-header))I much prefer the linux C style to the GNU style.
(setq c-default-style '((java-mode . "java")
(awk-mode . "awk")
(other . "linux")))CMake
(use-package cmake-mode
:mode
"CMakeLists.txt"
"\\.cmake\\'")Docker
(use-package dockerfile-mode
:mode "Dockerfile\(-.*\)?")HTML (web-mode)
web-mode is designed to handle HTML-ish templates.
(use-package web-mode
:mode
"\\.erb\\'"
"\\.html\\'"
"\\.jinja\\'"
"\\.mustache\\'"
:config
(setq web-mode-markup-indent-offset 2
web-mode-css-indent-offset 2
web-mode-code-indent-offset 2))
(use-package emmet-mode
:after web-mode
:config
(add-hook 'web-mode-hook 'emmet-mode))Javascript
js2-mode is a wrapper around js-mode which cleans it up and adds a bunch of features.
(use-package js2-mode
:mode "\\.js\\'"
:config
(setq js2-basic-offset 2)
(when (fboundp 'flycheck-mode)
(set-face-attribute 'js2-error nil
:inherit 'flycheck-error-list-error
:underline '(:color foreground-color :style wave))
(set-face-attribute 'js2-warning nil
:inherit 'flycheck-error-list-warning
:underline '(:color foreground-color :style wave))))tern is a js navigation package which extends js-mode.
(use-package tern
:after js2-mode
:diminish tern-mode
:config
(add-hook 'js-mode-hook (lambda () (tern-mode t))))
(use-package company-tern
:after (js2-mode tern company)
:config
(add-to-list 'company-backends 'company-tern)
(setq company-tern-property-marker ""))JSON
(use-package json-mode
:mode "\\.json\\'"
:config
(setq json-reformat:indent-width 2))Lisp
macrostep is a really useful way to debug macros by expanding them.
(use-package macrostep
:general
(:keymaps 'emacs-lisp-mode-map
"C-x e" 'macrostep-expand))go
(use-package go-mode
:mode "\\.go\\'"
;; TODO: Fix go-guru
;;:general
;;(:keymaps 'go-mode-map
;; "M-." 'go-guru-definition
;; "C-c o" 'go-guru-map)
:config
(setq gofmt-command "goimports")
(defun my-go-mode-hook ()
(add-hook 'before-save-hook 'gofmt-before-save nil t)
(subword-mode 1))
(add-hook 'go-mode-hook 'my-go-mode-hook))
(use-package company-go
:after (go-mode company)
:config
(setq company-go-show-annotation t)
(belak/register-company-backend 'go-mode-hook 'company-go))These are helper functions, initially taken from dominikh’s dotfiles.
(defun go-instrument-returns ()
"Add print statements before each return call.
Originally taken from https://github.com/dominikh/dotfiles/blob/master/emacs.d/go.el"
(interactive)
(save-excursion
(save-restriction
(let ((cnt 0))
(narrow-to-defun)
(beginning-of-defun)
(while (re-search-forward "^[[:space:]]+return")
(setq cnt (1+ cnt))
(beginning-of-line)
(open-line 1)
(funcall indent-line-function)
(insert (format "log.Println(\"return statement %d\") /* RETURN INSTRUMENT */" cnt))
(forward-line 2))))))
(defun go-deinstrument-returns ()
"Remove print statements added by `go-instrument-returns'.
Originally taken from https://github.com/dominikh/dotfiles/blob/master/emacs.d/go.el"
(interactive)
(save-excursion
(save-restriction
(narrow-to-defun)
(beginning-of-defun)
(while (re-search-forward "^.+/\\* RETURN INSTRUMENT \\*/\n" nil t)
(replace-match "" nil nil)))))Groovy
I really don’t want to, but I guess I have to for work.
(use-package groovy-mode
:mode "\\.groovy\\'")LESS
(use-package less-css-mode
:mode "\\.less\\'")Markdown
(use-package markdown-mode
:mode ("\\.md\\'" . gfm-mode))org
Make sure org mode is set up in a manner that doesn’t suck. Meaning, make code blocks act more like their native counterparts, enable fancy indenting and allow for shift select.
If the extra require looks hacky, that’s because it is. The :demand
makes sure the config runs because the package is already loaded to
run this config file. The :diminish keyword fails because
org-indent-mode does not exist by the time diminish is called.
(use-package org
:demand
:mode ("\\.org\\'" . org-mode)
:diminish org-indent-mode
:init
(require 'org-indent)
:config
(setq org-completion-use-ido t
org-src-fontify-natively t
org-src-tab-acts-natively t
org-log-done t
org-log-done-with-time t
org-log-refile t
org-support-shift-select t)
(add-hook 'org-mode-hook 'auto-fill-mode))Puppet
(use-package puppet-mode
:mode "\\.pp\\'")Python
(use-package python
:ensure nil
:mode ("\\.py\\'" . python-mode)
:config
(add-hook 'python-mode-hook #'subword-mode))Cycle between apostrophes and quotes in python strings. Converts strings like ‘this’ to strings like “this”.
(use-package python-switch-quotes
:after python
:bind (:map python-mode-map
("C-c '" . python-switch-quotes)))After doing python dev for a while, it’s nice to be able to tweak my
setup. After trying other major packages (elpy and jedi) I’ve settled
on anaconda-mode and virtualenvwrapper. It provides a nice mix of
tweakability and convenience.
anaconda-mode provides code navigation and docs. Additionally, if
company-mode is enabled, company-anaconda will also be enabled.
(use-package anaconda-mode
:diminish anaconda-mode
:config
(add-hook 'python-mode-hook 'anaconda-mode))
(use-package company-anaconda
:after (anaconda-mode company)
:config (add-to-list 'company-backends 'company-anaconda))This adds some basic features for requirements files, such as highlighting and auto-completion of names from PyPI.
(use-package pip-requirements
:mode
"requirements.txt"
"requirements/\\.txt\\'")virtualenvwrapper is a pretty awesome small package which aims to
emulate python’s virtualenvwrapper. It adds some functions to switch
between virtualenvs and provides a consistent location to put them.
If projectile is enabled, this will also add a hook which will load
the virtualenv matching the basename of the project when switching
buffers.
(use-package virtualenvwrapper
:config
(when (fboundp 'projectile-mode)
(advice-add 'switch-to-buffer :after
(lambda (&rest arg-list)
(if (and (projectile-project-p)
(venv-is-valid (projectile-project-name)))
(venv-workon (projectile-project-name)))))))Elpy does all the things, so we used to use that. Unfortunately, it proved to be relatively slow and buggy, so we’ve since moved on.
(use-package elpy
:disabled t
:config
(setq elpy-modules (remove 'elpy-module-flymake elpy-modules))
(elpy-enable))Allow emacs to understand versioned python shebangs.
(add-to-list 'interpreter-mode-alist '("python2" . python-mode))
(add-to-list 'interpreter-mode-alist '("python3" . python-mode))Ruby
(use-package ruby-mode
:mode "\\.rb\\'"
:config
(add-hook 'ruby-mode-hook #'subword-mode))Rust
Rust is a fairly recent addition which I’d like to learn more about, which is why the settings here are fairly minimal.
(use-package rust-mode
:mode
"\\.rs\\'")
(use-package racer
:after rust-mode
:config
(add-hook 'rust-mode-hook #'racer-mode))
(use-package flycheck-rust
:after (rust-mode flycheck-mode)
:config
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup))
(use-package rustfmt
:disabled t
:after rust
:bind (("C-c C-f" . rustfmt-format-buffer)))systemd
(use-package systemd
:mode ("\\.service\'" . systemd-mode))toml
(use-package toml-mode
:mode "\\.toml\\'")YAML
(use-package yaml-mode
:mode "\\.yml\\'")Various Packages
ag
(use-package ag)anzu
anzu shows how many matches in isearch. This should be loaded after spaceline so we know to disable the additional things anzu puts into the modeline.
(use-package anzu
:demand
:diminish anzu-mode
:config
(when (fboundp 'spaceline-install)
(setq anzu-cons-mode-line-p nil))
(global-anzu-mode))all-the-icons
(use-package all-the-icons)flyspell
flyspell does what it says on the tin. It’s a spell-checker similar to flycheck.
(use-package flyspell
:diminish flyspell-mode
:config (add-hook 'text-mode-hook (lambda () (flyspell-mode 1))))golden-ratio-mode (disabled)
Auto-resize frames based on the golden ratio to hopefully make sure everything stays readable and the focused frame is the most important.
(use-package golden-ratio
:disabled t
:diminish golden-ratio-mode
:config
(golden-ratio-mode 1))helm
Helm is a much fancier replacement for ido.
(defvar belak/enable-helm t)
(use-package helm
:diminish helm-mode
:if belak/enable-helm
:bind (("M-x" . helm-M-x)
("C-x b" . helm-mini)
("C-x C-f" . helm-find-files)
;; Reverse tab and C-z
:map helm-map
("<tab>" . helm-execute-persistent-action)
("C-z" . helm-select-action)
:map org-mode-map
("C-c h" . helm-org-in-buffer-headings))
:config
(helm-mode 1)
;; Resize based on the number of results
(helm-autoresize-mode 1)
;; Turn on fuzzy matching for everything we can
(setq helm-M-x-fuzzy-match t
helm-mode-fuzzy-match t
helm-completion-in-region-fuzzy-match t))(use-package helm-ag
:if belak/enable-helm
:after helm
:commands
helm-ag
helm-ag-project-root)
(use-package helm-swoop
:if belak/enable-helm
:after helm
:bind ("C-S-s" . helm-swoop)
:config
(setq helm-swoop-speed-or-color t
helm-swoop-pre-input-function (lambda () "")))
helm-projectile should only be loaded if helm is used. It’s
currently disabled.
(use-package helm-projectile
:if belak/enable-helm
:after (helm projectile)
:config
(setq projectile-completion-system 'helm)
(helm-projectile-on))hl-todo
I originally used fic-mode, but it appears that hl-todo is a little better and is updated more frequently. This lets us highlight TODO, FIXME, XXX, and other similar keywords.
(use-package hl-todo
:config
(setq hl-todo-keyword-faces '(("FIXME" . hl-todo)
("TODO" . hl-todo)
("XXX" . hl-todo)))
(hl-todo-set-regexp)
(global-hl-todo-mode))hlinum
(use-package hlinum
:config
(hlinum-activate))ido
ido (interactively-do) is a better interface for selecting things.
(defvar belak/enable-ido nil)
(use-package ido
:ensure nil
:if belak/enable-ido
:config
(setq completion-ignored-extensions
'(".o" ".elc" "~" ".bin" ".bak" ".obj" ".map" ".a" ".ln" ".mod" ".gz"
".aux" ".tdo" ".fmt" ".swp" ".pdfsync" ".pdf" ".vrb" ".idx" ".ind"
".bbl" ".toc" ".blg" ".snm" ".ilg" ".log" ".out" ".pyc" ".DS_Store"
"-blx.bib" ".run.xml" ".hi" ".fls" ".fdb_latexmk" ".bcf" ".rel")
ido-use-filename-at-point nil
resize-mini-windows t
ido-use-virtual-buffers t
ido-auto-merge-work-directories-length -1)
(ido-mode 1)
(ido-everywhere 1))
;; smex is a better replacement for M-x built around ido.
(use-package smex
:after ido
:if belak/enable-ido
:general
("M-x" 'smex)
("M-X" 'smex-major-mode-commands)
:config
(setq smex-history-length 50))
;; Use ido everywhere possible.
(use-package ido-completing-read+
:after ido
:if belak/enable-ido
:config
(ido-ubiquitous-mode 1))
;; ido is much more readable when all the options are displayed
;; vertically.
(use-package ido-vertical-mode
:after ido
:if belak/enable-ido
:config
(setq ido-vertical-define-keys 'C-n-C-p-up-down-left-right
ido-vertical-show-count t)
(ido-vertical-mode 1))
;; flx-ido changes the matching algorithm to improve the flex
;; matching support.
(use-package flx-ido
:after ido
:if belak/enable-ido
:config
(setq ido-enable-flex-matching t
flx-ido-threshold 10000))ivy (disabled)
ivy is an alternative to ido which comes with a number of fancy features, but it’s disabled because I haven’t found the time to fix my config just yet.
(use-package ivy
:disabled t
:demand t
:diminish ivy-mode
:general
("C-c C-r" 'ivy-resume)
:config
;; swiper is a replacement for isearch which uses ivy.
(use-package swiper
:general
("C-s" 'swiper))
;; counsel is a bunch of functions which replace builtins so they'll
;; work much better with ivy.
(use-package counsel
:general
("M-x" 'counsel-M-x)
("C-x C-f" 'counsel-find-file))
(setq projectile-completion-system 'ivy
magit-completing-read-function 'ivy-completing-read
ivy-use-virtual-buffers t)
;;(setq ivy-re-builders-alist '((t . ivy--regex-fuzzy)))
(ivy-mode 1))multiple-cursors (disabled)
Add multiple cursors and phi-search (which uses multiple cursors) to make multi-line editing work a bit better.
(use-package multiple-cursors
:disabled t
:config
(use-package phi-search
:bind
("C-s" . phi-search)
("C-r" . phi-search-backward)
("M-%" . phi-replace-query)))paradox
Paradox is a replacement for package-list-packages offering a few
extra features. Note that we only load it on those commands because
it’s something that only really matters when we manually start it up.
(use-package paradox
:commands
paradox-list-packages
paradox-enable
:config
(setq paradox-automatically-star t)
(setq paradox-execute-asynchronously t)
;; Paradox is much more useful in emacs mode than evil mode because
;; it rebinds so many things.
(when (fboundp 'evil-mode)
(add-to-list 'evil-emacs-state-modes 'paradox-menu-mode)))Other
(use-package password-store
:commands password-store-get)persistent-scratch makes it possible to use the scratch buffer without worrying about losing it.
(use-package persistent-scratch
:config
(persistent-scratch-setup-default)
(persistent-scratch-autosave-mode 1))(use-package project-explorer
:general
("C-c e" 'project-explorer-toggle)
:config
(setq pe/omit-gitignore t))(use-package rainbow-delimiters
:commands rainbow-delimiters-mode)(use-package rainbow-mode
:commands rainbow-mode)(use-package simple-mpc
:general
("C-c m" 'simple-mpc)
;;(when (fboundp 'evil-mode)
;; (general-nmap :prefix belak/evil-leader
;; "m" 'simple-mpc))
:config
(when (fboundp 'evil-mode)
(add-hook 'simple-mpc-mode-hook 'evil-emacs-state)))(use-package slime
:config
(setq slime-contribs '(fancy)))smart-mode-line is a package which aims to provide a better mode-line with little configuration. I’ve tried to use powerline (and making my own small framework) and it just involved too much work to maintain a small feature.
(use-package smart-mode-line
:disabled t
:config
(setq sml/no-confirm-load-theme t
sml/shorten-directory t
sml/theme 'respectful)
(sml/setup))In spite of the name, I use this to make sure that when I scroll, there are still lines between the cursor and the top of the file.
(use-package smooth-scrolling
:config
(setq smooth-scroll-margin 5
scroll-conservatively 101
scroll-preserve-screen-position t
auto-window-vscroll nil
scroll-margin 1
scroll-step 1
mouse-wheel-scroll-amount '(1 ((shift) . 1))
mouse-wheel-progressive-speed t
mouse-wheel-follow-mouse t)
(smooth-scrolling-mode 1))undo-tree makes the undo features a bit more bearable.
(use-package undo-tree
:diminish undo-tree-mode
:config
(global-undo-tree-mode 1))(use-package highlight-indentation
:diminish highlight-identation-mode
:config
(add-hook 'python-mode-hook 'highlight-indentation-mode))Dim the font color of text in surrounding paragraphs.
(use-package focus)Builtins
This section includes packages which are built into emacs (with a few exceptions sitting outside this block).
Highlight the current column
(global-hl-line-mode)(use-package paren
:ensure nil
:config
(show-paren-mode 1)
(setq show-paren-style 'parenthesis
show-paren-delay 0))recentf adds some useful functionality to ido which remembers previously opened files.
(use-package recentf
:ensure nil
:config
(setq recentf-max-saved-items 50)
;;(add-to-list 'recentf-exclude "[/\\]\\.elpa/")
;;(add-to-list 'recentf-exclude "[/\\]\\.ido\\.last\\'" )
;;(add-to-list 'recentf-exclude "[/\\]\\.git/")
;;(add-to-list 'recentf-exclude ".*\\.gz\\'")
;;(add-to-list 'recentf-exclude ".*-autoloads\\.el\\'")
;;(add-to-list 'recentf-exclude "[/\\]archive-contents\\'")
;;(add-to-list 'recentf-exclude "[/\\]\\.loaddefs\\.el\\'")
;;(add-to-list 'recentf-exclude "url/cookies")
;;(add-to-list 'recentf-exclude ".*\\emacs.bmk\\'")
;;(add-to-list 'recentf-exclude "README\\.el\\'")
;;(add-to-list 'recentf-exclude "/custom\\.el\\'")
(recentf-mode 1))Save the last location when you leave a file.
(use-package saveplace
:ensure nil
:config
(setq-default save-place t))Ensure we’re using sane buffer naming
(use-package uniquify
:ensure nil
:config
(setq uniquify-buffer-name-style 'forward
uniquify-strip-common-suffix nil))(use-package whitespace
:ensure nil
:config
(setq whitespace-style '(trailing face tabs tab-mark lines-tail)
whitespace-display-mappings '((space-mark 32 [183] [46])
(newline-mark 10 [182 10])
(tab-mark 9 [9655 9] [92 9])))
(global-whitespace-mode t)
(setq whitespace-global-modes '(text-mode prog-mode org-mode)))Other Settings
Legacy
Disable most of the vc backends.
(setq vc-handled-backends '(Git Hg))Most markup modes are derived from text-mode, so we can turn on auto-fill for all of them.
(add-hook 'text-mode-hook 'turn-on-auto-fill)
(diminish 'auto-fill-function)popwin tries to make the behavior of compilation buffers, search buffers, etc, a bit more sane.
(use-package popwin
:ensure t
:bind (("C-c P" . popwin:popup-last-buffer))
:config
;; also add ag, flycheck, and occur to pop
(add-to-list 'popwin:special-display-config `"*ag search*")
(add-to-list 'popwin:special-display-config `"*ripgrep-search*")
(add-to-list 'popwin:special-display-config `"*Flycheck errors*")
(add-to-list 'popwin:special-display-config `"*Occur*")
;; don't auto-select the compile process buffer as it's only for information
(add-to-list 'popwin:special-display-config `("*Compile-Log*" :noselect t))
;; enable
(popwin-mode))These are old settings this need to be reorganized.
;; TODO: This section is pretty much everything that didn't fit nicely
;; into a use-package block. It would be nice to refactor this a bit.
;; We pick a super generic fallback so it should work everywhere.
(defvar belak/frame-font "Monospace 12")
(cond ((linux-p)
;; On linux, we just fall back to the default "monospace" font
;; because we can set it the same everywhere.
(setq belak/frame-font nil
x-gtk-use-system-tooltips nil))
((osx-p)
(setq belak/frame-font "Source Code Pro 12")))
;; We want to ensure the font is set after the window frame is
;; created.
(add-hook 'after-make-window-system-frame-hooks
(lambda () (when belak/frame-font (set-frame-font belak/frame-font))))
;; Remove most gui features because I rarely use any of them.
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(setq use-dialog-box nil
use-file-dialog nil)
;; Various appearance settings
(setq column-number-mode t
line-number-mode t
tooltip-delay 0
tooltip-short-delay 0)
(setq-default tab-width 4)
;; I find that when I want to use zap, I almost never want to include
;; the next character, so we replace zap-to-chat with zap-up-to-char.
(autoload 'zap-up-to-char "misc")
(global-set-key [remap zap-to-char] 'zap-up-to-char)
(defvar save-place-file)
(setq save-place-file (concat user-emacs-directory "places")
backup-directory-alist `(("." . ,(concat user-emacs-directory "backups")))
auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
;; Make sure we only have to type 'y' or 'n', not the full word
;; because that takes too many keystrokes.
(fset 'yes-or-no-p 'y-or-n-p)
(setq lazy-highlight-initial-delay 0
make-pointer-invisible t
vc-follow-symlinks t
require-final-newline t
load-prefer-newer t
inhibit-splash-screen t)
(setq history-length 50)
;; Middle clicking should paste, but not adjust point and paste at the
;; then adjusted point.
(setq mouse-yank-at-point t)
;; As a former vim user, I like escape to actually quit
;; everywhere. This was taken from
;; https://github.com/davvil/.emacs.d/blob/master/init.el
(defun minibuffer-keyboard-quit ()
"Abort recursive edit.
In Delete Selection mode, if the mark is active, just
deactivate it; then it takes a second \\[keyboard-quit] to
abort the minibuffer."
(interactive)
(if (and delete-selection-mode transient-mark-mode mark-active)
(setq deactivate-mark t)
(when (get-buffer "*Completions*") (delete-windows-on "*Completions*"))
(abort-recursive-edit)))
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)
;; Ensure all trailing whitespace is removed
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;; Highlight between matching parens
(electric-pair-mode 1)
;; Show which function we're in
;;(which-function-mode 1)
;; Delete text if we start typing
;; TODO: This may be possible to do with a variable.
(delete-selection-mode)
;; Disable cursor blinking
(blink-cursor-mode -1)
;; Show modifier combinations almost immediately.
(setq echo-keystrokes 0.1)
;; This is a common hook for all modes that are based on the generally
;; programming mode.
(add-hook 'prog-mode-hook
(lambda ()
;; Newer versions of emacs define line numbers natively so
;; we use that if it's available and fall back to
;; linum-mode if it's not.
(if (boundp 'display-line-numbers)
(progn
(setq display-line-numbers 'relative
display-line-numbers-current-absolute t)
(force-mode-line-update))
(linum-mode 1))
(setq show-trailing-whitespace t)))
;; Revert buffers automatically if they've changed on disk
(global-auto-revert-mode 1)
(setq auto-revert-verbose nil)
(diminish 'auto-revert-mode)Custom
We still want to be able to have non-public configs, such as for passwords and what not, so we put them in a separate file and load it, but ignore errors, for instance if it doesn’t exist. This has the added advantage of making it so customizations will go to this file and not to init.el, which is version controlled.
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file t)Tasks [0/18]
This section is all about stuff I’d like to get into my emacs init but haven’t found the time yet.
- [ ] Fix the strange issue with js2-mode faces in base16
- [ ] Replace all :bind blocks with :general blocks
- [ ] Clean up Legacy section
- [ ] Add some ag bindings (really, add back ag-support)
- [ ] Look into eldoc mode
- [ ] Learn
paredit - [ ] Look into avy/ivy (can probably grab from smf)
- [ ] Look into slime for elisp
- [ ] Set up ediff like https://github.com/dakrone/dakrone-dotfiles/blob/master/.emacs.d/settings.org#ediff
- [ ] Set up smartparens like https://github.com/dakrone/dakrone-dotfiles/blob/master/.emacs.d/settings.org#smartparens
- [ ] Set up anzu like https://github.com/dakrone/dakrone-dotfiles/blob/master/.emacs.d/settings.org#anzu
- [ ] Find a way to bootstrap go-oracle
- [ ] Move away from org-mode config
- [ ] Grab goto-chr from smf
- [ ] Look at ripgrep to maybe replace ag
- [ ] Whole-line-or-region-mode?
- [ ] dwim?
- [ ] hungry-delete
- [ ] dumb-jump
- [ ] guide-key?