;;; hideshow.el --- minor mode cmds to selectively display code/comment blocks
-;; Copyright (C) 1994-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2012 Free Software Foundation, Inc.
;; Author: Thien-Thi Nguyen <ttn@gnu.org>
;; Dan Nicolaescu <dann@ics.uci.edu>
;; Unfortunately, these workarounds do not restore hideshow state.
;; If someone figures out a better way, please let me know.
-;; * Correspondance
+;; * Correspondence
;;
-;; Correspondance welcome; please indicate version number. Send bug
+;; Correspondence welcome; please indicate version number. Send bug
;; reports and inquiries to <ttn@gnu.org>.
;; * Thanks
:group 'languages)
(defcustom hs-hide-comments-when-hiding-all t
- "*Hide the comments too when you do an `hs-hide-all'."
+ "Hide the comments too when you do an `hs-hide-all'."
:type 'boolean
:group 'hideshow)
(defcustom hs-minor-mode-hook nil
- "*Hook called when hideshow minor mode is activated or deactivated."
+ "Hook called when hideshow minor mode is activated or deactivated."
:type 'hook
:group 'hideshow
:version "21.1")
(defcustom hs-isearch-open 'code
- "*What kind of hidden blocks to open when doing `isearch'.
+ "What kind of hidden blocks to open when doing `isearch'.
One of the following symbols:
code -- open only code blocks
(bibtex-mode ("@\\S(*\\(\\s(\\)" 1))
(java-mode "{" "}" "/[*/]" nil nil)
(js-mode "{" "}" "/[*/]" nil)))
- "*Alist for initializing the hideshow variables for different modes.
+ "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).
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.")
+ "Function called if non-nil when doing `hs-hide-all' for non-comments.")
(defvar hs-allow-nesting nil
- "*If non-nil, hiding remembers internal blocks.
+ "If non-nil, hiding remembers internal blocks.
This means that when the outer block is shown again,
any previously hidden internal blocks remain hidden.")
(defvar hs-hide-hook nil
- "*Hook called (with `run-hooks') at the end of commands to hide text.
+ "Hook called (with `run-hooks') at the end of commands to hide text.
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.
+ "Hook called (with `run-hooks') at the end of commands to show text.
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.
+ "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:
(overlay-put ov 'display nil))))
(overlay-put ov 'invisible (and hide-p 'hs)))
+(defun hs-looking-at-block-start-p ()
+ "Return non-nil if the point is at the block start."
+ (and (looking-at hs-block-start-regexp)
+ (save-match-data (not (nth 8 (syntax-ppss))))))
+
(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."
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)
- (when (looking-at hs-block-start-regexp)
- (let* ((mdata (match-data t))
- (header-beg (match-beginning 0))
- (header-end (match-end 0))
- p q ov)
+ (when (hs-looking-at-block-start-p)
+ (let ((mdata (match-data t))
+ (header-end (match-end 0))
+ p q ov)
;; `p' is the point at the end of the block beginning, which
;; may need to be adjusted
(save-excursion
as cdr."
(save-excursion
;; the idea is to look backwards for a comment start regexp, do a
- ;; forward comment, and see if we are inside, then extend extend
+ ;; forward comment, and see if we are inside, then extend
;; forward and backward as long as we have comments
(let ((q (point)))
+ (skip-chars-forward "[:blank:]")
(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...
(let ((done nil)
(here (point)))
;; look if current line is block start
- (if (looking-at hs-block-start-regexp)
+ (if (hs-looking-at-block-start-p)
(point)
;; look backward for the start of a block that contains the cursor
(while (and (re-search-backward hs-block-start-regexp nil t)
- (not (setq done
- (< here (save-excursion
- (hs-forward-sexp (match-data t) 1)
- (point)))))))
+ ;; go again if in a comment or a string
+ (or (save-match-data (nth 8 (syntax-ppss)))
+ (not (setq done
+ (< here (save-excursion
+ (hs-forward-sexp (match-data t) 1)
+ (point))))))))
(if done
(point)
(goto-char here)
(forward-comment (buffer-size))
(and (< (point) maxp)
(re-search-forward hs-block-start-regexp maxp t)))
- (if (> arg 1)
- (hs-hide-level-recursive (1- arg) minp maxp)
- (goto-char (match-beginning hs-block-start-mdata-select))
- (hs-hide-block-at-point t)))
+ (when (save-match-data
+ (not (nth 8 (syntax-ppss)))) ; not inside comments or strings
+ (if (> arg 1)
+ (hs-hide-level-recursive (1- arg) minp maxp)
+ (goto-char (match-beginning hs-block-start-mdata-select))
+ (hs-hide-block-at-point t))))
(goto-char maxp))
(defmacro hs-life-goes-on (&rest body)
(end-of-line)
(when (and (not c-reg)
(hs-find-block-beginning)
- (looking-at hs-block-start-regexp))
+ (hs-looking-at-block-start-p))
;; point is inside a block
(goto-char (match-end 0)))))
(end-of-line)
(forward-comment (point-max)))
(re-search-forward re (point-max) t))
(if (match-beginning 1)
- ;; we have found a block beginning
+ ;; We have found a block beginning.
(progn
(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)))
+ (unless (if hs-hide-all-non-comment-function
+ (funcall hs-hide-all-non-comment-function)
+ (hs-hide-block-at-point t))
+ ;; Go to end of matched data to prevent from getting stuck
+ ;; with an endless loop.
+ (goto-char (match-end 0))))
;; found a comment, probably
(let ((c-reg (hs-inside-comment-p)))
(when (and c-reg (car c-reg))
(<= (count-lines (car c-reg) (nth 1 c-reg)) 1)))
(message "(not enough comment lines to hide)"))
((or c-reg
- (looking-at hs-block-start-regexp)
+ (hs-looking-at-block-start-p)
(hs-find-block-beginning))
(hs-hide-block-at-point end c-reg)
(run-hooks 'hs-hide-hook))))))
q (cadr c-reg))))
((and (hs-find-block-beginning)
;; ugh, fresh match-data
- (looking-at hs-block-start-regexp))
+ (hs-looking-at-block-start-p))
(setq p (point)
q (progn (hs-forward-sexp (match-data t) 1) (point)))))
(when (and p q)
;;;###autoload
(define-minor-mode hs-minor-mode
"Minor mode to selectively hide/show code and comment blocks.
+With a prefix argument ARG, enable the mode if ARG is positive,
+and disable it otherwise. If called from Lisp, enable the mode
+if ARG is omitted or nil.
+
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'.