-;;; hideshow.el --- minor mode cmds to selectively display blocks of code
+;;; hideshow.el --- minor mode cmds to selectively display code/comment blocks
-;; Copyright (C) 1994, 95, 96, 97, 98, 99 Free Software Foundation
+;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01 Free Software Foundation
-;; Author: Thien-Thi Nguyen <ttn@netcom.com>
+;; Author: Thien-Thi Nguyen <ttn@gnu.org>
;; Dan Nicolaescu <dann@ics.uci.edu>
;; Keywords: C C++ java lisp tools editing comments blocks hiding outlines
-;; Maintainer-Version: 5.9
+;; Maintainer-Version: 5.58.2.4
;; Time-of-Day-Author-Most-Likely-to-be-Recalcitrant: early morning
;; This file is part of GNU Emacs.
;; * Commands provided
;;
-;; This file provides `hs-minor-mode'. When active, eight commands are
-;; available, implementing block hiding and showing. They (and their
+;; This file provides Hideshow Minor Mode. When active, nine commands
+;; are available, implementing block hiding and showing. They (and their
;; keybindings) are:
;;
-;; hs-hide-block C-c h
-;; hs-show-block C-c s
-;; hs-hide-all C-c H
-;; hs-show-all C-c S
-;; hs-show-region C-c R
-;; hs-hide-level C-c L
-;; hs-mouse-toggle-hiding [(shift button-2)]
+;; hs-hide-block C-c @ C-h
+;; hs-show-block C-c @ C-s
+;; hs-hide-all C-c @ C-M-h
+;; hs-show-all C-c @ C-M-s
+;; hs-hide-level C-c @ C-l
+;; hs-toggle-hiding C-c @ C-c
+;; hs-mouse-toggle-hiding [(shift mouse-2)]
;; hs-hide-initial-comment-block
;;
;; Blocks are defined per mode. In c-mode, c++-mode and java-mode, they
;; The command `M-x hs-minor-mode' toggles the minor mode or sets it
;; (similar to other minor modes).
+;; * Suggested usage
+;;
+;; First make sure hideshow.el is in a directory in your `load-path'.
+;; You can optionally byte-compile it using `M-x byte-compile-file'.
+;; Then, add the following to your ~/.emacs:
+;;
+;; (load-library "hideshow")
+;; (add-hook 'X-mode-hook ; other modes similarly
+;; (lambda () (hs-minor-mode 1)))
+;;
+;; 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 w/ `run-hooks'.
+;;
+;; Additionally, Joseph Eydelnant writes:
+;; I enjoy your package hideshow.el Ver. 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)))
+;;
+;; [Your hideshow hacks here!]
+
;; * Customization
;;
;; You can use `M-x customize-variable' on the following variables:
;;
-;; hs-hide-comments-when-hiding-all -- self-explanatory!
-;; hs-isearch-open -- what kind of hidden blocks to
+;; - hs-hide-comments-when-hiding-all -- self-explanatory!
+;; - hs-hide-all-non-comment-function -- if non-nil, when doing a
+;; `hs-hide-all', this function
+;; is called w/ no arguments
+;; - hs-isearch-open -- what kind of hidden blocks to
;; open when doing isearch
;;
+;; Some languages (e.g., Java) are deeply nested, so the normal behavior
+;; of `hs-hide-all' (hiding all but top-level blocks) results in very
+;; little information shown, which is not very useful. You can use the
+;; variable `hs-hide-all-non-comment-function' to implement your idea of
+;; what is more useful. For example, the following code shows the next
+;; nested level in addition to the top-level:
+;;
+;; (defun ttn-hs-hide-level-1 ()
+;; (hs-hide-level 1)
+;; (forward-sexp 1))
+;; (setq hs-hide-all-non-comment-function 'ttn-hs-hide-level-1)
+;;
;; Hideshow works w/ 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
;; Hooks are run after some commands:
;;
;; hs-hide-hook in hs-hide-block, hs-hide-all, hs-hide-level
-;; hs-show-hook hs-show-block, hs-show-all, hs-show-region
+;; hs-show-hook hs-show-block, hs-show-all
;;
-;; All hooks are run w/ `run-hooks'. See docs for each variable or hook
-;; for more info.
+;; One of `hs-hide-hook' or `hs-show-hook' is run for the toggling
+;; commands when the result of the toggle is to hide or show blocks,
+;; respectively. All hooks are run w/ `run-hooks'. See docs for each
+;; variable or hook for more info.
;;
;; Normally, hideshow tries to determine appropriate values for block
;; and comment definitions by examining the buffer's major mode. If
;; variable `hs-special-modes-alist'. Packages that use hideshow should
;; do something like:
;;
-;; (let ((my-mode-hs-info '(my-mode "{{" "}}" ...)))
-;; (if (not (member my-mode-hs-info hs-special-modes-alist))
-;; (setq hs-special-modes-alist
-;; (cons my-mode-hs-info hs-special-modes-alist))))
+;; (add-to-list 'hs-special-modes-alist '(my-mode "{{" "}}" ...))
;;
;; If you have an entry that works particularly well, consider
;; submitting it for inclusion in hideshow.el. See docstring for
;; `hs-special-modes-alist' for more info on the entry format.
-
-;; * Suggested usage
;;
-;; First make sure hideshow.el is in a directory in your `load-path'.
-;; You can optionally byte-compile it using `M-x byte-compile-file'.
-;; Then, add the following to your ~/.emacs:
+;; See also variable `hs-set-up-overlay' for per-block customization of
+;; appearance or other effects associated with overlays. For example:
;;
-;; (load-library "hideshow")
-;; (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, `hs-minor-mode-hook' is run w/ `run-hooks'. A good hook
-;; to add is `hs-hide-initial-comment-block'.
+;; (setq 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)))))
;; * Bugs
;;
;; writes this, please send me a copy.
;;
;; (2) Sometimes `hs-headline' can become out of sync. To reset, type
-;; `M-x hs-minor-mode' twice (that is, deactivate then activate
+;; `M-x hs-minor-mode' twice (that is, deactivate then re-activate
;; hideshow).
;;
-;; (3) Hideshow 5.x is developed and tested on GNU Emacs 20.4.
+;; (3) Hideshow 5.x is developed and tested on GNU Emacs 20.7.
;; XEmacs compatibility may have bitrotted since 4.29.
;;
+;; (4) 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 "(" and ")".
+;;
+;; The workaround is to clear `hs-minor-mode-hook' when byte-compiling:
+;;
+;; (defadvice byte-compile-file (around
+;; byte-compile-file-hideshow-off
+;; act)
+;; (let ((hs-minor-mode-hook nil))
+;; ad-do-it))
+;;
+;; (5) Hideshow interacts badly with Ediff and `vc-diff'. At the moment, the
+;; suggested workaround is to turn off hideshow entirely, for example:
+;;
+;; (defun turn-off-hideshow () (hs-minor-mode -1))
+;; (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.
+;; If someone figures out a better way, please let me know.
+
+;; * Correspondance
+;;
;; Correspondance welcome; please indicate version number. Send bug
-;; reports and inquiries to <ttn@netcom.com>.
+;; reports and inquiries to <ttn@gnu.org>.
;; * Thanks
;;
;; Thanks go to the following people for valuable ideas, code and
;; bug reports.
;;
-;; adahome@ix.netcom.com Dean Andrews
-;; alfh@ifi.uio.no Alf-Ivar Holm
-;; bauer@itsm.uni-stuttgart.de Holger Bauer
-;; christoph.conrad@post.rwth-aachen.de Christoph Conrad
-;; d.love@dl.ac.uk Dave Love
-;; dirk@ida.ing.tu-bs.de Dirk Herrmann
-;; gael@gnlab030.grenoble.hp.com Gael Marziou
-;; jan.djarv@sa.erisoft.se Jan Djarv
-;; leray@dev-lme.pcc.philips.com Guillaume Leray
-;; moody@mwt.net Moody Ahmad
-;; preston.f.crow@dartmouth.edu Preston F. Crow
-;; qhslali@aom.ericsson.se Lars Lindberg
-;; reto@synopsys.com Reto Zimmermann
-;; sheff@edcsgw2.cr.usgs.gov Keith Sheffield
-;; smes@post1.com Chew Meng Kuan
-;; tonyl@eng.sun.com Tony Lam
-;; ware@cis.ohio-state.edu Pete Ware
-;;
-;; Special thanks go to Dan Nicolaescu <dann@ics.uci.edu>, 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.
+;; 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
+;;
+;; 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
;;
:group 'hideshow)
(defcustom hs-minor-mode-hook nil
- "*Hook called when hideshow minor mode is activated."
+ "*Hook called when hideshow minor mode is activated or deactivated."
:type 'hook
- :group 'hideshow)
+ :group 'hideshow
+ :version "21.1")
-(defcustom hs-isearch-open 'block
+(defcustom hs-isearch-open 'code
"*What kind of hidden blocks to open when doing `isearch'.
One of the following symbols:
- block -- open only blocks
- comment -- open only comments
- t -- open both blocks and comments
- nil -- open neither blocks nor comments
+ code -- open only code blocks
+ comment -- open only comment blocks
+ t -- open both code and comment blocks
+ nil -- open neither code nor comment blocks
This has effect iff `search-invisible' is set to `open'."
- :type '(choice (const :tag "open only blocks" block)
- (const :tag "open only comments" comment)
- (const :tag "open both blocks and comments" t)
+ :type '(choice (const :tag "open only code blocks" code)
+ (const :tag "open only comment blocks" comment)
+ (const :tag "open both code and comment blocks" t)
(const :tag "don't open any of them" nil))
:group 'hideshow)
'((c-mode "{" "}" "/[*/]" nil hs-c-like-adjust-block-beginning)
(c++-mode "{" "}" "/[*/]" nil hs-c-like-adjust-block-beginning)
(bibtex-mode ("^@\\S(*\\(\\s(\\)" 1))
- (java-mode "{" "}" "/[*/]" nil hs-c-like-adjust-block-beginning)
- )
+ (java-mode "{" "}" "/[*/]" nil hs-c-like-adjust-block-beginning))
"*Alist for initializing the hideshow variables for different modes.
Each element has the form
(MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC).
As a special case, START may be a list of the form (COMPLEX-START
MDATA-SELECTOR), where COMPLEX-START is a regexp w/ multiple parts and
MDATA-SELECTOR an integer that specifies which sub-match is the proper
-place to adjust point, before calling `hs-forward-sexp-func'. For
-example, see the `hs-special-modes-alist' entry for `bibtex-mode'.
+place to adjust point, before calling `hs-forward-sexp-func'. Point
+is adjusted to the beginning of the specified match. For example,
+see the `hs-special-modes-alist' entry for `bibtex-mode'.
For some major modes, `forward-sexp' does not work properly. In those
cases, FORWARD-SEXP-FUNC specifies another function to use instead.
appropriate values. The regexps should not contain leading or trailing
whitespace. Case does not matter.")
+(defvar hs-hide-all-non-comment-function nil
+ "*Function called if non-nil when doing `hs-hide-all' for non-comments.")
+
(defvar hs-hide-hook nil
"*Hook called (with `run-hooks') at the end of commands to hide text.
-These commands include `hs-hide-all', `hs-hide-block' and `hs-hide-level'.")
+These commands include the toggling commands (when the result is to hide
+a block), `hs-hide-all', `hs-hide-block' and `hs-hide-level'.")
(defvar hs-show-hook nil
"*Hook called (with `run-hooks') at the end of commands to show text.
-These commands include `hs-show-all', `hs-show-block' and `hs-show-region'.")
+These commands include the toggling commands (when the result is to show
+a block), `hs-show-all' and `hs-show-block'..")
+
+(defvar hs-set-up-overlay nil
+ "*Function called with one arg, OV, a newly initialized overlay.
+Hideshow puts a unique overlay on each range of text to be hidden
+in the buffer. Here is a simple example of how to use this variable:
+
+ (defun display-code-line-counts (ov)
+ (when (eq 'code (overlay-get ov 'hs))
+ (overlay-put ov 'display
+ (format \"... / %d\"
+ (count-lines (overlay-start ov)
+ (overlay-end ov))))))
+
+ (setq hs-set-up-overlay 'display-code-line-counts)
+
+This example shows how to get information from the overlay as well
+as how to set its `display' property. See `hs-make-overlay' and
+info node `(elisp)Overlays'.")
;;---------------------------------------------------------------------------
;; internal variables
(defvar hs-minor-mode-map nil
"Keymap for hideshow minor mode.")
+(defvar hs-minor-mode-menu nil
+ "Menu for hideshow minor mode.")
+
(defvar hs-c-start-regexp nil
"Regexp for beginning of comments.
Differs from mode-specific comment regexps in that
for `hs-block-start-regexp'.
For example, in c-like modes, if we wish to also hide the curly braces
-(if you think they occupy too much space on the screen), this function
+\(if you think they occupy too much space on the screen), this function
should return the starting point (at the end of line) of the hidden
region.
-It is called with a single argument ARG which is the the position in
+It is called with a single argument ARG which is the position in
buffer after the block beginning.
It should return the position from where we should start hiding.
;;---------------------------------------------------------------------------
;; system dependency
-; ;; xemacs compatibility
-; (when (string-match "xemacs\\|lucid" emacs-version)
-; ;; use pre-packaged compatiblity layer
-; (require 'overlay))
-;
-; ;; xemacs and emacs-19 compatibility
-; (when (or (not (fboundp 'add-to-invisibility-spec))
-; (not (fboundp 'remove-from-invisibility-spec)))
-; ;; `buffer-invisibility-spec' mutators snarfed from Emacs 20.3 lisp/subr.el
-; (defun add-to-invisibility-spec (arg)
-; (cond
-; ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
-; (setq buffer-invisibility-spec (list arg)))
-; (t
-; (setq buffer-invisibility-spec
-; (cons arg buffer-invisibility-spec)))))
-; (defun remove-from-invisibility-spec (arg)
-; (if buffer-invisibility-spec
-; (setq buffer-invisibility-spec
-; (delete arg buffer-invisibility-spec)))))
-
-;; hs-match-data
(defalias 'hs-match-data 'match-data)
;;---------------------------------------------------------------------------
;; support functions
(defun hs-discard-overlays (from to)
+ "Delete hideshow overlays in region defined by FROM and TO."
(when (< to from)
(setq from (prog1 to (setq to from))))
- (mapcar (lambda (ov)
- (when (overlay-get ov 'hs)
- (delete-overlay ov)))
- (overlays-in from to)))
+ (dolist (ov (overlays-in from to))
+ (when (overlay-get ov 'hs)
+ (delete-overlay ov))))
+
+(defun hs-make-overlay (b e kind &optional b-offset e-offset)
+ "Return a new overlay in region defined by B and E with type KIND.
+KIND is either `code' or `comment'. Optional fourth arg B-OFFSET
+when added to B specifies the actual buffer position where the block
+begins. Likewise for optional fifth arg E-OFFSET. If unspecified
+they are taken to be 0 (zero). The following properties are set
+in the overlay: 'invisible 'hs 'hs-b-offset 'hs-e-offset. Also,
+depending on variable `hs-isearch-open', the following properties may
+be present: 'isearch-open-invisible 'isearch-open-invisible-temporary.
+If variable `hs-set-up-overlay' is non-nil it should specify a function
+to call with the newly initialized overlay."
+ (unless b-offset (setq b-offset 0))
+ (unless e-offset (setq e-offset 0))
+ (let ((ov (make-overlay b e))
+ (io (if (eq 'block hs-isearch-open)
+ ;; backward compatibility -- `block'<=>`code'
+ 'code
+ hs-isearch-open)))
+ (overlay-put ov 'invisible 'hs)
+ (overlay-put ov 'hs kind)
+ (overlay-put ov 'hs-b-offset b-offset)
+ (overlay-put ov 'hs-e-offset e-offset)
+ (when (or (eq io t) (eq io kind))
+ (overlay-put ov 'isearch-open-invisible 'hs-isearch-show)
+ (overlay-put ov 'isearch-open-invisible-temporary
+ 'hs-isearch-show-temporary))
+ (when hs-set-up-overlay (funcall hs-set-up-overlay ov))
+ ov))
(defun hs-isearch-show (ov)
+ "Delete overlay OV, and set `hs-headline' to nil.
+
+This function is meant to be used as the `isearch-open-invisible'
+property of an overlay."
(setq hs-headline nil)
- (hs-flag-region (overlay-start ov) (overlay-end ov) nil))
+ (delete-overlay ov))
(defun hs-isearch-show-temporary (ov hide-p)
+ "Hide or show overlay OV, and set `hs-headline', all depending on HIDE-P.
+If HIDE-P is non-nil, `hs-headline' is set to nil and overlay OV is hidden.
+Otherwise, `hs-headline' is set to the line of text at the head of OV, and
+OV is shown.
+
+This function is meant to be used as the `isearch-open-invisible-temporary'
+property of an overlay."
(setq hs-headline
- (if hide-p
- nil
- (or hs-headline
- (let ((start (overlay-start ov)))
- (buffer-substring
- (save-excursion (goto-char start)
- (beginning-of-line)
- (skip-chars-forward " \t")
- (point))
- start)))))
+ (if hide-p
+ nil
+ (or hs-headline
+ (let ((start (overlay-start ov)))
+ (buffer-substring
+ (save-excursion (goto-char start)
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (point))
+ start)))))
(force-mode-line-update)
+ ;; handle `display' property specially
+ (let (value)
+ (if hide-p
+ (when (setq value (overlay-get ov 'hs-isearch-display))
+ (overlay-put ov 'display value)
+ (overlay-put ov 'hs-isearch-display nil))
+ (when (setq value (overlay-get ov 'display))
+ (overlay-put ov 'hs-isearch-display value)
+ (overlay-put ov 'display nil))))
(overlay-put ov 'invisible (and hide-p 'hs)))
-(defun hs-flag-region (from to flag)
- "Hide or show lines from FROM to TO, according to FLAG.
-If FLAG is nil then text is shown, while if FLAG is non-nil the text is
-hidden. Actually flag is really either `comment' or `block' depending
-on what kind of block it is suppose to hide."
- (save-excursion
- ;; first clear it all out
- (hs-discard-overlays from to)
- ;; now create overlays if needed
- (when flag
- (let ((overlay (make-overlay from to)))
- (overlay-put overlay 'invisible 'hs)
- (overlay-put overlay 'intangible t)
- (overlay-put overlay 'hs flag)
- (when (or (eq hs-isearch-open t) (eq hs-isearch-open flag))
- (mapcar
- (lambda (pair)
- (overlay-put overlay (car pair) (cdr pair)))
- '((isearch-open-invisible . hs-isearch-show)
- (isearch-open-invisible-temporary . hs-isearch-show-temporary))))
- overlay))))
-
(defun hs-forward-sexp (match-data arg)
"Adjust point based on MATCH-DATA and call `hs-forward-sexp-func' w/ ARG.
Original match data is restored upon return."
(defun hs-hide-comment-region (beg end &optional repos-end)
"Hide a region from BEG to END, marking it as a comment.
Optional arg REPOS-END means reposition at end."
- (hs-flag-region (progn (goto-char beg) (end-of-line) (point))
- (progn (goto-char end) (end-of-line) (point))
- 'comment)
+ (let ((beg-eol (progn (goto-char beg) (end-of-line) (point)))
+ (end-eol (progn (goto-char end) (end-of-line) (point))))
+ (hs-discard-overlays beg-eol end-eol)
+ (hs-make-overlay beg-eol end-eol 'comment beg end))
(goto-char (if repos-end end beg)))
(defun hs-hide-block-at-point (&optional end comment-reg)
and then further adjusted to be at the end of the line."
(if comment-reg
(hs-hide-comment-region (car comment-reg) (cadr comment-reg) end)
- (if (looking-at hs-block-start-regexp)
- (let* ((mdata (hs-match-data t))
- (pure-p (match-end 0))
- (p
- ;; `p' is the point at the end of the block beginning,
- ;; which may need to be adjusted
- (save-excursion
- (goto-char (funcall (or hs-adjust-block-beginning
- 'identity)
- pure-p))
- ;; whatever the adjustment, we move to eol
- (end-of-line)
- (point)))
- (q
- ;; `q' is the point at the end of the block
- (progn (hs-forward-sexp mdata 1)
- (end-of-line)
- (point))))
- (if (and (< p (point)) (> (count-lines p q) 1))
- (overlay-put (hs-flag-region p q 'block)
- 'hs-ofs
- (- pure-p p)))
- (goto-char (if end q (min p pure-p)))))))
+ (when (looking-at hs-block-start-regexp)
+ (let* ((mdata (hs-match-data t))
+ (pure-p (match-end 0))
+ (p
+ ;; `p' is the point at the end of the block beginning,
+ ;; which may need to be adjusted
+ (save-excursion
+ (goto-char (funcall (or hs-adjust-block-beginning
+ 'identity)
+ pure-p))
+ ;; whatever the adjustment, we move to eol
+ (end-of-line)
+ (point)))
+ (q
+ ;; `q' is the point at the end of the block
+ (progn (hs-forward-sexp mdata 1)
+ (end-of-line)
+ (point))))
+ (when (and (< p (point)) (> (count-lines p q) 1))
+ (hs-discard-overlays p q)
+ (hs-make-overlay p q 'code (- pure-p p)))
+ (goto-char (if end q (min p pure-p)))))))
(defun hs-safety-is-job-n ()
"Warn if `buffer-invisibility-spec' does not contain symbol `hs'."
- (unless (and (listp buffer-invisibility-spec)
- (assq 'hs buffer-invisibility-spec))
- (message "Warning: `buffer-invisibility-spec' does not contain hs!!")
- (sit-for 2)))
+ (unless (and (listp buffer-invisibility-spec)
+ (assq 'hs buffer-invisibility-spec))
+ (message "Warning: `buffer-invisibility-spec' does not contain hs!!")
+ (sit-for 2)))
(defun hs-inside-comment-p ()
"Return non-nil if point is inside a comment, otherwise nil.
(let ((q (point)))
(when (or (looking-at hs-c-start-regexp)
(re-search-backward hs-c-start-regexp (point-min) t))
+ ;; first get to the beginning of this comment...
+ (while (and (not (bobp))
+ (= (point) (progn (forward-comment -1) (point))))
+ (forward-char -1))
+ ;; ...then extend backwards
(forward-comment (- (buffer-size)))
(skip-chars-forward " \t\n\f")
(let ((p (point))
- (not-hidable nil))
+ (hidable t))
(beginning-of-line)
(unless (looking-at (concat "[ \t]*" hs-c-start-regexp))
;; we are in this situation: (example)
(while (and (< (point) q)
(> (point) p)
(not (looking-at hs-c-start-regexp)))
- (setq p (point));; use this to avoid an infinite cycle
+ (setq p (point)) ;; use this to avoid an infinite cycle
(forward-comment 1)
(skip-chars-forward " \t\n\f"))
- (if (or (not (looking-at hs-c-start-regexp))
- (> (point) q))
- ;; we cannot hide this comment block
- (setq not-hidable t)))
+ (when (or (not (looking-at hs-c-start-regexp))
+ (> (point) q))
+ ;; we cannot hide this comment block
+ (setq hidable nil)))
;; goto the end of the comment
(forward-comment (buffer-size))
(skip-chars-backward " \t\n\f")
(end-of-line)
- (if (>= (point) q)
- (list (if not-hidable nil p) (point))))))))
+ (when (>= (point) q)
+ (list (and hidable p) (point))))))))
(defun hs-grok-mode-type ()
"Set up hideshow variables for new buffers.
c-start-regexp)))
hs-forward-sexp-func (or (nth 4 lookup) 'forward-sexp)
hs-adjust-block-beginning (nth 5 lookup)))
- (progn
- (setq hs-minor-mode nil)
- (error "%s Mode doesn't support Hideshow Minor Mode" mode-name))))
+ (setq hs-minor-mode nil)
+ (error "%s Mode doesn't support Hideshow Minor Mode" mode-name)))
(defun hs-find-block-beginning ()
"Reposition point at block-start.
-Return point, or nil if top-level."
+Return point, or nil if original point was not in a block."
(let ((done nil)
(here (point)))
;; look if current line is block start
(setq minp (1+ (point)))
(funcall hs-forward-sexp-func 1)
(setq maxp (1- (point))))
- (hs-flag-region minp maxp nil) ; eliminate weirdness
+ (hs-discard-overlays minp maxp) ; eliminate weirdness
(goto-char minp)
(while (progn
(forward-comment (buffer-size))
(hs-hide-level-recursive (1- arg) minp maxp)
(goto-char (match-beginning hs-block-start-mdata-select))
(hs-hide-block-at-point t)))
- (hs-safety-is-job-n)
+ (hs-safety-is-job-n)
(goto-char maxp))
(defmacro hs-life-goes-on (&rest body)
(if (and c-reg (nth 0 c-reg))
;; point is inside a comment, and that comment is hidable
(goto-char (nth 0 c-reg))
- (if (and (not c-reg)
- (hs-find-block-beginning)
- (looking-at hs-block-start-regexp))
- ;; point is inside a block
- (goto-char (match-end 0)))))
+ (when (and (not c-reg)
+ (hs-find-block-beginning)
+ (looking-at hs-block-start-regexp))
+ ;; point is inside a block
+ (goto-char (match-end 0)))))
(end-of-line)
(let ((overlays (overlays-at (point)))
(found nil))
(while (and (not found) (overlayp (car overlays)))
- (setq found (overlay-get (car overlays) 'hs)
- overlays (cdr overlays)))
+ (setq found (overlay-get (car overlays) 'hs)
+ overlays (cdr overlays)))
found)))
(defun hs-c-like-adjust-block-beginning (initial)
(hs-life-goes-on
(message "Hiding all blocks ...")
(save-excursion
- (hs-flag-region (point-min) (point-max) nil) ; eliminate weirdness
+ (hs-discard-overlays (point-min) (point-max)) ; eliminate weirdness
(goto-char (point-min))
- (if hs-hide-comments-when-hiding-all
- (let ((c-reg nil)
- (count 0)
- (block-and-comment-re
- (concat "\\("
- hs-block-start-regexp
- "\\)\\|\\("
- hs-c-start-regexp
- "\\)")))
- (while (re-search-forward block-and-comment-re (point-max) t)
- (if (match-beginning 1) ;; we have found a block beginning
- (progn
- (goto-char (match-beginning 1))
- (hs-hide-block-at-point t)
- (message "Hiding ... %d" (setq count (1+ count))))
- ;;found a comment
- (setq c-reg (hs-inside-comment-p))
- (if (and c-reg (car c-reg))
- (if (> (count-lines (car c-reg) (nth 1 c-reg)) 1)
- (progn
- (hs-hide-block-at-point t c-reg)
- (message "Hiding ... %d" (setq count (1+ count))))
- (goto-char (nth 1 c-reg)))))))
- (let ((count 0)
- (buf-size (buffer-size)))
- (while
+ (let ((count 0)
+ (re (concat "\\("
+ hs-block-start-regexp
+ "\\)"
+ (if hs-hide-comments-when-hiding-all
+ (concat "\\|\\("
+ hs-c-start-regexp
+ "\\)")
+ ""))))
+ (while (progn
+ (unless hs-hide-comments-when-hiding-all
+ (forward-comment (point-max)))
+ (re-search-forward re (point-max) t))
+ (if (match-beginning 1)
+ ;; we have found a block beginning
(progn
- (forward-comment buf-size)
- (re-search-forward hs-block-start-regexp (point-max) t))
- (goto-char (match-beginning 0))
- (hs-hide-block-at-point t)
- (message "Hiding ... %d" (setq count (1+ count))))))
- (hs-safety-is-job-n))
+ (goto-char (match-beginning 1))
+ (if hs-hide-all-non-comment-function
+ (funcall hs-hide-all-non-comment-function)
+ (hs-hide-block-at-point t)))
+ ;; found a comment, probably
+ (let ((c-reg (hs-inside-comment-p))) ; blech!
+ (when (and c-reg (car c-reg))
+ (if (> (count-lines (car c-reg) (nth 1 c-reg)) 1)
+ (hs-hide-block-at-point t c-reg)
+ (goto-char (nth 1 c-reg))))))
+ (message "Hiding ... %d" (setq count (1+ count)))))
+ (hs-safety-is-job-n))
(beginning-of-line)
(message "Hiding all blocks ... done")
(run-hooks 'hs-hide-hook)))
(interactive)
(hs-life-goes-on
(message "Showing all blocks ...")
- (hs-flag-region (point-min) (point-max) nil)
+ (hs-discard-overlays (point-min) (point-max))
(message "Showing all blocks ... done")
(run-hooks 'hs-show-hook)))
;; first see if we have something at the end of the line
(catch 'eol-begins-hidden-region-p
(let ((here (point)))
- (mapcar (lambda (ov)
- (when (overlay-get ov 'hs)
- (goto-char
- (cond
- (end (overlay-end ov))
- ((eq 'comment (overlay-get ov 'hs)) here)
- (t (+ (overlay-start ov) (overlay-get ov 'hs-ofs)))))
- (delete-overlay ov)
- (throw 'eol-begins-hidden-region-p t)))
- (save-excursion (end-of-line) (overlays-at (point))))
+ (dolist (ov (save-excursion (end-of-line) (overlays-at (point))))
+ (when (overlay-get ov 'hs)
+ (goto-char
+ (cond (end (overlay-end ov))
+ ((eq 'comment (overlay-get ov 'hs)) here)
+ (t (+ (overlay-start ov) (overlay-get ov 'hs-b-offset)))))
+ (delete-overlay ov)
+ (throw 'eol-begins-hidden-region-p t)))
nil))
;; not immediately obvious, look for a suitable block
(let ((c-reg (hs-inside-comment-p))
(setq p (point)
q (progn (hs-forward-sexp (hs-match-data t) 1) (point)))))
(when (and p q)
- (hs-flag-region p q nil)
+ (hs-discard-overlays p q)
(goto-char (if end q (1+ p)))))
(hs-safety-is-job-n)
(run-hooks 'hs-show-hook))))
-(defun hs-show-region (beg end)
- "Show all lines from BEG to END, without doing any block analysis.
-Note: `hs-show-region' is intended for use when `hs-show-block' signals
-\"unbalanced parentheses\" and so is an emergency measure only. You may
-become very confused if you use this command indiscriminately.
-The hook `hs-show-hook' is run; see `run-hooks'."
- (interactive "r")
- (hs-life-goes-on
- (hs-flag-region beg end nil)
- (hs-safety-is-job-n)
- (run-hooks 'hs-show-hook)))
-
(defun hs-hide-level (arg)
"Hide all blocks ARG levels below this block.
The hook `hs-hide-hook' is run; see `run-hooks'."
(hs-safety-is-job-n)
(run-hooks 'hs-hide-hook)))
+(defun hs-toggle-hiding ()
+ "Toggle hiding/showing of a block.
+See `hs-hide-block' and `hs-show-block'."
+ (interactive)
+ (hs-life-goes-on
+ (if (hs-already-hidden-p)
+ (hs-show-block)
+ (hs-hide-block))))
+
(defun hs-mouse-toggle-hiding (e)
"Toggle hiding/showing of a block.
This command should be bound to a mouse key.
(interactive "@e")
(hs-life-goes-on
(mouse-set-point e)
- (if (hs-already-hidden-p)
- (hs-show-block)
- (hs-hide-block))))
+ (hs-toggle-hiding)))
(defun hs-hide-initial-comment-block ()
"Hide the first block of comments in a file.
When hideshow minor mode is on, the menu bar is augmented with hideshow
commands and the hideshow commands are enabled.
The value '(hs . t) is added to `buffer-invisibility-spec'.
-Last, the normal hook `hs-minor-mode-hook' is run; see `run-hooks'.
The main commands are: `hs-hide-all', `hs-show-all', `hs-hide-block',
-`hs-show-block', `hs-hide-level' and `hs-show-region'. There is also
+`hs-show-block', `hs-hide-level' and `hs-toggle-hiding'. There is also
`hs-hide-initial-comment-block' and `hs-mouse-toggle-hiding'.
Turning hideshow minor mode off reverts the menu bar and the
variables to default values and disables the hideshow commands.
+Lastly, the normal hook `hs-minor-mode-hook' is run using `run-hooks'.
+
Key bindings:
\\{hs-minor-mode-map}"
(interactive "P")
(setq hs-headline nil
- hs-minor-mode (if (null arg)
- (not hs-minor-mode)
- (> (prefix-numeric-value arg) 0)))
+ hs-minor-mode (if (null arg)
+ (not hs-minor-mode)
+ (> (prefix-numeric-value arg) 0)))
(if hs-minor-mode
(progn
- (easy-menu-add hs-minor-mode-menu)
- (make-variable-buffer-local 'line-move-ignore-invisible)
- (setq line-move-ignore-invisible t)
- (add-to-invisibility-spec '(hs . t)) ; hs invisible
(hs-grok-mode-type)
- (run-hooks 'hs-minor-mode-hook))
+ (easy-menu-add hs-minor-mode-menu)
+ (set (make-local-variable 'line-move-ignore-invisible) t)
+ (add-to-invisibility-spec '(hs . t)))
(easy-menu-remove hs-minor-mode-menu)
- (remove-from-invisibility-spec '(hs . t))))
+ (remove-from-invisibility-spec '(hs . t)))
+ (run-hooks 'hs-minor-mode-hook))
;;---------------------------------------------------------------------------
;; load-time actions
;; keymaps and menus
-(if hs-minor-mode-map
- nil
+(unless hs-minor-mode-map
(setq hs-minor-mode-map (make-sparse-keymap))
(easy-menu-define hs-minor-mode-menu
hs-minor-mode-map
(lambda (ent)
(define-key hs-minor-mode-map (aref ent 2) (aref ent 1))
(if (aref ent 0) ent "-----"))
- ;; I believe there is nothing bound on these keys.
+ ;; These bindings roughly imitate those used by Outline mode.
;; menu entry command key
- '(["Hide Block" hs-hide-block "\C-ch"]
- ["Show Block" hs-show-block "\C-cs"]
- ["Hide All" hs-hide-all "\C-cH"]
- ["Show All" hs-show-all "\C-cS"]
- ["Hide Level" hs-hide-level "\C-cL"]
- ["Show Region" hs-show-region "\C-cR"]
- [nil hs-mouse-toggle-hiding [(shift button2)]]
+ '(["Hide Block" hs-hide-block "\C-c@\C-h"]
+ ["Show Block" hs-show-block "\C-c@\C-s"]
+ ["Hide All" hs-hide-all "\C-c@\C-\M-h"]
+ ["Show All" hs-show-all "\C-c@\C-\M-s"]
+ ["Hide Level" hs-hide-level "\C-c@\C-l"]
+ ["Toggle Hiding" hs-toggle-hiding "\C-c@\C-c"]
+ [nil hs-mouse-toggle-hiding [(shift mouse-2)]]
)))))
;; some housekeeping
-(or (assq 'hs-minor-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'hs-minor-mode hs-minor-mode-map)
- minor-mode-map-alist)))
-(or (assq 'hs-minor-mode minor-mode-alist)
- (setq minor-mode-alist (append minor-mode-alist
- (list '(hs-minor-mode " hs")))))
+(add-to-list 'minor-mode-map-alist (cons 'hs-minor-mode hs-minor-mode-map))
+(add-to-list 'minor-mode-alist '(hs-minor-mode " hs") t)
;; make some variables permanently buffer-local
-(mapcar (lambda (var)
- (make-variable-buffer-local var)
- (put var 'permanent-local t))
- '(hs-minor-mode
- hs-c-start-regexp
- hs-block-start-regexp
- hs-block-start-mdata-select
- hs-block-end-regexp
- hs-forward-sexp-func
- hs-adjust-block-beginning))
+(dolist (var '(hs-minor-mode
+ hs-c-start-regexp
+ hs-block-start-regexp
+ hs-block-start-mdata-select
+ hs-block-end-regexp
+ hs-forward-sexp-func
+ hs-adjust-block-beginning))
+ (make-variable-buffer-local var)
+ (put var 'permanent-local t))
;;---------------------------------------------------------------------------
;; that's it
(provide 'hideshow)
+;;; arch-tag: 378b6852-e82a-466a-aee8-d9c73859a65e
;;; hideshow.el ends here