emacs-diffs
[Top][All Lists]
Advanced

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

master dea41d4c24 1/2: Add new minor mode `header-line-indent-mode'


From: Lars Ingebrigtsen
Subject: master dea41d4c24 1/2: Add new minor mode `header-line-indent-mode'
Date: Fri, 13 May 2022 15:24:45 -0400 (EDT)

branch: master
commit dea41d4c24d0d33e359cbfe34054d9048761adfd
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Add new minor mode `header-line-indent-mode'
    
    This is mostly factored out from tabulated-list.el (with bugs fixed).
    
    * doc/lispref/modes.texi (Header Lines): Document it.
    * lisp/display-line-numbers.el (header-line-indent): New variable.
    (header-line-indent--line-number-width)
    (header-line-indent--watch-line-number-width)
    (header-line-indent--window-scroll-function): New helper functions.
    (header-line-indent-mode): New minor mode.
    
    * lisp/display-line-numbers.el (header-line-indent-width): New
    variable.
    
    * lisp/emacs-lisp/tabulated-list.el (tabulated-list-line-number-width)
    (tabulated-list-watch-line-number-width)
    (tabulated-list-window-scroll-function): Make into obsolete aliases.
    (tabulated-list-mode): Use 'header-line-indent-mode'.
    
    * lisp/emacs-lisp/tabulated-list.el (tabulated-list-init-header):
    Adjust the header line format and computation.
    
    * src/buffer.c (syms_of_buffer): Mention header-line-indent-mode.
---
 doc/lispref/modes.texi            | 18 ++++++++-
 etc/NEWS                          |  6 +++
 lisp/display-line-numbers.el      | 78 +++++++++++++++++++++++++++++++++++++++
 lisp/emacs-lisp/tabulated-list.el | 74 +++++++++++++------------------------
 src/buffer.c                      |  7 +++-
 5 files changed, 131 insertions(+), 52 deletions(-)

diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index a0c1c488fe..ddcda661a0 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -2575,7 +2575,23 @@ mode line feature, except that it's controlled by
 This variable, local in every buffer, specifies how to display the
 header line, for windows displaying the buffer.  The format of the value
 is the same as for @code{mode-line-format} (@pxref{Mode Line Data}).
-It is normally @code{nil}, so that ordinary buffers have no header line.
+It is normally @code{nil}, so that ordinary buffers have no header
+line.
+
+@findex header-line-indent-mode
+If @code{display-line-numbers-mode} is used, and you want the header
+line to be indented by the same amount as the buffer contents, you can
+use the @code{header-line-indent-mode} minor mode.  This minor mode
+keeps the @code{header-line-indent} variable updated, so that you can
+say something like:
+
+@lisp
+(setq header-line-format
+      `("" header-line-format ,my-header-line))
+@end lisp
+
+This can be useful if you're displaying columnar data, and the header
+line should align with that data in the buffer.
 @end defvar
 
 @defun window-header-line-height &optional window
diff --git a/etc/NEWS b/etc/NEWS
index d93a79ed36..f8f6d93cc2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1807,6 +1807,12 @@ functions.
 
 * Lisp Changes in Emacs 29.1
 
++++
+** New minor mode 'header-line-indent-mode'.
+This is meant to be used in modes that have a header line that should
+be kept aligned with the buffer contents when the user switches
+'display-line-numbers-mode' on or off.
+
 +++
 ** New predicate 'char-uppercase-p'.
 This returns non-nil if its argument its an uppercase character.
diff --git a/lisp/display-line-numbers.el b/lisp/display-line-numbers.el
index 860aa758bc..897a88398f 100644
--- a/lisp/display-line-numbers.el
+++ b/lisp/display-line-numbers.el
@@ -108,6 +108,84 @@ the mode is on, set `display-line-numbers' directly."
 (define-globalized-minor-mode global-display-line-numbers-mode
   display-line-numbers-mode display-line-numbers--turn-on)
 
+
+
+;;;###autoload
+(defvar header-line-indent ""
+  "String to indent at the start if the header line.
+This is used in `header-line-indent-mode', and buffers that have
+this switched on should have a `header-line-format' that look like:
+
+  (\"\" header-line-indent THE-REST...)
+
+Also see `header-line-indent-width'.")
+
+;;;###autoload
+(defvar header-line-indent-width 0
+  "The width of the current line numbers displayed.
+This is updated when `header-line-indent-mode' is switched on.
+
+Also see `header-line-indent'.")
+
+(defun header-line-indent--line-number-width ()
+  "Return the width taken by `display-line-numbers' in the current buffer."
+  ;; line-number-display-width returns the value for the selected
+  ;; window, which might not be the window in which the current buffer
+  ;; is displayed.
+  (if (not display-line-numbers)
+      0
+    (let ((cbuf-window (get-buffer-window (current-buffer) t)))
+      (if (window-live-p cbuf-window)
+          (with-selected-window cbuf-window
+            (truncate (line-number-display-width 'columns)))
+        4))))
+
+(defun header-line-indent--watch-line-number-width (_window)
+  (let ((width (header-line-indent--line-number-width)))
+    (setq header-line-indent-width width)
+    (unless (= (length header-line-indent) width)
+      (setq header-line-indent (make-string width ?\s)))))
+
+(defun header-line-indent--window-scroll-function (window _start)
+  (let ((width (with-selected-window window
+                 (truncate (line-number-display-width 'columns)))))
+    (setq header-line-indent-width width)
+    (unless (= (length header-line-indent) width)
+      (setq header-line-indent (make-string width ?\s)))))
+
+;;;###autoload
+(define-minor-mode header-line-indent-mode
+  "Mode to indent the header line in `display-line-numbers-mode' buffers.
+This means that the header line will be kept indented so that it
+has blank space that's as wide as the displayed line numbers in
+the buffer.
+
+Buffers that have this switched on should have a
+`header-line-format' that look like:
+
+  (\"\" header-line-indent THE-REST...)
+
+The `header-line-indent-width' variable is also kept updated, and
+has the width of `header-line-format'.  This can be used, for
+instance, in `:align-to' specs, like:
+
+  (space :align-to (+ header-line-indent-width 10))"
+  :lighter nil
+  (if header-line-indent-mode
+      (progn
+        (setq-local header-line-indent ""
+                    header-line-indent-width 0)
+        (add-hook 'pre-redisplay-functions
+                  #'header-line-indent--watch-line-number-width nil t)
+        (add-hook 'window-scroll-functions
+                  #'header-line-indent--window-scroll-function nil t))
+    (setq-local header-line-indent ""
+                header-line-indent-width 0)
+    (remove-hook 'pre-redisplay-functions
+                 #'header-line-indent--watch-line-number-width t)
+    (remove-hook 'window-scroll-functions
+                 #'header-line-indent--window-scroll-function t)))
+
 (provide 'display-line-numbers)
 
 ;;; display-line-numbers.el ends here
diff --git a/lisp/emacs-lisp/tabulated-list.el 
b/lisp/emacs-lisp/tabulated-list.el
index b740a7457a..7d815a3ced 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -264,18 +264,14 @@ variables `tabulated-list-tty-sort-indicator-asc' and
 Populated by `tabulated-list-init-header'.")
 (defvar tabulated-list--header-overlay nil)
 
-(defun tabulated-list-line-number-width ()
-  "Return the width taken by `display-line-numbers' in the current buffer."
-  ;; line-number-display-width returns the value for the selected
-  ;; window, which might not be the window in which the current buffer
-  ;; is displayed.
-  (if (not display-line-numbers)
-           0
-    (let ((cbuf-window (get-buffer-window (current-buffer) t)))
-      (if (window-live-p cbuf-window)
-          (with-selected-window cbuf-window
-            (line-number-display-width 'columns))
-        4))))
+(define-obsolete-function-alias 'tabulated-list-line-number-width
+  'header-line-indent--line-number-width "29.1")
+(define-obsolete-function-alias 'tabulated-list-watch-line-number-width
+  'header-line-indent--watch-line-number-width "29.1")
+(define-obsolete-function-alias 'tabulated-list-watch-line-number-width
+  'header-line-indent--watch-line-number-width "29.1")
+(define-obsolete-function-alias 'tabulated-list-window-scroll-function
+  'header-line-indent--window-scroll-function "29.1")
 
 (defun tabulated-list-init-header ()
   "Set up header line for the Tabulated List buffer."
@@ -289,9 +285,9 @@ Populated by `tabulated-list-init-header'.")
          (hcols (mapcar #'car tabulated-list-format))
          (tabulated-list--near-rows (list hcols hcols))
         (cols nil))
-    (if display-line-numbers
-        (setq x (+ x (tabulated-list-line-number-width))))
-    (push (propertize " " 'display `(space :align-to ,x)) cols)
+    (push (propertize " " 'display
+                      `(space :align-to (+ header-line-indent-width ,x)))
+          cols)
     (dotimes (n len)
       (let* ((col (aref tabulated-list-format n))
              (not-last-col (< n (1- len)))
@@ -342,20 +338,25 @@ Populated by `tabulated-list-init-header'.")
             (when (> shift 0)
               (setq cols
                     (cons (car cols)
-                          (cons (propertize (make-string shift ?\s)
-                                            'display
-                                            `(space :align-to ,(+ x shift)))
-                                (cdr cols))))
+                          (cons
+                           (propertize
+                            (make-string shift ?\s)
+                            'display
+                            `(space :align-to
+                                    (+ header-line-indent-width ,(+ x shift))))
+                           (cdr cols))))
               (setq x (+ x shift)))))
        (if (>= pad-right 0)
-           (push (propertize " "
-                             'display `(space :align-to ,next-x)
-                             'face 'fixed-pitch)
+           (push (propertize
+                   " "
+                  'display `(space :align-to
+                                    (+ header-line-indent-width ,next-x))
+                  'face 'fixed-pitch)
                  cols))
         (setq x next-x)))
     (setq cols (apply 'concat (nreverse cols)))
     (if tabulated-list-use-header-line
-       (setq header-line-format cols)
+       (setq header-line-format (list "" 'header-line-indent cols))
       (setq-local tabulated-list--header-string cols))))
 
 (defun tabulated-list-print-fake-header ()
@@ -770,23 +771,6 @@ Interactively, N is the prefix numeric argument, and 
defaults to
   (interactive "p")
   (tabulated-list-widen-current-column (- n)))
 
-(defvar tabulated-list--current-lnum-width nil)
-(defun tabulated-list-watch-line-number-width (_window)
-  (if display-line-numbers
-      (let ((lnum-width (tabulated-list-line-number-width)))
-        (when (not (= tabulated-list--current-lnum-width lnum-width))
-          (setq-local tabulated-list--current-lnum-width lnum-width)
-          (tabulated-list-init-header)))))
-
-(defun tabulated-list-window-scroll-function (window _start)
-  (if display-line-numbers
-      (let ((lnum-width
-             (with-selected-window window
-               (line-number-display-width 'columns))))
-        (when (not (= tabulated-list--current-lnum-width lnum-width))
-          (setq-local tabulated-list--current-lnum-width lnum-width)
-          (tabulated-list-init-header)))))
-
 (defun tabulated-list-next-column (&optional arg)
   "Go to the start of the next column after point on the current line.
 If ARG is provided, move that many columns."
@@ -857,15 +841,7 @@ as the ewoc pretty-printer."
   ;; Avoid messing up the entries' display just because the first
   ;; column of the first entry happens to begin with a R2L letter.
   (setq bidi-paragraph-direction 'left-to-right)
-  ;; This is for if/when they turn on display-line-numbers
-  (add-hook 'display-line-numbers-mode-hook #'tabulated-list-revert nil t)
-  ;; This is for if/when they customize the line-number face or when
-  ;; the line-number width needs to change due to scrolling.
-  (setq-local tabulated-list--current-lnum-width 0)
-  (add-hook 'pre-redisplay-functions
-            #'tabulated-list-watch-line-number-width nil t)
-  (add-hook 'window-scroll-functions
-            #'tabulated-list-window-scroll-function nil t))
+  (header-line-indent-mode))
 
 (put 'tabulated-list-mode 'mode-class 'special)
 
diff --git a/src/buffer.c b/src/buffer.c
index 57137b2a06..548d7b1c65 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5598,8 +5598,11 @@ the mode line appears at the bottom.  */);
                     &BVAR (current_buffer, header_line_format),
                     Qnil,
                     doc: /* Analogous to `mode-line-format', but controls the 
header line.
-The header line appears, optionally, at the top of a window;
-the mode line appears at the bottom.  */);
+The header line appears, optionally, at the top of a window; the mode
+line appears at the bottom.
+
+Also see `header-line-indent-mode' if `display-line-number-mode' is
+used.  */);
 
   DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, 
mode_line_format),
                     Qnil,



reply via email to

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