/.emacs.d

My emacs configuration

Primary LanguageEmacs LispBSD 2-Clause "Simplified" LicenseBSD-2-Clause

Manu’s Emacs Configuration

General

Here we have general editing and system settings.

Bind Key

We use the bind-key package, which provides useful functions for creating personal keybindings

(use-package bind-key
  :ensure t)

Shell Environment variables

We use the exec-path-from-shell package to grab some environment variable definitions from the shell environment.

(use-package exec-path-from-shell
  :ensure t
  :config
  (if (not (eq system-type 'windows-nt))
      (progn
        (if (not (string= "" (exec-path-from-shell-getenv "TMPDIR")))
            (add-to-list 'exec-path-from-shell-variables "TMPDIR"))
        (add-to-list 'exec-path-from-shell-variables "LANG")
        (add-to-list 'exec-path-from-shell-variables "LC_ALL")
        (exec-path-from-shell-initialize)
        )
    )
  )

Revert buffer

We re-bind the revert-buffer command, which is originally on super-u, which is inconvenient for Mac.

(bind-key "M-U" 'revert-buffer)

TRAMP

We configure TRAMP, a package that provides transparent remote file access over various protocols.

(use-package tramp
  :ensure t
  :init
  (progn
    ;; Tramp saves backups to the local directory, for speed.
    (setq tramp-auto-save-directory "\"/tmp\"")
    ;; Disable vc for tramp files
    (setq vc-ignore-dir-regexp
          (format "\\(%s\\)\\|\\(%s\\)"
                  vc-ignore-dir-regexp
                  tramp-file-name-regexp))
    )
  )

Company mode

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
    (add-hook 'prog-mode-hook 'global-company-mode)
    (bind-key "C-<tab>" 'company-complete)
    )
  )

Real-Time Syntax Checking

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
    (add-hook 'prog-mode-hook 'flycheck-mode)
    ;; Set the flake8rc location for the flake8 checker
    (setq flycheck-flake8rc "~/.config/flake8")
    )
  )

Mac OSX Key Bindings

We set the alt, command, and super modifiers to meta.

(setq ns-alternate-modifier 'meta)
(setq ns-command-modifier 'meta)
(setq x-super-keysym 'meta)

File Backups

We store backups in a temporary folder.

(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq tramp-backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))

File Position Persistence

We save the cursor position at visited files in between sessions.

(use-package saveplace
  :ensure t
  :init
  (progn
    (setq-default save-place t)
    (setq save-place-file "~/.emacs.d/.saved-places")
    )
  )

camelCase Navigation

We want to navigate camelCase words as separate words.

(use-package subword
  :diminish subword-mode
  :init
  (global-subword-mode)
)

Parentheses

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)

Jumping Around Buffers

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))

Multiple Cursors

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)
         ("C->" . mc/mark-next-like-this)
         ("C-<" . mc/mark-previous-like-this)
         ("C-=" . mc/mark-all-like-this-dwim))
  )

Completion in an ELISP Minibffer

(bind-key "TAB" 'completion-at-point read-expression-map)

Spell Checking

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)
  )

Color Scheme

(use-package solarized-theme
  :ensure t
  :init
  (load-theme 'solarized-light)
  )

Opening URLs

In order to open URLs in the correct external browser, we set the browser program based on which executable exists (for now, we support mac’s “open” and gnome’s “gnome-open”).

(setq browse-url-generic-program
      (cond
       ((string= system-type "gnu/linux") "gnome-open")
       (t "open")
       )
      )
;; The function to open a url should use the generic program
(setq browse-url-browser-function 'browse-url-generic)

File Management

We configure dired, the emacs file manager.

(use-package dired+
  :ensure t
  :commands dired
  :config
  )
;; Running dired-omit mode should hide all dotfiles
(setq dired-omit-files "^\\..*$")
;; Never prompt for recursive copies of a directory
(setq dired-recursive-copies 'always)
;; Never prompt for recursive deletes of a directory
(setq dired-recursive-deletes 'always)

Window and Frame Navigation

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)
         )
  )

UTF-8 Encoding

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")

Fill Column

We set the fill column to a reasonable default.

(setq-default fill-column 80)

Blinking Cursor

We don’t want the cursor to blink.

(blink-cursor-mode -1)

Column numbers

We want to see the column number we’re at on each line.

(setq column-number-mode t)

Undo/Redo

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)
  )

Turn off All Menus and Tool Bars and Whizbangs

We don’t need that stuff.

(setq inhibit-startup-screen t)
(menu-bar-mode -1)
(scroll-bar-mode -1)
(tool-bar-mode -1)

No Tabs

We disable indenting with tabs.

(setq-default indent-tabs-mode nil)

Navigating sentences

We put one space after sentences, so we want emacs to recognize these sentences for navigation and editing.

(setq sentence-end-double-space nil)

Case-sensitivity in searches

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)

Whitespace mode

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)
  )

Git

We use magit

(use-package magit
  :ensure t
  :init
  (bind-key "C-c m" 'magit-status)
  )

;; For vc-git-grep
(require 'vc-git)

Minibuffer completion

We use ido to complete wherever possible.

(use-package ido
  :ensure t
  :config
  (progn
    (ido-mode 1)
    (ido-everywhere 1)
    (setq ido-use-faces nil)
    (setq ido-auto-merge-work-directories-length -1)
    ;; Don't record history in ido.last
    (setq ido-enable-last-directory-history nil)
    (setq ido-record-commands nil)
    (setq ido-max-work-directory-list 0)
    (setq ido-max-work-file-list 0)
    )
  )
;; flx-ido provides better completion than regular
(use-package flx-ido
  :ensure t
  :config
  (flx-ido-mode 1)
  )
;; ido-ubiquitous provides ido completion for all minibuffer stuff
(use-package ido-ubiquitous
  :ensure t
  :config
  (ido-ubiquitous-mode 1)
  )
;; smex provides ido completion in functions
(use-package smex
  :ensure t
  :config
  (progn
    (global-set-key (kbd "M-x") 'smex)
    (global-set-key (kbd "M-X") 'smex-major-mode-commands)
    ;; This is the old M-x.
    (global-set-key (kbd "C-c C-c M-x") 'execute-extended-command)
    )
  )

Buffer menu

We use ibuffer, which is better than the default buffer menu

(bind-key "C-x C-b" 'ibuffer)

Wgrep

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)
  )

Find file in project

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)
  )

Languages

Here we have language-specific settings.

Python

(use-package jedi
  :ensure t
  :init
  (add-hook 'python-mode-hook 'jedi:setup)
  )
(use-package company-jedi
  :ensure t
  :config
  (progn
    (push 'company-jedi company-backends)
    ;; Disable auto-complete when we start jedi, because we don't want both
    ;; auto-complete and company running
    (add-hook 'jedi-mode-hook (lambda () (auto-complete-mode -1)))
    )
  )

;; Sets the python interpreter to be ipython. To trick emacs into
;; thinking we're still running regular python, we run ipython in
;; classic mode.
(setq
 python-shell-interpreter "ipython"
 python-shell-interpreter-args "-i --classic")

Go

(use-package go-mode
  :ensure t
  :mode "\\.go"
  :config
  (exec-path-from-shell-copy-env "GOPATH")
  )
(use-package company-go
  :ensure t
  :config
  (push 'company-go company-backends)
  )

SQL

(use-package sql
  :ensure t
  :mode ("\\.sql" . sql-mode)
  )
(setq sql-mysql-login-params (quote (user server port password)))

HTML/XML/Javascript

(use-package js2-mode
  :ensure t
  :mode "\\.js"
  )
(use-package web-mode
  :ensure t
  :mode "\\.jsx"
  :config
  (progn
    (setq web-mode-enable-auto-quoting nil)
    )
  )

OCaml

(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)
      ))

CSS

(use-package rainbow-mode
  :ensure t
  :init
  (add-hook 'css-mode-hook 'rainbow-mode)
  )

LaTeX

;; 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)
    (setq-default TeX-master nil)))

(use-package preview
  :commands LaTeX-preview-setup
  :init
  (progn
    (setq-default
     preview-scale 1.4
     preview-scale-function
     '(lambda ()
        (* (/ 10.0 (preview-document-pt)) preview-scale)))))

;; Use company-auctex
(use-package company-auctex
  :ensure t
  :config
  (company-auctex-init)
)

Haskell

(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)
    )
  )

C/C++

(use-package cc-mode)
;; Use rtags, a clang-based completion and navigation database for c++
(use-package rtags
  :config
  (require 'flycheck-rtags)
  )

Bison

(use-package bison-mode
  :ensure t
  :mode "\\.y"
  )

Scala

(use-package scala-mode2
  :ensure t
  )

(use-package ensime
  :ensure t
  :config
  (add-hook 'scala-mode-hook 'ensime-scala-mode-hook))

Clojure

;; Use the cider package
(use-package cider
  :ensure t
  )

Erlang

(use-package erlang
  :ensure t
  )

YAML

(use-package yaml-mode
  :config
  (require 'yaml-mode))