Subject: bug#52129: 29.0.50; Wish: Extend `:align-to center' to work on lines in buffer

From: Eli Zaretskii <[email-masked]>
Date: Sat, 27 Nov 2021 11:15:16 +0200

> From: Arthur Miller <[email-masked]>
> Cc: [email-masked]
> Date: Sat, 27 Nov 2021 09:47:58 +0100
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > I don't understand what exactly are you asking for.  Is your problem
> > that you have to prepend some character to the string and put the
> > :align-to spec on that character?  Because AFAIU that simple measure
> > should achieve your goal.
> 
> You mean something like this:
> 
> #+begin_src emacs-lisp
> (defun evc--time ()
>   (propertize
>    (time-stamp-string " %H:%M") 'face evc--time-face 'display '(space :align-to center)))
> 
> (defun evc--date ()
>   (propertize
>    (concat
>     " "
>     (capitalize (time-stamp-string "%A")) ". "
>     (capitalize (time-stamp-string "%B %d"))) 'face evc--date-face 'display '(space :align-to center)))

No, I mean to put this property:

    'display '(space :align-to center)

on a space character (or any other character, which will not be
displayed) that is prepended to the time-stamp-string you want to
display.

> (let* ((tlen (* 0.5 (string-pixel-width time)))
>              (dlen (* 0.5 (string-pixel-width date)))
>              (spct (propertize " " 'display `(space :align-to (- center (,tlen)))))
>              (spcd (propertize " " 'display `(space :align-to (- center (,dlen))))))
>         (insert spct time "\n" spcd date))
> 
> I hope above illustrates that it is not just to prepend a space, you have to
> calculate how much it should extend to.

So you want to center the string, not its first character?  OK, but
why is the above a problem?  It's simple enough code, I think.

> Also, even if it would be just to prepend a spacer character, the goal is still
> to align text in center of a line, so why can't we just renderer to do it for
> us, instead of having such procedural way of telling it what to do. Why can we
> not just tell:
> 
> (defun evc--time ()
>   (propertize
>    (time-stamp-string " %H:%M") 'face evc--time-face 'display '(line :align-to center)))
> 
> or something similar.

Because the Emacs display code examines buffer text one character at a
time, left to right, and produces the glyphs for display for each
character before it goes to the next.  You are asking the display
engine to know the display width of your string before it performs the
layout calculations for that string, and that cannot work.  The
display code cannot even assume that it will traverse all the
characters of a line, it could be forced to stop before it reaches the
end of the line, in which case it cannot know that width even
post-factum.

> Also what if the text is longer then visual line? Would it be possible for the
> rendering engine to center part of the tring with 'aligne-to center' property,
> and cull extensive part on sides that are outside. That is not acheavable with a spacer.

You want the display engine to decide where to break such a long line?
Or do you want to decide that up front and indicate that via the
portion of the text on which you put this hypothetical property?  IOW,
what exactly is the meaning of "cull" here?