Skip to content

agzam/occult.el

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

occult.el

https://github.com/agzam/occult.el/actions/workflows/run-tests.yml/badge.svg

Occult - from Latin occultus - “hidden, secret”

./test/screenshot.png

What

It lets you collapse any buffer region into a single-line summary using overlays. The hidden text remains fully present in the buffer - accessible to buffer-string, org-export, copy/kill, and LLM context extraction.

The first line of the folded region stays visible and navigable as regular text. Everything after it is hidden behind an ellipsis.

Why

Sometimes you want to visually declutter a buffer without losing content. LLM chat sessions get verbose, org documents accumulate boilerplate, eshell output floods the screen. Existing folding mechanisms (outline-mode, org-cycle, hideshow) are structure-aware - they fold headings, blocks, or defuns. They can’t fold an arbitrary selected region.

Occult works on any region in any buffer - including read-only and special-mode buffers. The hidden text is never removed from the buffer, so tools that read buffer content (LLM packages like gptel, eca, agent-shell; org-export; copy/kill) see the full unfolded text.

How

Install

Available on MELPA:

(use-package occult
  :ensure t)

Usage

Three commands:

  • occult-toggle - select a region and call it to collapse. Call it again with point on a fold to expand. TAB also toggles when point is on a fold.
  • occult-reveal-all - expand all folds in the current buffer.
  • occult-edit-region - open the fold at point in a narrowed indirect buffer for editing. Bound to e on the fold keymap.

Bind them however you like:

(global-set-key (kbd "C-c z") #'occult-toggle)
(global-set-key (kbd "C-c Z") #'occult-reveal-all)

Editing a fold

Press e with point on a fold (or call M-x occult-edit-region) to open the fold content in a separate indirect buffer. The base buffer’s fold stays collapsed while you edit; changes propagate live because the text is shared. A header line shows the current commit and abort key bindings. When the base buffer is read-only the session opens in view mode with a single close key instead.

Edit Occult Fold  │ C-c C-c commit │ C-c C-k abort
  • C-c C-c (customizable via occult-edit-commit-key) - commit and close the indirect buffer, keeping user changes.
  • C-c C-k (customizable via occult-edit-abort-key) - restore the original fold contents and close the indirect buffer.

Customization

VariableDefaultDescription
occult-indicator"📎 "Prefix glyph for the fold summary
occult-ellipsis"..."Suffix shown where text is hidden
occult-summary-max-length80Max visible chars from the first line
occult-auto-revealnilAuto-reveal mode: nil, echo, or expand
occult-edit-commit-key"C-c C-c"Key that commits an edit session
occult-edit-abort-key"C-c C-k"Key that aborts / closes an edit session

Search integration

Emacs isearch (C-s / C-r) finds text inside folds. Matches are temporarily revealed during search and permanently expanded if isearch exits inside a fold.

Evil users: / and ? (evil-ex-search-forward / evil-ex-search-backward) are also supported. When a search lands inside a fold, it is temporarily revealed and re-hidden when point moves away.

Evil fold bindings (zc / zo / za)

The native evil fold commands can be advised to work with occult. When a visual selection or occult fold is present, they delegate to occult; otherwise they fall through to default behavior.

  • zc / zC in visual state - create an occult fold from the selection
  • zo / zO on an occult fold - reveal it
  • za - toggle: create from visual selection or reveal existing fold
  • zR - also reveals all occult folds alongside native folds
(with-eval-after-load 'evil
  (dolist (fn '(evil-close-fold evil-close-fold-rec))
    (advice-add fn :around
                (lambda (fn &rest args)
                  (if (evil-visual-state-p)
                      (occult-hide-region (region-beginning) (region-end))
                    (apply fn args)))))

  (dolist (fn '(evil-open-fold evil-open-fold-rec))
    (advice-add fn :around
                (lambda (fn &rest args)
                  (if (cl-find-if (lambda (o) (overlay-get o 'occult))
                                  (overlays-at (point)))
                      (occult-toggle)
                    (apply fn args)))))

  (advice-add 'evil-open-folds :around
              (lambda (fn &rest args)
                (apply fn args)
                (occult-reveal-all)))

  (advice-add 'evil-toggle-fold :around
              (lambda (fn &rest args)
                (if (or (evil-visual-state-p)
                        (cl-find-if (lambda (o) (overlay-get o 'occult))
                                    (overlays-at (point))))
                    (occult-toggle)
                  (apply fn args)))))

Related packages

Other Emacs folding packages. Most fold by language structure or indentation; occult complements them by folding arbitrary regions into a one-line summary, keeping the underlying text accessible to buffer-string, org-export, kill/yank, and isearch.

  • hideshow - built-in hs-minor-mode for syntax-aware folding of comments and code blocks
  • folding / folding-mode - marker-based folding (triple-brace comments), by Jari Aalto
  • origami - parser-based structural folding with indentation fallback
  • lsp-origami - origami driven by LSP fold ranges
  • ts-fold - tree-sitter folding via external emacs-tree-sitter
  • treesit-fold - tree-sitter folding via built-in treesit (Emacs 29+)
  • yafolding - indentation-based folding

License

Copyright © 2026 Ag Ibragimov

GPL-3.0-or-later. See LICENSE.

About

Collapse selected region to a single-line summary

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors