]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/hideshow.el
Don't set overlay-arrow-string to "=>" as this is done
[gnu-emacs] / lisp / progmodes / hideshow.el
index 6573ab35e68d97fb3a5b27a716ea66b463e964b5..d4229cf44c66e7987517eb33577e26bd73ab7c4d 100644 (file)
@@ -1,11 +1,11 @@
-;;; 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)
 
@@ -208,8 +275,7 @@ This has effect iff `search-invisible' is set to `open'."
   '((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).
@@ -223,8 +289,9 @@ defined as text surrounded by START and END.
 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.
@@ -236,13 +303,36 @@ If any of the elements is left nil or omitted, hideshow tries to guess
 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
@@ -254,6 +344,9 @@ Use the command `hs-minor-mode' to toggle or set this variable.")
 (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
@@ -285,11 +378,11 @@ as opposed to hiding it from the position returned when searching
 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.
@@ -312,82 +405,87 @@ Note that `mode-line-format' is buffer-local.")
 ;;---------------------------------------------------------------------------
 ;; 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."
@@ -399,9 +497,10 @@ 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)
@@ -415,36 +514,35 @@ The block beginning is adjusted by `hs-adjust-block-beginning'
 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.
@@ -461,10 +559,15 @@ as cdr."
     (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)
@@ -483,19 +586,19 @@ as cdr."
             (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.
@@ -525,13 +628,12 @@ function; and adjust-block-beginning function."
                                         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
@@ -554,7 +656,7 @@ Return point, or nil if top-level."
     (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))
@@ -564,7 +666,7 @@ Return point, or nil if top-level."
         (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)
@@ -585,17 +687,17 @@ and `case-fold-search' are both t."
       (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)
@@ -620,41 +722,36 @@ If `hs-hide-comments-when-hiding-all' is non-nil, also hide the comments."
   (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)))
@@ -664,7 +761,7 @@ If `hs-hide-comments-when-hiding-all' is non-nil, also hide the comments."
   (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)))
 
@@ -697,16 +794,14 @@ See documentation for functions `hs-hide-block' and `run-hooks'."
     ;; 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))
@@ -720,23 +815,11 @@ See documentation for functions `hs-hide-block' and `run-hooks'."
              (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'."
@@ -749,6 +832,15 @@ 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.
@@ -757,9 +849,7 @@ See `hs-hide-block' and `hs-show-block'."
   (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.
@@ -783,40 +873,39 @@ With ARG, turn hideshow minor mode on if ARG is positive, off otherwise.
 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
@@ -829,41 +918,36 @@ Key bindings:
            (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