branch: elpa/magit
commit a47b5098c812b7a7932df802378cb754e3ad8639
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>

    Support displaying visibility indicator in left margin
    
    Closes #5424.
---
 lisp/magit-margin.el  | 60 +++++++++++++++++++++++++++++----------------------
 lisp/magit-section.el | 53 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 78 insertions(+), 35 deletions(-)

diff --git a/lisp/magit-margin.el b/lisp/magit-margin.el
index 1771fee93c4..6803c6f05eb 100644
--- a/lisp/magit-margin.el
+++ b/lisp/magit-margin.el
@@ -129,35 +129,43 @@ does not carry to other options."
 
 ;;; Core
 
-(defun magit-set-buffer-margins (&optional reset refresh)
-  (when-let ((option (magit--right-margin-option)))
-    (let* ((default (symbol-value option))
-           (default-width (nth 2 default)))
-      (when (or reset (not magit--right-margin-config))
-        (setq magit--right-margin-config (copy-sequence default)))
-      (pcase-let ((`(,enable ,style ,_width ,details ,details-width)
-                   magit--right-margin-config))
-        (when (functionp default-width)
-          (setf (nth 2 magit--right-margin-config)
-                (funcall default-width style details details-width)))
-        (dolist (window (get-buffer-window-list nil nil 0))
-          (with-selected-window window
-            (magit-set-window-margins window)
-            (if enable
-                (add-hook  'window-configuration-change-hook
-                           #'magit-set-window-margins nil t)
-              (remove-hook 'window-configuration-change-hook
-                           #'magit-set-window-margins t))))
-        (when (and enable (or refresh magit--right-margin-delayed))
-          (magit-refresh-buffer))))))
+(defun magit-set-buffer-margins (&optional reset-right refresh-right)
+  (let ((lmargin nil)
+        (rmargin nil)
+        (roption (magit--right-margin-option)))
+    (when (or lmargin roption)
+      (when roption
+        (let* ((default (symbol-value roption))
+               (default-width (nth 2 default)))
+          (when (or reset-right (not magit--right-margin-config))
+            (setq magit--right-margin-config (copy-sequence default)))
+          (pcase-let ((`(,enable ,style ,_width ,details ,details-width)
+                       magit--right-margin-config))
+            (setq rmargin enable)
+            (when (functionp default-width)
+              (setf (nth 2 magit--right-margin-config)
+                    (funcall default-width style details details-width))))))
+      (dolist (window (get-buffer-window-list nil nil 0))
+        (with-selected-window window
+          (magit-set-window-margins window)
+          (if (or lmargin rmargin)
+              (add-hook  'window-configuration-change-hook
+                         #'magit-set-window-margins nil t)
+            (remove-hook 'window-configuration-change-hook
+                         #'magit-set-window-margins t))))
+      (when (and rmargin (or refresh-right magit--right-margin-delayed))
+        (magit-refresh-buffer)))))
 
 (defun magit-set-window-margins (&optional window)
   (when (or window (setq window (get-buffer-window)))
-    (with-selected-window window
-      (set-window-margins
-       nil (car (window-margins))
-       (and (magit--right-margin-active)
-            (nth 2 magit--right-margin-config))))))
+    (pcase-let ((`(,left . ,right) (window-margins)))
+      (with-selected-window window
+        (set-window-margins
+         nil
+         (if (characterp (car magit-section-visibility-indicator)) 1 left)
+         (if (magit--right-margin-active)
+             (nth 2 magit--right-margin-config)
+           right))))))
 
 (cl-defun magit-make-margin-overlay (&optional string (previous-line nil 
sline))
   "Display STRING in the margin of the previous (or current) line.
diff --git a/lisp/magit-section.el b/lisp/magit-section.el
index 8e9dbf8d952..16c3fdda724 100644
--- a/lisp/magit-section.el
+++ b/lisp/magit-section.el
@@ -201,7 +201,7 @@ entries of this alist."
   "Whether and how to indicate that a section can be expanded/collapsed.
 
 If nil, then don't show any indicators.
-Otherwise the value has to have one of these two forms:
+Otherwise the value has to have one of these three forms:
 
 \(EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP)
 
@@ -212,6 +212,11 @@ Otherwise the value has to have one of these two forms:
   To provide extra padding around the indicator, set
   `left-fringe-width' in `magit-mode-hook'.
 
+\(EXPANDABLE-CHAR . COLLAPSIBLE-CHAR)
+
+  In this case every section that can be expanded or collapsed
+  gets an indicator in the left margin.
+
 \(STRING . BOOLEAN)
 
   In this case STRING (usually an ellipsis) is shown at the end
@@ -235,6 +240,9 @@ Otherwise the value has to have one of these two forms:
                  (cons  :tag "Use custom fringe indicators"
                         (variable :tag "Expandable bitmap variable")
                         (variable :tag "Collapsible bitmap variable"))
+                 (cons  :tag "Use margin indicators"
+                        (char :tag "Expandable char" ?+)
+                        (char :tag "Collapsible char" ?-))
                  (cons  :tag "Use ellipses at end of headings"
                         (string :tag "Ellipsis" "…")
                         (choice :tag "Use face kludge"
@@ -360,6 +368,24 @@ but that ship has sailed, thus this option."
   "Face used for child counts at the end of some section headings."
   :group 'magit-section-faces)
 
+(defface magit-left-margin '((t :inherit default))
+  "Face used for the left margin.
+
+Currently this is only used for section visibility indicators, and only
+when `magit-section-visibility-indicator' is configured to show them in
+the margin.
+
+Due to limitations of how the margin works in Emacs, this is only used
+for those parts of the margin that actually display an indicator.  For
+that reason you should probably avoid setting the background color.
+
+Reasonable values include ((t)), which causes the indicator to inherit
+the look of the heading (including section highlighting, if any), and
+\((t :inherit default), which prevents that and causes the margin to
+look like regular un-styled text in the buffer.  Building on that, you
+can make it look different, e.g., ((t :inherit default :weight bold)."
+  :group 'magit-section-faces)
+
 ;;; Classes
 
 (defvar magit--current-section-hook nil
@@ -391,9 +417,10 @@ but that ship has sailed, thus this option."
 (defvar-keymap magit-section-heading-map
   :doc "Keymap used in the heading line of all expandable sections.
 This keymap is used in addition to the section-specific keymap, if any."
-  "<double-down-mouse-1>" #'ignore
-  "<double-mouse-1>" #'magit-mouse-toggle-section
-  "<double-mouse-2>" #'magit-mouse-toggle-section)
+  "<double-down-mouse-1>"   #'ignore
+  "<double-mouse-1>"        #'magit-mouse-toggle-section
+  "<double-mouse-2>"        #'magit-mouse-toggle-section
+  "<left-margin> <mouse-1>" #'magit-mouse-toggle-section)
 
 (defvar-keymap magit-section-mode-map
   :doc "Parent keymap for keymaps of modes derived from `magit-section-mode'."
@@ -1968,18 +1995,26 @@ When `magit-section-preserve-visibility' is nil, return 
nil."
                         (cdr magit-section-visibility-indicator)))
            (kind (cl-typecase (car magit-section-visibility-indicator)
                    (symbol    'fringe)
+                   (character 'margin)
                    (string    'ellipsis))))
       (pcase kind
-        ('fringe
-         (let ((ov (magit--overlay-at beg 'magit-vis-indicator 'fringe)))
+        ((or 'fringe 'margin)
+         (let ((ov (magit--overlay-at beg 'magit-vis-indicator kind)))
            (unless ov
              (setq ov (make-overlay beg eoh nil t))
              (overlay-put ov 'evaporate t)
-             (overlay-put ov 'magit-vis-indicator 'fringe))
+             (overlay-put ov 'magit-vis-indicator kind))
            (overlay-put
             ov 'before-string
-            (propertize "fringe" 'display
-                        `(left-fringe ,indicator fringe)))))
+            (pcase kind
+              ('fringe
+               (propertize "fringe" 'display
+                           `(left-fringe ,indicator fringe)))
+              ('margin
+               (propertize "margin" 'display
+                           `((margin left-margin)
+                             ,(propertize (string indicator)
+                                          'face 'magit-left-margin))))))))
         ('ellipsis
          (let ((ov (magit--overlay-at (1- eoh) 'magit-vis-indicator 'eoh)))
            (cond ((oref section hidden)

Reply via email to