Martin Foot's Emacs Configuration

Table of Contents

This file stores my emacs configuration. The latest version can be found on GitHub. It is written using org-mode which is an excellent way to organise notes and, as it turns out, an excellent way to organise my configuration file. It is intended to be used with org-babel-load-file which parses this file, generates a config.el file, then executes that during emacs startup. In this way my Emacs configuration serves as both the configuration settings and a high level documentation of those settings. It provides an incredibly convenient way to organise configuration the full benefit of org mode's functionality available within the configuration file itself. More information can be found in the Installation instructions section.

I am not a long term emacs user yet, having started in October 2015 after using vim for around 7 years. As such I use evil-mode all the time. This file is a work in progress that I try to keep organised. Like many people experiencing a new editor rather than spending an extended period of time reading emacs' extensive documentation, the configuration here has been a mix of searching and reading other people's .emacs files. I would recommend taking small parts of it and asking the inbuilt help system what each command does. I've tried to keep each section documented. You can do this with C-h a.

Organising my configuration in this way came about after a general interest in literate programming and after seeing these:

I already make notes on all my work and a lot of personal tasks throughout the day. This way I know I can confirm exactly what queries I executed or steps I took on a support request, or the methods I took at resolving a certain issue. Since I've been using org to do this, having org's power inside my editor configuration was a huge plus.

This file makes a lot of use of the use-package function. This is a really nice way to keep the installation of a package, it's keybindings, configuration, packaged together in the config file. There's a good description on how it works here and you can see the project page here.

Note: Parts of this file are marked TODO. These are sections that require more work. They may not be properly documented, may be badly organised (maybe they should be part of other sections), or could be part of my old emacs configuration from before I used org-mode that I still haven't converted.

1 Installation instructions

Copy the <a href="config.org">raw version of this file</a> to <code>~/.emacs.d/config.org</code>.

Then add (org-babel-load-file (concat user-emacs-directory "config.org")) to ~/.emacs.

Here is the contents of my ~/.emacs file:

;; Martin's .emacs file
;;
;; Author: Martin Foot <martin@mfoot.com>

; Limit garbage collection to speed up startup (TODO revert this after the config is loaded)
(setq gc-cons-threshold 100000000)

;; Load the config
(org-babel-load-file (concat user-emacs-directory "config.org"))

(setq gc-cons-threshold 800000)

That's it.

The reason that this works is that some parts of this file are carefully organised. org-babel-load-file pulls out and executes emacs-lisp code blocks in the order they're in the file. This means that it's very important that my Package repositories section comes before any of the other non-standard config.

Small note for readers of the source file: The example above uses the org babel source language of lisp rather than emacs-lisp, meaning that it won't be executed by org-babel-load-file on startup. Initially I had a tangle block here so ~/.emacs.d/.emacs would be written conveniently by org, but it adds to the startup time of every emacs load. Removing the tangle block meant a recursive load, so my workaround is to change the source language. org-babel-load-file will only evaluate emacs-lisp blocks.

2 Package repositories

I use Melpa and Marmalade for repositories as well as Org's official repository.

(require 'package)
(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
(add-to-list 'package-archives '("marmalade" . "https://marmalade-repo.org/packages/") t)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(package-initialize)

Then, since I use use-package for every package from the repositories, initialise this first.

Note this is currently commented, it exists in .emacs.

;(unless (package-installed-p 'use-package)
;  (package-refresh-contents)
;  (package-install 'use-package))
;
;(eval-when-compile
;  (setq use-package-always-ensure t)
;  (setq use-package-verbose t) ; Put slow loading packages / config warnings in the *Messages* buffer
;  (require 'use-package)
;)

use-package has support for removing minor modes from the bottom. This requires the diminish package.

(use-package diminish
  :defer t
)

3 Startup time benchmarking

It's possible to benchmark startup time in emacs. This is useful if evaluating this gets too slow. I keep these lines commented as it's not something I do generally. It also isn't safe to run on every machine since the benchmark-init-el package needs to be downloaded manually.

;(add-to-list 'load-path "/home/martinfoot/repositories/benchmark-init-el/")
;(require 'benchmark-init-loaddefs)
;(benchmark-init/activate)

4 Load path

TODO: Fix this!

;;(add-to-list 'load-path "~/org-mode/lisp/")

5 User information

(setq user-full-name "Martin Foot"
      user-mail-address "martin@mfoot.com")

6 Parentheses

Use electric-pair-mode to automatically close inserted parentheses and braces. I don't have this enabled in text modes because when using org-mode it makes inserting links annoying.

(add-hook 'prog-mode-hook (lambda () (electric-pair-mode)))

show-paren-mode makes emacs highlight closing parentheses, braces, and curly braces.

(show-paren-mode)           ; Automatically highlight parenthesis pairs
(setq show-paren-delay 0) ; show the paren match immediately

Then I use [[https://github.com/Fanael/rainbow-delimiters][rainbow-delimiters]] to highlight nested parentheses in different colours.

(use-package rainbow-delimiters
  :diminish
  :defer t
  :config
  (add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
)

7 Fill columns and line highlighting

I find a 120 character line length is best for modern screens. Individual languages/major modes can override this.

In text-based modes (non-programming modes) I enable automatic line wrapping also.

(setq-default fill-column 120)
(add-hook 'text-mode-hook 'auto-fill-mode)

I also like a highlight on the screen to show the current cursor line.

(global-hl-line-mode)

I also like to highlight git changes in buffers in a git repository:

(use-package git-gutter+
  :diminish
  :defer t
  :config
  (global-git-gutter+-mode)
)

8 Indentation guides

When working with structured code it's nice to have an indentation guide.

(use-package indent-guide
  :defer t
  :diminish
  :config
  (add-hook 'prog-mode-hook (lambda () (indent-guide-mode)))
)

9 Shortcut help

It's very difficult to remember all the shortcuts available in emacs. The guide-key plugin pops up a list of available suggestions after a little while.

:diminish guide-key-mode configures the mode to not show up in the list of minor modes.

I've configured it to wait 0.5 seconds before popping up the suggestions list.

C-c
Active mode specific commands
C-x
Emacs commands
(use-package which-key
  :diminish which-key-mode
  :defer t
  :init
  (setq which-key-idle-delay 0.5)
  (which-key-mode)
)

10 Line numbering and cursor position

I've had a slight change of heart. Typically I would show line numbers everywhere, but now, instead, I leave them turned off to save space. If I need to jump to a specific line, I'm using Avy mode to enable g l for go to line. This is just as fast. See my Window navigation and scrolling section.

I also show the current cursor position column number in the bottom left of the screen:

(column-number-mode)

11 Yes or no prompts

Use 'y' or 'n' instead of 'yes' and 'no' in interactive prompts. This saves typing.

(defalias 'yes-or-no-p 'y-or-n-p)

I also configure emacs to ask me if I really want to quit when hitting C-x C-c because I find this way too easy to do.

(setq confirm-kill-emacs 'y-or-n-p)

12 Multiple cursors

Multiple cursors is cool.

(use-package multiple-cursors
  :diminish multiple-cursors-mode
  :defer t
  :init
  (global-set-key (kbd "C->") 'mc/mark-next-like-this)
  (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
  (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
)

13 Symbolic links

By default emacs doesn't follow symlinks

(setq vc-follow-symlinks t)

14 OS Clipboard integration

Add proper support for the OS clipboard integrations. Only tested under X.

First we enable the emacs copy buffer to be linked to the OS clipboard. Lines copied from the OS can be pasted into emacs and lines copied from emacs can be pasted into other OS windows.

(setq x-select-enable-clipboard t)

Now we enable 'primary selection'. The clipboard config above is for the operating system copy buffer with C-c and C-v. Primary selection is the mouse select buffer that usually works as pasted with a middle click. Enabling this allows selected text in emacs to be copied there so I can select in the program and paste into somewhere else using X.

(setq x-select-enable-primary t)
(setq mouse-drag-copy-region t)

15 Temporary backup files

Auto backup can be disabled in emacs with (setq make-backup-files nil) but rather than disabling them we can simply move the directory that they get placed in. This keeps them out of the way in case we need them.

I've used ~/.emacs-backups because my ~/.emacs.d is in git, I don't need to keep backups.

; From http://www.emacswiki.org/emacs/BackupDirectory
; and http://stackoverflow.com/questions/151945/how-do-i-control-how-emacs-makes-backup-files
(setq
   backup-by-copying t ; Ensure backups are copied, not renamed. Important for symlinks
   backup-directory-alist '(("" . "~/.emacs-backups")) ; Keep backups in ~/.emacs-backups, not the same directory tree
   delete-old-versions t ; Delete old versions without prompting
   kept-new-versions 10 ; Keep multiple versioned backup files
   kept-old-versions 0 ; Don't keep any beyond that
   version-control t) ; Use versioned backups

(setq vc-make-backup-files t) ; Backup even when it's a version controlled project

16 Font size

Add some keybindings to increase and decrease the font size

(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
;; C-x C-0 restores the default font size

17 Startup message

Don't show the default emacs startup message when it's opened

(setq inhibit-startup-message t)

Let's also show a fortune message in the scratch buffer when we start emacs:

Source here

(use-package fortune-cookie
  :defer t
  :diminish
  :config
  (setq fortune-cookie-cowsay-enable nil) ; Disable cowsay
  (fortune-cookie-mode)                   ; Enable fortune cookie mode
)

18 Terminal bells

Disable the terminal bell. Use a visible bell instead. A non-nil value causes emacs to try and flash the frame to represent a bell.

(setq visible-bell 1)

19 Menu bar

Don't show emacs' menu bar - I remember enough shortcuts and understand how to use the inbuilt help system if I don't remember the shortcut for something. When we're using graphical emacs, also disable the tooltips for the mouse an the scroll bar.

(when window-system
  (tooltip-mode -1)
  (tool-bar-mode -1)
  (scroll-bar-mode -1))

(menu-bar-mode -1)

20 Whitespace

Whitespace mode is enabled for all programming and text buffers.

(add-hook 'prog-mode-hook (lambda () (whitespace-mode)))
(add-hook 'text-mode-hook (lambda () (whitespace-mode)))

20.1 Trailing whitespace

Delete trailing whitespace automatically on save. I used to configure editors to highlight trailing whitespace, but it's pointless if it can be auto-deleted on save.

(add-hook 'before-save-hook 'delete-trailing-whitespace)

I also don't like seeing tabs mixed with spaces. This section needs some work however so is currently commented out. I need to customise the faces that whitespace-mode uses.

(setq whitespace-line-column 118) ; Highlight lines over 118 characters in whitespace-mode

20.2 Default emacs backspace behaviour

I despise emacs' default behaviour when hitting backspaces on tabs - it converts the tab into the tab-width number of spaces and inserts tab-width -1 spaces. This seems like an insane default.

(setq backward-delete-char-untabify-method nil)

20.3 Tabs

Display tabs as four spaces:

(setq-default tab-width 4)
;(setq-default tab-always-indent 'complete)

Set up the tab stop list. This is what emacs uses when it can't find an appropriate tab stop - i.e how much to try indenting when tab is hit.

(setq-default tab-stop-list (number-sequence 4 200 4))

Insert tabs by default when auto-formatting.

(setq-default indent-tabs-mode t)

electric-indent-mode is used to automatically indent a new line when RET is typed.

(electric-indent-mode)

20.4 TODO Highlighting font faces

Highlighting colours for whitespace indicators:

(custom-set-faces
 '(whitespace-hspace ((t (:foreground "black"))))
 '(whitespace-space ((t (:foreground "dark slate gray" :slant italic))))
 '(whitespace-tab ((t (:foreground "black")))))

20.5 Highlighting long lines

I have whitespace mode configured to show lines longer than 120 characters.

(setq whitespace-line-column 120)

20.6 Showing mixed tabs-spaces

I highlight mixed spaces and tabs, and have whitespace mode clean out blank lines at the beginning and end of files.

(setq whitespace-style (quote (face space-before-tab empty space-after-tab)))

20.7 Highlighting colours

21 Region selection

expand-region makes it really easy to quickly select regions of text getting larger.

(use-package expand-region
  :diminish
  :defer t
  :bind ("C-=" . er/expand-region)
)

22 Org Mode

When I originally wrote this file I had a few simple customisations here. As I discovered new features and customised more things it became larger and larger and I had to split it into subcategories.

22.1 Key bindings

This table lists (and defines) the key bindings that I often use. Most are set to the defaults but it provides both an easy way to set variables and a handy reference. Check the source for how the table is used.

Note to future me: If the key is already bound and you're setting a default here, you can find out the name of the function with C-h k <key combination>.

TODO: These are the header rows but they cause problems with org-babel evaluation. I would also like to use org's monospace markup but this is causing problems. I need to strip the "=" character out of the value in the table cells.

Key binding Description Function
C-c a View agenda org-agenda
C-c b Switch buffer between different org mode files org-switchb
C-c C-t Assign or modify a TODO state for the current node org-todo
C-c C-a View current task attachments / attach a file to current task org-attach
C-c C-b Move to previous heading at the same level org-backwards-heading-same-level
C-c C-d Set the deadline for a task org-deadline
C-c C-e Launch the org export dialog org-export-dispatch
C-c C-w Refile (move subtree elsewhere in document) org-refile
C-c C-s Schedule current note/task org-schedule
C-c C-t Toggle todo state to any allowed org-todo
C-c C-o Open link at point org-open-at-point
C-c $ Archive the subtree to the archive file (useful as large org files are slow) org-archive-subtree
C-c ' Edit the current code block in buffer in the correct major mode org-edit-special
C-c * Recalculate formulas on an org mode table org-ctrl-c-star
C-c { Enable the debugger for table formulas org-table-toggle-formula-debugger
(defun mfoot-define-key-bindings (input)
  (global-set-key (kbd (car input)) (last input)))
  ; Handle using org's monospace markup (=example=)
  ;(global-set-key (kbd (remove "=" (car input))) (remove "=" (last input))))

(mapcar #'mfoot-define-key-bindings org-key-bindings)

22.2 Task tracking

22.2.1 Task transition timing

I like to see timestamps for task transitions but I don't want them filling up screen real estate. Logging these into drawers makes them easily expandable and collapsible.

(setq org-log-into-drawer t)

22.2.2 TODO State transitions

State transitions are largely based on this document but I use IN_PROGRESS instead of NEXT.

(setq org-todo-keywords
  (quote ((sequence "TODO(t!)" "IN_PROGRESS(i!)" "|" "DONE(d!)")
  (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)")))
)

I have defined colours for each task state. TODO is red (bad), blocked is orange and magnta (somewhat bad), in progress is gold (OK) and complete is green.

(setq org-todo-keyword-faces
  (quote (("TODO" :foreground "red" :weight bold)
    ("IN_PROGRESS" :foreground "gold" :weight bold)
    ("DONE" :foreground "forest green" :weight bold)
    ("WAITING" :foreground "orange" :weight bold)
    ("HOLD" :foreground "magenta" :weight bold)
    ("CANCELLED" :foreground "forest green" :weight bold)
  )
))

Since I have more than two states, moving between them with the default S-<left> and S-<right> is slow. This enables C-c c t as a shortcut for quickly choosing the state. some of the states below have an "@" symbol next to them. This lets me write a reason why a task is cancelled or blocked, or what it's waiting on. The buffer will appear when selecting such a state that lets me enter the reason.

(setq org-use-fast-todo-selection t)

22.3 Agenda

Tell org mode where my notes are usually kept. This allows the agenda view to index all my org notes for TODO items and scheduled items. Some of these directories won't exist on some machines so we filter the list at startup based on whether or not the file exists.

(require 'cl) ; remove-if-not is inside the common-lisp package
(setq org-agenda-files
  (remove-if-not
    'file-exists-p
    '(
      "~/Repositories/notes"
      "~/repositories/notes"
      "~/repositories/life"
      "~/repositories/life/projects"
      "~/repositories/life/tasks")))
;(setq org-agenda-files (remove-if-not 'file-exists-p '("~/Repositories/notes" "~/repositories/notes")))

Set up a key binding for the org agenda

(global-set-key (kbd "C-c a") 'org-agenda)

22.4 Switching buffers

org-iswitchb is a quick way to switch org mode buffers.

(global-set-key (kbd "C-c b") 'org-iswitchb)

22.5 LaTeX entities

Enable pretty entities - shows e.g. α β γ as UTF-8 characters.

(setq org-pretty-entities t)

22.6 Emphasis and italics

In org-mode we can use several different emphasis types using different emphasis markup. When a block of text has some emphasis on it, get emacs to hide the markup characters:

(setq org-hide-emphasis-markers t)

22.7 Syntax highlighting for code blocks

Ensure native syntax highlighting is used for inline source blocks in org files

(setq org-src-fontify-natively t)

When emacs source-formats a code block, don't add spaces before it (it messes with syntax highlighting in major modes).

(setq org-edit-src-content-indentation 0)

Configure the languages that Babel will automatically syntax highlight

;; active Babel languages
(org-babel-do-load-languages
 'org-babel-load-languages
 '((sql . t)
   (shell . t)
   (ditaa . t)
   (dot . t)
   (calc . t)
   (java . t)
   (emacs-lisp . t)
   (ruby . t)
   (python . t)
   (gnuplot . t)
   (latex . t)
  )
)

22.8 Displaying images referenced in org files

When we're using a GUI emacs we can display embedded images on startup

(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)
(add-hook 'org-mode-hook 'org-display-inline-images)
(add-hook 'org-mode-hook 'org-babel-result-hide-all)

I use graphical emacs so that I can display inline images. Set them to have a maximum size so large images don't fill the screen.

(setq org-image-actual-width 800)

22.9 Export org's checkboxes as HTML checkboxes on HTML export

When exporting to HTML change check boxes into actual HTML check boxes.

(setq org-html-checkbox-type 'html)

22.10 Ditaa (generating images from textual block diagrams)

I use ditaa for block diagrams. This executes a java program and needs to know where to find the jar.

(setq org-ditaa-jar-path "/home/martin/bin/ditaa0_9.jar")

22.11 To Do list and agenda

I've been using a single TODO list file and using org-capture to capture todo items to my org agenda from anywhere. This tends to happen at home rather than at work as my work org files contain appropriate TODOs arranged by date headers. At home and in my blog I can capture TODO items and put them in this directory.

(if (file-exists-p "~/Dropbox/life/life.org")
  (setq org-default-notes-file "~/Dropbox/life/life.org")
  (setq org-default-notes-file "~/repositories/notes/notes.org")
)

(define-key global-map "\C-cc" 'org-capture)

Customise the colours of TODO task priority indicators:

(setq org-priority-faces '((?A :foreground "dark orange") (?B :foreground "tomato") (?C :foreground "firebrick")))

I would like a custom agenda view that shows me unscheduled TODO tasks:

(setq org-agenda-custom-commands
      '(("c" . "My Custom Agendas")
        ("cu" "Unscheduled TODO"
         ((todo ""
                ((org-agenda-overriding-header "\nUnscheduled TODO")
                 (org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled)))))
         nil
         nil)))

We'll also make the agenda view appear in the current window, not in a right split. It messes up existing splits.

(setq org-agenda-window-setup 'current-window)

TODO: Investigate org-capture, org-agenda etc. See http://pages.sachachua.com/.emacs.d/Sacha.html#orgheadline45. There is a HUGE wealth of information here.

22.12 Emoji

I rarely use smiley faces in notes, but sometimes the occasion calls for it. Emojify displays these emojis in interactive buffers.

Example: :)

(use-package emojify
  :diminish
  :defer t
)

22.13 Improved bullet point styles

22.13.1 Section headers

The org-bullets package allows pretty unicode bullet points.

These are taken from https://thraxys.wordpress.com/2016/01/14/pimp-up-your-org-agenda/.

(use-package org-bullets
  :defer t
  :diminish
  :init
  (setq org-bullets-bullet-list '("◉" "◎" "⚫" "○" "►" "◇"))
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
)

22.13.2 Bullet point lists

For bullet lists, I use a slightly modified (removed * chars) versino of Howard Abrams' Better bullets changes.

(font-lock-add-keywords 'org-mode
                        '(("^ *\\(-\\) "
                           (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))

22.14 Screenshot attachment

I use a package called org-attach-screenshot which is awesome. Calling the function hides emacs and allows you to grab a section of the screen to insert, where it uses org-attach to save it, embeds it at the cursor position, and calls org-redisplay-inline-images. This is great for capturing issues at work.

(use-package org-attach-screenshot
  :diminish
  :bind
  (("C-c S" . org-attach-screenshot))
)

22.15 Presentations

I use org-reveal for HTML/JS presentations.

TODO: Get org-reveal installed.

;(add-to-list 'load-path "~/.emacs.d/org-reveal/")
;(setq org-reveal-root (expand-file-name (concat user-emacs-directory "reveal.js")))
;(add-hook 'org-mode-hook (lambda () (load-library "ox-reveal"))) ;

23 Blog

My blog uses a static site generator called Jekyll. This parses YAML files and produces static HTML content which I then host on Amazon S3. I really like the power of org-mode in Emacs, so this configuration block enables me to write blog posts using org-mode and then use org-mode's publishing system to publish these files in a format that Jekyll understands. I can then run Jekyll normally and it will take these org-published files and convert them into the static website. The configuration here is based on Using org to Blog with Jekyll, so reading through that is a good idea before trying to understand this. I've adapted it slightly to work with the latest org-mode (the publishing functions changed name). I've also added an third part of the project that handles exporting this org mode config file into a /static/emacs-config directory. Whenever I run org-publish-all the latest version of the config file gets pulled in and so the config file hosted on my blog is always as up-to-date as the latest blog post.

Here we define a list of projects for org mode. When using the export processor (C-c C-e) a projects option now appears at the bottom from any file. Two projects are defined; one for the blog posts that get processed with the HTML publishing function, and one for static content that gets copied verbatim. I can select a project and select either one of the two projects or the component project that wraps both of them. Org will maintain timestamps and caches of these files so that it doesn't regenerate what it doesn't have to.

TODO: Describe folder structure. Link to GitHub?

Additionally I embed my Google Analytics tracking code in my org mode config for purely informational purposes. Everybody likes cool statistics. To do this I define a custom HTML export that derives from the default org HTML export. It includes a translation function that calls the default HTML template renderer then uses string manipulation to insert the Google Analytics code at the end of the <body> tag.

(defun mfoot-append-google-analytics-tag (template info)
  "Appends my Google Analytics script segment to the body"
  (let ((html-template (org-html-template template info)))
    (let ((pos (string-match (regexp-quote "</body>") html-template)))
      (concat (substring html-template 0 pos)
        "<script type=\"text/javascript\">
          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

          ga('create', 'UA-24568117-1', 'auto');
          ga('send', 'pageview');

        </script>"
        (substring html-template pos)))))

(eval-after-load "org"
  '(progn
    (require 'ox-html)
    (org-export-define-derived-backend 'mfoot-html-with-google-analytics 'html
      :translate-alist
      '(
        (template . mfoot-append-google-analytics-tag)
      )
    )
  )
)

(defun mfoot-export-emacs-config-to-file
  (plist filename pub-dir)
  "Export current buffer to an blog HTML file"
  (let* ((extension (concat "." org-html-extension))
    (org-export-coding-system org-html-coding-system))
    (org-publish-org-to 'mfoot-html-with-google-analytics filename extension plist pub-dir)))

(setq org-publish-project-alist
  '(
     ("org-mfoot" ; Export my blog to the Jekyll format for ~jekyll build~
       :base-directory "~/repositories/mfoot.com/org/"
       :base-extension "org"

       ;; Path to your Jekyll project.
       :publishing-directory "~/repositories/mfoot.com/jekyll/"
       :recursive t
       :publishing-function org-html-publish-to-html
       :html-extension "html"
       :body-only t ;; Only export section between <body> </body>

       :section-numbers nil
       :with-toc nil
       :auto-index nil
       :auto-preamble nil
       :body-only t
       :auto-postamble nil
     )

    ("org-static-mfoot"
          :base-directory "~/repositories/mfoot.com/org/"
          :base-extension "css\\|js\\|png\\|jpg\\|gif"
          :publishing-directory "~/repositories/mfoot.com/jekyll"
          :recursive t
          :publishing-function org-publish-attachment
    )

    ("emacs-dotfiles-mfoot.com" ; Publish an HTML version of this file to the static folder.
      :base-directory "~/repositories/dotfiles/.emacs.d/"
      :base-extension "org"
      :publishing-directory "~/repositories/mfoot.com/jekyll/static/emacs-config"
      :exclude ".*"
      :include ("config.org")
      :publishing-function mfoot-export-emacs-config-to-file
      :html-extension "html"
    )

    ("emacs-config.org-mfoot.com" ; Publish the raw version of this file alongside the HTML
      :base-directory "~/repositories/dotfiles/.emacs.d/"
      :base-extension "org"
      :publishing-directory "~/repositories/mfoot.com/jekyll/static/emacs-config"
      :exclude ".*"
      :include ("config.org")
      :publishing-function org-publish-attachment
    )

    ("mfoot.com" :components (
      "org-mfoot"
      "org-static-mfoot"
      "emacs-dotfiles-mfoot.com"
      "emacs-config.org-mfoot.com"
    )
  )
))

In addition, I need to install the htmlize package to provide syntax highlighting when exporting HTML. See here for more information.

(use-package htmlize
  :defer t
)

In order to get images to work both inside emacs and inside the generated output I need to register a custom image format. Emacs currently will only generate <a href /> tags for images it can actually resolve on the filesystem. Since my images on my blog are hosted under /images, emacs will generate file:///images URLs which is not useful. The following allows me to use img:../images/2015/11/photo.png as an image reference and have both emacs and the html generator generate the correct paths. This is modified from this StackOverflow answer.

(defun org-custom-link-img-follow (path)
  (org-open-file-with-emacs
   (format "../images/%s" path)))

(defun org-custom-link-img-export (path desc format)
  (cond
   ((eq format 'html)
    (format "<img src=\"/images/%s\" alt=\"%s\"/>" path desc))))

(org-add-link-type "img" 'org-custom-link-img-follow 'org-custom-link-img-export)

TODO: Write some notes on how I publish this to S3 with s3-website. I always forget this and have to check my bash history.

24 Window navigation and scrolling

Scroll smoothly rather than by paging

(setq scroll-step 1)

When the cursor moves past the top or bottom of the window, scroll one line at a time rather than jumping. I don't like having to find my place in the file again.

(setq scroll-conservatively 10000)

Add vim-like navigation between panes in a window using windmove.

(windmove-default-keybindings)
(global-set-key (kbd "C-c <left>") 'windmove-left)
(global-set-key (kbd "C-c <right>") 'windmove-right)
(global-set-key (kbd "C-c <up>") 'windmove-up)
(global-set-key (kbd "C-c <down>") 'windmove-down)

I use avy-mode for fast buffer navigation. As I use evil-mode I've bound gc to goto-char and gl to goto-line. This makes for some really fast navigation of the visible buffer.

(use-package avy
  :defer t
  :diminish
  :init (progn
    (use-package evil
      :diminish
      :defer t
    )
  )
  :config
  (define-key evil-normal-state-map (kbd "gc") 'avy-goto-char)
  (define-key evil-normal-state-map (kbd "gl") 'avy-goto-line)
)

25 Reloading files

I swap branches a lot. auto-reload-mode will automatically reload opened buffers (prompting to save or not)

(global-auto-revert-mode t)

26 Programming language support

I use flycheck mode for syntax highlighting and linting when programming. See https://github.com/flycheck/flycheck

(use-package flycheck
  :defer t
  :diminish
  :config
  (add-hook 'prog-mode-hook (lambda () (flycheck-mode)))
)

26.1 YAML

Add a major mode for yaml highlighting

(use-package yaml-mode
  :defer t
  :diminish
)

26.2 C

At work we use BSD-style C/C++. We also set the default indentation to four spaces.

(setq-default c-basic-offset 4)
(setq-default c-default-style "bsd")

26.3 Go

I've just started learning about Go so this is very basic. Enough to run through the tutorials.

(use-package go-mode
  :mode "\\.go"
  :init
  (setenv "GOPATH" "~/go")
  :config
  (add-hook 'go-mode-hook (lambda () (
    (add-hook 'before-save-hook 'gofmt-before-save)
  )))
)

26.4 SCSS

When doing web development, SCSS is really useful. We use scss-mode for this. By default hitting tab will insert four spaces. We'll modify this to use two in the same format that Twitter's Bootstrap library uses.

(use-package scss-mode
  :defer t
  :config
  (add-hook 'scss-mode-hook (lambda () (
    (setq css-indent-offset 2)
    (setq tab-always-indent nil) ; electric-indent-mode will insert tabs otherwise to minimise whitespace characters
    (setq indent-tabs-mode nil) ; Always use spaces for scss
  )))
)

27 Autocompletion

I use company-mode for autocompletion. It's bound to C-<space> in a similar way to eclipse. Since I use evil-mode I don't use emacs' default mark combo.

(use-package company
  :defer t
  :diminish
  :config
  (progn
    ;; Company mode interferes with yasnippets, so this fixes it and integrates them:
    ;; http://emacs.stackexchange.com/questions/10431/get-company-to-show-suggestions-for-yasnippet-names
    ;; Add yasnippet support for all company backends
    ;; https://github.com/syl20bnr/spacemacs/pull/179
    (defvar company-mode/enable-yas t
      "Enable yasnippet for all backends.")

    (defun company-mode/backend-with-yas (backend)
      (if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
          backend
        (append (if (consp backend) backend (list backend))
                '(:with company-yasnippet))))
    (setq company-backends (mapcar #'company-mode/backend-with-yas company-backends))

    (global-company-mode)
  )
)

28 Code folding

I've discovered yafolding-mode for all my code folding needs.

(use-package yafolding
  :defer t
  :diminish
  :config
  (add-hook 'prog-mode-hook (lambda()  (yafolding-mode)))
)

29 Git

Magit is awesome. It's git integration with emacs and it's incredibly well made. Taking the time to learn it is highly advised.

(use-package magit
  :diminish
  :bind (("C-x g" . magit-status))
  :config
  (setq magit-completing-read-function 'ivy-completing-read)
)

30 TODO Base editor configuration

I came from Vim and some of the default emacs functionality felt weird to me.

(set-face-attribute 'default nil :height 90)

(tool-bar-mode -1)

;; TODO: Try and get projectile-ag to work. Is git grep better?
;; Human readable sizes in dired
(setq dired-listing-switches "-alh")

30.1 Mouse support for terminals

Enable the mouse when running in a terminal.

(when (not (window-system))
  (xterm-mouse-mode +1))

31 TODO Package installation

All of the packages that I use get automatically installed. First we define required-packages and then a function that iterates over all of them, installing each one. My ~/.emacs configures Melpa and Marmalade before this gets executed.

(defvar required-packages
  '(
    ;; https://github.com/benprew/flymake-puppet
    ;;
    ;; Puppet flymake support with puppet-lint
    flymake-puppet


    ;; https://github.com/purcell/whitespace-cleanup-mode
    ;;
    ;; whitespace-cleanup is a handy function, but putting it in
    ;; before-save-hook for every buffer is overkill, and causes messy
    ;; diffs when editing third-party code that did not initially have
    ;; clean whitespace.  Additionally, whitespace preferences are
    ;; often project-specific, and it's inconvenient to set up
    ;; before-save-hook in a .dir-locals.el file.
    ;; whitespace-cleanup-mode is a minor mode which calls
    ;; whitespace-cleanup before saving the current buffer, but only
    ;; if the whitespace in the buffer was initially clean. It
    ;; determines this by quickly checking to see if
    ;; whitespace-cleanup would have any effect on the buffer
    whitespace-cleanup-mode

    ;; Provides git modification markers in the left hand side gutter~
    ;; window that shows which lines have been locally modified
    ;; compared to the git index
    ;;
    ;; This is currently commented out because it does not work well
    ;; with linum-mode.
    ; git-gutter

  markdown-mode
    dockerfile-mode
    yaml-mode


    ;; https://github.com/genehack/smart-tab
    ;;
    ;; An intelligent tab completion function for Emacs
    ;; http://www.emacswiki.org/emacs/TabCompletion
    smart-tab

    indent-guide

    ;; https://github.com/lunaryorn/puppet-mode
    ;;
    ;; Puppet Mode lets you edit Puppet 3 manifests with GNU Emacs 24.
    puppet-mode


  ) "a list of packages to ensure are installed at launch.")

32 Remote shells

I use tramp to edit files on remote machines. Locally I use zsh but this might not be installed on the target machine. Use bash when connecting to a remote host.

TODO: This sets my local shell also. I don't really use M-x shell yet, but if I move further into the "everything inside emacs" way, something like this (with hostname-specificity removed) might be useful.

(setq shell-file-name "/bin/bash")

33 Themes and visual config

33.1 Custom-safe-themes

Emacs requires used themes to be whitelisted. This section contains all of the hash identifiers of themes I'm OK with loading.

(custom-set-variables
'(custom-safe-themes
   (quote
     ("a8245b7cc985a0610d71f9852e9f2767ad1b852c2bdea6f4aadc12cce9c4d6d0" "1297a022df4228b81bc0436230f211bad168a117282c20ddcba2db8c6a200743" "3c83b3676d796422704082049fc38b6966bcad960f896669dfc21a7a37a748fa" "d677ef584c6dfc0697901a44b885cc18e206f05114c8a3b7fde674fce6180879" "8aebf25556399b58091e533e455dd50a6a9cba958cc4ebb0aab175863c25b9a4"
      default))) )

33.2 Smart mode line

Smart Mode Line is a mode-line for emacs.

Smart Mode Line is a sexy mode-line for Emacs. It aims to be easy to read from small to large monitors by using colors, a prefix feature, and smart truncation.

This is customised to use the solarized theme.

(use-package solarized-theme
  :defer t
  :init
  (load-theme 'solarized-dark)
  :config
  (use-package smart-mode-line
    :defer t
    :diminish
    :config
    (progn
      (setq sml/no-confirm-load-theme t)
      (sml/setup)
    )
  )
)

33.3 Displaying the time

Displaying the time in the bottom right of the mode line is useful. This displays the time, system load over the last minute, and if I have new emails.

(display-time-mode 1)

34 Editor augmentation

34.1 Vim customisations

Evil mode provides vim-style keybindings for emacs. It makes it much more usable for a long-time vim user. Evil-surround is an emacs wrapper of Tim Pope's vim-surround plugin. Evil-tabs is an emacs mode that allows tabs with vim's tab keybindings.

(use-package evil
  :diminish
  :config (evil-mode) ; Enable evil mode globally
)

(use-package evil-surround
  :defer t
  :diminish
  :config (global-evil-surround-mode t)
)

(use-package evil-tabs
  :defer t
  :diminish
  :config (global-evil-tabs-mode t)
)

By default emacs doesn't tab indent to the current level when you hit return. Move to vim style.

Note: actually electric-indent-mode is used for this.

(global-set-key (kbd "RET") 'newline-and-indent)

34.2 Projectile

Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies(when feasible). For instance - finding project files has a portable implementation written in pure Emacs Lisp without the use of GNU find (but for performance sake an indexing mechanism backed by external commands exists as well).

(use-package projectile
  :diminish
  :config
  (projectile-global-mode)
)

I use helm-projectile-ag quite a lot which requires the ag package.

(use-package ag
  :defer t
  :diminish
)

34.3 Recentf mode

As well as using Projectile for browsing projects, recentf shows recently opened files in the buffer list for fast switching to them.

(use-package recentf
  :diminish
  :config
  (recentf-mode)
  :bind
  ("C-x C-r" . recentf-open-files)
)

34.4 Neotree

Sometimes I need to see the directory structure for the current file. The NeoTree plugin helps here with a togglable pane that will pop up and disappear with the F8 key.

(use-package neotree
  :bind
  ([f8] . neotree-toggle)
)

34.5 Swiper

I've switched to Swiper from Helm.

(use-package counsel
  :ensure t
)

(use-package swiper
  :ensure t
  :config
  (ivy-mode 1)
  (setq ivy-use-virtual-buffers t)
  (global-set-key "\C-s" 'swiper)
  (global-set-key (kbd "C-c C-r") 'ivy-resume)
  (global-set-key (kbd "<f6>") 'ivy-resume)
  (global-set-key (kbd "M-x") 'counsel-M-x)
  (global-set-key (kbd "C-x C-f") 'counsel-find-file)
  (global-set-key (kbd "<f2> u") 'counsel-unicode-char)
  (global-set-key (kbd "C-c j") 'counsel-git-grep)
  (global-set-key (kbd "C-c k") 'counsel-ag)
  (global-set-key (kbd "C-x l") 'counsel-locate)
  (define-key read-expression-map (kbd "C-r") 'counsel-expression-history)
  (setq projectile-completion-system 'ivy)
)

34.6 Anzu

Anzu shows how many strings match the regex you're replacing and show the effect of replacement as the substitution is typed. This is awesome. Using %s/using/foo/ you'll see the change to foo in the buffer.

http://pragmaticemacs.com/emacs/prettier-text-replacement-with-anzu/

(use-package anzu
  :diminish
  :defer t
  :config (global-anzu-mode)
  :bind (
    ("M-%" . anzu-query-replace)
    ("C-M-%" . anzu-query-replace-regexp)
  )
)

34.7 Rainbow mode

Highlights CSS colours in their actual colour. For instance (probably won't be visible in the export):

div.example {
  background-color: #cc3;
}

This is enabled globally:

(use-package rainbow-mode
  :config
  (rainbow-mode)
  :diminish
  :defer t
)

34.8 Coffee mode

Major mode for editing CoffeeScript files.

(use-package coffee-mode
  :mode "\\.coffee$"
  :config (setq coffee-tab-width 2)
)

(use-package flymake-coffee
  :defer t
  :diminish
  :init
  (add-hook 'coffee-mode-hook 'flymake-coffee-load)
)

34.9 Docker

(use-package docker
  :defer t
  :diminish
)
(use-package dockerfile-mode
  :defer t
)

34.10 Ruby configuration

Provide a ruby-mode for editing ruby files.

(use-package enh-ruby-mode
  :mode "\\.rb$"
  :config
  (setq enh-ruby-deep-indent-paren nil) ; Don't indent ruby function parameters at column index of function parentheses
)

I use rspec a lot, and rspec-mode is very useful.

(use-package rspec-mode
  :mode "_spec.rb$"
  :config
  (setq rspec-use-rake-when-possible nil)
  (setq rspec-use-bundler-when-possible t)
  (setq rspec-use-rvm-when-possible t)
  (setenv "PATH" (concat (getenv "PATH") ":" "/usr/local/bin"))
  (eval-after-load "rspec-mode"
    '(progn
      (setenv "PAGER" (executable-find "cat"))
      (inf-ruby-switch-setup)
      (define-key global-map (kbd "M-T") 'rspec-toggle-spec-and-target)
    )
  )
)

ruby-end inserts end blocks whenever I type do automatically.

(use-package ruby-end
  :defer t
  :diminish
  :init
  (add-hook 'ruby-mode-hook #'ruby-end-mode)
)

The following allows using binding.pry in rspec-mode.

(use-package inf-ruby
  :init
  (add-hook 'after-init-hook 'inf-ruby-switch-setup)
  :bind
  ("C-c r r" . inf-ruby)
)

(use-package robe
  :defer t
  :init
  (add-hook 'enh-ruby-mode-hook 'robe-mode)
  (with-eval-after-load 'company (add-to-list 'company-backends 'company-robe))
)

(defun mfoot/rdb ()
  "Run rake db:rdb."
  (interactive)
  (let ((default-directory "~/repositories/cube/src/webapp"))
    (async-shell-command "bundle exec rake db:rdb" "*Bundle exec*")))

(defun mfoot/trdb ()
  "Run rake db:trdb."
  (interactive)
  (let ((default-directory "~/repositories/cube/src/webapp"))
    (async-shell-command "bundle exec rake db:trdb" "*Bundle exec*")))

(add-hook 'enh-ruby-mode-hook
  (lambda () (local-set-key (kbd "C-x r t") 'mfoot/trdb))
  (lambda () (local-set-key (kbd "C-x r d") 'mfoot/rdb)))

projectile-rails provides quick jump-to-model and jump-to-helper support for rails projects.

(use-package projectile-rails
  :defer t
  :diminish
  :init
  (add-hook 'projectile-mode-hook 'projectile-rails-on)
)

34.11 CMake

(use-package cmake-mode
  :diminish
  :mode ("CMakeLists.txt" . cmake-mode)
)

34.12 MySQL

Emacs has a built-in MySQL client. When using it, I want to disable line wrapping. I can use standard text navigation features to see what I need (source).

(add-hook 'sql-interactive-mode-hook (lambda () (toggle-truncate-lines t)))

35 Syntax highlighting and static analysis

I use flycheck as a framework for syntax checking and static analysis. E.g. it will provide language-specific syntax checking for known languages. Some languages also provide linting as well via flycheck.

TODO: This section should be merged with my use-package declaration for flycheck.

(add-hook 'prog-mode-hook (lambda () (flycheck-mode)))

36 Spell checking

I have several modes that execute flyspell-mode. There's a problem with this with xemacs by default: middle clicking to save a correction also inadvertently pastes whatever was in the selection buffer. This can be fixed by swapping around the bindings (source).

I don't flyspell org-mode buffers inside the PROPERTIES, LOGBOOK, or BEGIN_SRC..END_SRC blocks.

(add-hook 'prog-mode-hook (lambda () (flyspell-prog-mode)))
(add-hook 'text-mode-hook (lambda () (flyspell-mode)))

(eval-after-load "flyspell"
  '(progn
;     (define-key flyspell-mouse-map [down-mouse-2] nil)
;     (define-key flyspell-mouse-map [mouse-2] #'flyspell-correct-word))
     (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
     (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
  )
)

37 Presenting

I've been using org-reveal for presentations.

;; (use-package ox-reveal
;;   :ensure t
;;   :defer t
;;   :config
;;   (setq org-reveal-root (concat user-emacs-directory "reveal-js/reveal.js"))
;;   (add-hook 'org-mode-hook (lambda () (load-library 'ox-reveal)))
;; )

38 TODO Code snippet handling

I use yasnippet for code snippet handling. This is enabled globally.

(use-package yasnippet
  :config (yas-global-mode 1)
  :diminish
  :defer t
 )

39 TODO Other configuration

This section holds configuration from before I moved to using org-babel (i.e. it lived directly inside ~/.emacs). It is here just because I haven't had the time or the impetus to categorise and document it.

;; If we're at the end of a word and hit TAB, run the expand command
;; for tab completion. If we're not at the end of a word, run the
;; normal tab command
;; http://emacsblog.org/2007/03/12/tab-completion-everywhere/
(defun indent-or-expand (arg)
  "Either indent according to mode, or expand the word preceding point."
  (interactive "*P")
  (if (and
       (or (bobp) (= ?w (char-syntax (char-before))))
       (or (eobp) (not (= ?w (char-syntax (char-after))))))
      (dabbrev-expand arg)
    (indent-according-to-mode)))

(local-set-key (kbd "<tab>") 'indent-or-expand)

(add-to-list 'auto-mode-alist '("\\.hamlc$" . haml-mode))

;;; Things that are not in melpa
; NOTE: flymake-easy now is in melpa. What am I using that requires it? Is it one of the linters? Does it come in as a dependency? Check if this works without it.
;(add-to-list 'load-path "~/Dropbox/lisp/")
;(require 'flymake-easy)

(set-default 'tramp-default-proxies-alist (quote ((".*" "\\`root\\'" "/ssh:%h:"))))

Author: Martin Foot

Created: 2017-05-14 Sun 11:57

Validate