Simple and stylish comment-based outlines with speed keys for Emacs.
outli is a simple Emacs outliner for code, documents, and more which provides hierarchical hide/show, styles your headings, and emulates org-mode navigation and structure editing. It builds on the built-in outline-minor-mode and is simple by design, providing just a few key additional features beyond what outline already offers:
- Configurable heading syntax based on the concept of a
stem(fixed first characters) andrepeat-char(the number of which determines a heading's depth). Example level-two headers include classics such as;;;;and# **, but anything's possible. - Default header syntax based on comment char that just works for most modes.
- Header style options including color-matched overline and blended background color for the initial heading info.
TabandShift-Tabwork just like you'd expect from org-mode to toggle headings or document visibility.- Speed keys mirroring org-mode for easy navigation, visibility, and structure editing at headlines. Hit
?for the list of available keys. Additions includehto hide sub-levels below the current level, and1-5to specify such a level directly. - Exposes headings to imenu. A fast imenu browser like consult-imenu is recommended.
outli is in MELPA. Either install from there, or clone and point use-package at the correct path (or use straight, etc.).
(use-package outli
;:after lispy ; uncomment only if you use lispy; it also sets speed keys on headers!
:bind (:map outli-mode-map ; convenience key to get back to containing heading
("C-c C-p" . (lambda () (interactive) (outline-back-to-heading))))
:hook ((prog-mode text-mode) . outli-mode)) ; or whichever modes you preferYou should probably not enable outli in org-mode (which by default is prevented), or with other packages which operate on headings or use similar short bindings, like outshine or pdf-tools. If you want to disable individual modes within some larger mode hierarchy (like text-mode), you can either opt-in by adding them one-by-one, or include those modes in outli-heading-config with a disable entry; see below.
The main variable to customize is outli-heading-config, where you can set the stem and repeat char, and influence the styling, including whether to style the stem and repeat chars the same, whether to include the overline, or whether to omit styling altogether. Note that the t member of this alist is the default used for all modes which are not explicitly specified.
Configured defaults are:
- emacs-lisp-mode: stem
;;, repeat-char; - tex-mode:
%%,% - markdown-mode: (empty stem),
# - org-mode: disabled
- all others:
comment-start+ a space,*
The custom variable outli-blend controls whether a blended background is used to start the headline. After configuring outli-heading-config, you should restart outli-mode in any open buffers using it.
You can set defaults for the STYLE and NOBAR properties for all modes, which take effect if these parameters are omitted or nil in the outli-heading-config; see outli-default-style and outli-default-nobar.
outli inherits the underlying faces (colors) from outline-mode. By default, outline-mode only defines 8 faces. If you'd like headings to go deeper than this, increase outli-maximum-depth. At greater depths, the outline face a given outli face inherits from will "wrap around". If you'd like distinct heading faces at high depth, define more outline faces, e.g.:
s
(defface outline-9
'((t :inherit warning :weight bold))
"Level 9.")Customize outli-speed-commands to alter or disable speed keys, which work at the beginning of heading lines only (similar to org speed keys).
Try reveal-mode; see below.
(Significant releases only.)
- v0.3: Support heading depths greater than 8.
- v0.2.4: Released on MELPA
- v0.1: Allow indented headlines
-
How does this relate to outline-minor-mode?
outliis mostly a convenient wrapper around functionality that is built-in tooutline-mode, adding a few things likenarrow-to-subtreeandinsert-heading-respect-content(alaorg-mode). And of course the speed-key bindings, automatic comments-as-header patterns, and styling. -
How does this relate to outshine?
Mostly just conceptually. Outshine also provides (different) speed keys, for example. And a lot more, much of which isn't as relevant to modern emacs. Since it builds more directly on the built-in capabilities of outline-minor-mode,
outliis a much smaller and simpler package. -
I wish
outlistyling would update when I change themes: This should happen automatically in Emacs 29.1 and later. For earlier version, add the following to youruse-packagestanza::config (advice-add 'load-theme :after #'outli-handle-theme-change) ```
-
What is the syntax of
outli-heading-config?It's an alist, each entry of which looks like:
(MAJOR-MODE STEM REPEAT-CHAR STYLE NO-BAR)to configure a mode. or(MAJOR-MODE . nil)to explicitly preventoutlifrom running in this mode.I recommend using the customize interface to configure
outli:M-x customize-group outli. But it may help to know:MAJOR-MODE: A symbol for a major mode, or parent mode from which the current mode inherits, like'text-mode(note: omit the single apostrophe in the customize interface: it knows it's a symbol). A value oftis used to specify the default config.STEM: A string like"# ". The fixed "stem" of the headline pattern (omit quotes in the customize interface). Can also be an elisp expression which evaluates to a string.REPEAT-CHAR: A character like?*. The repeating character which specifies the level of a headline (again: no?needed in customize, just type the character). Can also be an elisp expression which evaluates to a character.STYLE: A style flag (symbol).nilfor default (maximum) styling, the symbolnonefor no special styling of headlines, andtfor matched styling between stem and repeat char. Can be omitted (defaults tonil). See alsooutli-default-style.NO-BAR: A flag for the overline bar. If non-nil, omit the overline. Can be omitted (defaults tonil). See alsooutli-default-nobar.
-
You can use arbitrary expressions for the stem and repeat chars; they'll get evaluated at run-time.
-
It's useful to target high-level modes like
prog-modeortext-mode, from which many modes inherit (see mode-minder to get a list of your major mode hierarchy). -
Try out the
hkey at headline start: it folds everything up to be no deeper than the current header's level. -
To prevent
outlifrom being enabled in a given mode (or family of derived modes), just include(MODE . nil)inoutli-heading-config. By default,org-modeis excluded in this way (since it has its own styling system). -
Some emacs tools like
isearchare smart about folding/unfolding text as you navigate through a buffer with them. But not all. To fix this, you can consider enablingreveal-modein buffers where you useoutli, then tools likexref, etc. will reveal folded targets, re-hiding them when you navigate away. -
I recommend
consult-org-headingand/orconsult-outlinefor quickly browsingoutliheadings. You can even combine these into one command, like:(defun my/consult-org-heading-or-outline () (interactive) (if (derived-mode-p 'org-mode) (consult-org-heading) (consult-outline)))
If you use
consult-imenu, you might like to separate headings, by adding this to theconsult-imenuconfig:(push '(?h "Headings") (plist-get (cdr (assoc 'emacs-lisp-mode consult-imenu-config)) :types))
outline-minor-mode: The built-in minor mode for outlining documents on whichoutlibuilds.- orgmode: The do-everything outliner mode.
- outshine: A feature-full
outline-minor-modeenhancement from whichoutlitook its inspiration. Has many legacy features. - outorg: Required by
outshine, this mode enables editing comment blocks in temporaryorg-modebuffers (the inverse of code-blocks inorg). - See more related packages for org-like behavior outside of org.