[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master c296bcc6c42 1/2: Support right-align in mode-line
From: |
Eli Zaretskii |
Subject: |
master c296bcc6c42 1/2: Support right-align in mode-line |
Date: |
Thu, 6 Jul 2023 03:34:02 -0400 (EDT) |
branch: master
commit c296bcc6c42ebb0fbc5078a137bbf6b501b8a44f
Author: Hugo Heagren <hugo@heagren.com>
Commit: Eli Zaretskii <eliz@gnu.org>
Support right-align in mode-line
* lisp/bindings.el (mode-line-right-align-edge): New custom
variable, controls where `mode-line-format-right-align' should
align to.
(mode-line-format-right-align): New function. If the symbol
`mode-line-format-right-align' appears in `mode-line-format',
then return return a padding string which aligns everything
after that symbol to the right. Padding width is altered with
the display property and depends on the value of
`mode-line-right-align-edge'.
(mode-line-format-right-align): New variable. Convenience
definition for including right alignment in `mode-line-format'.
* doc/lispref/modes.texi (Mode Line Variables): Document new
alignment functionality and user option. (Bug#62606)
---
doc/lispref/modes.texi | 10 ++++++++
etc/NEWS | 6 +++++
lisp/bindings.el | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 80 insertions(+)
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 8ca0afe1bca..b4f69e79155 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -2275,6 +2275,16 @@ current buffer is remote.
@defvar mode-line-client
This variable is used to identify @code{emacsclient} frames.
+@end defvar
+
+@defvar mode-line-format-right-align
+Anything following this symbol in @code{mode-line-format} will be
+right-aligned.
+@end defvar
+
+@defvar mode-line-right-align-edge
+This variable controls exactly @code{mode-line-format-right-align}
+aligns content to.
@end defvar
The following three variables are used in @code{mode-line-modes}:
diff --git a/etc/NEWS b/etc/NEWS
index e36e77fa97f..50fd1382866 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -92,6 +92,12 @@ plus, minus, check-mark, start, etc.
The 'tool-bar-position' frame parameter can be set to 'bottom' on all
window systems other than Nextstep.
+** Modeline elements can now be right-aligned
+Anything following the symbol 'mode-line-format-right-align' in
+'mode-line-format' will be right-aligned. Exactly where it is
+right-aligned to is controlled by the new user option
+'mode-line-right-align-edge'.
+
* Editing Changes in Emacs 30.1
diff --git a/lisp/bindings.el b/lisp/bindings.el
index c77b64c05da..f1a75b080be 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -304,6 +304,70 @@ Normally nil in most modes, since there is no process to
display.")
;;;###autoload
(put 'mode-line-process 'risky-local-variable t)
+(defcustom mode-line-right-align-edge 'window
+ "Where function `mode-line-format-right-align' should align to.
+Internally, that function uses `:align-to' in a display property,
+so aligns to the left edge of the given area. See info node
+`(elisp)Pixel Specification'.
+
+Must be set to a symbol. Acceptable values are:
+- `window': align to extreme right of window, regardless of margins
+ or fringes
+- `right-fringe': align to right-fringe
+- `right-margin': align to right-margin"
+ :type '(choice (const right-margin)
+ (const right-fringe)
+ (const window))
+ :group 'mode-line
+ :version "30.1")
+
+(defun mode--line-format-right-align ()
+ "Right-align all following mode-line constructs.
+
+When the symbol `mode-line-format-right-align' appears in
+`mode-line-format', return a string of one space, with a display
+property to make it appear long enough to align anything after
+that symbol to the right of the rendered mode line. Exactly how
+far to the right is controlled by `mode-line-right-align-edge'.
+
+It is important that the symbol `mode-line-format-right-align' be
+included in `mode-line-format' (and not another similar construct
+such as `(:eval (mode-line-format-right-align)'). This is because
+the symbol `mode-line-format-right-align' is processed by
+`format-mode-line' as a variable."
+ (let* ((rest (cdr (memq 'mode-line-format-right-align
+ mode-line-format)))
+ (rest-str (format-mode-line `("" ,@rest)))
+ (rest-width (string-pixel-width rest-str)))
+ (propertize " " 'display
+ ;; The `right' spec doesn't work on TTY frames
+ ;; when windows are split horizontally (bug#59620)
+ (if (and (display-graphic-p)
+ (not (eq mode-line-right-align-edge 'window)))
+ `(space :align-to (- ,mode-line-right-align-edge
+ (,rest-width)))
+ `(space :align-to (,(- (window-pixel-width)
+ (window-scroll-bar-width)
+ (window-right-divider-width)
+ (* (or (cdr (window-margins)) 1)
+ (frame-char-width))
+ ;; Manually account for value of
+ ;; `mode-line-right-align-edge' even
+ ;; when display is non-graphical
+ (pcase mode-line-right-align-edge
+ ('right-margin
+ (or (cdr (window-margins)) 0))
+ ('right-fringe
+ ;; what here?
+ (or (cadr (window-fringes)) 0))
+ (_ 0))
+ rest-width)))))))
+
+(defvar mode-line-format-right-align '(:eval (mode--line-format-right-align))
+ "Mode line construct to right align all following constructs.")
+;;;###autoload
+(put 'mode-line-format-right-align 'risky-local-variable t)
+
(defun bindings--define-key (map key item)
"Define KEY in keymap MAP according to ITEM from a menu.
This is like `define-key', but it takes the definition from the