summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2024-05-05 17:23:29 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2024-05-05 17:23:29 -0400
commit44036b32ba398cf284320285b60be35874b6eea5 (patch)
tree019a497e96ecf456af98e561a784bd108499d1f3
parent1529ad0315f8d4a96ca07969c1c91c1c50bb6075 (diff)
downloademacs-44036b32ba398cf284320285b60be35874b6eea5.tar.gz
eglot.el: Require `track-changes` unconditionally
* lisp/emacs-lisp/track-changes.el: Bump version. * lisp/progmodes/eglot.el: Require `track-changes` unconditionally. (Package-Requires:): Add `track-changes`. (eglot--track-changes-signal, eglot--signal-textDocument/didChange) (eglot--managed-mode): Remove non-track-changes alternative code. (eglot--before-change, eglot--after-change): Delete functions.
-rw-r--r--lisp/emacs-lisp/track-changes.el8
-rw-r--r--lisp/progmodes/eglot.el94
2 files changed, 25 insertions, 77 deletions
diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el
index 6562cc7eb86..2824a70586d 100644
--- a/lisp/emacs-lisp/track-changes.el
+++ b/lisp/emacs-lisp/track-changes.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
-;; Version: 1.1
+;; Version: 1.2
;; Package-Requires: ((emacs "24"))
;; This file is part of GNU Emacs.
@@ -74,6 +74,12 @@
;; id (lambda (beg end before)
;; ..DO THE THING..))))))))
+;;; News:
+
+;; Since v1.1:
+;;
+;; - New function `track-changes-inconsistent-state-p'.
+
;;; Code:
;; Random ideas:
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 47d45a100f2..57a019e126d 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -7,7 +7,7 @@
;; Maintainer: João Távora <joaotavora@gmail.com>
;; URL: https://github.com/joaotavora/eglot
;; Keywords: convenience, languages
-;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.24") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1") (compat "27.1"))
+;; Package-Requires: ((emacs "26.3") (compat "27.1") (eldoc "1.14.0") (external-completion "0.1") (flymake "1.2.1") (jsonrpc "1.0.24") (project "0.9.8") (seq "2.23") (track-changes "1.2") (xref "1.6.2"))
;; This is a GNU ELPA :core package. Avoid adding functionality
;; that is not available in the version of Emacs recorded above or any
@@ -103,14 +103,12 @@
(require 'pcase)
(require 'compile) ; for some faces
(require 'warnings)
-(eval-when-compile
- (require 'subr-x))
(require 'filenotify)
(require 'ert)
(require 'text-property-search nil t)
(require 'diff-mode)
(require 'diff)
-(require 'track-changes nil t)
+(require 'track-changes)
(require 'compat)
;; These dependencies are also GNU ELPA core packages. Because of
@@ -135,6 +133,10 @@
;; the loaded file is not the one that should have been loaded.
(mapc reload '(project flymake xref jsonrpc external-completion))))
+;; Keep the eval-when-compile requires at the end, in case it's already been
+;; required unconditionally by some earlier `require'.
+(eval-when-compile (require 'subr-x))
+
;; forward-declare, but don't require (Emacs 28 doesn't seem to care)
(defvar markdown-fontify-code-blocks-natively)
(defvar company-backends)
@@ -1983,13 +1985,10 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
("utf-8"
(eglot--setq-saving eglot-current-linepos-function #'eglot-utf-8-linepos)
(eglot--setq-saving eglot-move-to-linepos-function #'eglot-move-to-utf-8-linepos)))
- (if (fboundp 'track-changes-register)
- (unless eglot--track-changes
- (setq eglot--track-changes
- (track-changes-register
- #'eglot--track-changes-signal :disjoint t)))
- (add-hook 'after-change-functions #'eglot--after-change nil t)
- (add-hook 'before-change-functions #'eglot--before-change nil t))
+ (unless eglot--track-changes
+ (setq eglot--track-changes
+ (track-changes-register
+ #'eglot--track-changes-signal :disjoint t)))
(add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t)
;; Prepend "didClose" to the hook after the "nonoff", so it will run first
(add-hook 'kill-buffer-hook #'eglot--signal-textDocument/didClose nil t)
@@ -2026,8 +2025,6 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
(when eglot--track-changes
(track-changes-unregister eglot--track-changes)
(setq eglot--track-changes nil))
- (remove-hook 'after-change-functions #'eglot--after-change t)
- (remove-hook 'before-change-functions #'eglot--before-change t)
(remove-hook 'kill-buffer-hook #'eglot--managed-mode-off t)
(remove-hook 'kill-buffer-hook #'eglot--signal-textDocument/didClose t)
(remove-hook 'before-revert-hook #'eglot--signal-textDocument/didClose t)
@@ -2607,7 +2604,7 @@ buffer."
`(:triggerKind 2 :triggerCharacter ,trigger) `(:triggerKind 1)))))
(defvar-local eglot--recent-changes nil
- "Recent buffer changes as collected by `eglot--before-change'.")
+ "Recent buffer changes as collected by `eglot--track-changes-fetch'.")
(cl-defmethod jsonrpc-connection-ready-p ((_server eglot-lsp-server) _what)
"Tell if SERVER is ready for WHAT in current buffer."
@@ -2615,56 +2612,9 @@ buffer."
(defvar-local eglot--change-idle-timer nil "Idle timer for didChange signals.")
-(defun eglot--before-change (beg end)
- "Hook onto `before-change-functions' with BEG and END."
- (when (listp eglot--recent-changes)
- ;; Records BEG and END, crucially convert them into LSP
- ;; (line/char) positions before that information is lost (because
- ;; the after-change thingy doesn't know if newlines were
- ;; deleted/added). Also record markers of BEG and END
- ;; (github#259)
- (push `(,(eglot--pos-to-lsp-position beg)
- ,(eglot--pos-to-lsp-position end)
- (,beg . ,(copy-marker beg nil))
- (,end . ,(copy-marker end t)))
- eglot--recent-changes)))
-
(defvar eglot--document-changed-hook '(eglot--signal-textDocument/didChange)
"Internal hook for doing things when the document changes.")
-(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--versioned-identifier)
- (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)))
- (eglot--track-changes-signal nil))
-
(defun eglot--track-changes-fetch (id)
(if (eq eglot--recent-changes :pending) (setq eglot--recent-changes nil))
(track-changes-fetch
@@ -2704,15 +2654,14 @@ Records BEG, END and PRE-CHANGE-LENGTH locally."
(lambda (buf)
(eglot--when-live-buffer buf
(when eglot--managed-mode
- (if (and (fboundp 'track-changes-inconsistent-state-p)
- (track-changes-inconsistent-state-p))
+ (if (track-changes-inconsistent-state-p)
;; Not a good time (e.g. in the middle of Quail thingy,
;; bug#70541): reschedule for the next idle period.
- (eglot--add-one-shot-hook
- 'post-command-hook
- (lambda ()
- (eglot--when-live-buffer buf
- (eglot--track-changes-signal id))))
+ (eglot--add-one-shot-hook
+ 'post-command-hook
+ (lambda ()
+ (eglot--when-live-buffer buf
+ (eglot--track-changes-signal id))))
(run-hooks 'eglot--document-changed-hook)
(setq eglot--change-idle-timer nil)))))
(current-buffer))))
@@ -2819,8 +2768,7 @@ When called interactively, use the currently active server"
(defun eglot--signal-textDocument/didChange ()
"Send textDocument/didChange to server."
- (when eglot--track-changes
- (eglot--track-changes-fetch eglot--track-changes))
+ (eglot--track-changes-fetch eglot--track-changes)
(when eglot--recent-changes
(let* ((server (eglot--current-server-or-lose))
(sync-capability (eglot-server-capable :textDocumentSync))
@@ -2838,12 +2786,6 @@ When called interactively, use the currently active server"
(buffer-substring-no-properties (point-min)
(point-max)))))
(cl-loop for (beg end len text) in (reverse eglot--recent-changes)
- ;; github#259: `capitalize-word' and commands based
- ;; on `casify_region' will cause multiple duplicate
- ;; empty entries in `eglot--before-change' calls
- ;; without an `eglot--after-change' reciprocal.
- ;; Weed them out here.
- when (numberp len) ;FIXME: Not needed with `track-changes'.
vconcat `[,(list :range `(:start ,beg :end ,end)
:rangeLength len :text text)]))))
(setq eglot--recent-changes nil)