Skip to content

Latest commit

 

History

History
executable file
·
1639 lines (1277 loc) · 40.8 KB

config.org

File metadata and controls

executable file
·
1639 lines (1277 loc) · 40.8 KB

Emacs Configuration

I’ve been using Emacs extensively since the summer of 2013, and along the way I’ve become accustomed to many different tweaks for it.

This configuration uses the use-package package from John Wiegley, which is a fantastic way to manage package configurations.

If you see any keybindings that seem weird to you, it’s probably because I type with the Dvorak keyboard layout, so things’ll probably seem strange on other keyboard layouts. I may assign a keybinding just because it’s more on convenient on Dvorak. Though for the most part, I try to follow Emacs and assign bindings by mnemonics, would should make sense for any layout.

Installing Emacs

On macOS, homebrew is an easy way to install emacs.

Here’s what the parameters means.

--with-cocoa
installs emacs with the macOS GUI version
--with-imagemagick
installs emacs with imagemagick support for image processing
--with-gnutls
installs emacs with GnuTLS for encrypted SSL and TLS connections
brew install emacs --with-cocoa --with-imagemagick --with-gnutls

Personal Information

(setq user-full-name "Daniel Mai"
      user-mail-address "[email protected]")

Customize settings

Set up the customize file to its own separate file, instead of saving customize settings in init.el.

(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file)

Theme

Convenient theme functions

(defun switch-theme (theme)
  "Disables any currently active themes and loads THEME."
  ;; This interactive call is taken from `load-theme'
  (interactive
   (list
    (intern (completing-read "Load custom theme: "
                             (mapc 'symbol-name
                                   (custom-available-themes))))))
  (let ((enabled-themes custom-enabled-themes))
    (mapc #'disable-theme custom-enabled-themes)
    (load-theme theme t)))

(defun disable-active-themes ()
  "Disables any currently active themes listed in `custom-enabled-themes'."
  (interactive)
  (mapc #'disable-theme custom-enabled-themes))

(bind-key "s-<f12>" 'switch-theme)
(bind-key "s-<f11>" 'disable-active-themes)

Doom theme

(use-package doom-themes
  :ensure t
  :config
  (customize-set-variable 'doom-molokai-brighter-comments t)
  (switch-theme 'doom-molokai))

Cyberpunk theme

The cyberpunk theme is dark and colorful. However, I don’t like the boxes around the mode line.

(use-package cyberpunk-theme
  :if (window-system)
  :ensure t
  :init
  (progn
    (load-theme 'cyberpunk t)
    (set-face-attribute `mode-line nil
                        :box nil)
    (set-face-attribute `mode-line-inactive nil
                        :box nil)))

I tend to switch themes more often than normal. For example, switching to a lighter theme (such as the default) or to a different theme depending on the time of day or my mood. Normally, switching themes is a multi-step process with disable-theme and load-theme. The switch-theme function will do that in one swoop. I just choose which theme I want to go to.

Solarized theme

Here’s some configuration for bbatsov’s solarized themes.

(use-package solarized-theme
  :ensure t
  :init
  (setq solarized-use-variable-pitch nil)
  :config
  (switch-theme 'solarized-dark))

Monokai theme

(use-package monokai-theme
  :if (window-system)
  :ensure t
  :init
  (setq monokai-use-variable-pitch nil)
  (switch-theme 'monokai))

Waher theme

(use-package waher-theme
  if (window-system)
  :ensure t
  :init
  (load-theme 'waher))

Font

Fira Code is a nice monospaced font.

To install it on macOS, you can use Homebrew with Homebrew Cask.

# You may need to run these two lines if you haven't set up Homebrew
# Cask and its fonts formula.
brew install caskroom/cask/brew-cask
brew tap caskroom/fonts

brew cask install font-fira-code

To install it on Ubuntu, install the package fonts-firacode.

sudo apt-get install fonts-firacode

And here’s how we tell Emacs to use the font we want to use.

(add-to-list 'default-frame-alist
             (cond
              ((string-equal system-type "darwin")    '(font . "Fira Code-14"))
              ((string-equal system-type "gnu/linux") '(font . "Fira Code-12"))))

Note: To view all fonts that are available to use, run the following:

(font-family-list)

Display emojis. Source of system-specific fonts is in the README for the emacs-ac-emoji package.

(let ((font (if (= emacs-major-version 25)
                "Symbola"
              (cond ((string-equal system-type "darwin")    "Apple Color Emoji")
                    ((string-equal system-type "gnu/linux") "Symbola")))))
  (set-fontset-font t 'unicode font nil 'prepend))

Sane defaults

Let’s start with some sane defaults, shall we?

Sources for this section include Magnars Sveen and Sacha Chua.

;; These functions are useful. Activate them.
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)

;; Answering just 'y' or 'n' will do
(defalias 'yes-or-no-p 'y-or-n-p)

;; Keep all backup and auto-save files in one directory
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))

;; UTF-8 please
(setq locale-coding-system 'utf-8) ; pretty
(set-terminal-coding-system 'utf-8) ; pretty
(set-keyboard-coding-system 'utf-8) ; pretty
(set-selection-coding-system 'utf-8) ; please
(prefer-coding-system 'utf-8) ; with sugar on top

;; Turn off the blinking cursor
(blink-cursor-mode -1)

(setq-default indent-tabs-mode nil)
(setq-default indicate-empty-lines t)

;; Don't count two spaces after a period as the end of a sentence.
;; Just one space is needed.
(setq sentence-end-double-space nil)

;; delete the region when typing, just like as we expect nowadays.
(delete-selection-mode t)

(show-paren-mode t)

(column-number-mode t)

(global-visual-line-mode)
(diminish 'visual-line-mode)

(setq uniquify-buffer-name-style 'forward)

;; -i gets alias definitions from .bash_profile
(setq shell-command-switch "-ic")

;; Don't beep at me
(setq visible-bell nil)
(setq ring-bell-function (lambda () nil))

The following function for occur-dwim is taken from Oleh Krehel from his blog post at (or emacs. It takes the current region or the symbol at point as the default value for occur.

(defun occur-dwim ()
  "Call `occur' with a sane default."
  (interactive)
  (push (if (region-active-p)
            (buffer-substring-no-properties
             (region-beginning)
             (region-end))
          (thing-at-point 'symbol))
        regexp-history)
  (call-interactively 'occur))

(bind-key "M-s o" 'occur-dwim)

Here we make page-break characters look pretty, instead of appearing as ^L in Emacs. Here’s an informative article called “Using Page-Breaks in GNU Emacs” by Eric J. M. Ritz.

(use-package page-break-lines
  :ensure t)

Mac customizations

There are configurations to make when running Emacs on macOS (hence the “darwin” system-type check).

(when (string-equal system-type "darwin")
  ;; Non-native fullscreen
  (setq ns-use-native-fullscreen nil)
  ;; delete files by moving them to the trash
  (setq delete-by-moving-to-trash t)
  (setq trash-directory "~/.Trash")

  ;; Don't make new frames when opening a new file with Emacs
  (setq ns-pop-up-frames nil)

  ;; set the Fn key as the hyper key
  (setq ns-function-modifier 'hyper)

  ;; Use Command-` to switch between Emacs windows (not frames)
  (bind-key "s-`" 'other-window)

  ;; Use Command-Shift-` to switch Emacs frames in reverse
  (bind-key "s-~" (lambda() () (interactive) (other-window -1)))

  ;; Because of the keybindings above, set one for `other-frame'
  (bind-key "s-1" 'other-frame)

  ;; Fullscreen!
  (setq ns-use-native-fullscreen nil) ; Not Lion style
  (bind-key "<s-return>" 'toggle-frame-fullscreen)

  ;; buffer switching
  (bind-key "s-{" 'previous-buffer)
  (bind-key "s-}" 'next-buffer)

  ;; Compiling
  (bind-key "H-c" 'compile)
  (bind-key "H-r" 'recompile)
  (bind-key "H-s" (defun save-and-recompile () (interactive) (save-buffer) (recompile)))

  ;; disable the key that minimizes emacs to the dock because I don't
  ;; minimize my windows
  ;; (global-unset-key (kbd "C-z"))

  ;; Not going to use these commands
  (put 'ns-print-buffer 'disabled t)
  (put 'suspend-frame 'disabled t))

exec-path-from-shell makes the command-line path with Emacs’s shell match the same one on macOS.

(use-package exec-path-from-shell
  :ensure t
  :init
  (exec-path-from-shell-initialize))

Open other apps from Emacs

(defun open-dir-in-finder ()
  "Open a new Finder window to the path of the current buffer"
  (interactive)
  (start-process "mai-open-dir-process" nil "open" "."))

(defun open-dir-in-iterm ()
  "Open the current directory of the buffer in iTerm."
  (interactive)
  (let* ((iterm-app-path "/Applications/iTerm.app")
         (iterm-brew-path "/opt/homebrew-cask/Caskroom/iterm2/1.0.0/iTerm.app")
         (iterm-path (if (file-directory-p iterm-app-path)
                         iterm-app-path
                       iterm-brew-path)))
    (start-process "mai-open-dir-process" nil "open" "-a" iterm-path ".")))

(defun open-dir-in-studio ()
  "Open the current directory in Android Studio."
  (interactive)
  (start-process "mai-open-dir-process" nil "studio" "."))

(bind-key "C-c o f" 'open-dir-in-finder)
(bind-key "C-c o t" 'open-dir-in-iterm)
(bind-key "C-c o a" 'open-dir-in-studio)

El Capitan fixes

http://stuff-things.net/2015/10/05/emacs-visible-bell-work-around-on-os-x-el-capitan/

(when (string-equal system-type "darwin")
  (let* ((cmd "sw_vers -productVersion")
         (macos-version (string-to-number
                         (cadr (split-string
                                (shell-command-to-string cmd)
                                "\\."))))
         (elcapitan-version 11))
    (when (>= macos-version elcapitan-version)
      (setq visible-bell nil)
      (setq ring-bell-function 'ignore)

      ;; El Capitan full screen animation is quick and delightful (enough to start using it).
      (setq ns-use-native-fullscreen t))))

Title bar appearance

(when (string-equal system-type "darwin")
  (add-to-list 'default-frame-alist
               '(ns-transparent-titlebar . t))
  (add-to-list 'default-frame-alist
               '(ns-appearance . dark))) ;; light or dark

List buffers

ibuffer is the improved version of list-buffers.

;; make ibuffer the default buffer lister.
(defalias 'list-buffers 'ibuffer)

source: http://ergoemacs.org/emacs/emacs_buffer_management.html

(add-hook 'dired-mode-hook 'auto-revert-mode)

;; Also auto refresh dired, but be quiet about it
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)

source: Magnars Sveen

Recentf

(use-package recentf
  :config
  (recentf-mode t)
  (setq recentf-max-saved-items 500))

Org mode

Truly the way to live life in plain text. I mainly use it to take notes and save executable source blocks. I’m also starting to make use of its agenda, timestamping, and capturing features.

It goes without saying that I also use it to manage my Emacs config.

Installation

Although Org mode ships with Emacs, the latest version can be installed externally. The configuration here follows the Org mode ELPA installation instructions.

(use-package org
  :ensure org-plus-contrib)

On Org mode version 9 I wasn’t able to execute source blocks out of the box. Others have ran into the same issue too. The solution is to remove the .elc files from the package directory:

rm ${ORG_DIR}/*.elc

Org activation bindings

Set up some global key bindings that integrate with Org Mode features.

(bind-key "C-c l" 'org-store-link)
(bind-key "C-c c" 'org-capture)
(bind-key "C-c a" 'org-agenda)

Org agenda

Learned about this delq and mapcar trick from Sacha Chua’s config.

(setq org-agenda-files
      (delq nil
            (mapcar (lambda (x) (and (file-exists-p x) x))
                    '("~/Dropbox/Agenda"))))

Org capture

(bind-key "C-c c" 'org-capture)
(setq org-default-notes-file "~/Dropbox/Notes/notes.org")
(setq org-capture-bookmark nil)

Org setup

Speed commands are a nice and quick way to perform certain actions while at the beginning of a heading. It’s not activated by default.

See the doc for speed keys by checking out the documentation for speed keys in Org mode.

(setq org-use-speed-commands t)
(setq org-image-actual-width 550)
(setq org-highlight-latex-and-related '(latex script entities))

Org tags

The default value is -77, which is weird for smaller width windows. I’d rather have the tags align horizontally with the header. 45 is a good column number to do that.

(setq org-tags-column 45)

Org babel languages

(use-package ob-restclient
  :ensure t)
(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)
   (C . t)
   (calc . t)
   (latex . t)
   (java . t)
   (ruby . t)
   (lisp . t)
   (scheme . t)
   (shell . t)
   (sqlite . t)
   (js . t)
   (restclient . t)
   (ledger . t)))

(defun my-org-confirm-babel-evaluate (lang body)
  "Do not confirm evaluation for these languages."
  (not (or (string= lang "C")
           (string= lang "java")
           (string= lang "python")
           (string= lang "emacs-lisp")
           (string= lang "sqlite"))))
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)

Org babel/source blocks

I like to have source blocks properly syntax highlighted and with the editing popup window staying within the same window so all the windows don’t jump around. Also, having the top and bottom trailing lines in the block is a waste of space, so we can remove them.

I noticed that fontification doesn’t work with markdown mode when the block is indented after editing it in the org src buffer—the leading #s for headers don’t get fontified properly because they appear as Org comments. Setting org-src-preserve-indentation makes things consistent as it doesn’t pad source blocks with leading spaces.

(setq org-src-fontify-natively t
      org-src-window-setup 'current-window
      org-src-strip-leading-and-trailing-blank-lines t
      org-src-preserve-indentation t
      org-src-tab-acts-natively t)

Org templates

Source block templates

(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("sh" . "src sh"))
(add-to-list 'org-structure-template-alist '("md" . "src markdown"))
(add-to-list 'org-structure-template-alist '("gq" . "src graphql"))

Org exporting

Pandoc exporter

Pandoc converts between a huge number of different file formats.

(use-package ox-pandoc
  :no-require t
  :defer 10
  :ensure t)

LaTeX exporting

I’ve had issues with getting BiBTeX to work correctly with the LaTeX exporter for PDF exporting. By changing the command to `latexmk` references appear in the PDF output like they should. Source: http://tex.stackexchange.com/a/161619.

(setq org-latex-pdf-process (list "latexmk -pdf %f"))

Tramp

(use-package tramp)

Locate

Using macOS Spotlight within Emacs by modifying the locate function.

I usually use ~helm-locate~, which does live updates the spotlight search list as you type a query.

;; mdfind is the command line interface to Spotlight
(setq locate-command "mdfind")

Window

Convenient keybindings to resize windows.

(bind-key "s-C-<left>"  'shrink-window-horizontally)
(bind-key "s-C-<right>" 'enlarge-window-horizontally)
(bind-key "s-C-<down>"  'shrink-window)
(bind-key "s-C-<up>"    'enlarge-window)

Whenever I split windows, I usually do so and also switch to the other window as well, so might as well rebind the splitting key bindings to do just that to reduce the repetition.

(defun vsplit-other-window ()
  "Splits the window vertically and switches to that window."
  (interactive)
  (split-window-vertically)
  (other-window 1 nil))
(defun hsplit-other-window ()
  "Splits the window horizontally and switches to that window."
  (interactive)
  (split-window-horizontally)
  (other-window 1 nil))

(bind-key "C-x 2" 'vsplit-other-window)
(bind-key "C-x 3" 'hsplit-other-window)

Winner mode

Winner mode allows you to undo/redo changes to window changes in Emacs and allows you.

(use-package winner
  :config
  (winner-mode t)
  :bind (("C-c <left>" . winner-undo)
         ("C-c <right>" . winner-redo)))

Transpose frame

(use-package transpose-frame
  :ensure t
  :bind ("C-c t" . transpose-frame))

Ido

(use-package ido
  :disabled t
  :init
  (setq ido-enable-flex-matching t)
  (setq ido-everywhere t)
  (ido-mode t)
  (use-package ido-vertical-mode
    :ensure t
    :defer t
    :init (ido-vertical-mode 1)
    (setq ido-vertical-define-keys 'C-n-and-C-p-only)))

Whitespace mode

(use-package whitespace
  :bind ("<f10>" . whitespace-mode))

Keybindings

Revert buffer

(bind-key "C-c u" #'revert-buffer)

hippie-expand

(use-package hippie-exp
  :bind (("C-c /" . hippie-expand)))

auth-sources

(use-package auth-source
  :config
  (customize-set-variable 'auth-sources
                          '((:source "~/.authinfo.gpg"))))

ELPA packages

These are the packages that are not built into Emacs.

Ag

(use-package ag
  :commands ag
  :ensure t)

Ace Window

ace-window is a package that uses the same idea from ace-jump-mode for buffer navigation, but applies it to windows. The default keys are 1-9, but it’s faster to access the keys on the home row, so that’s what I have them set to (with respect to Dvorak, of course).

(use-package ace-window
  :ensure t
  :config
  (setq aw-keys '(?a ?o ?e ?u ?h ?t ?n ?s))
  (ace-window-display-mode)
  :bind ("s-o" . ace-window))

C-Eldoc

This package displays function signatures in the mode line.

(use-package c-eldoc
  :commands c-turn-on-eldoc-mode
  :ensure t
  :init (add-hook 'c-mode-hook #'c-turn-on-eldoc-mode))

Clojure

(use-package clojure-mode
  :defer t
  :ensure t)

Cider

(use-package cider
  :ensure t)

Dash

Integration with Dash, the API documentation browser on macOS. The binding s-D is the same as Cmd-Shift-D, the same binding that dash uses in Android Studio (trying to keep things consistent with the tools I use).

(use-package dash-at-point
  :if (string-equal system-type "darwin")
  :ensure t
  :bind (("s-D"     . dash-at-point)
         ("C-c e"   . dash-at-point-with-docset)))

Docker

(use-package docker
  :ensure t
  :bind (("C-c d c" . docker-containers)
         ("C-c d i" . docker-images)
         ("C-c d v" . docker-volumes)))

Dockerfile

(use-package dockerfile-mode
  :ensure t)

Kubernetes

(use-package kubernetes
  :ensure t
  :commands (kubernetes-overview))

Helm

(use-package helm
  :disabled t
  :ensure t
  :diminish helm-mode
  :bind (("C-c h" . helm-command-prefix)
         ("C-x b" . helm-mini)
         ("C-`" . helm-resume)
         ("M-x" . helm-M-x)
         ("C-x C-f" . helm-find-files)
         ("C-x C-r" . helm-recentf))
  :init
  (require 'helm-config)
  :config
  (setq helm-locate-command "mdfind -interpret -name %s %s"
        helm-ff-newfile-prompt-p nil
        helm-M-x-fuzzy-match t)
  (helm-mode))
(use-package helm-projectile
  :ensure t
  :after helm-mode
  :commands helm-projectile
  :bind ("C-c p h" . helm-projectile))
(use-package helm-ag
  :ensure t
  :after helm-mode)
(use-package helm-swoop
  :ensure t
  :after helm-mode
  :bind ("H-w" . helm-swoop))

Ivy

(use-package ivy
  :ensure t
  :diminish (ivy-mode . "")
  :bind
  (:map ivy-mode-map
   ("C-'" . ivy-avy))
  :config
  (ivy-mode 1)
  ;; add ‘recentf-mode’ and bookmarks to ‘ivy-switch-buffer’.
  (setq ivy-use-virtual-buffers t)
  ;; number of result lines to display
  (setq ivy-height 10)
  ;; Show candidate index and total count
  (setq ivy-count-format "(%d/%d) ")
  ;; no regexp by default
  (setq ivy-initial-inputs-alist nil)
  ;; configure regexp engine.
  (setq ivy-re-builders-alist
	;; allow input not in order
        '((t   . ivy--regex-ignore-order))))
(use-package avy
  :ensure t
  :bind ("C-S-s" . avy-goto-char))
(use-package counsel
  :ensure t
  :bind (("M-x" . counsel-M-x)
         ("C-x C-r" . counsel-recentf)
         ("C-c h i" . counsel-imenu)
         ("C-h v" . counsel-describe-variable)
         ("C-h f" . counsel-describe-function)))
(use-package counsel-projectile
  :ensure t
  :config
  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
  (counsel-projectile-mode)
  (setq counsel-projectile-switch-project-action 'dired))
(use-package swiper
  :ensure t
  :bind (("C-c s" . swiper)))

Magit

A great interface for git projects. It’s much more pleasant to use than the git interface on the command line. Use an easy keybinding to access magit.

(use-package magit
  :ensure t
  :defer t
  :bind (("C-c g" . magit-status)
         ("C-c G" . magit-dispatch)
         ("C-c m l" . magit-log-buffer-file)
         ("C-c m b" . magit-blame))
  :config
  (setq magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
  (setq magit-diff-refine-hunk t))

Fullscreen magit

The following code makes magit-status run alone in the frame, and then restores the old window configuration when you quit out of magit.

No more juggling windows after commiting. It’s magit bliss.

Source: Magnar Sveen

;; full screen magit-status
(defadvice magit-status (around magit-fullscreen activate)
  (window-configuration-to-register :magit-fullscreen)
  ad-do-it
  (delete-other-windows))

(defun magit-quit-session ()
  "Restores the previous window configuration and kills the magit buffer"
  (interactive)
  (kill-buffer)
  (jump-to-register :magit-fullscreen))

Forge

Magit extension to interact with GitHub/GitLab.

(use-package forge
  :ensure t
  :after magit)

Edit With Emacs

Editing input boxes from Chrome with Emacs. Pretty useful to keep all significant text-writing on the web within emacs. I typically use this with posts on Discourse, which has a post editor that overrides normal Emacs key bindings with other functions. As such, markdown-mode is used.

(use-package edit-server
  :ensure t
  :config
  (edit-server-start)
  (setq edit-server-default-major-mode 'markdown-mode)
  (setq edit-server-new-frame nil))

Elfeed

(use-package elfeed
  :ensure t
  :defer t)

Expand region

(use-package expand-region
  :ensure t
  :bind ("C-@" . er/expand-region))

Flycheck

Still need to set up hooks so that flycheck automatically runs in python mode, etc. js2-mode is already really good for the syntax checks, so I probably don’t need the jshint checks with flycheck for it.

(use-package flycheck
  :ensure t
  :defer 10
  :config (setq flycheck-html-tidy-executable "tidy5"))

Linter setups

Install the HTML5/CSS/JavaScript linters.

brew tap homebrew/dupes
brew install tidy
npm install -g jshint
npm install -g csslint

Git Link

(use-package git-link
  :ensure t)

graphviz-dot-mode

Create a .dot buffer in dot-mode and then quickly preview the rendered dot diagram with C-c C-p.

(use-package graphviz-dot-mode
  :ensure t)

Macrostep

Macrostep allows you to see what Elisp macros expand to. Learned about it from the package highlight talk for use-package.

(use-package macrostep
  :ensure t
  :bind ("H-`" . macrostep-expand))

Markdown mode

Install cmark or your Markdown processor of choice and set it as markdown-command before using the live previewer commands.

(use-package markdown-mode
  :ensure t
  :mode (("\\.markdown\\'" . markdown-mode)
         ("\\.md\\'"       . markdown-mode))
  :config
  (setq markdown-command "cmark"))

Multiple cursors

We’ll also need to (require 'multiple-cusors) because of an autoload issue.

(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-c C-<"     . mc/mark-all-like-this)
         ("C-!"         . mc/mark-next-symbol-like-this)))

Mustache

(use-package mustache-mode
  :ensure t)

pinentry

(use-package pinentry
  :ensure t
  :if (string-equal system-type "gnu/linux")
  :config
  (pinentry-start))

Projectile

Project navigation and management library for Emacs.

http://batsov.com/projectile/

(use-package projectile
  :ensure t
  :diminish projectile-mode
  :commands (projectile-mode projectile-switch-project)
  :bind (("C-c p p" . projectile-switch-project)
         ("C-c p s s" . projectile-ag)
         ("C-c p s r" . projectile-ripgrep))
  :config
  (setq projectile-keymap-prefix (kbd "C-c p"))
  (projectile-global-mode t)
  (setq projectile-enable-caching t)
  (setq projectile-switch-project-action 'projectile-dired))

Python

Integrates with IPython.

(use-package python-mode
  :defer t
  :ensure t)

Racket

Starting to use Racket now, mainly for programming paradigms class, though I’m looking forward to some “REPL-driven development” whenever I get the chance.

(use-package racket-mode
  :ensure t
  :commands racket-mode
  :config
  (setq racket-smart-open-bracket-enable t))

(use-package geiser
  :ensure t
  :defer t
  :config
  (setq geiser-default-implementation '(racket)))

Restclient

See Emacs Rocks! Episode 15 to learn how restclient can help out with testing APIs from within Emacs. The HTTP calls you make in the buffer aren’t constrainted within Emacs; there’s the restclient-copy-curl-command to get the equivalent curl call string to keep things portable.

(use-package restclient
  :ensure t
  :mode ("\\.restclient\\'" . restclient-mode))

Smartscan

Quickly jumps between other symbols found at point in Emacs.

http://www.masteringemacs.org/article/smart-scan-jump-symbols-buffer

(use-package smartscan
  :ensure t
  :config (global-smartscan-mode 1)
  :bind (("s-n" . smartscan-symbol-go-forward)
         ("s-p" . smartscan-symbol-go-backward)))

Smex

Smex integrates ido with M-x. I used to use this before moving on to helm.

(use-package smex
  :if (not (featurep 'helm-mode))
  :disabled t
  :ensure t
  :bind ("M-x" . smex))

Smoothscrolling

This makes it so C-n-ing and C-p-ing won’t make the buffer jump around so much.

(use-package smooth-scrolling
  :ensure t
  :config
  (smooth-scrolling-mode))

Webmode

(use-package web-mode
  :ensure t)

Yasnippet

Yeah, snippets! I start with snippets from Andrea Crotti’s collection and have also modified them and added my own.

It takes a few seconds to load and I don’t need them immediately when Emacs starts up, so we can defer loading yasnippet until there’s some idle time.

Setting yas-indent-line to 'fixed fixes Python indentation behavior when typing a templated snippet.

(use-package yasnippet
  :ensure t
  :diminish yas-minor-mode
  :config
  (setq yas-snippet-dirs (concat user-emacs-directory "snippets"))
  (setq yas-indent-line 'fixed)
  (yas-global-mode))

Emmet

According to their website, “Emmet — the essential toolkit for web-developers.”

(use-package emmet-mode
  :ensure t
  :commands emmet-mode
  :config
  (add-hook 'html-mode-hook 'emmet-mode)
  (add-hook 'css-mode-hookg 'emmet-mode))

Zoom-frm

zoom-frm is a nice package that allows you to resize the text of entire Emacs frames (this includes text in the buffer, mode line, and minibuffer). The zoom-in/out command acts similar to the text-scale-adjust command—you can chain zooming in, out, or resetting to the default size once the command has been initially called.

Changing the frame-zoom-font-difference essentially enables a “presentation mode” when calling toggle-zoom-frame.

(use-package frame-fns
  :load-path "site-lisp/frame-fns"
  :no-require t)
(use-package frame-cmds
  :load-path "site-lisp/frame-cmds"
  :no-require t)
(use-package zoom-frm
  :load-path "site-lisp/zoom-frm"
  :bind (("C-M-=" . zoom-in/out)
         ("H-z"   . toggle-zoom-frame)
         ("s-<f1>" . toggle-zoom-frame))
  :config
  (setq frame-zoom-font-difference 10))

Scratch

Convenient package to create *scratch* buffers that are based on the current buffer’s major mode. This is more convienent than manually creating a buffer to do some scratch work or reusing the initial *scratch* buffer.

(use-package scratch
  :ensure t
  :commands scratch)

Shell pop

(use-package shell-pop
  :ensure t
  :bind ("M-<f12>" . shell-pop))

SLIME

The Superior Lisp Interaction Mode for Emacs. First, Install SBCL with brew.

brew install sbcl
(use-package slime
  :ensure t
  :defer 10
  :init
  (setq inferior-lisp-program "/usr/local/bin/sbcl")
  (add-to-list 'slime-contribs 'slime-fancy))

Quickrun

(use-package quickrun
  :defer 10
  :ensure t
  :bind ("C-c r" . quickrun))

Visible mode

I found out about this mode by looking through simple.el. I use it to see raw org-mode files without going to a different mode like text-mode, which is what I had done in order to see invisible text (with org hyperlinks). The entire buffer contents will be visible while still being in org mode.

(use-package visible-mode
  :bind (("H-v" . visible-mode)
         ("s-<f2>" . visible-mode)))

Undo Tree

(use-package undo-tree
  :ensure t)

Crux

Collection of Ridiculously Useful eXtensions

(use-package crux
  :ensure t
  :bind (("C-c o o" . crux-open-with)
         ("C-c o u" . crux-view-url)))

graphql-mode

(use-package graphql-mode
  :mode (("\\.q\\'" . graphql-mode))
  :ensure t)

json-mode

(use-package json-mode
  :ensure t
  :config
  (customize-set-variable 'json-mode-hook
                          #'(lambda ()
                              (setq tab-width 2))))

terminal-here

(use-package terminal-here
  :ensure t
  :if (string-equal system-type "gnu/linux")
  :bind (("C-c o t" . terminal-here-launch)
         ("C-c o p" . terminal-here-project-launch)))

yaml-mode

(use-package yaml-mode
  :ensure t)

company-mode

Auto completion.

(use-package company
  :ensure t
  :config
  (setq company-tooltip-limit 20)
  (setq company-idle-delay .15)
  (setq company-echo-delay 0)
  (setq company-begin-commands '(self-insert-command))
  (define-key company-active-map (kbd "C-n") #'company-select-next)
  (define-key company-active-map (kbd "C-p") #'company-select-previous))

go-mode

First, install all of the Go tools.

go get -u golang.org/x/tools/...

This includes tools like, godef, goimports, and guru which are used in this config.

(use-package go-mode
  :ensure t
  :config
  (bind-key "C-." #'godef-jump go-mode-map)
  (bind-key "C-x 4 C-." #'godef-jump-other-window go-mode-map)
  (bind-key "C-c C-r" #'go-remove-unused-imports)
  (add-hook 'before-save-hook #'gofmt-before-save)
  (setq gofmt-command "goimports")
  (customize-set-variable 'go-mode-hook
                          #'(lambda ()
                              (setq tab-width 4)
                              (setq display-line-numbers 'relative))))

Use go-eldoc to see things like function signatures in the modeline .

(use-package go-eldoc
  :ensure t
  :config
  (go-eldoc-setup))

go-guru is great for source code analysis. The most common thing I use it for is go-guru-referrers, which finds all references to a particular thing across the workspace.

(use-package go-guru
  :ensure t
  :config
  ;; Search entire workspace
  (customize-set-variable 'go-guru-scope "...")
  (add-hook 'go-mode-hook #'go-guru-hl-identifier-mode))

To set up autocompletion with Go, first get gocode: https://github.com/nsf/gocode.

go get -u github.com/nsf/gocode
(use-package company-go
  :ensure t
  :config
  (add-hook 'go-mode-hook (lambda ()
                            (set (make-local-variable 'company-backends)
                                 '(company-go))
                            (company-mode))))
(use-package gotest
  :ensure t
  :bind (:map go-mode-map
              ("C-c C-t p" . go-test-current-project)
              ("C-c C-t f" . go-test-current-file)
              ("C-c C-t ." . go-test-current-test)
              ("C-c r" . go-run))
  :config
  (setq go-test-verbose t))

jade-mode

(use-package jade-mode
  :ensure t
  :config
  (add-hook 'jade-mode-hook
            #'(lambda ()
                (setq tab-width 2)
                (setq indent-tabs-mode t))))

nginx-mode

(use-package nginx-mode
  :ensure t
  :config
  (setq nginx-indent-level 2))

Keychain

Install ~keychain~ first, which will manage the SSH agent on Linux systems. This is useful when using SSH keys with passwords, such as with SSH git access or SSHing into other machines. The following must be run already before starting Emacs.

eval "$(keychain --eval --agents ssh id_rsa)"
(use-package keychain-environment
  :if (string-equal system-type "gnu/linux")
  :ensure t
  :config
  (keychain-refresh-environment))

Computer-specific settings

Load some computer-specific settings, such as the name and email address. The way the settings are loaded is based off of Magnar Sveen’s config.

In my case, the computers I use usually use the same username (my name, go figure), so instead of basing the specific settings from the username, I use the hostname. The system-name is a built-in function which returns the host name of the machine you are running on, as a string.

(defvar mai/user-settings-dir nil
  "The directory with user-specific Emacs settings for this
  user.")

;; Settings for currently logged in user
(setq mai/user-settings-dir
      (concat user-emacs-directory "users/" (system-name)))
(add-to-list 'load-path mai/user-settings-dir)

;; Load settings specific for the current user
(when (file-exists-p mai/user-settings-dir)
  (mapc 'load (directory-files mai/user-settings-dir nil "^[^#].*el$")))

Finda

(load "~/.finda/integrations/emacs/finda.el" t)

Languages

C/Java

I don’t like the default way that Emacs handles indentation. For instance,

int main(int argc, char *argv[])
{
  /* What's with the brace alignment? */
  if (check)
    {
    }
  return 0;
}
switch (number)
    {
    case 1:
        doStuff();
        break;
    case 2:
        doStuff();
        break;
    default:
        break;
    }

Luckily, I can modify the way Emacs formats code with this configuration.

(defun my-c-mode-hook ()
  (setq c-basic-offset 4)
  (c-set-offset 'substatement-open 0)   ; Curly braces alignment
  (c-set-offset 'case-label 4))         ; Switch case statements alignment

(add-hook 'c-mode-hook 'my-c-mode-hook)
(add-hook 'java-mode-hook 'my-c-mode-hook)

Misc

Non-ELPA packages

Some packages aren’t in ELPA, so they’re stored in the site-lisp directory and loaded here.

Titlecase

As in the titlecase package instructions, the titlecase command needs to be in the $PATH for this to work.

(use-package titlecase
  :load-path "~/.emacs.d/site-lisp")

Display Time

When displaying the time with display-time-mode, I don’t care about the load average.

(setq display-time-default-load-average nil)

Display Battery Mode

See the documentation for battery-mode-line-format for the format characters.

(setq battery-mode-line-format "[%b%p%% %t]")

Docview keybindings

Convenience bindings to use doc-view with the arrow keys.

(use-package doc-view
  :commands doc-view-mode
  :config
  (define-key doc-view-mode-map (kbd "<right>") 'doc-view-next-page)
  (define-key doc-view-mode-map (kbd "<left>") 'doc-view-previous-page))

OS X scrolling

(setq mouse-wheel-scroll-amount (quote (0.01)))

Emacsclient

(use-package server
  :config
  (server-start))

Dired

(use-package dired
  :config
  (customize-set-variable 'dired-listing-switches
                          "-avl"))

Typescript

(use-package typescript-mode
  :ensure t)

Settings

(global-hl-line-mode 1)