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.
This commit is contained in:
parent
72b5b41941
commit
dea41d4c24
5 changed files with 131 additions and 52 deletions
|
@ -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
|
||||
|
|
6
etc/NEWS
6
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue