]> git.eshelyaron.com Git - emacs.git/commitdiff
New commands to show/hide outlines by regexp (bug#49731)
authorJuri Linkov <juri@linkov.net>
Mon, 3 Jun 2024 17:18:46 +0000 (20:18 +0300)
committerEshel Yaron <me@eshelyaron.com>
Mon, 3 Jun 2024 19:33:22 +0000 (21:33 +0200)
* 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)

etc/NEWS
lisp/outline.el

index eb2f9290725b92b9eb5ef30cbd06ef7b97e7979c..f7f4c7dfad23bf17f72288ffb083e797e34ec203 100644 (file)
--- 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
index 40a75701cbf48fbb5838368f5a48b02baaa306fc..5f4d4f3dcbaae6e05bac6cdf6be5c2dc3fcb532e 100644 (file)
@@ -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) "\\|"))))
+
 \f
 ;;; Visibility cycling