lisp-docstring-toggle
provides commands to hide and show Lisp docstrings in
code buffers. It solves a specific problem: while comprehensive inline
documentation aids code understanding, it creates visual clutter during code
review, refactoring, or study, forcing the reader to scroll through multiple
screens to view a few hundred lines of actual code.
Unlike general code folding tools (such as outline-mode
or hideshow
) that
hide entire forms, lisp-docstring-toggle
targets only docstrings. Function
signatures, argument lists, and implementation bodies remain visible.
The package operates through Emacs overlays, which hide text without modifying
buffer content. This integrates cleanly with custom font-lock rules (like
hl-todo
), undo/redo, and other Emacs text properties.
- Install the package (see Installation)
- Add to your configuration:
(add-hook 'emacs-lisp-mode-hook #'lisp-docstring-toggle-setup)
- Open a Lisp file and press
C-c C-d t
Docstrings are now hidden. Press C-c C-d t
again to show them.
(use-package lisp-docstring-toggle
:ensure t
:hook ((emacs-lisp-mode lisp-mode) . lisp-docstring-toggle-setup))
Clone the repository:
git clone https://github.com/gggion/lisp-docstring-toggle.git ~/.emacs.d/lisp/lisp-docstring-toggle
Add to your configuration:
(add-to-list 'load-path "~/.emacs.d/lisp/lisp-docstring-toggle")
(require 'lisp-docstring-toggle)
(add-hook 'emacs-lisp-mode-hook #'lisp-docstring-toggle-setup)
(add-hook 'lisp-mode-hook #'lisp-docstring-toggle-setup)
(straight-use-package
'(lisp-docstring-toggle :type git :host github
:repo "gggion/lisp-docstring-toggle"))
(use-package lisp-docstring-toggle
:ensure t
:vc (:fetcher github :repo "gggion/lisp-docstring-toggle")
:hook ((emacs-lisp-mode lisp-mode) . lisp-docstring-toggle-setup))
In packages.el
:
(package! lisp-docstring-toggle
:recipe (:host github :repo "gggion/lisp-docstring-toggle"))
In config.el
:
(use-package! lisp-docstring-toggle
:hook ((emacs-lisp-mode lisp-mode) . lisp-docstring-toggle-setup))
The primary command is lisp-docstring-toggle
(bound to C-c C-d t
), which toggles
visibility of all docstrings in the buffer.
When docstrings are visible:
(defun example-function-1 (arg)
"This is a comprehensive docstring explaining
the function's purpose, arguments, and return value.
ARG is the input argument.
Returns the result of computation."
(+ arg 1))
(defun example-function-2 (arg)
"This is another comprehensive docstring explaining
the function's purpose, arguments, and return value.
ARG is the input argument.
Returns the result of computation."
(+ arg 2))
After invoking lisp-docstring-toggle
:
(defun example-function-1 (arg)
"[…]"
(+ arg 1))
(defun example-function-2 (arg)
"[…]"
(+ arg 2))
The function signature and body remain visible. Only the docstring is hidden.
Use lisp-docstring-toggle-at-point
(C-c C-d .
) to toggle only the docstring in
the current form.
This is useful for selectively hiding verbose docstrings while keeping others visible. Point can be:
- At the opening parenthesis of a form
- Anywhere inside a form
- On the
defun
,defvar
, or other definition keyword
If point is outside any form, the command displays an error message.
The command lisp-docstring-toggle-debug-show-snippets
(C-c C-d D
) opens a buffer
showing all detected docstrings with:
- Clickable position links for navigation
- Character counts
- First and last two lines of content
This is useful for:
- Verifying that docstrings are detected correctly
- Navigating to specific docstrings
- Troubleshooting detection issues with mixed fontification
The user option lisp-docstring-toggle-hide-style
controls how docstrings are
hidden. It accepts three values:
Setting the value to 'complete
(the default) hides all docstring content:
(setq lisp-docstring-toggle-hide-style 'complete)
Result:
(defun example () "[…]" (body))
Only the ellipsis indicator is visible.
Setting the value to 'partial
shows the first N characters:
(setq lisp-docstring-toggle-hide-style 'partial
lisp-docstring-toggle-partial-chars 40)
Result:
(defun example () "This is a comprehensive docstring ex[…]" (body))
The opening quote, first 40 characters, and closing quote remain visible.
This style provides context about the docstring’s content while reducing visual clutter.
Setting the value to 'first-line
shows only the first line:
(setq lisp-docstring-toggle-hide-style 'first-line)
Result:
(defun example () "This is a comprehensive docstring […]" (body))
This is useful for docstrings that follow the Emacs convention of placing a summary on the first line.
The user option lisp-docstring-toggle-ellipsis
controls the indicator shown for
hidden docstrings.
Default value:
(setq lisp-docstring-toggle-ellipsis "[…]")
Alternative indicators:
;; Subtle Unicode ellipsis
(setq lisp-docstring-toggle-ellipsis " ⋯")
;; ASCII alternative
(setq lisp-docstring-toggle-ellipsis "...")
;; Descriptive indicator
(setq lisp-docstring-toggle-ellipsis " [hidden]")
;; No indicator
(setq lisp-docstring-toggle-ellipsis nil)
Setting the value to nil
hides docstrings without any visual indicator.
(use-package lisp-docstring-toggle
:ensure t
:hook ((emacs-lisp-mode lisp-mode) . lisp-docstring-toggle-setup)
:custom
;; Show first 20 characters of docstrings when hiding
(lisp-docstring-toggle-hide-style 'partial)
(lisp-docstring-toggle-partial-chars 20)
;; Use a subtle ellipsis indicator
(lisp-docstring-toggle-ellipsis " ⋯"))
The package works with any major mode that:
- Uses
font-lock-doc-face
for docstring highlighting - Supports
beginning-of-defun
andend-of-defun
navigation - Uses string literals (enclosed in quotes) for docstrings
Tested and working in Emacs 29.1+ with:
emacs-lisp-mode
(built-in)lisp-mode
(built-in)scheme-mode
(built-in)clojure-mode
(MELPA package)fennel-mode
(MELPA package)hy-mode
(MELPA package)
Other Lisp modes should work if they use font-lock-doc-face
.
The package does not work with:
- Python (
python-mode
uses triple-quoted strings with different conventions) - Rust (documentation comments use
///
syntax) - C/C++ (Doxygen comments are not string literals)
- Other non-Lisp languages
The package handles mixed fontification from hl-todo
correctly. Keywords like
TODO
, FIXME
, and NOTE
within docstrings are detected properly:
(defun example ()
"This function needs work. TODO: Optimize this."
;; ^^^^
;; Different face from hl-todo
(body))
The detection algorithm finds the complete docstring despite face splits.
You can use lisp-docstring-toggle
alongside outline-mode
or hideshow
for
different folding levels:
- Use
hideshow
to fold function bodies - Use
lisp-docstring-toggle
to fold docstrings within visible functions
The two mechanisms operate independently because they use different overlay properties and invisibility specs. You can combine them for multi-level folding.
The docstring detection algorithm operates in stages:
- Font-lock identification: Scan for characters with
font-lock-doc-face
- Form boundary detection: Use
beginning-of-defun
andend-of-defun
to locate the containing form - String literal parsing: Search backward for the opening quote, forward for the closing quote
- Escape handling: Count consecutive backslashes before each quote. An even count (including zero) means the quote is unescaped and terminates the string. An odd count means the quote is escaped and is part of the string content.
- Validation: Ensure the detected region is actually a string literal
This multi-stage approach handles:
- Mixed fontification (for example,
hl-todo
highlighting within docstrings) - Escaped quotes within docstrings
- Malformed or incomplete forms
- Nested string literals
Overlays created by this package have these properties:
invisible
: Set to'lisp-docstring-toggle
for invisibility controllisp-docstring-toggle
: Set tot
for overlay identificationevaporate
: Set tot
for automatic cleanup when text is deletedafter-string
: Contains the ellipsis indicator (if configured)
The invisible
property works through Emacs’s invisibility specification system.
Adding 'lisp-docstring-toggle
to buffer-invisibility-spec
activates hiding.
Removing it reveals all hidden text.
See also: (Elisp Manual) Overlay Properties
lisp-docstring-toggle
does not:
- Fold code blocks or function bodies (use
hideshow
oroutline-mode
) - Work with non-Lisp languages (detection relies on Lisp-specific conventions)
- Detect docstrings in all nested forms (requires more testing)
- Modify buffer content (operates purely through display properties)
- Provide project-wide docstring management (operates per-buffer)
For general code folding, consider outline-mode
, hideshow
, or origami.el
. For
documentation generation, see tools like eldoc
, helpful
, or language-specific
documentation systems.
If docstrings are not being hidden:
- Verify font-lock is active:
M-x font-lock-mode
should show “enabled” - Check if docstrings use
font-lock-doc-face
: Place cursor on a docstring and runM-x describe-char
- Run
M-x lisp-docstring-toggle-debug-show-snippets
to see what is detected
On very large files (more than 100k lines), initial detection may be slow due to font-lock-ensure
. This is a one-time cost per toggle operation.
If you experience issues with other packages:
- Disable other folding packages temporarily
- Check for conflicting keybindings with
M-x describe-key
- Report the issue at https://github.com/gggion/lisp-docstring-toggle/issues
Bug reports and feature requests are welcome at: https://github.com/gggion/lisp-docstring-toggle/issues
When reporting bugs, please include:
- Emacs version (
M-x emacs-version
) - Major mode where the issue occurs
- Minimal reproduction steps
- Output of
M-x lisp-docstring-toggle-debug-show-snippets
Pull requests should:
- Include tests for new functionality
- Follow existing code style
- Update documentation as needed
This package was inspired by:
hideif.el
: Overlay management patternspel-hide-docstring.el
: Partial visibility conceptfont-lock.el
andlisp-mode.el
: Docstring detection conventions
GPLv3