emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 0a15956f49: * lisp/outline.el (outline-minor-mode-use-margins): N


From: Juri Linkov
Subject: master 0a15956f49: * lisp/outline.el (outline-minor-mode-use-margins): New user option.
Date: Mon, 19 Sep 2022 15:36:56 -0400 (EDT)

branch: master
commit 0a15956f495338b4f2260c7676a6040436a90645
Author: Juri Linkov <juri@linkov.net>
Commit: Juri Linkov <juri@linkov.net>

    * lisp/outline.el (outline-minor-mode-use-margins): New user option.
    
    (outline--use-margins, outline--use-buttons, outline--use-rtl):
    New buffer-local internal variables.
    (outline-open, outline-close): Move :ascent center to default of 
define-icon.
    Use ASCII-art for text.  Fix docstring and help-echo.
    (outline-close-rtl, outline-open-in-margins)
    (outline-close-in-margins, outline-close-rtl-in-margins): New icon
    definitions.
    (outline-minor-mode-highlight-buffer): Remove outline--insert-open-button
    since initial outline--fix-up-all-buttons is added now to 
outline-minor-mode.
    (outline-minor-mode): Set buffer-local outline--use-buttons,
    outline--use-margins and outline--use-rtl.  Show/hide margins for
    outline--use-margins.  Add hook after-change-functions for editable buffers.
    Move outline--fix-up-all-buttons for both cases: font-lock and 
non-font-lock.
    (outline--use-buttons-p): Remove function.
    (outline--make-button-overlay): Use outline--use-rtl icon outline-close-rtl.
    (outline--make-margin-overlay): New function.
    (outline--insert-open-button, outline--insert-close-button): Add optional
    arg 'use-margins'.
    (outline--fix-up-all-buttons): Call outline--insert-close-button
    and outline--insert-open-button with arg outline--use-margins.
    (outline-cycle-buffer): Remove outline--fix-up-all-buttons
    that is already called from outline-flag-region.
    
    * lisp/emacs-lisp/icons.el (icons--create): Handle keywords :rotation
    and :ascent with the default value 'center (bug#57813).
    
    * doc/emacs/text.texi (Outline Mode): Mention 
outline-minor-mode-use-margins.
---
 doc/emacs/text.texi      |   5 ++
 etc/NEWS                 |  13 +++-
 lisp/emacs-lisp/icons.el |   6 +-
 lisp/outline.el          | 169 ++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 157 insertions(+), 36 deletions(-)

diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index fa8eaf0924..35dce18d02 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -1003,6 +1003,11 @@ 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-use-margins
+  If @code{outline-minor-mode-use-margins} is non-@code{nil}, Outline
+minor mode will use the window margins in addition to ellipsis to show
+that a section is hidden.
+
 @vindex outline-minor-mode-cycle
   If the @code{outline-minor-mode-cycle} user option is
 non-@code{nil}, the @kbd{TAB} and @kbd{S-@key{TAB}} keys are enabled on the
diff --git a/etc/NEWS b/etc/NEWS
index ee333a84e4..821da805ca 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -962,7 +962,14 @@ or is itself too long.
 *** 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.  The default is nil in editing modes, but
-non-nil in 'special-mode' and its derivatives.
+non-nil in 'help-mode' and its derivatives.
+
++++
+*** New user option 'outline-minor-mode-use-margins'.
+If non-nil, Outline Minor Mode will use the window margins to
+hide/show outlines in addition to the ellipsis.  The default is
+non-nil in 'special-mode' and its derivatives, and it can be used in
+editing modes.
 
 ** Windows
 
@@ -1489,8 +1496,8 @@ characters instead of just 'SPC' and 'TAB'.
 This mode adds some highlighting, fixes the 'M-q' command, and has
 commands for doing maintenance of the Emacs NEWS files.  In addition,
 this mode turns on 'outline-minor-mode', and thus displays
-customizable icons (see 'icon-preference') on heading lines.  To
-disable these icons, customize 'outline-minor-mode-use-buttons' to a
+customizable icons (see 'icon-preference') in the margins.  To
+disable these icons, customize 'outline-minor-mode-use-margins' to a
 nil value.
 
 ---
diff --git a/lisp/emacs-lisp/icons.el b/lisp/emacs-lisp/icons.el
index ff4f20c207..ccc3657793 100644
--- a/lisp/emacs-lisp/icons.el
+++ b/lisp/emacs-lisp/icons.el
@@ -202,7 +202,11 @@ present if the icon is represented by an image."
                             :height (if (eq height 'line)
                                         (window-default-line-height)
                                       height)
-                            :scale 1 :ascent 'center)
+                            :scale 1
+                            :rotation (plist-get keywords :rotation)
+                            :ascent (if (plist-member keywords :ascent)
+                                        (plist-get keywords :ascent)
+                                      'center))
             (create-image file))))))
 
 (cl-defmethod icons--create ((_type (eql 'emoji)) icon _keywords)
diff --git a/lisp/outline.el b/lisp/outline.el
index e3fbd8b327..ab37e398e9 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -292,25 +292,65 @@ buffers (yet) -- that will be amended in a future 
version."
   :safe #'booleanp
   :version "29.1")
 
+(defvar-local outline--use-buttons nil
+  "Non-nil when buffer displays clickable buttons on the headings.")
+
+(defvar-local outline--use-rtl nil
+  "Non-nil when direction of clickable buttons is right-to-left.")
+
+(defcustom outline-minor-mode-use-margins '(derived-mode . special-mode)
+  "Whether to display clickable buttons in the margins.
+The value should be a `buffer-match-p' condition.
+
+These buttons can be used to hide and show the body under the heading.
+Note that this feature is meant to be used in editing buffers."
+  :type 'buffer-predicate
+  :safe #'booleanp
+  :version "29.1")
+
+(defvar-local outline--use-margins nil
+  "Non-nil when buffer displays clickable buttons in the margins.")
+
 (define-icon outline-open nil
-  '((image "outline-open.svg" "outline-open.pbm"
-           :height 15 :ascent center)
+  '((image "outline-open.svg" "outline-open.pbm" :height 15)
     (emoji "🔽")
     (symbol " ▼ ")
-    (text " open "))
-  "Icon used for buttons for opening a section in outline buffers."
+    (text " v "))
+  "Icon used for buttons for opened sections in outline buffers."
   :version "29.1"
-  :help-echo "Open this section")
+  :help-echo "Close this section")
 
 (define-icon outline-close nil
-  '((image "outline-close.svg" "outline-close.pbm"
-           :height 15 :ascent center)
+  '((image "outline-close.svg" "outline-close.pbm" :height 15)
     (emoji "▶️")
     (symbol " ▶ ")
-    (text " close "))
-  "Icon used for buttons for closing a section in outline buffers."
+    (text " > "))
+  "Icon used for buttons for closed sections in outline buffers."
   :version "29.1"
-  :help-echo "Close this section")
+  :help-echo "Open this section")
+
+(define-icon outline-close-rtl outline-close
+  '((image "outline-close.svg" "outline-close.pbm" :height 15 :rotation 180)
+    (emoji "◀️")
+    (symbol " ◀ ")
+    (text " < "))
+  "Right-to-left icon used for buttons in closed outline sections."
+  :version "29.1")
+
+(define-icon outline-open-in-margins outline-open
+  '((image "outline-open.svg" "outline-open.pbm" :height 10))
+  "Icon used for buttons for opened sections in margins."
+  :version "29.1")
+
+(define-icon outline-close-in-margins outline-close
+  '((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation -90))
+  "Icon used for buttons for closed sections in margins."
+  :version "29.1")
+
+(define-icon outline-close-rtl-in-margins outline-close-rtl
+  '((image "outline-open.svg" "outline-open.pbm" :height 10 :rotation 90))
+  "Right-to-left icon used for closed sections in margins."
+  :version "29.1")
 
 
 (defvar outline-level #'outline-level
@@ -439,9 +479,7 @@ outline font-lock faces to those of major mode."
           (when (or (memq outline-minor-mode-highlight '(append override))
                     (and (eq outline-minor-mode-highlight t)
                          (not (get-text-property (match-beginning 0) 'face))))
-            (overlay-put overlay 'face (outline-font-lock-face)))
-          (when (outline--use-buttons-p)
-            (outline--insert-open-button)))
+            (overlay-put overlay 'face (outline-font-lock-face))))
         (goto-char (match-end 0))))))
 
 ;;;###autoload
@@ -456,13 +494,37 @@ See the command `outline-mode' for more information on 
this mode."
             (key-description outline-minor-mode-prefix) 
outline-mode-prefix-map)
   (if outline-minor-mode
       (progn
+        (cond
+         ((buffer-match-p outline-minor-mode-use-margins (current-buffer))
+          (setq-local outline--use-margins t))
+         ((buffer-match-p outline-minor-mode-use-buttons (current-buffer))
+          (setq-local outline--use-buttons t)))
+        (when (and (or outline--use-buttons outline--use-margins)
+                   (eq (current-bidi-paragraph-direction) 'right-to-left))
+          (setq-local outline--use-rtl t))
+        (when outline--use-margins
+          (if outline--use-rtl
+              (setq-local right-margin-width (1+ right-margin-width))
+            (setq-local left-margin-width (1+ left-margin-width)))
+          (setq-local fringes-outside-margins t)
+          ;; Force display of margins
+          (set-window-buffer nil (window-buffer)))
+        (when (or outline--use-buttons outline--use-margins)
+          (add-hook 'after-change-functions
+                    (lambda (beg end _len)
+                      (when outline--use-buttons
+                        (remove-overlays beg end 'outline-button t))
+                      (when outline--use-margins
+                        (remove-overlays beg end 'outline-margin t))
+                      (outline--fix-up-all-buttons beg end))
+                    nil t))
         (when outline-minor-mode-highlight
           (if (and global-font-lock-mode (font-lock-specified-p major-mode))
               (progn
                 (font-lock-add-keywords nil outline-font-lock-keywords t)
-                (font-lock-flush)
-                (outline--fix-up-all-buttons))
+                (font-lock-flush))
             (outline-minor-mode-highlight-buffer)))
+        (outline--fix-up-all-buttons)
        ;; Turn off this mode if we change major modes.
        (add-hook 'change-major-mode-hook
                  (lambda () (outline-minor-mode -1))
@@ -476,16 +538,19 @@ See the command `outline-mode' for more information on 
this mode."
           (font-lock-remove-keywords nil outline-font-lock-keywords))
       (remove-overlays nil nil 'outline-overlay t)
       (font-lock-flush))
+    (when outline--use-margins
+      (if outline--use-rtl
+          (setq-local right-margin-width (1- right-margin-width))
+        (setq-local left-margin-width (1- left-margin-width)))
+      (setq-local fringes-outside-margins nil)
+      ;; Force removal of margins
+      (set-window-buffer nil (window-buffer)))
     (setq line-move-ignore-invisible nil)
     ;; Cause use of ellipses for invisible text.
     (remove-from-invisibility-spec '(outline . t))
     ;; When turning off outline mode, get rid of any outline hiding.
     (outline-show-all)))
 
-(defun outline--use-buttons-p ()
-  (and outline-minor-mode
-       (buffer-match-p outline-minor-mode-use-buttons (current-buffer))))
-
 (defvar-local outline-heading-alist ()
   "Alist associating a heading for every possible level.
 Each entry is of the form (HEADING . LEVEL).
@@ -1000,8 +1065,11 @@ If non-nil, EVENT should be a mouse event."
       (overlay-put o 'follow-link 'mouse-face)
       (overlay-put o 'mouse-face 'highlight)
       (overlay-put o 'outline-button t))
-    (let ((icon
-           (icon-elements (if (eq type 'close) 'outline-close 'outline-open)))
+    (let ((icon (icon-elements (if (eq type 'close)
+                                   (if outline--use-rtl
+                                       'outline-close-rtl
+                                     'outline-close)
+                                 'outline-open)))
           (inhibit-read-only t))
       ;; In editing buffers we use overlays only, but in other buffers
       ;; we use a mix of text properties, text and overlays to make
@@ -1015,10 +1083,40 @@ If non-nil, EVENT should be a mouse event."
         (overlay-put o 'face (plist-get icon 'face))))
     o))
 
-(defun outline--insert-open-button ()
+(defun outline--make-margin-overlay (type)
+  (let ((o (seq-find (lambda (o)
+                       (overlay-get o 'outline-margin))
+                     (overlays-at (point)))))
+    (unless o
+      (setq o (make-overlay (point) (1+ (point))))
+      (overlay-put o 'follow-link 'mouse-face)
+      (overlay-put o 'mouse-face 'highlight)
+      (overlay-put o 'outline-margin t))
+    (let ((icon (icon-elements (if (eq type 'close)
+                                   (if outline--use-rtl
+                                       'outline-close-rtl-in-margins
+                                     'outline-close-in-margins)
+                                 'outline-open-in-margins)))
+          (inhibit-read-only t))
+      (overlay-put
+       o 'before-string
+       (propertize " " 'display
+                   `((margin ,(if outline--use-rtl
+                                  'right-margin 'left-margin))
+                     ,(or (plist-get icon 'image)
+                          (plist-get icon 'string))))))
+    o))
+
+(defun outline--insert-open-button (&optional use-margins)
   (with-silent-modifications
     (save-excursion
-        (beginning-of-line)
+      (beginning-of-line)
+      (if use-margins
+          (let ((o (outline--make-margin-overlay 'open)))
+            (overlay-put o 'help-echo "Click to hide")
+            (overlay-put o 'keymap
+                         (define-keymap
+                           "<mouse-2>" #'outline-hide-subtree)))
         (when (derived-mode-p 'special-mode)
           (let ((inhibit-read-only t))
             (insert "  ")
@@ -1028,12 +1126,19 @@ If non-nil, EVENT should be a mouse event."
           (overlay-put o 'keymap
                        (define-keymap
                          "RET" #'outline-hide-subtree
-                         "<mouse-2>" #'outline-hide-subtree))))))
+                         "<mouse-2>" #'outline-hide-subtree
+                         "<left-margin> <mouse-1>" 
#'outline-hide-subtree)))))))
 
-(defun outline--insert-close-button ()
+(defun outline--insert-close-button (&optional use-margins)
   (with-silent-modifications
     (save-excursion
-        (beginning-of-line)
+      (beginning-of-line)
+      (if use-margins
+          (let ((o (outline--make-margin-overlay 'close)))
+            (overlay-put o 'help-echo "Click to show")
+            (overlay-put o 'keymap
+                         (define-keymap
+                           "<mouse-2>" #'outline-show-subtree)))
         (when (derived-mode-p 'special-mode)
           (let ((inhibit-read-only t))
             (insert "  ")
@@ -1043,10 +1148,11 @@ If non-nil, EVENT should be a mouse event."
           (overlay-put o 'keymap
                        (define-keymap
                          "RET" #'outline-show-subtree
-                         "<mouse-2>" #'outline-show-subtree))))))
+                         "<mouse-2>" #'outline-show-subtree
+                         "<left-margin> <mouse-1>" 
#'outline-show-subtree)))))))
 
 (defun outline--fix-up-all-buttons (&optional from to)
-  (when (outline--use-buttons-p)
+  (when (or outline--use-buttons outline--use-margins)
     (when from
       (save-excursion
         (goto-char from)
@@ -1057,8 +1163,8 @@ If non-nil, EVENT should be a mouse event."
              (outline-end-of-heading)
              (seq-some (lambda (o) (eq (overlay-get o 'invisible) 'outline))
                        (overlays-at (point))))
-           (outline--insert-close-button)
-         (outline--insert-open-button)))
+           (outline--insert-close-button outline--use-margins)
+         (outline--insert-open-button outline--use-margins)))
      (or from (point-min)) (or to (point-max)))))
 
 (define-obsolete-function-alias 'hide-subtree #'outline-hide-subtree "25.1")
@@ -1627,8 +1733,7 @@ With a prefix argument, show headings up to that LEVEL."
      (t
       (outline-show-all)
       (setq outline--cycle-buffer-state 'show-all)
-      (message "Show all")))
-    (outline--fix-up-all-buttons)))
+      (message "Show all")))))
 
 
 (defvar-keymap outline-navigation-repeat-map



reply via email to

[Prev in Thread] Current Thread [Next in Thread]