Subject: Re: bug#54488: 29.0.50; move-to-column/overlay-related regression in latest master, perhaps 28?

From: João Távora <[email-masked]>
Date: Tue, 22 Mar 2022 14:54:13 +0000

Eli Zaretskii <[email-masked]> writes:

> So I need your help with understanding what exactly fails in the
> original use case, due to this change.  Specifically, how does the
> code involved in this use move-to-column/current-column when there are
> display strings with embedded newlines around?

I think I alluded to/explained this in the original bug report.  I'll
try again: eglot needs just move-to-column that it runs in a narrowed
region containing only the line and obtain an upper bound of the
"LSP-abiding" column that the LSP server means (unfortunately the
LSP-abiding column may differ from Emacs's understanding of columns
because of different assumpting regarding length of character
encodings).

Eglot then gets (point) and tries "encode-coding-string" to measure
things.

In Emacs 29, before the fix, that (point) seems to -- very surprisingly
-- return something beyond the narrowed region and so
encode-coding-string will complain with args out of range.

In the example I gave you, that narrowed region, (point-max) is 176.

- that (point) form returns 179 in Emacs 29 -- error obviously.
- that (point) form returns 167 in Emacs 27 -- no error.

This is the code more or less in Eglot:

(defun eglot-move-to-lsp-abiding-column (column)
  "Move to COLUMN abiding by the LSP spec."
  (save-restriction
    (cl-loop
     with lbp = (line-beginning-position)
     initially
     (narrow-to-region lbp (line-end-position))
     (move-to-column column)
     for diff = (- column
                   (/ (- (length (encode-coding-region (or lbp (line-beginning-position))
                                      (point) 'utf-16 t))
                                  2)
                       2))
     until (zerop diff)
     do (condition-case eob-err
            (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2))
          (end-of-buffer (cl-return eob-err))))))

João