Function: eglot--after-change
eglot--after-change is a byte-compiled function defined in
eglot.el.gz.
Signature
(eglot--after-change BEG END PRE-CHANGE-LENGTH)
Documentation
Hook onto after-change-functions.
Records BEG, END and PRE-CHANGE-LENGTH locally.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/eglot.el.gz
(defun eglot--after-change (beg end pre-change-length)
"Hook onto `after-change-functions'.
Records BEG, END and PRE-CHANGE-LENGTH locally."
(cl-incf eglot--docver)
(pcase (car-safe eglot--recent-changes)
(`(,lsp-beg ,lsp-end
(,b-beg . ,b-beg-marker)
(,b-end . ,b-end-marker))
;; github#259 and github#367: with `capitalize-word' & friends,
;; `before-change-functions' records the whole word's `b-beg' and
;; `b-end'. Similarly, when `fill-paragraph' coalesces two
;; lines, `b-beg' and `b-end' mark end of first line and end of
;; second line, resp. In both situations, `beg' and `end'
;; received here seemingly contradict that: they will differ by 1
;; and encompass the capitalized character or, in the coalescing
;; case, the replacement of the newline with a space. We keep
;; both markers and positions to detect and correct this. In
;; this specific case, we ignore `beg', `len' and
;; `pre-change-len' and send richer information about the region
;; from the markers. I've also experimented with doing this
;; unconditionally but it seems to break when newlines are added.
(if (and (= b-end b-end-marker) (= b-beg b-beg-marker)
(or (/= beg b-beg) (/= end b-end)))
(setcar eglot--recent-changes
`(,lsp-beg ,lsp-end ,(- b-end-marker b-beg-marker)
,(buffer-substring-no-properties b-beg-marker
b-end-marker)))
(setcar eglot--recent-changes
`(,lsp-beg ,lsp-end ,pre-change-length
,(buffer-substring-no-properties beg end)))))
(_ (setf eglot--recent-changes :emacs-messup)))
;; JT@2025-11-14: Not 100% sure an idle timer is right to coalesce
;; multiple edits into a single didChange notification. It allows,
;; for example, user to modify the buffer in one place, spend
;; arbitrary time in quick successive movement and edit again. Only
;; after the idle delay will the change be sent. A regular timer
;; would be simpler would notify the server to start processing
;; changes sooner.
(when eglot--change-idle-timer (cancel-timer eglot--change-idle-timer))
(let ((buf (current-buffer)))
(setq eglot--change-idle-timer
(run-with-idle-timer
eglot-send-changes-idle-time
nil (lambda () (eglot--when-live-buffer buf
(when eglot--managed-mode
(eglot--signal-textDocument/didChange)
(setq eglot--change-idle-timer nil))))))))