** 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
(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)
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