]> git.eshelyaron.com Git - emacs.git/commitdiff
Support right-align in mode-line
authorHugo Heagren <hugo@heagren.com>
Sat, 1 Apr 2023 21:27:25 +0000 (22:27 +0100)
committerEli Zaretskii <eliz@gnu.org>
Thu, 6 Jul 2023 07:31:46 +0000 (10:31 +0300)
* 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
etc/NEWS
lisp/bindings.el

index 8ca0afe1bca991ea4e6dc13f32a33e80475ae65b..b4f69e7915561d72b4e94d4b8eaae27cd1d7db67 100644 (file)
@@ -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}:
index e36e77fa97f83843eca04df679c2e0c0ad894c1b..50fd1382866fa59798c1c3605886c2f5d8c7a85f 100644 (file)
--- 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'.
+
 \f
 * Editing Changes in Emacs 30.1
 
index c77b64c05daea7c7ff2bac37c8fc2e441762c6c1..f1a75b080be891ec22fd07255660faa2435fe594 100644 (file)
@@ -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