all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: hugo@heagren.com
To: Eli Zaretskii <eliz@gnu.org>
Cc: 62606@debbugs.gnu.org
Subject: bug#62606: [PATCH] function to align mode-line elements to right
Date: Sat, 06 May 2023 15:14:24 +0100	[thread overview]
Message-ID: <c457017315dd02f88787813cc9cf2b8f@heagren.com> (raw)
In-Reply-To: <83355iygw3.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 3936 bytes --]

Thanks for the feedback. A new patch is attached.

> From: 	Eli Zaretskii
> Date: 	Sun, 02 Apr 2023 08:47:40 +0300

> What would be the situations where the user could want this alignment?

It's merely an aesthetic thing -- I just like having some of my
information right-aligned. I think the motivation for the tab bar
right-align function is similar?

> One possible issue with right alignment is that when the total size of
> the mode-line text changes (e.g., the mode lighter changes), the
> leftmost part of it will move horizontally, something that could be
> unpleasant and even annoying.

This doesn't happen with my proposed setup (though I agree it would be
annoying if it did!). The user includes the symbol
`mode-line-format-right-align' in their mode line format. This is a
variable which holds a mode-line construct `(:eval
(mode-line-format-right-align))'. So whenever the mode-line is reloaded
(and therefore, whenever the length could change), the space used to pad
the right-aligned part to the right is recalculated. The only situation
where this could go wrong would be if the length of the left part of the
mode-line changed /during/ the process of reloading the mode-line, which
seems unlikely to happen.

> Also, what happens if the mode-line text is longer than the window
> width.  What are user expectations in that case, and does :align-to
> meet those expectations?

Then the text overflows to the right. The behaviour with my patch is the
same as without: the text furthest to the right is not visible. The way
the patch is written would mean that the padding used to align text to
the right would be nil (i.e. a zero-width) string, but this is not
really relevant because it won't be visible (because it will be off the
right-hand edge of the screen).

> > The functin aligns to the right /fringe/ rather than the margin because
> > some modes (e.g. [visual-fill-column-mode]) mess around the margin size,
> > but the right-align should be unaffected by this.
> This detail should not be hard-coded, IMO.

On reflection, I think you're right.

> It should be up to the calling Lisp program (or maybe even user
> option) whether the alignment is to the right margin or to the window
> edge.

I found this easier to implement as a user option -- I've added
`mode-line-right-align-edge' to the patch.

> Also, did you test this when the fringe is inside the margins and the
> margins have non-zero width?

Yes. It does exactly what you expect (i.e. if
`mode-line-right-align-edge' is set to `right-fringe' then align
to the fringe, it set to `right-margin' etc.). Setting
`mode-line-right-align-edge' to `window' aligns to the right of
the window even in these circumstances.

> The call to string-pixel-width will significantly slow down redisplay
> of the mode line.

Yes, unfortunately.

> I wonder whether this feature should be implemented in C instead, to
> avoid the slowdown.

This would be great, but I definitely don't have the skills to do it.
Unless someone else does this, perhaps we could include my lisp
implementation for now, document the slowness (in the docstring),
and put a C implementation on the wishlist/TODO?

> This should use display-graphic-p, not window-system.

Fixed.

> Did you test this in a session which has both GUI and TTY frames?

Yes, it behaves correctly (i.e. right-aligns in both, even when the
same buffer is simultaneously displayed in both).

> From: 	Juri Linkov
> Date: 	Sun, 02 Apr 2023 19:19:01 +0300

> Here `format-mode-line' returns an empty string when
> `mode-line-format-right-align' was added in the middle of
> `mode-line-format'. For a strange reason, it expects that
> `mode-line-format' should start with a string. So everything is fine
> after replacing in your patch

Thanks for pointing this out. I've fixed it in the new patch (though my
fix uses a back-quote construction, but the effect is the same).

Hope the new version is better. Thoughts?

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Support-right-align-in-mode-line.patch --]
[-- Type: text/x-diff; name=0001-Support-right-align-in-mode-line.patch, Size: 4513 bytes --]

From 770e2a0617c650755f1be3de15ffbe13a9664a53 Mon Sep 17 00:00:00 2001
From: Hugo Heagren <hugo@heagren.com>
Date: Sat, 1 Apr 2023 22:27:25 +0100
Subject: [PATCH] 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'.
---
 lisp/bindings.el | 64 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/lisp/bindings.el b/lisp/bindings.el
index 34aa8399a96..7ba9f325061 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -304,6 +304,70 @@ mode-line-process
 ;;;###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.
+
+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
+- right: synonym for right-margin (supported because this is how the
+  display property understands this, see info node `(elisp)Specified
+  Space'.)"
+  :type '(choice (const right)
+                 (const right-margin)
+                 (const right-fringe)
+                 (const window))
+  :group 'mode-line)
+
+(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
+                                           ((or 'right '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
-- 
2.20.1


  reply	other threads:[~2023-05-06 14:14 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-01 22:27 bug#62606: [PATCH] function to align mode-line elements to right hugo
2023-04-02  5:47 ` Eli Zaretskii
2023-05-06 14:14   ` hugo [this message]
2023-05-06 14:39     ` Eli Zaretskii
2023-06-05 20:45       ` hugo
2023-06-06 11:24         ` Eli Zaretskii
2023-06-09 12:47           ` hugo
2023-06-09 13:13             ` Eli Zaretskii
     [not found]               ` <f60acc21a937b413f6528264f233ebfe@heagren.com>
2023-06-09 14:52                 ` Eli Zaretskii
2023-04-02 16:19 ` Juri Linkov
2023-06-09 16:03 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-09 16:17   ` Eli Zaretskii
2023-06-09 16:52     ` bug#62606: R2L modelines (was: bug#62606: [PATCH] function to align mode-line elements to right) Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-19 19:06   ` bug#62606: [PATCH] function to align mode-line elements to right hugo
2023-06-24 12:05     ` Eli Zaretskii
2023-06-26 10:06       ` hugo
2023-06-26 11:55         ` Eli Zaretskii
2023-07-02 12:43           ` hugo
2023-07-06  7:35             ` Eli Zaretskii
     [not found] ` <handler.62606.D62606.168862894016990.notifdone@debbugs.gnu.org>
2023-07-14 16:37   ` Juri Linkov
2023-07-17 17:56     ` Juri Linkov
     [not found]       ` <CALDnm53v4O9cYcYwcqGpYVb4xVOw6t+FM1xX21k7HFxWyuiSaQ@mail.gmail.com>
     [not found]         ` <83fryrs1l8.fsf@gnu.org>
     [not found]           ` <87edebjcku.fsf@gmail.com>
     [not found]             ` <835xznro5i.fsf@gnu.org>
2024-01-21 10:20               ` João Távora
2024-01-21 10:27                 ` Eli Zaretskii
2024-01-21 10:39                   ` João Távora

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c457017315dd02f88787813cc9cf2b8f@heagren.com \
    --to=hugo@heagren.com \
    --cc=62606@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.