Skip to content

gggion/lisp-docstring-toggle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

lisp-docstring-toggle: Toggle visibility of Lisp docstrings

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.

Screenshots

https://github.com/gggion/lisp-docstring-toggle/blob/screenshots/test.gif?raw=true

Quick Start

  1. Install the package (see Installation)
  2. Add to your configuration:
    (add-hook 'emacs-lisp-mode-hook #'lisp-docstring-toggle-setup)
        
  3. 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.

Installation

From MELPA (NOT YET)

(use-package lisp-docstring-toggle
  :ensure t
  :hook ((emacs-lisp-mode lisp-mode) . lisp-docstring-toggle-setup))

From source

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)

With straight.el

(straight-use-package
 '(lisp-docstring-toggle :type git :host github
                         :repo "gggion/lisp-docstring-toggle"))

With use-package and recipe

(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))

Doom Emacs

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))

Usage

Commands

Toggle all docstrings

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.

Toggle docstring at point

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.

Debug docstring detection

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

Customization

Hiding styles

The user option lisp-docstring-toggle-hide-style controls how docstrings are hidden. It accepts three values:

Complete hiding

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.

Partial visibility

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.

First line only

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.

Customizing the ellipsis

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.

Complete configuration example

(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 ""))

Compatibility

Supported major modes

The package works with any major mode that:

  1. Uses font-lock-doc-face for docstring highlighting
  2. Supports beginning-of-defun and end-of-defun navigation
  3. 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

Interaction with other packages

hl-todo

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.

outline-mode and hideshow

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.

Technical details

Detection algorithm

The docstring detection algorithm operates in stages:

  1. Font-lock identification: Scan for characters with font-lock-doc-face
  2. Form boundary detection: Use beginning-of-defun and end-of-defun to locate the containing form
  3. String literal parsing: Search backward for the opening quote, forward for the closing quote
  4. 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.
  5. 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

Overlay properties

Overlays created by this package have these properties:

  • invisible: Set to 'lisp-docstring-toggle for invisibility control
  • lisp-docstring-toggle: Set to t for overlay identification
  • evaporate: Set to t for automatic cleanup when text is deleted
  • after-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

Limitations

lisp-docstring-toggle does not:

  • Fold code blocks or function bodies (use hideshow or outline-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.

Troubleshooting

Docstrings not detected

If docstrings are not being hidden:

  1. Verify font-lock is active: M-x font-lock-mode should show “enabled”
  2. Check if docstrings use font-lock-doc-face: Place cursor on a docstring and run M-x describe-char
  3. Run M-x lisp-docstring-toggle-debug-show-snippets to see what is detected

Performance issues

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.

Conflicts with other packages

If you experience issues with other packages:

  1. Disable other folding packages temporarily
  2. Check for conflicting keybindings with M-x describe-key
  3. Report the issue at https://github.com/gggion/lisp-docstring-toggle/issues

Contributing

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

Acknowledgments

This package was inspired by:

  • hideif.el: Overlay management patterns
  • pel-hide-docstring.el: Partial visibility concept
  • font-lock.el and lisp-mode.el: Docstring detection conventions

License

GPLv3

About

Docstring visibility control for Lisp code

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published