Subject: Re: bug#47712: 27.1; Provide `string-display-width` function, which takes properties into account, `substring-width`

From: Daniel Mendler <[email-masked]>
Date: Mon, 12 Apr 2021 14:50:25 +0200

On 4/12/21 2:21 PM, Eli Zaretskii wrote:
> That is easy to work around, right?  Just insert the string into a
> temporary buffer and say with-current-buffer (and/or
> with-selected-window, if needed).

I have not tested this but I suspect this to be slow for a few thousand 
strings.

>> The function `string-width` instead takes a string argument
>> returning the number of columns needed to display this string. This
>> function is needed to compute widths of strings which are not yet
>> displayed.
> 
> But you compute the width because you are going to display that string
> soon enough, right?  Or did I misunderstand the purpose?

I am using it to generate candidate strings for `completing-read` and 
Org is using it to format tables. So no, I don't think that's soon enough.

> In general, calculating a string's width out of display context is
> meaningless in Emacs.  More about that below.

I know about the context dependence. But there is the `string-width` 
function which is also computed in the current context. I am only asking 
for an improved version of already existing functionality. My most 
minimal feature request is just a function `substring-width`.

> That's exactly my point: by not using the display code, you allow up
> front inaccurate results.  There's no practical way to implement this
> in Lisp without yielding inaccurate and even grossly incorrect results
> in some cases (see below), so any such implementation will be limited
> from the get-go, in ways that are hard to even document precisely, let
> alone use reliably.  Thus, users of such an implementation are bound
> to be unpleasantly surprised if they try using it in a situation
> different from yours.

I agree that it would not work in all case. But why does `string-width` 
exist then? Is it deprecated?

>> Instead it computes the `string-width` of a flattened string, where
>> the invisible parts have been removed and the displayed parts have
>> been replaced.
> 
> Yes, I understood what the code does.  But it only handles some of the
> possible use cases, and will fail in others.  For example, it ignores
> faces (which could change the metrics of characters); it assumes that
> all the characters of the string can be displayed by the buffer's
> fonts (because "tofu" has very different dimensions); it uses
> char-width to measure a character's width (which is only accurate for
> text-mode frames); it doesn't handle display properties that aren't
> strings, such as (space :align-to N); etc.

That's right. In particular not supporting the :space alignment property 
is a serious limitation. But in text-mode frames the computation will 
return a correct result if it considers 'invisible and 'display recursively.

> So I urge you to try to use window-text-pixel-size for org-table and
> elsewhere, because that's what that function is for.  If it lacks some
> feature or has bugs, we will improve it.

It is fair to reject the feature request for a 
`string-display/property-width` function, because it would be hard to 
implement a generally useful function.

However if you attack `string-width` for not computing something 
correct, then one may want to consider deprecating `string-width` 
altogether or at least make it clear in the documentation that this 
function should not be used and something else based on the window 
function should be used instead.

Note that `gnus-correct-length` has been replaced by `string-width`, so 
maybe Lars can say something about the justification for `string-width`?