This file includes custom settings for various Emacs features and makes use of numerous third-party packages to add functionality to Emacs. Although this file contains most of the important customization, there is some initial set-up in init.el, and some additional package-specific variable settings in custom.el.
Here we have general editing and system settings.
We use the bind-key package, which provides useful functions for creating personal keybindings
(use-package bind-key
:ensure t)
Disable version control when we’re in TRAMP
(setq vc-ignore-dir-regexp
(format "\\(%s\\)\\|\\(%s\\)"
vc-ignore-dir-regexp
tramp-file-name-regexp))
We set the command key to meta and the alt key to super
(setq ns-alternate-modifier 'super)
(setq ns-command-modifier 'meta)
TRAMP settings
;; There are a lot of settings we want to enable only if we are or are not
;; visiting a TRAMP file, so we provide a helper method to check if we're in a
;; tramp file.
(defun is-current-file-tramp ()
(tramp-tramp-file-p (buffer-file-name (current-buffer))))
(add-hook
'find-file-hook
(lambda () (if (is-current-file-tramp) (setq-local make-backup-files nil))))
We store backups in a temporary folder.
;; Backup file settings
(setq
backup-by-copying t ; don't clobber symlinks
delete-old-versions t
kept-new-versions 6
kept-old-versions 2
version-control t) ; use versioned backups
;; Save by default in ~/.saves folder
(push (cons "." "~/.saves") backup-directory-alist)
We save the cursor position at visited files in between sessions, except if we’re in a TRAMP buffer.
(use-package saveplace
:ensure t
:init
(progn
(setq-default save-place t)
(setq save-place-file "~/.emacs.d/.saved-places")
)
:config
(setq save-place-ignore-files-regexp
(format "\\(%s\\)\\|\\(%s\\)"
save-place-ignore-files-regexp
tramp-file-name-regexp))
)
We want to navigate camelCase words as separate words.
(use-package subword
:diminish subword-mode
:init
(global-subword-mode)
)
Most of the automatic parentheses management libraries in emacs are either overkill or buggy, so we just add a bare minimum few key-bindings and settings
;; Add a key-binding to delete matching pairs
(bind-key "M-D" 'delete-pair)
;; Show matching parentheses
(add-hook 'prog-mode-hook 'show-paren-mode)
We use ace-jump mode, which highlights all occurences of a character you enter in the current buffer and lets you immediately jump to the place you want.
(use-package ace-jump-mode
:ensure t
:demand
:bind ("C-c c" . ace-jump-char-mode))
We use the multiple-cursors package, which provides multiple cursors editing similar to what you would find in SublimeText.
(use-package multiple-cursors
:ensure t
:bind ("C-S-C C-S-C" . mc/edit-lines)
)
(bind-key "TAB" 'completion-at-point read-expression-map)
We use flyspell.
(use-package flyspell
:ensure t
:defer t
:init
(progn
(add-hook 'prog-mode-hook 'flyspell-prog-mode)
(add-hook 'text-mode-hook 'flyspell-mode)
)
:config
;; Sets flyspell correction to use two-finger mouse click
(define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word)
)
We define keybindings for navigating to different windows and frames. We copy the windmove-default-keybindings and framemove-default-keybindings functions and modify them to use my-keys-minor-mode-map.
(use-package windmove
:ensure t
:bind (("S-<left>" . windmove-left)
("S-<right>" . windmove-right)
("S-<up>" . windmove-up)
("S-<down>" . windmove-down)
)
)
(use-package framemove
:ensure t
:bind (("C-S-<left>" . fm-left-frame)
("C-S-<right>" . fm-right-frame)
("C-S-<up>" . fm-up-frame)
("C-S-<down>" . fm-down-frame)
)
)
We set everything to UTF-8 encoding.
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(setq current-language-environment "UTF-8")
(prefer-coding-system 'utf-8)
(setenv "LC_CTYPE" "UTF-8")
We don’t want the cursor to blink.
(blink-cursor-mode -1)
We want to see the column number we’re at on each line.
(setq column-number-mode t)
By default, emacs doesn’t have an actual redo function. The way you redo an edit is by undoing a previous undo. This can quickly get confusing when you’re not exactly sure how much you want to undo or redo, so we use undo tree, which provides an actual redo function for emacs and maintains all edit history by keeping a tree of undos and redos.
(use-package undo-tree
:ensure t
:diminish undo-tree-mode
:init
(global-undo-tree-mode)
)
We don’t need that stuff.
(setq inhibit-startup-screen t)
(menu-bar-mode -1)
(scroll-bar-mode -1)
(tool-bar-mode -1)
We disable indenting with tabs.
(setq-default indent-tabs-mode nil)
We put one space after sentences, so we want emacs to recognize these sentences for navigation and editing.
(setq sentence-end-double-space nil)
By default, we want case sensitivity in searches and replaces to be smart. That is, if your search doesn’t use capital letters, emacs will ignore case. If it does, emacs will be case-sensitive.
(setq-default case-fold-search t)
Turn on whitespace mode, which helps track down and clean up bad whitespace in code. Additional settings for whitespace mode can be found in custom.el.
(use-package whitespace
:ensure t
:diminish whitespace-mode
:init
(add-hook 'prog-mode-hook 'whitespace-mode)
)
We use magit
(use-package magit
:ensure t
:init
(bind-key "C-c m" 'magit-status)
)
;; For vc-git-grep
(require 'vc-git)
We use ibuffer, which is better than the default buffer menu
(bind-key "C-x C-b" 'ibuffer)
Wgrep mode turns the grep buffer into an editable buffer, so you can make changes to the results of a grep query and then save them across files.
(use-package wgrep
:ensure t
:init
(require 'wgrep)
)
Create a binding for finding a file in a large project
;; find-file-in-project-by-selected is better than plain old
;; find-file-in-project, because it lets you narrow down the list of candidates
;; with a keyword before giving you the interactive menu. This is much faster
;; than starting with the interactive menu for large projects.
(use-package find-file-in-project
:ensure t
:init
(bind-key "C-c f" 'find-file-in-project-by-selected)
)
Here we have programming-language-related settings
Company is a generic auto-completion framework. It allows you to define backends that source completions from different sources, so you can have language-specific completions
(use-package company
:ensure t
:config
(progn
;; Enable company mode in every programming mode
(add-hook 'prog-mode-hook 'company-mode)
;; Set my own default company backends
(setq-default
company-backends
'(
company-nxml
company-css
company-cmake
company-files
company-dabbrev-code
company-keywords
company-dabbrev
company-elisp
))
)
)
We use flycheck to check syntax and style in code. flycheck will run language-specific code checkers based on the file type and highlight problems.
(use-package flycheck
:ensure t
:init
(progn
;; Enable flycheck mode as long as we're not in TRAMP
(add-hook
'prog-mode-hook
(lambda () (if (not (is-current-file-tramp)) (flycheck-mode 1))))
)
)
Rtags provides completion and symbol navigation for specific code-bases
;; Use rtags for navigation
(use-package rtags
:ensure t
:config
(progn
;; Start rtags upon entering a C/C++ file
(add-hook
'c-mode-common-hook
(lambda () (if (not (is-current-file-tramp))
(rtags-start-process-unless-running))))
(add-hook
'c++-mode-common-hook
(lambda () (if (not (is-current-file-tramp))
(rtags-start-process-unless-running))))
;; Flycheck setup
(require 'flycheck-rtags)
(defun my-flycheck-rtags-setup ()
(flycheck-select-checker 'rtags)
;; RTags creates more accurate overlays.
(setq-local flycheck-highlighting-mode nil)
(setq-local flycheck-check-syntax-automatically nil))
;; c-mode-common-hook is also called by c++-mode
(add-hook 'c-mode-common-hook #'my-flycheck-rtags-setup)
;; Keybindings
(rtags-enable-standard-keybindings c-mode-base-map "\C-cr")
)
)
;; Use irony for completion
(use-package irony
:ensure t
:config
(progn
(add-hook
'c-mode-common-hook
(lambda () (if (not (is-current-file-tramp)) (irony-mode))))
(add-hook
'c++-mode-common-hook
(lambda () (if (not (is-current-file-tramp)) (irony-mode))))
(add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
(use-package company-irony
:ensure t
:config
(push 'company-irony company-backends)
)
)
)
We use elpy
(use-package elpy
:ensure t
:config
(progn
(elpy-enable)
(elpy-use-ipython)
;; Fixes the weird prompt in new IPython versions
(setq python-shell-interpreter "ipython"
python-shell-interpreter-args "--simple-prompt -i")
)
)
;; Auctex
(use-package auctex
:ensure t
:mode ("\\.tex\\'" . latex-mode)
:commands (latex-mode LaTeX-mode plain-tex-mode)
:init
(progn
(add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup)
(add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
(add-hook 'LaTeX-mode-hook #'flyspell-mode)
(add-hook 'LaTeX-mode-hook #'turn-on-reftex)
(setq TeX-auto-save t
TeX-parse-self t
TeX-save-query nil
TeX-PDF-mode t)
))
;; Use company-auctex
(use-package company-auctex
:ensure t
:config
(company-auctex-init)
)
(use-package web-mode
:ensure t
:config
(progn
;; Enable web mode in the following modes
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.jsx?\\'" . web-mode))
;; Set the content type to "jsx" for the following file extensions
(setq web-mode-content-types-alist
'(("jsx" . "\\.js[x]?\\'")))
)
)
(use-package go-mode
:ensure t
:mode "\\.go"
)
(use-package company-go
:ensure t
:config
(push 'company-go company-backends)
)
(use-package sql
:ensure t
:mode ("\\.sql" . sql-mode)
)
(setq sql-mysql-login-params (quote (user server port password)))
(if (file-exists-p (expand-file-name "~/.opam"))
(progn
;; Setup environment variables using opam
(dolist (var (car (read-from-string
(shell-command-to-string "opam config env --sexp"))))
(setenv (car var) (cadr var)))
;; Update the emacs path
(setq exec-path (append (parse-colon-path (getenv "PATH"))
(list exec-directory)))
;; Update the emacs load path
(add-to-list 'load-path
(expand-file-name "../../share/emacs/site-lisp"
(getenv "OCAML_TOPLEVEL_PATH")))
;; utop
(use-package utop
:ensure t
:config
(autoload 'utop-setup-ocaml-buffer "utop" "Toplevel for OCaml" t)
)
;; ocp-indent
(require 'ocp-indent)
;; merlin
(require 'merlin)
(add-hook 'tuareg-mode-hook 'merlin-mode t)
(setq merlin-command 'opam)
(push 'merlin-company-backend company-backends)
))
(use-package rainbow-mode
:ensure t
:init
(add-hook 'css-mode-hook 'rainbow-mode)
)
(use-package haskell-mode
:ensure t
:mode "\\.hs"
:config
(progn
;; Turn on haskell-mode features automatically
(add-hook 'haskell-mode-hook 'haskell-indentation-mode)
(add-hook 'haskell-mode-hook 'interactive-haskell-mode)
(add-hook 'haskell-mode-hook 'haskell-decl-scan-mode)
(add-hook 'haskell-mode-hook 'haskell-doc-mode)
)
)
(use-package bison-mode
:ensure t
:mode "\\.y"
)
(use-package erlang
:ensure t
)
(use-package yaml-mode
:config
(require 'yaml-mode))
(use-package perl6-mode
:ensure t
:defer t
)
(use-package rust-mode
:ensure t
)
(use-package cargo
:ensure t
:config
(add-hook 'rust-mode-hook 'cargo-minor-mode)
)
(use-package racer
:ensure t
:config
(progn
(add-hook 'rust-mode-hook #'racer-mode)
(add-hook 'racer-mode-hook #'eldoc-mode)
(add-hook 'racer-mode-hook #'company-mode)
)
)
(use-package flycheck-rust
:ensure t
:config
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup)
)