emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/eglot2emacs 6dba74d8cb 051/120: Defend against broken move-to-co


From: João Távora
Subject: feature/eglot2emacs 6dba74d8cb 051/120: Defend against broken move-to-column in recent emacs
Date: Thu, 20 Oct 2022 07:16:52 -0400 (EDT)

branch: feature/eglot2emacs
commit 6dba74d8cb7e0172641ac6fdd7dfcd80bd22a1c4
Author: João Távora <joaotavora@gmail.com>
Commit: João Távora <joaotavora@gmail.com>

    Defend against broken move-to-column in recent emacs
    
    * eglot.el (eglot-lsp-abiding-column): Use (min (point) (point-max))
    
    This is a defensive fix for an Emacs/company-mode problem described
    below.
    
    The problem can be reproduced in Eglot before this commit with:
    
    ~/Source/Emacs/emacs/src/emacs -Q -f package-initialize -L       \
    ~/Source/Emacs/company-mode -l company -f global-company-mode -l \
     eglot.el ~/tmp/issue-860/args_out_of_range.c -f eglot -f        \
     display-line-numbers-mode -f toggle-debug-on-error
    
      1 // args_out_of_range.c
      2 struct Book {
      3   int id;
      4   char title[50]
      5 } book = { 1024, "C" };
      6
      7 int main(int argc, char *argv[])
      8 {
      9
     10   // Error when typing the dot to make "book."
     11   book
     12   return 0;
     13 }
    
    When one types the dot after the "book" on line 11, company-mode
    displays a two-line overlay that visually encompasses line 12 after
    "book", which has the "return 0;" statement.  That line happens to
    also hold a warning about incorrect syntax, one that starts at column
    2.
    
    Eglot uses 'move-to-column' to go that precise place.
    
    In Emacs 27.2, move-to-column is unaffected by previous company-mode
    overlays, even if the current line is being co-used visually by the
    overlay.  It moves to the right buffer position.
    
    In Emacs master, this isn't true.  It seems to be confounded by the
    company-mode overlay and moves to eob, which eventually breaks Eglot
    with a backtrace such as this one:
    
    Debugger entered--Lisp error: (args-out-of-range #<buffer 
args_out_of_range.c> 110 124)
      encode-coding-region(110 124 utf-16 t)
      (length (encode-coding-region (or lbp (line-beginning-position)) (point) 
'utf-16 t))
      (- (length (encode-coding-region (or lbp (line-beginning-position)) 
(point) 'utf-16 t)) 2)
      (/ (- (length (encode-coding-region (or lbp (line-beginning-position)) 
(point) 'utf-16 t)) 2) 2)
      eglot-lsp-abiding-column(110)
      (- column (eglot-lsp-abiding-column lbp))
      (setq diff (- column (eglot-lsp-abiding-column lbp)))
      (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 
diff)))
      (while (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not 
(= 0 diff))) (condition-case eob-err (forward-char (/ (if (> diff 0) (1+ diff) 
(1- diff)) 2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq 
--cl-var-- nil))
      (let* ((lbp (line-beginning-position)) (diff nil) (--cl-var-- t)) 
(narrow-to-region lbp (line-end-position)) (move-to-column column) (while 
(progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 diff))) 
(condition-case eob-err (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 
2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq --cl-var-- nil)) 
nil)
      (catch '--cl-block-nil-- (let* ((lbp (line-beginning-position)) (diff 
nil) (--cl-var-- t)) (narrow-to-region lbp (line-end-position)) (move-to-column 
column) (while (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) 
(not (= 0 diff))) (condition-case eob-err (forward-char (/ (if (> diff 0) (1+ 
diff) (1- diff)) 2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq 
--cl-var-- nil)) nil))
      (save-restriction (catch '--cl-block-nil-- (let* ((lbp 
(line-beginning-position)) (diff nil) (--cl-var-- t)) (narrow-to-region lbp 
(line-end-position)) (move-to-column column) (while (progn (setq diff (- column 
(eglot-lsp-abiding-column lbp))) (not (= 0 diff))) (condition-case eob-err 
(forward-char (/ (if ... ... ...) 2)) (end-of-buffer (throw '--cl-block-nil-- 
eob-err))) (setq --cl-var-- nil)) nil)))
      eglot-move-to-lsp-abiding-column(2)
    
    GitHub-reference: fix https://github.com/joaotavora/eglot/issues/860
---
 lisp/progmodes/eglot.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index ea9299ab59..3bd2d844c8 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1312,7 +1312,8 @@ fully LSP-compliant servers, this should be set to
   "Calculate current COLUMN as defined by the LSP spec.
 LBP defaults to `line-beginning-position'."
   (/ (- (length (encode-coding-region (or lbp (line-beginning-position))
-                                      (point) 'utf-16 t))
+                                      ;; Fix github#860
+                                      (min (point) (point-max)) 'utf-16 t))
         2)
      2))
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]