From: Juri Linkov Date: Mon, 3 Jun 2024 17:18:46 +0000 (+0300) Subject: New commands to show/hide outlines by regexp (bug#49731) X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4858960e18d41a83a25c6be2e1247c264e415fec;p=emacs.git New commands to show/hide outlines by regexp (bug#49731) * lisp/outline.el (outline-mode-prefix-map): Bind "/ s" to 'outline-show-by-heading-regexp', and "/ h" to 'outline-hide-by-heading-regexp'. (outline-show-by-heading-regexp) (outline-hide-by-heading-regexp): New commands. (outline-hidden-headings-regexp): New helper function. (cherry picked from commit 4395f4d4530db77156b20209c1a81dce22c6e62d) --- diff --git a/etc/NEWS b/etc/NEWS index eb2f9290725..f7f4c7dfad2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -158,6 +158,12 @@ Set 'describe-mode-outline' to nil to get back the old behavior. ** Outline mode +*** New commands to show/hide outlines by regexp. +'/ h' ('outline-hide-by-heading-regexp') asks for a regexp and then +hides the body lines of all outlines whose heading lines match the +regexp. '/ s' ('outline-show-by-heading-regexp') does the same but +shows the matched outlines. + +++ *** 'outline-minor-mode' is supported in tree-sitter major modes. It can be used in all tree-sitter major modes that set either the diff --git a/lisp/outline.el b/lisp/outline.el index 40a75701cbf..5f4d4f3dcba 100644 --- a/lisp/outline.el +++ b/lisp/outline.el @@ -92,6 +92,8 @@ imitate the function `looking-at'.") (define-key map "\C-o" 'outline-hide-other) (define-key map "\C-^" 'outline-move-subtree-up) (define-key map "\C-v" 'outline-move-subtree-down) + (keymap-set map "/ s" #'outline-show-by-heading-regexp) + (keymap-set map "/ h" #'outline-hide-by-heading-regexp) (define-key map [(control ?<)] 'outline-promote) (define-key map [(control ?>)] 'outline-demote) (define-key map "\C-m" 'outline-insert-heading) @@ -1661,6 +1663,48 @@ LEVEL, decides of subtree visibility according to beg end))) (run-hooks 'outline-view-change-hook))) +(defun outline-show-by-heading-regexp (regexp) + "Show outlines whose headings match REGEXP." + (interactive (list (read-regexp "Regexp to show outlines"))) + (let (outline-view-change-hook) + (outline-map-region + (lambda () + (when (string-match-p regexp (buffer-substring (pos-bol) (pos-eol))) + (outline-show-branches) ;; To reveal all parent headings + (outline-show-entry))) + (point-min) (point-max))) + (run-hooks 'outline-view-change-hook)) + +(defun outline-hide-by-heading-regexp (regexp) + "Hide outlines whose headings match REGEXP." + (interactive (list (read-regexp "Regexp to hide outlines"))) + (let (outline-view-change-hook) + (outline-map-region + (lambda () + (when (string-match-p regexp (buffer-substring (pos-bol) (pos-eol))) + (outline-hide-subtree))) + (point-min) (point-max))) + (run-hooks 'outline-view-change-hook)) + +(defun outline-hidden-headings-regexp () + "Return a regexp that matches all currently hidden outlines. +This is useful to save the hidden outlines and restore them later, +for example, after reverting the buffer." + (let ((headings)) + (outline-map-region + (lambda () + (when (save-excursion + (outline-end-of-heading) + (seq-some (lambda (o) (eq (overlay-get o 'invisible) + 'outline)) + (overlays-at (point)))) + (push (buffer-substring (pos-bol) (pos-eol)) headings))) + (point-min) (point-max)) + (when headings + (mapconcat (lambda (heading) + (concat "\\`" (regexp-quote heading) "\\'")) + (nreverse headings) "\\|")))) + ;;; Visibility cycling