Documentation
Commentary
* Commands provided
This file provides the Hideshow minor mode, it includes the
following commands (and their keybindings) to hiding and showing
code and comment blocks:
`hs-hide-block' C-c @ C-h/C-d
`hs-show-block' C-c @ C-s
`hs-hide-all' C-c @ C-M-h/C-t
`hs-show-all' C-c @ C-M-s/C-a
`hs-hide-level' C-c @ C-l
`hs-toggle-hiding' C-c @ C-c/C-e or S-<mouse-2>
`hs-hide-initial-comment-block'
`hs-cycle' C-c @ TAB
`hs-toggle-all' C-c @ <backtab>
All these commands are defined in `hs-prefix-map',
`hs-minor-mode-map' and `hs-indicators-map'.
Blocks are defined per mode. For example, in c-mode and similar,
they are simply text between curly braces, while in Lisp-ish modes
parens are used. Multi-line comment blocks can also be hidden.
Read-only buffers are not a problem, since hideshow doesn't modify
the text.
The command `M-x hs-minor-mode' toggles the minor mode or sets it
buffer-local.
* Suggested usage
Add the following to your init file:
(add-hook 'X-mode-hook #'hs-minor-mode) ; other modes similarly
where X = {emacs-lisp,c,c++,perl,...}. You can also manually toggle
hideshow minor mode by typing `M-x hs-minor-mode'. After hideshow is
activated or deactivated, `hs-minor-mode-hook' is run with `run-hooks'.
To enable indentation-based hiding/showing turn on `hs-indentation-mode'.
Additionally, Joseph Eydelnant writes:
I enjoy your package hideshow.el Version 5.24 2001/02/13
a lot and I've been looking for the following functionality:
toggle hide/show all with a single key.
Here are a few lines of code that lets me do just that.
(defvar my-hs-hide nil "Current state of hideshow for toggling all.")
;;;###autoload
(defun my-toggle-hideshow-all () "Toggle hideshow all."
(interactive)
(setq my-hs-hide (not my-hs-hide))
(if my-hs-hide
(hs-hide-all)
(hs-show-all)))
* Customization
Hideshow provides the following user options:
- `hs-hide-comments-when-hiding-all'
- `hs-hide-all-non-comment-function'
- `hs-isearch-open'
- `hs-set-up-overlay'
- `hs-display-lines-hidden'
- `hs-show-indicators'
- `hs-indicator-type'
- `hs-indicator-maximum-buffer-size'
- `hs-allow-nesting'
- `hs-cycle-filter'
- `hs-indentation-respect-end-block'
The variable `hs-hide-all-non-comment-function' may be useful if you
only want to hide some N levels blocks for some languages/files or
implement your idea of what is more useful. For example, the
following code shows the next nested level in addition to the
top-level for java:
(defun ttn-hs-hide-level-2 ()
(when (funcall hs-looking-at-block-start-predicate)
(hs-hide-level 2)))
(add-hook 'java-mode-hook
(lambda ()
(setq-local hs-hide-all-non-comment-function
#'ttn-hs-hide-level-2)))
Hideshow works with incremental search (isearch) by setting the variable
`hs-headline', which is the line of text at the beginning of a hidden
block that contains a match for the search. You can have this show up
in the mode line by modifying the variable `mode-line-format'. For
example, the following code prepends this info to the mode line:
(unless (memq 'hs-headline mode-line-format)
(setq mode-line-format
(append '("-" hs-headline) mode-line-format)))
The following hooks are run after some commands:
hs-hide-hook => hs-hide-block hs-hide-all hs-hide-level hs-cycle
hs-show-hook => hs-show-block hs-show-all hs-cycle
The variable `hs-set-up-overlay' allow customize the appearance of
the hidden block and other effects associated with overlays. For
example:
(setopt hs-set-up-overlay
(defun my-display-code-line-counts (ov)
(when (eq 'code (overlay-get ov 'hs))
(overlay-put ov 'display
(propertize
(format " [... <%d>] "
(count-lines (overlay-start ov)
(overlay-end ov)))
'face 'font-lock-type-face)))))
* Extending hideshow
** Adding support for a major mode
Normally, hideshow tries to determine appropriate values for block
and comment definitions by examining the major mode settings. If the
major mode is not derived from `prog-mode', hideshow will not
activate. If you want to override this, you can set any of the
following variables: `hs-block-start-regexp',
`hs-block-start-mdata-select', `hs-block-end-regexp',
`hs-c-start-regexp', `hs-forward-sexp-function',
`hs-adjust-block-beginning-function', `hs-adjust-block-end-function',
`hs-find-block-beginning-function', `hs-find-next-block-function',
`hs-looking-at-block-start-predicate', `hs-inside-comment-predicate',
`hs-treesit-things'.
These variables help hideshow know what is considered a block, which
function to use to get the block positions, etc.
A (code) block is defined as text surrounded by
`hs-block-start-regexp' and `hs-block-end-regexp'.
For some major modes, forward-sexp does not work properly. In those
cases, `hs-forward-sexp-function' specifies another function to use
instead.
*** Non-regexp matching
By default, Hideshow uses regular expressions to match blocks. For
something more advanced than regexp is necessary to modify these
variables (see their docstring):
- `hs-forward-sexp-function'
- `hs-find-block-beginning-function'
- `hs-find-next-block-function'
- `hs-looking-at-block-start-predicate'
- `hs-inside-comment-predicate' (For comments)
- `hs-block-end-regexp' (Preferably, this should be set to nil)
*** Tree-sitter support
All the treesit based modes already have support for hiding/showing
using the treesit thing `list' (see `treesit-major-mode-setup').
However, for some modes the `list' thing is not enough for detecting
the proper code block and the range to hide, you can set the variable
`hs-treesit-things' to override this, but ensure you have the proper
values in `hs-adjust-block-end-function' and `hs-adjust-block-beginning-function' to
properly hide the code block.
** Migrating from `hs-special-modes-alist'
Starting with Emacs 31, `hs-special-modes-alist' has been deprecated.
Instead, modes should use the buffer-local variables that replace
each of the options in `hs-special-modes-alist'. The following table
shows the old elements of `hs-special-modes-alist' and their
replacement buffer-local variables:
Instead of this Use this
-----------------------------------------------------------------------
START `hs-block-start-regexp'
(START . MDATA) `hs-block-start-regexp' and `hs-block-start-mdata-select'
END `hs-block-end-regexp'
COMMENT-START `hs-c-start-regexp'
FORWARD-SEXP-FUNC `hs-forward-sexp-function'
ADJUST-BEG-FUNC `hs-adjust-block-beginning-function'
FIND-BLOCK-BEGINNING-FUNC `hs-find-block-beginning-function'
FIND-NEXT-BLOCK-FUNC `hs-find-next-block-function'
LOOKING-AT-BLOCK-START-P-FUNC `hs-looking-at-block-start-predicate')
* Bugs
1) Sometimes `hs-headline' can become out of sync. To reset, type
`M-x hs-minor-mode' twice (that is, deactivate then re-activate
hideshow).
2) Some buffers can't be `byte-compile-file'd properly. This is because
`byte-compile-file' inserts the file to be compiled in a temporary
buffer and switches `normal-mode' on. In the case where you have
`hs-hide-initial-comment-block' in `hs-minor-mode-hook', the hiding of
the initial comment sometimes hides parts of the first statement (seems
to be only in `normal-mode'), so there are unbalanced parenthesis.
The workaround is to clear `hs-minor-mode-hook' when byte-compiling:
(define-advice byte-compile-file (:around
(fn &rest rest)
byte-compile-file-hideshow-off)
(let (hs-minor-mode-hook)
(apply #'fn rest)))
3) Hideshow interacts badly with Ediff and `vc-diff'. At the moment, the
suggested workaround is to turn off hideshow entirely, for example:
(add-hook 'ediff-prepare-buffer-hook #'turn-off-hideshow)
(add-hook 'vc-before-checkin-hook #'turn-off-hideshow)
In the case of `vc-diff', here is a less invasive workaround:
(add-hook 'vc-before-checkin-hook
(lambda ()
(goto-char (point-min))
(hs-show-block)))
Unfortunately, these workarounds do not restore hideshow state.
* Thanks
Thanks go to the following people for valuable ideas, code and
bug reports.
Dean Andrews, Alf-Ivar Holm, Holger Bauer, Christoph Conrad, Dave Love,
Dirk Herrmann, Gael Marziou, Jan Djarv, Guillaume Leray, Moody Ahmad,
Preston F. Crow, Lars Lindberg, Reto Zimmermann, Keith Sheffield,
Chew Meng Kuan, Tony Lam, Pete Ware, François Pinard, Stefan Monnier,
Joseph Eydelnant, Michael Ernst, Peter Heslin
Special thanks go to Dan Nicolaescu, who reimplemented hideshow using
overlays (rather than selective display), added isearch magic, folded
in custom.el compatibility, generalized comment handling, incorporated
mouse support, and maintained the code in general. Version 4.0 is
largely due to his efforts.
* History (author commentary)
Hideshow was inspired when I learned about selective display. It was
reimplemented to use overlays for 4.0 (see above). WRT older history,
entries in the masterfile corresponding to versions 1.x and 2.x have
been lost. XEmacs support is reliable as of 4.29. State save and
restore was added in 3.5 (not widely distributed), and reliable as of
4.30. Otherwise, the code seems stable. Passes checkdoc as of 4.32.
Version 5.x uses new algorithms for block selection and traversal,
unbundles state save and restore, and includes more isearch support.
Consumers
Reverse Dependencies
- vlog-mode
- rtest
- vhdl-mode
- fold-dwim
- jfolding
- boogie-friends
- ecb
- emacspeak
- ensime
- ess
- hideshow-org
- io-mode
- nsis-mode
- racket-mode
- scion
- company-coq
- php+-mode
- nxhtml
- haskell-mode
- rails
- bicycle
- el-search
- dylan
- imenu-list
- python-mode
- eide
- elpy
- esn
- haskell-tng-mode
- vhdl-ext
- verilog-ext
- jtsx
- vsh-mode
- roc-ts-mode
- hideshowvis
- savefold
- q-mode
- anju
- sysml-mode
- shexc-ts-mode