aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkobarity2022-08-25 14:28:22 +0200
committerLars Ingebrigtsen2022-08-25 14:28:22 +0200
commit74d0304ad446dbad6fed887784ffbc3d0fdb59fd (patch)
tree24d19b5b0bf6fffc140bf50302aecf3dc35e153f
parent0ce30e92958538bb16bbefa1460580853fe82371 (diff)
downloademacs-74d0304ad446dbad6fed887784ffbc3d0fdb59fd.tar.gz
emacs-74d0304ad446dbad6fed887784ffbc3d0fdb59fd.zip
Extend `hs-special-modes-alist' for languages such as Python
* lisp/progmodes/hideshow.el (hs-special-modes-alist): Add elements FIND-BLOCK-BEGINNING-FUNC, FIND-NEXT-BLOCK-FUNC, and LOOKING-AT-BLOCK-START-P-FUNC. (hs-find-block-beginning-func): New variable to hold FIND-BLOCK-BEGINNING-FUNC. (hs-find-next-block-func): New variable to hold FIND-NEXT-BLOCK-FUNC. (hs-looking-at-block-start-p-func): New variable to hold LOOKING-AT-BLOCK-START-P-FUNC. (hs-grok-mode-type): Set new variables from `hs-special-modes-alist'. (hs-find-next-block): New function. (Misc.): Update callers of the above functions. * test/lisp/progmodes/hideshow-tests.el: New test file (bug#56635).
-rw-r--r--lisp/progmodes/hideshow.el93
1 files changed, 74 insertions, 19 deletions
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index f574ec84fbe..c0796fc2eeb 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -267,7 +267,9 @@ This has effect only if `search-invisible' is set to `open'."
267 )) 267 ))
268 "Alist for initializing the hideshow variables for different modes. 268 "Alist for initializing the hideshow variables for different modes.
269Each element has the form 269Each element has the form
270 (MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC). 270 (MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC
271 FIND-BLOCK-BEGINNING-FUNC FIND-NEXT-BLOCK-FUNC
272 LOOKING-AT-BLOCK-START-P-FUNC).
271 273
272If non-nil, hideshow will use these values as regexps to define blocks 274If non-nil, hideshow will use these values as regexps to define blocks
273and comments, respectively for major mode MODE. 275and comments, respectively for major mode MODE.
@@ -288,6 +290,15 @@ cases, FORWARD-SEXP-FUNC specifies another function to use instead.
288See the documentation for `hs-adjust-block-beginning' to see what is the 290See the documentation for `hs-adjust-block-beginning' to see what is the
289use of ADJUST-BEG-FUNC. 291use of ADJUST-BEG-FUNC.
290 292
293See the documentation for `hs-find-block-beginning-func' to see
294what is the use of FIND-BLOCK-BEGINNING-FUNC.
295
296See the documentation for `hs-find-next-block-func' to see what
297is the use of FIND-NEXT-BLOCK-FUNC.
298
299See the documentation for `hs-looking-at-block-start-p-func' to
300see what is the use of LOOKING-AT-BLOCK-START-P-FUNC.
301
291If any of the elements is left nil or omitted, hideshow tries to guess 302If any of the elements is left nil or omitted, hideshow tries to guess
292appropriate values. The regexps should not contain leading or trailing 303appropriate values. The regexps should not contain leading or trailing
293whitespace. Case does not matter.") 304whitespace. Case does not matter.")
@@ -433,6 +444,39 @@ It should not move the point.
433 444
434See `hs-c-like-adjust-block-beginning' for an example of using this.") 445See `hs-c-like-adjust-block-beginning' for an example of using this.")
435 446
447(defvar-local hs-find-block-beginning-func #'hs-find-block-beginning
448 "Function used to do `hs-find-block-beginning'.
449It should reposition point at the beginning of the current block
450and return point, or nil if original point was not in a block.
451
452Specifying this function is necessary for languages such as
453Python, where regexp search and `syntax-ppss' check is not enough
454to find the beginning of the current block.")
455
456(defvar-local hs-find-next-block-func #'hs-find-next-block
457 "Function used to do `hs-find-next-block'.
458It should reposition point at next block start.
459
460It is called with three arguments REGEXP, MAXP, and COMMENTS.
461REGEXP is a regexp representing block start. When block start is
462found, `match-data' should be set using REGEXP. MAXP is a buffer
463position that bounds the search. When COMMENTS is nil, comments
464should be skipped. When COMMENTS is not nil, REGEXP matches not
465only beginning of a block but also beginning of a comment. In
466this case, the function should find nearest block or comment.
467
468Specifying this function is necessary for languages such as
469Python, where regexp search is not enough to find the beginning
470of the next block.")
471
472(defvar-local hs-looking-at-block-start-p-func #'hs-looking-at-block-start-p
473 "Function used to do `hs-looking-at-block-start-p'.
474It should return non-nil if the point is at the block start.
475
476Specifying this function is necessary for languages such as
477Python, where `looking-at' and `syntax-ppss' check is not enough
478to check if the point is at the block start.")
479
436(defvar hs-headline nil 480(defvar hs-headline nil
437 "Text of the line where a hidden block begins, set during isearch. 481 "Text of the line where a hidden block begins, set during isearch.
438You can display this in the mode line by adding the symbol `hs-headline' 482You can display this in the mode line by adding the symbol `hs-headline'
@@ -565,7 +609,7 @@ The block beginning is adjusted by `hs-adjust-block-beginning'
565and then further adjusted to be at the end of the line." 609and then further adjusted to be at the end of the line."
566 (if comment-reg 610 (if comment-reg
567 (hs-hide-comment-region (car comment-reg) (cadr comment-reg) end) 611 (hs-hide-comment-region (car comment-reg) (cadr comment-reg) end)
568 (when (hs-looking-at-block-start-p) 612 (when (funcall hs-looking-at-block-start-p-func)
569 (let ((mdata (match-data t)) 613 (let ((mdata (match-data t))
570 (header-end (match-end 0)) 614 (header-end (match-end 0))
571 p q ov) 615 p q ov)
@@ -672,7 +716,14 @@ function; and adjust-block-beginning function."
672 0 (1- (match-end 0))) 716 0 (1- (match-end 0)))
673 c-start-regexp))) 717 c-start-regexp)))
674 hs-forward-sexp-func (or (nth 4 lookup) #'forward-sexp) 718 hs-forward-sexp-func (or (nth 4 lookup) #'forward-sexp)
675 hs-adjust-block-beginning (or (nth 5 lookup) #'identity))) 719 hs-adjust-block-beginning (or (nth 5 lookup) #'identity)
720 hs-find-block-beginning-func (or (nth 6 lookup)
721 #'hs-find-block-beginning)
722 hs-find-next-block-func (or (nth 7 lookup)
723 #'hs-find-next-block)
724 hs-looking-at-block-start-p-func
725 (or (nth 8 lookup)
726 #'hs-looking-at-block-start-p)))
676 (setq hs-minor-mode nil) 727 (setq hs-minor-mode nil)
677 (error "%s Mode doesn't support Hideshow Minor Mode" 728 (error "%s Mode doesn't support Hideshow Minor Mode"
678 (format-mode-line mode-name)))) 729 (format-mode-line mode-name))))
@@ -683,7 +734,7 @@ Return point, or nil if original point was not in a block."
683 (let ((done nil) 734 (let ((done nil)
684 (here (point))) 735 (here (point)))
685 ;; look if current line is block start 736 ;; look if current line is block start
686 (if (hs-looking-at-block-start-p) 737 (if (funcall hs-looking-at-block-start-p-func)
687 (point) 738 (point)
688 ;; look backward for the start of a block that contains the cursor 739 ;; look backward for the start of a block that contains the cursor
689 (while (and (re-search-backward hs-block-start-regexp nil t) 740 (while (and (re-search-backward hs-block-start-regexp nil t)
@@ -698,19 +749,25 @@ Return point, or nil if original point was not in a block."
698 (goto-char here) 749 (goto-char here)
699 nil)))) 750 nil))))
700 751
752(defun hs-find-next-block (regexp maxp comments)
753 "Reposition point at next block-start.
754Skip comments if COMMENTS is nil, and search for REGEXP in
755region (point MAXP)."
756 (when (not comments)
757 (forward-comment (point-max)))
758 (and (< (point) maxp)
759 (re-search-forward regexp maxp t)))
760
701(defun hs-hide-level-recursive (arg minp maxp) 761(defun hs-hide-level-recursive (arg minp maxp)
702 "Recursively hide blocks ARG levels below point in region (MINP MAXP)." 762 "Recursively hide blocks ARG levels below point in region (MINP MAXP)."
703 (when (hs-find-block-beginning) 763 (when (funcall hs-find-block-beginning-func)
704 (setq minp (1+ (point))) 764 (setq minp (1+ (point)))
705 (funcall hs-forward-sexp-func 1) 765 (funcall hs-forward-sexp-func 1)
706 (setq maxp (1- (point)))) 766 (setq maxp (1- (point))))
707 (unless hs-allow-nesting 767 (unless hs-allow-nesting
708 (hs-discard-overlays minp maxp)) 768 (hs-discard-overlays minp maxp))
709 (goto-char minp) 769 (goto-char minp)
710 (while (progn 770 (while (funcall hs-find-next-block-func hs-block-start-regexp maxp nil)
711 (forward-comment (buffer-size))
712 (and (< (point) maxp)
713 (re-search-forward hs-block-start-regexp maxp t)))
714 (when (save-match-data 771 (when (save-match-data
715 (not (nth 8 (syntax-ppss)))) ; not inside comments or strings 772 (not (nth 8 (syntax-ppss)))) ; not inside comments or strings
716 (if (> arg 1) 773 (if (> arg 1)
@@ -747,8 +804,8 @@ and `case-fold-search' are both t."
747 (goto-char (nth 0 c-reg)) 804 (goto-char (nth 0 c-reg))
748 (end-of-line) 805 (end-of-line)
749 (when (and (not c-reg) 806 (when (and (not c-reg)
750 (hs-find-block-beginning) 807 (funcall hs-find-block-beginning-func)
751 (hs-looking-at-block-start-p)) 808 (funcall hs-looking-at-block-start-p-func))
752 ;; point is inside a block 809 ;; point is inside a block
753 (goto-char (match-end 0))))) 810 (goto-char (match-end 0)))))
754 (end-of-line) 811 (end-of-line)
@@ -790,10 +847,8 @@ If `hs-hide-comments-when-hiding-all' is non-nil, also hide the comments."
790 hs-c-start-regexp 847 hs-c-start-regexp
791 "\\)") 848 "\\)")
792 "")))) 849 ""))))
793 (while (progn 850 (while (funcall hs-find-next-block-func re (point-max)
794 (unless hs-hide-comments-when-hiding-all 851 hs-hide-comments-when-hiding-all)
795 (forward-comment (point-max)))
796 (re-search-forward re (point-max) t))
797 (if (match-beginning 1) 852 (if (match-beginning 1)
798 ;; We have found a block beginning. 853 ;; We have found a block beginning.
799 (progn 854 (progn
@@ -838,8 +893,8 @@ Upon completion, point is repositioned and the normal hook
838 (<= (count-lines (car c-reg) (nth 1 c-reg)) 1))) 893 (<= (count-lines (car c-reg) (nth 1 c-reg)) 1)))
839 (message "(not enough comment lines to hide)")) 894 (message "(not enough comment lines to hide)"))
840 ((or c-reg 895 ((or c-reg
841 (hs-looking-at-block-start-p) 896 (funcall hs-looking-at-block-start-p-func)
842 (hs-find-block-beginning)) 897 (funcall hs-find-block-beginning-func))
843 (hs-hide-block-at-point end c-reg) 898 (hs-hide-block-at-point end c-reg)
844 (run-hooks 'hs-hide-hook)))))) 899 (run-hooks 'hs-hide-hook))))))
845 900
@@ -868,9 +923,9 @@ See documentation for functions `hs-hide-block' and `run-hooks'."
868 (when (car c-reg) 923 (when (car c-reg)
869 (setq p (car c-reg) 924 (setq p (car c-reg)
870 q (cadr c-reg)))) 925 q (cadr c-reg))))
871 ((and (hs-find-block-beginning) 926 ((and (funcall hs-find-block-beginning-func)
872 ;; ugh, fresh match-data 927 ;; ugh, fresh match-data
873 (hs-looking-at-block-start-p)) 928 (funcall hs-looking-at-block-start-p-func))
874 (setq p (point) 929 (setq p (point)
875 q (progn (hs-forward-sexp (match-data t) 1) (point))))) 930 q (progn (hs-forward-sexp (match-data t) 1) (point)))))
876 (when (and p q) 931 (when (and p q)