Subject: Re: bug#71323: 28.2; global-display-line-numbers-mode in org file do strange identation when headers are folded

From: Eli Zaretskii <[email-masked]>
Date: Sun, 02 Jun 2024 15:20:41 +0300

tags 71323 notabug
thanks

> From: Mikhail Efremov <[email-masked]>
> Date: Sun, 02 Jun 2024 15:10:46 +0600
> 
> * Description
> 
> There is an issue with not so large org files with
> global-display-line-numbers-mode is toggled on. You may reproduce it:
> 
> 1. ~emacs -Q~
> 2. open an org file with 1000+ lines of different headers' layers
> unfolded.
> 3. ~M-x global-display-line-numbers-mode~
> 4. Check that unfolded headers on lines 999-1000 are indented fine:
>   - numbers are right-aligned;
>   - same-level headers are indented equally with the same indent width
>   relative to line numbers.
> 5. Fold all headers with the property: on the screen of the buffer
> there
> are single-, two- and three-digits lines' numbers are presented.
> 
> Then, you should see the picture like this:
> 
>   1 * header1
>  24 * header2
> 132 * header3
> 1019 * header4
> 
> The same behavior is on ~emacs -nw -Q~.
> 
> The issue is valid also on built from sources emacs: GNU Emacs 29.3
> (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version
> 1.16.0) of 2024-04-08
> 
> * Motivation
> 
> This behavior on the one hand constantly shifts
> left-to-right-and-vice-versa the buffer's text and also confuses with
> headers' identation level.
> 
> * Definition of Done
> 
> After the steps of reproducing the desired view is:
>    1 * header1
>   24 * header2
>  132 * header3
> 1019 * header4

You should be able to have this if you customize
display-line-numbers-width-start to a non-nil value.  Consider also
customizing display-line-numbers-grow-only to a non-nil value.

> * Details of implementation
> 
> I guess there is a problem with line's mode algorithm, from my side
> it looks like it taking into account only 1 digit difference for an
> identation, then if there is 2 or more digits differnece, then all
> after the first-digit diff identations are broken.

No, that's not what happens.  The problem is that the required width
of the line-number display needs to be calculated when the window is
about to be shown on display or redisplayed due to scrolling etc.  At
that time, the display-engine code which does this calculation cannot
know up front how many lines are hidden by 'invisible' text properties
and overlays, something that Org uses a lot, and therefore cannot
correctly estimate the largest line number to be shown.  So its
estimation of the maximum number of the line in the window are
incorrect in those cases.

Customizing display-line-numbers-width-start fixes that problem, for a
price of a slightly slower initial display of the window.  It could
still fail if you add a lot of lines to the buffer, in which case
toggling display-line-numbers-mode off and on again should fix it.

> The posible solution is to count total lines number and reserving
> line's numbers side width from total lines count number's width.

That's exactly what the above user option does, when non-nil.

There's no bug here.