diff options
| author | kobarity | 2022-08-25 14:28:22 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-08-25 14:28:22 +0200 |
| commit | 74d0304ad446dbad6fed887784ffbc3d0fdb59fd (patch) | |
| tree | 24d19b5b0bf6fffc140bf50302aecf3dc35e153f | |
| parent | 0ce30e92958538bb16bbefa1460580853fe82371 (diff) | |
| download | emacs-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.el | 93 |
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. |
| 269 | Each element has the form | 269 | Each 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 | ||
| 272 | If non-nil, hideshow will use these values as regexps to define blocks | 274 | If non-nil, hideshow will use these values as regexps to define blocks |
| 273 | and comments, respectively for major mode MODE. | 275 | and comments, respectively for major mode MODE. |
| @@ -288,6 +290,15 @@ cases, FORWARD-SEXP-FUNC specifies another function to use instead. | |||
| 288 | See the documentation for `hs-adjust-block-beginning' to see what is the | 290 | See the documentation for `hs-adjust-block-beginning' to see what is the |
| 289 | use of ADJUST-BEG-FUNC. | 291 | use of ADJUST-BEG-FUNC. |
| 290 | 292 | ||
| 293 | See the documentation for `hs-find-block-beginning-func' to see | ||
| 294 | what is the use of FIND-BLOCK-BEGINNING-FUNC. | ||
| 295 | |||
| 296 | See the documentation for `hs-find-next-block-func' to see what | ||
| 297 | is the use of FIND-NEXT-BLOCK-FUNC. | ||
| 298 | |||
| 299 | See the documentation for `hs-looking-at-block-start-p-func' to | ||
| 300 | see what is the use of LOOKING-AT-BLOCK-START-P-FUNC. | ||
| 301 | |||
| 291 | If any of the elements is left nil or omitted, hideshow tries to guess | 302 | If any of the elements is left nil or omitted, hideshow tries to guess |
| 292 | appropriate values. The regexps should not contain leading or trailing | 303 | appropriate values. The regexps should not contain leading or trailing |
| 293 | whitespace. Case does not matter.") | 304 | whitespace. Case does not matter.") |
| @@ -433,6 +444,39 @@ It should not move the point. | |||
| 433 | 444 | ||
| 434 | See `hs-c-like-adjust-block-beginning' for an example of using this.") | 445 | See `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'. | ||
| 449 | It should reposition point at the beginning of the current block | ||
| 450 | and return point, or nil if original point was not in a block. | ||
| 451 | |||
| 452 | Specifying this function is necessary for languages such as | ||
| 453 | Python, where regexp search and `syntax-ppss' check is not enough | ||
| 454 | to 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'. | ||
| 458 | It should reposition point at next block start. | ||
| 459 | |||
| 460 | It is called with three arguments REGEXP, MAXP, and COMMENTS. | ||
| 461 | REGEXP is a regexp representing block start. When block start is | ||
| 462 | found, `match-data' should be set using REGEXP. MAXP is a buffer | ||
| 463 | position that bounds the search. When COMMENTS is nil, comments | ||
| 464 | should be skipped. When COMMENTS is not nil, REGEXP matches not | ||
| 465 | only beginning of a block but also beginning of a comment. In | ||
| 466 | this case, the function should find nearest block or comment. | ||
| 467 | |||
| 468 | Specifying this function is necessary for languages such as | ||
| 469 | Python, where regexp search is not enough to find the beginning | ||
| 470 | of 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'. | ||
| 474 | It should return non-nil if the point is at the block start. | ||
| 475 | |||
| 476 | Specifying this function is necessary for languages such as | ||
| 477 | Python, where `looking-at' and `syntax-ppss' check is not enough | ||
| 478 | to 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. |
| 438 | You can display this in the mode line by adding the symbol `hs-headline' | 482 | You 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' | |||
| 565 | and then further adjusted to be at the end of the line." | 609 | and 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. | ||
| 754 | Skip comments if COMMENTS is nil, and search for REGEXP in | ||
| 755 | region (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) |