From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C
Date: Thu, 24 Oct 2024 22:11:36 +0100 [thread overview]
Message-ID: <CAKDRQS6hgFrer3WkRSL-XWZcONiD-BXUZ=+TQ-nhY5Nq7D8HYQ@mail.gmail.com> (raw)
In-Reply-To: <86frolcrl2.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 5361 bytes --]
>
> Why would you need to truncate? and which part needs to be truncated?
>
> My suggestion is to align the <Type>s part so that it and the
> following pseudo-scrollbar end exactly at the window edge. With this
> arrangement, you shouldn't need to truncate at least the <Type>s part.
> This can be dome by using :align-to which counts from 'right', which
> is the right edge of the text area.
> Actually, I don't understand why you'd need to truncate anything,
> since the dimensions of the child frame can be calculated such that
> the longest completion candidate will still fit without truncation.
> Or what am I missing?
The :align-to of the padding between candidate and annotation can only be
calculated by adding the prefix column width, calculated from the longest
prefix width, the candidate width, calculated the same way, and the suffix
column width minus the pixel width of the suffix. The reason for this is
that `string-pixel-width` will be called on all of these concatenated
strings, and the maximum of which will be given as the width to a function
to render the child frame. This also answers your next question, yes the
pop up width is already calculated dynamically, but against a max width,
this is what I mean by "confined", hence the need for truncation before
blitzing the strings to a child frame. :align-to (- right suffix-width)
will lead `string-pixel-width` to return a ridiculously large number that,
funnily enough, is calculated from the current window's text area width,
instead of the child frame's window, of which the size is unknown at this
time.
As to the reason for a max width, let's just say there exists language
servers such as Rust Analyzer, that will return the signature of a function
as the completion annotation, which can be quite long. Nobody wants their
completion pop up box taking up half the screen.
Of course, one can also adjusts the child frame parameters to let it deal
with min/max size, margins and allow the user to resize, but the
beautifully emulated scroll bar will have to be sacrificed because either I
delete it from Corfu or the window will start truncating from the scroll
bar when the user resizes the window to be smaller than the content width.
> > There are 2 options - `truncate-string-to-width`, which is
> > bugged, or set the `truncate-line` buffer local to t and let Emacs'
> window system do its magic, which will be
> > performant and correct, and I can even replace the arrow in an ellipsis,
> but truncation will start to truncate off
> > the emulated scroll bar.
>
> You assumed something I didn't say and didn't have in mind. There
> should be no need to use truncate-lines.
>
I didn't assume anything. It's just a logical conclusion. Do you have it in
mind now?
This is not about refusal. It isn't like what you are asking is easy
to do, and the "Emacs devs" are just a lazy bunch. I looked at the
> code involved, and I currently have no idea how to implement what you
> have in mind so that it works in all the cases, those which you
> mentioned and those you didn't, and works in a way that will be useful
> for Lisp programs. You may think it's easy, but it isn't. Some
> things are even conceptually not simple, for example whether it is
> okay or not to break a string between U+1F3C2 and the following
> U+1F3FF, and if so, how to discover that subject to how the current
> character-composition machinery in Emacs was designed and implemented.
>
You already have `string-glyph-split` which works correctly, (a job well
done BTW, even more comformant than Chrome and Webkit). There are only 3
things you need to do for a hypothetical `glyph-pixel-width`:
1. With no faces, find the width of a character glyph from the default font
or whatever `char-displayable-p` returns. This is easy, I can already do
this from Elisp reasonably fast by going straight to the terminal using
`composite-get-gstring`.
2. With faces, resolve the font from the faces, go to 1. Still no need
to deal with windows. Can be done correctly in Elisp, but incredibly slowly
due to anon faces, face lists and having to go through the recursive
`face-attribute-merged-with`. The logic in `face-attribute-merged-with` can
be duplicated and modified to deal with anon faces, and run iteratively,
but still a few orders of magnitude slower than it needs to be.
3. Display properties is when you start to need a window, as a first try,
you can delegate this back to the current slow path via
`window-text-pixel-size`.
1 and 2 will be the vast vast majority of the use case. It's okay to be
slower for 3 due to the involvement of a window.
As a point of reference, this benchmark finishes in ~0.10s in my MacBook
Pro M1 Pro, this is 6 FPS for measuring 10k glyph widths.
```elisp
(let ((s "1")) 'face 'completions-common-part)))
(benchmark-run 10000 (string-pixel-width s)))
```
The following finishes in ~0.9s. Using the procedure described in case 1
above already cuts the time down by half.
```elisp
(benchmark-run 10000 (string-pixel-width "1"))
```
Getting boths cases down 1 order of magnitude is all I'm hoping for.
I'm not saying emacs-devs are lazy, I'm just saying after 14 years, Emacs
finally can split strings with emojis correctly, can we go one step further
and give Emacs users the ability to layout in pixel precision in a
more performant manner please?
[-- Attachment #2: Type: text/html, Size: 6732 bytes --]
next prev parent reply other threads:[~2024-10-24 21:11 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-23 5:01 Need `truncate-string-to-pixel-width` and `glyph-pixel-width` functions in C Jimmy Yuen Ho Wong
2024-10-23 8:01 ` Eli Zaretskii
2024-10-23 13:52 ` Jimmy Yuen Ho Wong
2024-10-23 17:39 ` Eli Zaretskii
2024-10-23 20:03 ` Jimmy Yuen Ho Wong
2024-10-24 9:55 ` Eli Zaretskii
2024-10-24 14:26 ` Jimmy Yuen Ho Wong
2024-10-24 14:39 ` Eli Zaretskii
2024-10-24 15:33 ` Jimmy Yuen Ho Wong
2024-10-24 16:02 ` Eli Zaretskii
2024-10-24 16:49 ` Jimmy Yuen Ho Wong
2024-10-24 17:56 ` Eli Zaretskii
2024-10-24 21:11 ` Jimmy Yuen Ho Wong [this message]
2024-10-25 7:21 ` Eli Zaretskii
2024-10-25 13:35 ` Jimmy Yuen Ho Wong
2024-10-25 15:11 ` Eli Zaretskii
2024-10-28 20:21 ` Jimmy Yuen Ho Wong
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='CAKDRQS6hgFrer3WkRSL-XWZcONiD-BXUZ=+TQ-nhY5Nq7D8HYQ@mail.gmail.com' \
--to=wyuenho@gmail.com \
--cc=eliz@gnu.org \
--cc=emacs-devel@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.