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

From: Arthur Miller <[email-masked]>
Date: Sat, 27 Nov 2021 12:06:19 +0100

Eli Zaretskii <[email-masked]> writes:

>> 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.

Aha, like this?:

(defun evc--time ()
  (concat (propertize " " 'display '(space :align-to center))
          (propertize
           (time-stamp-string " %H:%M") 'face evc--time-face)))

That still seems to be dependanble on when the time string is inserted? Because
when I test to insert like this:

(defun evc--update ()
  (let ((time (evc--time))
        (date (evc--date)))
    (when (frame-live-p evc--frame)
      (select-frame evc--frame))
    (with-current-buffer evc--buffer
      (erase-buffer)
      (insert time "\n" date)
      (goto-char 1))))

the string is not centered correctly; there is ~70 pixels difference between
left and right margins.

Maybe if I inserted longer string first, fitted frame to buffer, and than
inserted time, but I don't think it is relevant if you say it is not possible to
do it due to renderer only looking at one char at a time.

> 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,

Meant mostly that display engine would keep marked portion of the string
centered on the display, for example if there is some more important of the
string or so, but at the second thought I don't see much use of such
feature.

Anyway, I understand now when you say that renderer only looks at one char at a
time.

Is there any way to make it aware of surrounding context, like entire line? Or
would that be too demanding computationally? I guess there is a reason why it is
made one char at a time.