“Fix” the tab key for visibility cycling in Org and Evil mode

Emacs’ Org mode uses the TAB key to call org-cycle, which cycles visibility for headers. Every TAB press on a headline cycles through a different function1:

  1. The first press folds the headline’s subtree, showing only the headline itself
  2. The scond press shows the headline and its direct descendants, but keeps them folded
  3. The third press shows the headline’s complete subtree

However, running Emacs with Evil mode in a terminal breaks the TAB key for cycling through header visibility in Org mode.

Most terminals map both TAB and C-i to U+0009 (Character Tabulation) for historical reasons, meaning they’re recognised as the same keypress. Because of this, there is no way to map different functions to them inside Emacs.

Evil remaps C-i to evil-jump-forward to emulate Vim’s jump lists feature2, which overwrites the default mapping for the TAB key in Org mode.

To fix the tab key’s functionality in Org mode, sacrifice Evil’s C-i backward jumping by turning it off in your configuration with the evil-want-C-i-jump option.

This option needs to be set before Evil is loaded to take effect, so put it in the early init file:

;; Disable C-i to jump forward to restore TAB functionality in Org mode.
(setq evil-want-C-i-jump nil)

With use-package, set the evil-want-C-i-jump before the package is loaded by using the :init keyword:

;; Install Evil and disable C-i to jump forward to restore TAB functionality in Org mode.
(use-package evil
             :init (setq evil-want-C-i-jump nil)
             :config (evil-mode))

  1. Vim and Evil don’t have a direct equivalent to fold cycling, but they have three different commands that achieve the same result:

    1. zf folds the headline’s subtree
    2. zo opens the headline’s subtree to show its direct descendants
    3. zO opens the complete subtree
    ↩︎
  2. Vim and Evil remember jumps between lines and files in the “jump list”. Because the jump locations are stored, you can use C-o to jump to a previous location, and C-i to jump back. For example:

    1. To move to the next empty line, press } in normal mode
    2. To jump back to where you came from, press C-o
    3. To jump back to that empty line, press C-i
    ↩︎