mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
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
|
This variable, local in every buffer, specifies how to display the
|
||||||
header line, for windows displaying the buffer. The format of the value
|
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}).
|
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
|
@end defvar
|
||||||
|
|
||||||
@defun window-header-line-height &optional window
|
@defun window-header-line-height &optional window
|
||||||
|
|
|
||||||
6
etc/NEWS
6
etc/NEWS
|
|
@ -1807,6 +1807,12 @@ functions.
|
||||||
|
|
||||||
* Lisp Changes in Emacs 29.1
|
* 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'.
|
** New predicate 'char-uppercase-p'.
|
||||||
This returns non-nil if its argument its an uppercase character.
|
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
|
(define-globalized-minor-mode global-display-line-numbers-mode
|
||||||
display-line-numbers-mode display-line-numbers--turn-on)
|
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)
|
(provide 'display-line-numbers)
|
||||||
|
|
||||||
;;; display-line-numbers.el ends here
|
;;; display-line-numbers.el ends here
|
||||||
|
|
|
||||||
|
|
@ -264,18 +264,14 @@ variables `tabulated-list-tty-sort-indicator-asc' and
|
||||||
Populated by `tabulated-list-init-header'.")
|
Populated by `tabulated-list-init-header'.")
|
||||||
(defvar tabulated-list--header-overlay nil)
|
(defvar tabulated-list--header-overlay nil)
|
||||||
|
|
||||||
(defun tabulated-list-line-number-width ()
|
(define-obsolete-function-alias 'tabulated-list-line-number-width
|
||||||
"Return the width taken by `display-line-numbers' in the current buffer."
|
'header-line-indent--line-number-width "29.1")
|
||||||
;; line-number-display-width returns the value for the selected
|
(define-obsolete-function-alias 'tabulated-list-watch-line-number-width
|
||||||
;; window, which might not be the window in which the current buffer
|
'header-line-indent--watch-line-number-width "29.1")
|
||||||
;; is displayed.
|
(define-obsolete-function-alias 'tabulated-list-watch-line-number-width
|
||||||
(if (not display-line-numbers)
|
'header-line-indent--watch-line-number-width "29.1")
|
||||||
0
|
(define-obsolete-function-alias 'tabulated-list-window-scroll-function
|
||||||
(let ((cbuf-window (get-buffer-window (current-buffer) t)))
|
'header-line-indent--window-scroll-function "29.1")
|
||||||
(if (window-live-p cbuf-window)
|
|
||||||
(with-selected-window cbuf-window
|
|
||||||
(line-number-display-width 'columns))
|
|
||||||
4))))
|
|
||||||
|
|
||||||
(defun tabulated-list-init-header ()
|
(defun tabulated-list-init-header ()
|
||||||
"Set up header line for the Tabulated List buffer."
|
"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))
|
(hcols (mapcar #'car tabulated-list-format))
|
||||||
(tabulated-list--near-rows (list hcols hcols))
|
(tabulated-list--near-rows (list hcols hcols))
|
||||||
(cols nil))
|
(cols nil))
|
||||||
(if display-line-numbers
|
(push (propertize " " 'display
|
||||||
(setq x (+ x (tabulated-list-line-number-width))))
|
`(space :align-to (+ header-line-indent-width ,x)))
|
||||||
(push (propertize " " 'display `(space :align-to ,x)) cols)
|
cols)
|
||||||
(dotimes (n len)
|
(dotimes (n len)
|
||||||
(let* ((col (aref tabulated-list-format n))
|
(let* ((col (aref tabulated-list-format n))
|
||||||
(not-last-col (< n (1- len)))
|
(not-last-col (< n (1- len)))
|
||||||
|
|
@ -342,20 +338,25 @@ Populated by `tabulated-list-init-header'.")
|
||||||
(when (> shift 0)
|
(when (> shift 0)
|
||||||
(setq cols
|
(setq cols
|
||||||
(cons (car cols)
|
(cons (car cols)
|
||||||
(cons (propertize (make-string shift ?\s)
|
(cons
|
||||||
|
(propertize
|
||||||
|
(make-string shift ?\s)
|
||||||
'display
|
'display
|
||||||
`(space :align-to ,(+ x shift)))
|
`(space :align-to
|
||||||
|
(+ header-line-indent-width ,(+ x shift))))
|
||||||
(cdr cols))))
|
(cdr cols))))
|
||||||
(setq x (+ x shift)))))
|
(setq x (+ x shift)))))
|
||||||
(if (>= pad-right 0)
|
(if (>= pad-right 0)
|
||||||
(push (propertize " "
|
(push (propertize
|
||||||
'display `(space :align-to ,next-x)
|
" "
|
||||||
|
'display `(space :align-to
|
||||||
|
(+ header-line-indent-width ,next-x))
|
||||||
'face 'fixed-pitch)
|
'face 'fixed-pitch)
|
||||||
cols))
|
cols))
|
||||||
(setq x next-x)))
|
(setq x next-x)))
|
||||||
(setq cols (apply 'concat (nreverse cols)))
|
(setq cols (apply 'concat (nreverse cols)))
|
||||||
(if tabulated-list-use-header-line
|
(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))))
|
(setq-local tabulated-list--header-string cols))))
|
||||||
|
|
||||||
(defun tabulated-list-print-fake-header ()
|
(defun tabulated-list-print-fake-header ()
|
||||||
|
|
@ -770,23 +771,6 @@ Interactively, N is the prefix numeric argument, and defaults to
|
||||||
(interactive "p")
|
(interactive "p")
|
||||||
(tabulated-list-widen-current-column (- n)))
|
(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)
|
(defun tabulated-list-next-column (&optional arg)
|
||||||
"Go to the start of the next column after point on the current line.
|
"Go to the start of the next column after point on the current line.
|
||||||
If ARG is provided, move that many columns."
|
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
|
;; Avoid messing up the entries' display just because the first
|
||||||
;; column of the first entry happens to begin with a R2L letter.
|
;; column of the first entry happens to begin with a R2L letter.
|
||||||
(setq bidi-paragraph-direction 'left-to-right)
|
(setq bidi-paragraph-direction 'left-to-right)
|
||||||
;; This is for if/when they turn on display-line-numbers
|
(header-line-indent-mode))
|
||||||
(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))
|
|
||||||
|
|
||||||
(put 'tabulated-list-mode 'mode-class 'special)
|
(put 'tabulated-list-mode 'mode-class 'special)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5598,8 +5598,11 @@ the mode line appears at the bottom. */);
|
||||||
&BVAR (current_buffer, header_line_format),
|
&BVAR (current_buffer, header_line_format),
|
||||||
Qnil,
|
Qnil,
|
||||||
doc: /* Analogous to `mode-line-format', but controls the header line.
|
doc: /* Analogous to `mode-line-format', but controls the header line.
|
||||||
The header line appears, optionally, at the top of a window;
|
The header line appears, optionally, at the top of a window; the mode
|
||||||
the mode line appears at the bottom. */);
|
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),
|
DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format),
|
||||||
Qnil,
|
Qnil,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue