1
0
Fork 0
dotfiles/emacs.d/emacs.org

35 KiB

Mike Gerwitz's Emacs Configuration

Introduction

This is my personal Emacs configuration. It is written in a literate style; this file serves as both a document and the configuration source code.

This is a work-in-progress; I am still relatively new to Emacs (I have been using Vim for over a decade, and Emacs only since late 2014). But even so, there's a lot here; you'd be surprised how quickly you can accumulate configuration options and actual code to customize Emacs. And that really speaks to its flexibility and appeal to developers: nearly everything is written in lisp, and nearly everything can be changed, often at runtime. The amount of customization the average Emacs user performs does not mean that Emacs is too complicated or does a poor job at configuration.

Contract this to my Vim configuration, which struggles to even reach 200 lines after over a decade (but I do use a number of plugins). There's beauty in that too.

Please forgive any atrocities that could be handled more elegantly or efficiently (and send me a patch!).

Lexical Binding

All variables in this file are lexically bound—that is, they are bound to the scope of the containing expression rather than being defined globally. This is what you would expect from most sane languages, such as Scheme.

  ;; -*- lexical-binding: t -*-

Word of Warning

Do not edit the generated file. It will be overridden during re-tangling.

  ;;;
  ;;; WARNING: This source file is the tangled output
  ;;;          of init.org; do not modify!
  ;;;

General Settings

Package Archives

These are the archives from which I may download packages. This will be refined as I explore them in more detail.

  (setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/")
                           ("org" . "http://orgmode.org/elpa/")
                           ("marmalade" . "http://marmalade-repo.org/packages/")
                           ("melpa" . "http://melpa.milkbox.net/packages/")))

Packages installed from the archives are initialized simply:

  (package-initialize)

Bookmarks

If I take the time to save my position in a buffer, I would prefer that I do not lose that information. Setting bookmark-save-flag will automatically save after each modification.

  (setq bookmark-save-flag 1)

User Interface

The editor is my canvas. That may sound corny, but I'm looking at this thing for a good part of every day of my life; it needs to be pleasing to both the eyes and the fingers. If returning to your editor—buffers open and waiting; cursor beckoning—is not titillating, then your editor is either misconfigured or not for you. (Or maybe you don't care, which is really a shame.)

<<<Evil Mode>>>

Evil mode is an extensible vi layer for Emacs. I have always been attracted to a number of Emacs features, most notably its use of a Lisp dialect. The barrier was its keybindings, which are inferior to those of Vim.

A combination of the two, however, is potent.

Evil has since grown into an excellent project that provides a surprisingly strong Vim-like experience in Emacs. There are some rough edges, and not all things are wholly consistent, but development continues and I will continue to submit patches to help things along.

Before loading evil mode: the default is to leave the default Emacs C-u keybinding, which is universal-argument; this is very inconvenient, since I use C-u very frequently, which is PgUp (<prior>) in Vim.

  (setq evil-want-C-u-scroll t)
  (evil-mode t)

Suspending Emacs

Evil overrides C-z, for whatever perverted reason, to enter "Emacs" mode rather than suspending Emacs. I do not like this behavior. Instead, I have C-z in Normal mode continue to suspend Emacs. In Insert mode, however, it retains Evil's functionality and enters "Emacs" mode; this makes sense, I think, because Emacs is similar to Insert mode in that most keybindings echo.

  (evil-define-key 'normal global-map
    ;; note that you can still return to Emacs mode in insert mode
    "\C-z" 'suspend-frame)

UI Stripping

The first thing that a new (or unconfigured) user encounters is the splash screen. It provides little value to an experienced user and is annoying.

  (setq inhibit-splash-screen t)

I am accustomed to the beautifully simple interface of Vim—which I have used exclusively for over a decade. Therefore, I strip the text-mode UI (and the GUI) of annoyances such as the menu bar.

  (menu-bar-mode -1)
  (tool-bar-mode -1)

I do not use the Emacs GUI—I am fond of the command line and a terminal does just fine. This also fits well into my use of GNU screen and SSH, allowing me to re-attach to remote sessions with ease. But in the event that it happens to load (maybe the 'nox' package was not installed), or I choose to load it, I want it to be as consistent with the texi-mode UI as possible.

  (when (display-graphic-p)
    (scroll-bar-mode -1)
    (fringe-mode 0)
    (tooltip-mode -1)
    (use-diablog-box nil)
    (add-to-list 'default-frame-alist
                 '(font . "DejaVu Sans Mono-7")))

Layout

Your window layout defines how you perceive and interact with a significant portion of your virtual world. It provides a physical presence to the content of this virtual world, defining where in the physical world it is rendered. Humans have a place for most things in their environment; I see no difference here.

Window Height

I open a lot of files in my editor in a single session (which I leave running as long as my screen session remains running, which is usually until the box is rebooted, which is quite rare). In Vim, I would manage this with a generous number of splits spread across various tabs. Spacial orientation is important for me (allowing a file to "live" in a certain location in the physical world) and offers a number of benefits, so I produce a number of vertical splits (as much as six, depending on the resolution, but I find that four is a sweet spot), and numerous horizontal splits within them. I then "focus" on a window within the split by maximizing its height to the available space; in Vim, I set the minimum window height to 0, so this shrinks all other windows in the vertical split down to their status/mode lines.

I do it often enough that I have a shortcut for doing so:

  (defun evil-window-select-expand (direction)
    "Select window in DIRECTION and expand to fill available frame height"
    (windmove-do-window-select direction)
    (evil-window-set-height nil))

  ;; move up/down a window and expand to full height
  (mapc #'(lambda (assoc)
            (eval `(evil-define-key 'normal global-map
                     ,(car assoc)
                     (lambda ()
                       (interactive)
                       (evil-window-select-expand ,(cdr assoc))))))
        '(("\C-k" . 'up)
          ("\C-j" . 'down)))

Unfortunately, Emacs' default behavior prohibits a zero-height window: window-min-height respects window-safe-min-height, which defaults to 1. Changing the latter to 0 will cause the first visible line in the window to render, but the mode line is not rendered. I'll explore changing the rendering logic in the future; for now, I will live with a minimum window height of 1.

  (setq window-min-height 1)

Minibuffer Height

The minibuffer (displayed at the very bottom of the editor when invoking a command, for instance) is able to display multiple lines of text. The default behavior is to allow the minibuffer to grow in height, but not return to its original height as its content shrinks (e.g. erasing newlines); this is annoying to me, and prods at my [minor] OCD.

The better behavior is to resize to fit the contents, always.

  (setq resize-mini-windows t)

Window Layout Undo/Redo

It should be obvious from the previous sections that I would be rather displeased if my window layout were to be disrupted, since that could easily destroy months of accumulating buffers and layout organization. This could happen for a number of reasons, including my unfamiliarity with Emacs, me fat-fingering keys, or rude packages modifying the layout and not restoring it.

Winner Mode is packaged with Emacs since version 20. It allows you to undo and redo layout changes using C <LEFT> and C <RIGHT>.

  (winner-mode)

I have saved myself many times using this package.

Frames

In Vim, I made aggressive use of tabs to organize my many splits into coherent groups. When I first moved to Emacs, this made for an awkward transition: Emacs has a concept of frames, and they are not rendered like tabs (at least not without help). On the CLI, with the default behavior, you wouldn't even be able to tell that they exist.

To my surprise, I ended up finding Emacs' frames to be superior to Vim's tabs. I'll write more about that when I get the chance.

Cycling Frames

Vim cycles tabs using gt (next tab) and gT (previous tab). Since I do not display frames as tabs, this is admittedly of limited use to me when I have a large number of frames open; however, it can still be useful under certain circumstances.

  (evil-define-key 'normal global-map
    "gt" 'other-frame
    "gT" (lambda (n)
           (interactive "p")
           (other-frame (- n))))
Selecting Frame By Name

One powerful feature that Vim lacks (without a plugin) is the ability to name tabs, which becomes important when you (ab)use them the way I do. Emacs has this support built-in; you can set frame names with set-frame-name. The frame name is displayed, by default, in the mode line before the filename.

This means that we can select a frame using its name rather than its position in the ring (like Vim). Emacs provides no default keybinding for select-frame-by-name, so I provide my own:

  (evil-define-key 'normal global-map
    "\C-w/" 'select-frame-by-name)
Switching Between Two Frames

I often find myself switching between two frames during development. Reasons vary, but two projects may be strongly related or concurrently developed; a single project may be organized into separate frames for spacial recognition; I may be suffering from context switching due to work on multiple, different projects; etc. The two frames could be wholly arbitrary. Switching between them can be frustrating, even with the minimal work of typing C-x b ... with autocompletion. That frustration makes switching a displeasure, which means that something is wrong with my editor configuration.

  (defun select-prev-frame-name ()
    (interactive)
    (let ((name (cadr frame-name-history)))
      (if name
          (progn
            (select-frame-by-name name)
            (setq frame-name-history
                  (cons name frame-name-history)))
        (user-error "No previous frame"))))

select-prev-frame-name uses Emacs' built-in frame-name-history to determine the name of the previously visited frame and raise it. I bind this for convenience:

  (evil-define-key 'normal global-map
    "\C-w," 'select-prev-frame-name)

Minibuffer

Icomplete

icomplete-mode provides a massive increase in life expectancy for Emacs users by doing its best to provide suggestions for command completion in the minibuffer. You should use it.

  (icomplete-mode)

Recursive Buffers

The default behavior of Emacs does not permit recursive minibuffers—that is, minibuffer commands while within a minibuffer. It's too arbitrary of a restriction for me, and is something that occasionally comes in handy.

  (setq enable-recursive-minibuffers t)

Mode Line

Emacs users do some pretty kinky stuff with their mode lines, especially in graphical environments. I don't do much of anything at the moment (most of my useful information is part of my GNU screen hardstatus line).

Point Column

I do want to know the column position of point; this is useful for a variety of things, including observing line length and column numbers for error messages. In the case of the latter, I normally use the Vim (Evil-supported) command N|, which takes me to column N, but having the column number in the mode line allows me to verify that I didn't fat-finger the number.

  (column-number-mode 1)

Scrolling

The first order of business is to get scrolling into a sane state with evil mode. In particular, the use of C-u to scroll up.

Emacs uses C-u as a command modifier. Since evil mode allows the use of Emacs commands, it retains this key binding by default. Fortunately, this can be corrected with a simple configuration value:

  (setq evil-want-C-u-scroll t)

<<<Scroll Margin>>>

It is useful to be able to see lines of text that surround point; this allows scanning without having to move point or scroll the window, which is slower than moving your eyeballs, and is more distracting. Having point at the very first or last line of a window also makes me feel a bit uncomfortable—like having no peripheral vision. It also helps to visually state, without looking at the mode line, whether the window has reached the end of the buffer.

We do not want too much of a scroll margin (as it is called), since that would reduce the effective amount of lines visible on the screen during editing—if wanted to edit the last line in a window, and the scroll margin was $n$, then I'd lose $n$ lines at the top when I scroll to it. Further, using evil-window-bottom (L in Normal mode) takes into account the scroll margin, meaning the last $n$ lines of the window are not as easily accessible. Similar arguments can be made for evil-scroll-line-to-bottom (zb in Normal mode) and others.

All of that said, I have found a three-line scroll margin to treat me well over the years.

  (setq scroll-margin 3)

Tracking Point

<<<sec:tracking-point>>> When point moves off of the screen, the default Emacs behavior is to re-center point in the window at that line. This is odd to me, but perhaps because it's not something that I am used to happening; the sudden jump of such a large amount of text (considering modern resolutions and my terminal font size) disrupts me.

Instead, the window should scroll just enough to keep point on the screen, subject to the scroll margin.

 (setq scroll-conservatively 1)

Recentering

There are other operations (in addition to tracking point) that cause point to be recentered. The default behavior on a TTY is to redraw the entire frame when this occurs, possibly to cater to buggy VTEs. This is highly undesirable for me—it is both a performance issue and terrible eye sore due to my high terminal resolution. Fortunately, this behavior can be disabled.

 (setq recenter-redisplay nil)

In the rare instances where redrawing is actually an issue, there is always redraw-display.

<<<Line Numbering>>>

Line numbering is useful for eyeballing text when line numbers are referenced (e.g. error messages when compiling source code), for getting an idea of where you are in a file, peer programming, and other things. I have used line numbers for over a decade. They are not enabled by default in Emacs (or Vim/vi).

I originally used <<<linum mode>>> for line numbering, but found that it was far too slow for my large terminal resolution. So, I gave <<<nlinum mode>>> a try; this was much faster, but was still a bottleneck. So I wrote a more strongly optimized procedure to handle rendering:

  ;; line numbering (we ignore nlinum-format for performance)
  (setq nlinum-format-function
        (lambda (line width)
          (let ((str (concat (number-to-string line) " ")))
            (when (< (length str) width)
              ;; Left pad to try and right-align the line-numbers.
              (setq str (concat (make-string (- width (length str)) ?0)
                                str)))
            (put-text-property 0 width 'face 'linum str)
            ;; FIXME: this relies on the fact that the format has a
            ;; trailing space
            (put-text-property (1- width) width 'face 'hidden str)
            str)))

That helped considerably. But I was still left disappointed by profiler results when trying to determine slowdowns.

As it turns out, I don't need line numbers; I've been experimenting with leaving line numbers disabled, and things have been going well; my eyes are adjusting moving to the mode line if I need the line number, and I find that it's rare that I even need that. For instance, if I need to visit a particular line, I enter the line number, not scroll to it.

I will, however enable nlinum mode in peer programming situations or code review, since it facilities discussion. Line numbers also help to provide context when navigating large files.

  (evil-define-key 'normal global-map
    "\C-n" 'nlinum-mode)

Sentences

<<<Sentence mode>>> is a minor mode that will highlight the entire sentence under point. I find this useful not only as a reading aid, but also compositionally—it allows me to see the length of sentences in my work and points out suspicious sentences that may be run-ons; yada. I use semi-colons aggressively in my written works as well, so sentence highlighting consequently highlights groups of ideas.

  (require 'sentence-highlight)

See Mode Hooks for major modes making use of this minor mode.

Errors

The command ]e is analogous to ]s below. A negative numeric argument can be used to cause next-error to go back, but a Vim-like ]e is still provided for convenience.

  (evil-define-key 'normal global-map
    "]e" 'next-error
    "[e" 'previous-error)

Spell Checking

Vim's spell checking keybindings are useful. Unfortunately, I have not yet put the time into a solution for [s; flyspell-goto-previous-error does not exist and flyspell-goto-next-error is not written such that this is easy to do. flyspell-check-previous-highlighted-word searches backwards, but then invokes spelling correction, which is not desirable. A solution will likely involve Flyspell refactoring and a patch.

  (evil-define-key 'normal global-map
    "]s" 'flyspell-goto-next-error)

Hidden Content

When modes permit customization via faces, it is sometimes useful to be able to hide text entirely.

  (defface hidden '((t (:foreground nil :background nil)))
    "Hide text")

<<<Session>>>

Session management allows you to continue where you left off at an earlier point in time, usually restoring buffers, windows, frames, and other configuration options. This is especially important for myself, since I use (usually) a single Emacs session with many hundreds of buffers, a dozen or more frames (each named), and often dozens of windows per frame, spatially memorized. I simply cannot afford to lose such a session.

Session saving is provided by Emacs' built-in <<<desktop mode>>>.

  (setq desktop-restore-frames             t
        desktop-resture-in-current-display t
        desktop-restore-forces-onscreen    nil)

To ensure that no information is lost, I save desktop sessions on auto-save:

  (add-hook 'auto-save-hook
            'desktop-save-in-desktop-dir-quiet)

The -quiet suffix there is to ensure that saving does not produce errors if we are not the owner of the session:

  (defun desktop-save-in-desktop-dir-quiet ()
    (interactive)
    (if (eq (desktop-owner) (emacs-pid))
        (desktop-save desktop-dirname)))

Saving Session Frame Names

<<sec:frame-name>> I am unsure why the default is to not save frame names (it may have simply been overlooked; I should probably ask), but that is deeply frustrating due to the number of frames that I maintain. Fortunately, it is an easy problem to solve:

  ;; this first line is suggested by the frameset-filter-alist docs
  (setq frameset-filter-alist (copy-tree frameset-filter-alist))
  (add-to-list 'frameset-filter-alist
               '(name . nil))

Command History

Have you ever been in a situation where you know you did something a number of days ago, but you don't remember exactly how you did it? Of course!

My shell history length is quite large, but I don't think that such is necessary with Emacs, since most commands issued to Emacs are not M-x-commands.

  (setq history-length 1024)

Files and <<<Version Control>>>

<<<sec:version-control>>>

Backups

With modern source code management systems, old-school version control using backups following a naming convention are not often needed. That said, there are two particular cases where it is still valuable: for files that are not [yet] under version control, or as a save-my-ass feature in the event that work had not been committed.

  (setq version-control                t
        backup-directory-alist         '(("." . "~/tmp/"))
        auto-save-file-name-transforms '((".*" "~/tmp/" t))
        kept-new-versions              100
        kept-old-versions              20
        delete-old-versions            t)

On a similar note, Emacs creates lock files by default—they are intended to prevent users from concurrently editing the same file using Emacs (or any other editor that checks for the lock). Since all my shared editing is done via a VCS, this does nothing but create annoying files.

  ;; not defined until Emacs 24.3
  (setq create-lockfiles nil)

Reverting

Emacs' concept of "reverting" involves discarding changes in a buffer and loading the contents of its respective file from disk. Most editors have some sort of facility for handling this type of situation, as it is an important one: overwriting a file with changes to an out-of-date version risks clobbering data. Emacs does, fortunately, prompt in such a situation.

When working with version control systems—namely Git, in my situation—switching branches may yield file changes. I switch branches regularly, and it is important that my editor reflects those (often vast) changes; waiting until I have already made modifications to a file before discovering that it has changed is unacceptable.

  (global-auto-revert-mode)

Mode Hooks and Configuration

<<<sec:mode-hooks>>> Here I define all the minor modes that shall be enabled when the corresponding major mode(s) take effect.

  (defun disable-mode-fn (mode)
    "Return function to disable `MODE'"
    (lambda ()
      (if (boundp mode)
          (funcall mode -1)
        (warn (concat
               "disable-mode-fn: unknown mode: "
               (symbol-name mode))))))

  (defconst my-mode-hooks
    `((turn-on-auto-fill . (text-mode-hook
                            prog-mode-hook))

      ;; perf issues
      ;; (fci-mode         . (prog-mode-hook))

      ;; highlight lines (no global mode, since that makes disabling
      ;; it per-buffer a PITA)
      (hl-line-mode . (text-mode-hook
                       prog-mode-hook))

      (show-paren-mode     . (prog-mode-hook))
      (electric-pair-mode  . (prog-mode-hook))
      (which-function-mode . (prog-mode-hook))
      (flyspell-prog-mode  . (prog-mode-hook))
      (adaptive-wrap-prefix-mode  . (prog-mode-hook))

      (js2-mode . (js-mode-hook))
      (js3-mode . (js-mode-hook))

      (flyspell-mode      . (text-mode-hook))

      (whitespace-mode . (text-mode-hook
                          prog-mode-hook))

      ;; skimpy tabbing
      (,(apply-partially 'set-tab-width 2) . (shell-mode-hook
                                              nxml-mode-hook))

      ;; knock it off prog modes
      (,(apply-partially 'set-fill-column 76) . (prog-mode-hook))

      (sentence-highlight-mode . (text-mode-hook))

      ;; these modes do not cooperate with electric-pair-mode
      (,(disable-mode-fn 'electric-pair-mode) . (nxml-mode-hook))

      ;; flyspell is too much atop of the slow nxml processing
      (,(disable-mode-fn 'flyspell-mode) . (nxml-mode-hook))

      ;; FIXME: until I can figure out a consistent solution to face
      ;; precedence; it highlights whitespace in its own face, unless you load
      ;; whitespace-mode after it, so we'll get rid of it for now
      (,(disable-mode-fn 'whitespace-mode) . (message-mode-hook))

      ;; no line highlighting in terminals
      (,(disable-mode-fn 'hl-line-mode) . (term-mode-hook))

      ;; nxml's parent mode is text-mode, but I treat it more like a
      ;; programming language
      (,(disable-mode-fn 'sentence-highlight-mode) . (nxml-mode-hook)))
    "List of pairs defining functions to be applied to hooks

  The purpose of this is to be able to determine, at a glance, all modes to
  which the given function or minor mode apply.  It is trivial to see the
  reverse by inspecting the runtime value of those hooks.")

  ;; apply mode hooks
  (mapc (lambda (pair)
          (let ((f     (car pair))
                (modes (cdr pair)))
            (mapc (lambda (mode)
                    (add-hook mode f t))
                  modes)))
        my-mode-hooks)

File Extensions

  (add-to-list
   'auto-mode-alist
   '("\\.md\\'" . markdown-mode))

Ediff

Most modern resolutions are wide-screen; that is the case for me, even on my laptop. The name split-window-horizontally is deceptive: it's what is more often referred to in other software as a "vertical split": two side-by-side windows.

  (setq ediff-split-window-function
        'split-window-horizontally)

JavaScript

Indentation

js-mode's indentation strategy is abhorrent.

  (add-hook 'js-mode-hook
            (lambda ()
              (setq indent-line-function 'indent-relative)))

Linting and Code Quality

ESLint is a linting and codestyle tool for ECMAScript. Flycheck supports it.

  (add-hook 'js-mode-hook 'flycheck-mode t)

This code is based on an Emacs StackExchange answer:

  (defun my-flycheck-find-eslint ()
    (let* ((root (locate-dominating-file
                  (or (buffer-file-name)
                      default-directory)
                  "node_modules"))
           (esbin (and root
                       (expand-file-name
                        "node_modules/.bin/eslint"
                        root))))
      (and esbin
           (file-executable-p esbin)
           esbin)))

  (defun my-flycheck-set-eslint ()
    (setq-local flycheck-javascript-eslint-executable
                (my-flycheck-find-eslint)))

  (add-hook 'flycheck-mode-hook #'my-flycheck-set-eslint)

Web Mode

  (setq web-mode-markup-indent-offset 2
        web-mode-enable-auto-pairing  t
        web-mode-enable-auto-closing  t)

Editing

I'm told that Emacs is an operating system. I'm also told that it is an editor. I've been convinced of both.

<<<Fill Column>>> (<<<Line Length>>>)

The fill column determines what column line wrapping should occur beyond. The default value is 70. In general, I'm okay with this, but it deserves a bit of discussion. Line length is one of those religious debates that nobody will win. But I can tell you why many hackers and technical people tend toward smaller line lengths, and why I choose the lengths that I do.

TODO; I don't have the time for my line-length dissertation right now.

My default line length is 76. My rationale:

  • Standard Unix terminal column size of 80;
  • Minus three characters (reasonable) for line numbering (77);
  • Minus another character to delimit line number from text (76).

Further, the above also allows for (without line numbering) up to three levels of nested quotes using the standard block quote delimiter (">"; see Replying (to mail)).

  (setq-default fill-column 76)

That is not always an appropriate default, though; I may override it for other modes. See also Mode Hooks.

Whitespace

Various types of whitespace are important to recognize. With a fixed-width font (which, if you're reading this document, you should be using!), we don't have to worry so much about the number of spaces between printable characters, since that can be fairly well eye-balled. But leading and trailing whitespace are of particular importance.

Leading whitespace is used for indentation, and is generally either tabs or spaces. Distinguishing between the two is vital for consistency, and sometimes semantically (e.g. Makefiles' need for tabs in recipes). Trailing whitespace is almost always a bad thing, so that should be made apparent. Newlines can be recognized by, well, a line break.

  (setq-default
   whitespace-style '(face
                      spaces
                      tabs
                      newline
                      space-mark
                      tab-mark
                      trailing))

TODO: How do I address Unicode NBR? Carriage returns?

Tab Width and Stops

It is important to respect others' whitespace decisions; if tabs already exist, then they should be retained. Certain languages (e.g. Make) also assign meaning to tab characters.

But just setting the tab width is not enough; in Emacs, the act of tabbing is governed by tab stops. I therefore define set-tab-width to both set the tab width for display of the tab character and to generate the proper tab-stop-list:

  (defun set-tab-width (width)
    "Set tab width to WIDTH and generate tab stops"
    (interactive "nTab width: ")
    (setq tab-width width)
    (setq tab-stop-list
          (number-sequence width 120 width)))

I use this primarily in mode hooks, but I do generally prefer a default of four characters:

  (defun global-set-tab-width (width)
    "Set tab width to WIDTH and generate tab stops"
    (interactive "nTab width: ")
    (setq-default tab-width width)
    (setq-default tab-stop-list
                  (number-sequence width 120 width)))

  (global-set-tab-width 4)

Indentation

One thing that really annoys me is when my editor tries to be too smart: especially about something like indentation, which is so precise and variable. There are certain languages with strong indentation standards where this is okay (e.g. Lisp); but for the most part, no.

Triggering re-indentation is trivial enough (C-M-\); I don't want it to happen every time I start a new line.

  (set 'electric-indent-chars
       (remq ?\n electric-indent-chars))

Indentation, by default, by my preference, should never insert tabs.

  (setq-default indent-tabs-mode nil)

TODO: But some projects I work on (such as GNU screen) do use tabs; write a hook that will detect this and properly set indent-tabs-mode.

Indentation should also be done automatically when hitting RET, kind of like Vim's autoindent:

  (define-key global-map
    (kbd "RET") 'newline-and-indent)
Indentation Depth

Certain modes provide their own indentation settings, and my indentation preferences vary depending on language. This list is incomplete.

  (setq sh-indentation  2
        sh-basic-offset 2)

Searching

Proper searching of text is an art—and I don't mean from a parsing standpoint. Knowing how to navigate and mark portions of a text can be a powerful productivity boost.

Hi Lock mode is one of those simple things that can really have a great impact when you're trying to grok something with a number of pieces. It is also great during presentations or peer programming/review:

  (global-hi-lock-mode t)

Sentences

It is beneficial to be able to recognize, at a glance, the length of a complete sentence; it helps to understand the scope of an idea or set of ideas.

  (require 'sentence-highlight)

Org Mode

Undo Tree

Undo tree does exactly what it says: maintains undo history in a tree structure and allows visually navigating those branches.

It has a number of options that can be toggled using the visualizer keybindings, but timestamps are a useful default:

(setq undo-tree-visualizer-timestamps t)

The diff is also nice (which can be toggled with d by default), but it doesn't play well with my window splitting, so I just enable it when I want it.

Mail

Web Browsing

There's more to be said on this topic; consider this section a TODO. I do most things from the command line, so w3m is a suitable default.

  (require 'w3m)
  (setq browse-url-browser-function
        'w3m-browse-url)

With that said, there are situations where I may wish to toggle between w3m and my default browser (w3m obviously does not support certain modern web browser features).

  (define-key global-map
    (kbd "\C-C \C-X \C-W")
    (lambda ()
      (interactive)
      (setq browse-url-browser-function
            (if (eq browse-url-browser-function 'browse-url-default-browser)
                'w3m-browse-url
              'browse-url-default-browser))
      (message (symbol-name browse-url-browser-function))))

Security and Cryptography

GnuPG

Emacs' GnuPG (GPG) interface is <<<EasyPG>>>.

GPG Pinentry

The GPG pinentry dialog is a neat console-based dialog that consumes the TTY and prompts for a password. In general, this works well; with Emacs, I noticed that it fights for input.

As long as allow-loopback-pinentry is set in gpg-agent.conf, loopback can be set as the pinentry mode, which allows the caller to handle the request. In our case, that means that the minibuffer will be used.

  (setq epa-pinentry-mode 'loopback)