]> git.eshelyaron.com Git - emacs.git/commitdiff
Add buttons to outlining and tweak `C-h b' buffer
authorLars Ingebrigtsen <larsi@gnus.org>
Sun, 31 Oct 2021 22:13:52 +0000 (23:13 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Sun, 31 Oct 2021 22:13:58 +0000 (23:13 +0100)
* lisp/help.el (describe-bindings-outline): Change default to t.
(describe-bindings): Tweak the look and remove the explanation.

* lisp/outline.el (outline-minor-mode-use-buttons):
(outline-minor-mode-buttons): New user options.
(outline-hide-subtree): Update buttons.
(outline--make-button, outline--make-button-overlay)
(outline--insert-open-button, outline--insert-close-button)
(outline--fix-up-all-buttons): New functions.

doc/emacs/text.texi
etc/NEWS
lisp/help.el
lisp/outline.el

index dc8ca903b729908cffa9fbce8963fc2d10fa5c48..53291332d36856caef2fb42c8cf271dc1d799ec0 100644 (file)
@@ -996,6 +996,13 @@ specific file (@pxref{File Variables}).
 major mode's special commands.  (The variable
 @code{outline-minor-mode-prefix} controls the prefix used.)
 
+@vindex outline-minor-mode-use-buttons
+  If @code{outline-minor-mode-use-buttons} is non-@code{nil}, Outline
+minor mode will use buttons (at the start of the header lines) in
+addition to ellipsis to show that a section is hidden.  Using
+@kbd{RET} (or clicking on the button with a mouse) will toggle
+displaying the section.
+
 @vindex outline-minor-mode-cycle
   If the @code{outline-minor-mode-cycle} user option is
 non-@code{nil}, the @kbd{TAB} and @kbd{S-TAB} keys are enabled on the
index e7360d267dca3abeb1b2e64f4791db6fdcb52a33..57c64f7cadbb214cb924a7106a28d40cbc8b8672 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -48,6 +48,10 @@ time.
 
 ** Help
 
+---
+*** 'C-h b' uses outlining by default.
+Set 'describe-bindings-outline' to nil to get the old behaviour.
+
 ---
 *** Jumping to function/variable source now saves mark before moving point.
 Jumping to source from "*Help*" buffer moves the point when the source
@@ -57,6 +61,17 @@ buffer is already open.  Now, the old point is pushed to mark ring.
 *** New key bindings in *Help* buffers: 'n' and 'p'.
 These will take you (respectively) to the next and previous "page".
 
+** Outline Minor Mode
+
++++
+*** New user option 'outline-minor-mode-use-buttons'.
+If non-nil, Outline Minor Mode will use buttons to hide/show outlines
+in addition to the ellipsis.
+
+---
+*** New user option 'outline-minor-mode-buttons'.
+This is a list of pairs of open/close strings used to display buttons.
+
 ** Fonts
 
 ---
index deeb892280f0a96516caa6681bd780b7d5bb5ccd..af68c5717b048534491bb203cd67c12297da079b 100644 (file)
@@ -561,11 +561,11 @@ To record all your input, use `open-dribble-file'."
               'font-lock-face 'help-key-binding
               'face 'help-key-binding))
 
-(defcustom describe-bindings-outline nil
+(defcustom describe-bindings-outline t
   "Non-nil enables outlines in the output buffer of `describe-bindings'."
   :type 'boolean
   :group 'help
-  :version "28.1")
+  :version "29.1")
 
 (defun describe-bindings (&optional prefix buffer)
   "Display a buffer showing a list of all defined keys, and their definitions.
@@ -592,18 +592,19 @@ or a buffer name."
         (setq-local outline-level (lambda () 1))
         (setq-local outline-minor-mode-cycle t
                     outline-minor-mode-highlight t)
+        (setq-local outline-minor-mode-use-buttons t)
         (outline-minor-mode 1)
         (save-excursion
+          (goto-char (point-min))
           (let ((inhibit-read-only t))
-            (goto-char (point-min))
-            (insert (substitute-command-keys
-                     (concat "\\<outline-minor-mode-cycle-map>Type "
-                             "\\[outline-cycle] or \\[outline-cycle-buffer] "
-                             "on headings to cycle their visibility.\n\n")))
             ;; Hide the longest body
             (when (and (re-search-forward "Key translations" nil t)
                        (fboundp 'outline-cycle))
-              (outline-cycle))))))))
+              (outline-cycle))
+            ;; Hide ^Ls.
+            (while (search-forward "\n\f\n" nil t)
+              (put-text-property (1+ (match-beginning 0)) (1- (match-end 0))
+                                 'invisible t))))))))
 
 (defun where-is (definition &optional insert)
   "Print message listing key sequences that invoke the command DEFINITION.
index 52a94b4d9f4a4e9b6eb8953c1ad17ed1f5311009..a7f54364f05088582a06d0fcf4d7205a8123046e 100644 (file)
@@ -272,6 +272,21 @@ in the file it applies to.")
 (defvar outline-font-lock-faces
   [outline-1 outline-2 outline-3 outline-4
    outline-5 outline-6 outline-7 outline-8])
+
+(defcustom outline-minor-mode-use-buttons nil
+  "If non-nil, use clickable buttons on the headings.
+The `outline-minor-mode-buttons' variable specifies how the
+buttons should look."
+  :type 'boolean
+  :version "29.1")
+
+(defcustom outline-minor-mode-buttons
+  '(("▶️". "🔽")
+    ("▶" . "▼"))
+  "List of close/open pairs to use if using buttons."
+  :type 'sexp
+  :version "29.1")
+
 \f
 (defvar outline-level #'outline-level
   "Function of no args to compute a header's nesting level in an outline.
@@ -388,6 +403,8 @@ faces to major mode's faces."
                          (goto-char (match-beginning 0))
                          (not (get-text-property (point) 'face))))
             (overlay-put overlay 'face (outline-font-lock-face)))
+          (when outline-minor-mode-use-buttons
+            (outline--insert-open-button))
           (when outline-minor-mode-cycle
             (overlay-put overlay 'keymap outline-minor-mode-cycle-map)))
         (goto-char (match-end 0))))))
@@ -923,11 +940,64 @@ Note that this does not hide the lines preceding the first heading line."
 
 (define-obsolete-function-alias 'show-all #'outline-show-all "25.1")
 
-(defun outline-hide-subtree ()
-  "Hide everything after this heading at deeper levels."
-  (interactive)
+(defun outline-hide-subtree (&optional event)
+  "Hide everything after this heading at deeper levels.
+If non-nil, EVENT should be a mouse event."
+  (interactive (list last-nonmenu-event))
+  (mouse-set-point event)
+  (when (and outline-minor-mode-use-buttons outline-minor-mode)
+    (outline--insert-close-button))
   (outline-flag-subtree t))
 
+(defun outline--make-button (type)
+  (cl-loop for (close . open) in outline-minor-mode-buttons
+           when (and (char-displayable-p (aref close 0))
+                     (char-displayable-p (aref open 0)))
+           return (concat (if (eq type 'close)
+                              close
+                            open)
+                          " " (buffer-substring (point) (1+ (point))))))
+
+(defun outline--make-button-overlay (type)
+  (let ((o (seq-find (lambda (o)
+                       (overlay-get o 'outline-button))
+                     (overlays-at (point)))))
+    (unless o
+      (setq o (make-overlay (point) (1+ (point))))
+      (overlay-put o 'outline-button t))
+    (overlay-put o 'display (outline--make-button type))
+    o))
+
+(defun outline--insert-open-button ()
+  (save-excursion
+    (beginning-of-line)
+    (let ((o (outline--make-button-overlay 'open)))
+      (overlay-put o 'help-echo "Click to hide")
+      (overlay-put o 'keymap
+                   (define-keymap
+                     ["RET"] #'outline-hide-subtree
+                     ["<follow-link>"] 'mouse-face
+                     ["<mouse-2>"] #'outline-hide-subtree)))))
+
+(defun outline--insert-close-button ()
+  (save-excursion
+    (beginning-of-line)
+    (let ((o (outline--make-button-overlay 'close)))
+      (overlay-put o 'help-echo "Click to show")
+      (overlay-put o 'keymap
+                   (define-keymap
+                     ["RET"] #'outline-show-subtree
+                     ["<follow-link>"] 'mouse-face
+                     ["<mouse-2>"] #'outline-show-subtree)))))
+
+(defun outline--fix-up-all-buttons ()
+  (outline-map-region
+   (lambda ()
+     (if (eq (outline--cycle-state) 'show-all)
+         (outline--insert-open-button)
+       (outline--insert-close-button)))
+   (point-min) (point-max)))
+
 (define-obsolete-function-alias 'hide-subtree #'outline-hide-subtree "25.1")
 
 (defun outline-hide-leaves ()
@@ -943,9 +1013,12 @@ Note that this does not hide the lines preceding the first heading line."
 
 (define-obsolete-function-alias 'hide-leaves #'outline-hide-leaves "25.1")
 
-(defun outline-show-subtree ()
+(defun outline-show-subtree (&optional event)
   "Show everything after this heading at deeper levels."
-  (interactive)
+  (interactive (list last-nonmenu-event))
+  (mouse-set-point event)
+  (when (and outline-minor-mode-use-buttons outline-minor-mode)
+    (outline--insert-open-button))
   (outline-flag-subtree nil))
 
 (define-obsolete-function-alias 'show-subtree #'outline-show-subtree "25.1")
@@ -1295,7 +1368,9 @@ Return either 'hide-all, 'headings-only, or 'show-all."
      (t
       (outline-show-all)
       (setq outline--cycle-buffer-state 'show-all)
-      (message "Show all")))))
+      (message "Show all")))
+    (when outline-minor-mode-use-buttons
+      (outline--fix-up-all-buttons))))
 
 (defvar outline-navigation-repeat-map
   (let ((map (make-sparse-keymap)))