summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2023-04-28 11:51:01 +0800
committerPo Lu <luangruo@yahoo.com>2023-04-28 11:51:01 +0800
commita97c382682b483b34351c6757e54e3139fa27f89 (patch)
tree497b1b52dd955f593a0a39f1032e3fd55aabcc35 /lisp
parentdbd74657908e67e2a5001fbe440fb2a01a2f01af (diff)
parenta40f18162377d2f9a78d7443fd0f8106c8c28c3d (diff)
downloademacs-a97c382682b483b34351c6757e54e3139fa27f89.tar.gz
Merge from origin/emacs-29
a40f1816237 Fix two crashes upon startup 44ebd9cbd56 Eglot: explain how to update Eglot in manual (bug#62720) 941ef044f2e Eglot: fix edge case when deleting inlay hint overlays a365984d9e1 package-upgrade[-all]: Expand docstrings to note the curr... f965f35b33b Rename all functions called package-*-update-* to package... 31b58161bb5 Fix FOR_EACH_TAIL in c-ts-mode (bug#62951) 0cf6e0998ba * Makefile.in (distclean): Remove the 'native-lisp' direc... 933705d61e5 Improve greek-ibycus4 input method # Conflicts: # etc/NEWS
Diffstat (limited to 'lisp')
-rw-r--r--lisp/emacs-lisp/package-vc.el18
-rw-r--r--lisp/emacs-lisp/package.el44
-rw-r--r--lisp/leim/quail/greek.el1
-rw-r--r--lisp/progmodes/c-ts-mode.el99
-rw-r--r--lisp/progmodes/eglot.el27
-rw-r--r--lisp/treesit.el17
6 files changed, 170 insertions, 36 deletions
diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el
index a72bb084d31..83d697a2e90 100644
--- a/lisp/emacs-lisp/package-vc.el
+++ b/lisp/emacs-lisp/package-vc.el
@@ -24,7 +24,7 @@
;; While packages managed by package.el use tarballs for distributing
;; the source code, this extension allows for packages to be fetched
-;; and updated directly from a version control system.
+;; and upgraded directly from a version control system.
;;
;; To install a package from source use `package-vc-install'. If you
;; aren't interested in activating a package, you can use
@@ -672,19 +672,19 @@ installed package."
#'string=)))
;;;###autoload
-(defun package-vc-update-all ()
- "Attempt to update all installed VC packages."
+(defun package-vc-upgrade-all ()
+ "Attempt to upgrade all installed VC packages."
(interactive)
(dolist (package package-alist)
(dolist (pkg-desc (cdr package))
(when (package-vc-p pkg-desc)
- (package-vc-update pkg-desc))))
- (message "Done updating packages."))
+ (package-vc-upgrade pkg-desc))))
+ (message "Done upgrading packages."))
;;;###autoload
-(defun package-vc-update (pkg-desc)
- "Attempt to update the package PKG-DESC."
- (interactive (list (package-vc--read-package-desc "Update VC package: " t)))
+(defun package-vc-upgrade (pkg-desc)
+ "Attempt to upgrade the package PKG-DESC."
+ (interactive (list (package-vc--read-package-desc "Upgrade VC package: " t)))
;; HACK: To run `package-vc--unpack-1' after checking out the new
;; revision, we insert a hook into `vc-post-command-functions', and
;; remove it right after it ran. To avoid running the hook multiple
@@ -882,7 +882,7 @@ Rebuilding an installation means scraping for new autoload
cookies, re-compiling Emacs Lisp files, building and installing
any documentation, downloading any missing dependencies. This
command does not fetch new revisions from a remote server. That
-is the responsibility of `package-vc-update'. Interactively,
+is the responsibility of `package-vc-upgrade'. Interactively,
prompt for the name of the package to rebuild."
(interactive (list (package-vc--read-package-desc "Rebuild package: " t)))
(package-vc--unpack-1 pkg-desc (package-desc-dir pkg-desc)))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 240ea10cbfc..65bb226acb1 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2259,24 +2259,28 @@ had been enabled."
(message "Package `%s' installed." name))
(message "`%s' is already installed" name))))
-(declare-function package-vc-update "package-vc" (pkg))
+(declare-function package-vc-upgrade "package-vc" (pkg))
;;;###autoload
-(defun package-update (name)
- "Update package NAME if a newer version exists."
+(defun package-upgrade (name)
+ "Upgrade package NAME if a newer version exists.
+
+Currently, packages which are part of the Emacs distribution
+cannot be upgraded that way. Use `i' after `M-x list-packages' to
+upgrade to an ELPA version first."
(interactive
(list (completing-read
- "Update package: " (package--updateable-packages) nil t)))
+ "Upgrade package: " (package--upgradeable-packages) nil t)))
(let* ((package (if (symbolp name)
name
(intern name)))
(pkg-desc (cadr (assq package package-alist))))
(if (package-vc-p pkg-desc)
- (package-vc-update pkg-desc)
+ (package-vc-upgrade pkg-desc)
(package-delete pkg-desc 'force)
(package-install package 'dont-select))))
-(defun package--updateable-packages ()
+(defun package--upgradeable-packages ()
;; Initialize the package system to get the list of package
;; symbols for completion.
(package--archives-initialize)
@@ -2294,23 +2298,27 @@ had been enabled."
package-alist)))
;;;###autoload
-(defun package-update-all (&optional query)
+(defun package-upgrade-all (&optional query)
"Refresh package list and upgrade all packages.
-If QUERY, ask the user before updating packages. When called
-interactively, QUERY is always true."
+If QUERY, ask the user before upgrading packages. When called
+interactively, QUERY is always true.
+
+Currently, packages which are part of the Emacs distribution are
+not upgraded that way. Use `i' after `M-x list-packages' to
+upgrade to an ELPA version first."
(interactive (list (not noninteractive)))
(package-refresh-contents)
- (let ((updateable (package--updateable-packages)))
- (if (not updateable)
- (message "No packages to update")
+ (let ((upgradeable (package--upgradeable-packages)))
+ (if (not upgradeable)
+ (message "No packages to upgrade")
(when (and query
(not (yes-or-no-p
- (if (length= updateable 1)
- "One package to update. Do it? "
- (format "%s packages to update. Do it?"
- (length updateable))))))
- (user-error "Updating aborted"))
- (mapc #'package-update updateable))))
+ (if (length= upgradeable 1)
+ "One package to upgrade. Do it? "
+ (format "%s packages to upgrade. Do it?"
+ (length upgradeable))))))
+ (user-error "Upgrade aborted"))
+ (mapc #'package-upgrade upgradeable))))
(defun package--dependencies (pkg)
"Return a list of all dependencies PKG has.
diff --git a/lisp/leim/quail/greek.el b/lisp/leim/quail/greek.el
index 107f4131e38..0829097af5f 100644
--- a/lisp/leim/quail/greek.el
+++ b/lisp/leim/quail/greek.el
@@ -1116,6 +1116,7 @@ nil t t nil nil nil nil nil nil nil t)
("'U" ?Ύ)
("`R" ?Ῥ)
+ ("(R" ?Ῥ)
("+`" ?῭) ; #x1fed
("+'" ?΅) ; #x1fee
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index bbc7979667c..353100ca1ce 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -357,7 +357,9 @@ PARENT, BOL, ARGS are the same as other anchor functions."
"Indent rules supported by `c-ts-mode'.
MODE is either `c' or `cpp'."
(let ((common
- `(((parent-is "translation_unit") column-0 0)
+ `((c-ts-mode--for-each-tail-body-matcher prev-line c-ts-mode-indent-offset)
+
+ ((parent-is "translation_unit") column-0 0)
((query "(ERROR (ERROR)) @indent") column-0 0)
((node-is ")") parent 1)
((node-is "]") parent-bol 0)
@@ -969,6 +971,81 @@ if `c-ts-mode-emacs-sources-support' is non-nil."
(or (treesit-add-log-current-defun)
(c-ts-mode--defun-name (c-ts-mode--emacs-defun-at-point))))
+;;; FOR_EACH_TAIL fix
+;;
+;; FOR_EACH_TAIL (and FOR_EACH_TAIL_SAFE) followed by a unbracketed
+;; body will mess up the parser, which parses the thing as a function
+;; declaration. We "fix" it by adding a shadow parser, emacs-c (which
+;; is just c but under a different name). We use emacs-c to find each
+;; FOR_EACH_TAIL with a unbracketed body, and set the ranges of the C
+;; parser so that it skips those FOR_EACH_TAIL's. Note that we only
+;; ignore FOR_EACH_TAIL's with a unbracketed body. Those with a
+;; bracketed body parses more or less fine.
+
+(defvar c-ts-mode--for-each-tail-regexp
+ (rx "FOR_EACH_" (or "TAIL" "TAIL_SAFE" "ALIST_VALUE"
+ "LIVE_BUFFER" "FRAME"))
+ "A regexp matching all the FOR_EACH_TAIL variants.")
+
+(defun c-ts-mode--for-each-tail-body-matcher (_n _p bol &rest _)
+ "A matcher that matches the first line after a FOR_EACH_TAIL.
+For BOL see `treesit-simple-indent-rules'."
+ (when c-ts-mode-emacs-sources-support
+ (save-excursion
+ (goto-char bol)
+ (forward-line -1)
+ (skip-chars-forward " \t")
+ (looking-at c-ts-mode--for-each-tail-regexp))))
+
+(defvar c-ts-mode--emacs-c-range-query
+ (treesit-query-compile
+ 'emacs-c `(((declaration
+ type: (macro_type_specifier
+ name: (identifier) @_name)
+ @for-each-tail)
+ (:match ,c-ts-mode--for-each-tail-regexp
+ @_name))))
+ "Query that finds the FOR_EACH_TAIL with a unbracketed body.")
+
+(defvar-local c-ts-mode--for-each-tail-ranges nil
+ "Ranges covering all the FOR_EACH_TAIL's in the buffer.")
+
+(defun c-ts-mode--reverse-ranges (ranges beg end)
+ "Reverse RANGES and return the new ranges between BEG and END.
+Positions that were included RANGES are not in the returned
+ranges, and vice versa.
+
+Return nil if RANGES is nil. This way, passing the returned
+ranges to `treesit-parser-set-included-ranges' will make the
+parser parse the whole buffer."
+ (if (null ranges)
+ nil
+ (let ((new-ranges nil)
+ (prev-end beg))
+ (dolist (range ranges)
+ (when (< prev-end (car range))
+ (push (cons prev-end (car range)) new-ranges))
+ (setq prev-end (cdr range)))
+ (when (< prev-end end)
+ (push (cons prev-end end) new-ranges))
+ (nreverse new-ranges))))
+
+(defun c-ts-mode--emacs-set-ranges (beg end)
+ "Set ranges for the C parser to skip some FOR_EACH_TAIL's.
+BEG and END are described in `treesit-range-rules'."
+ (let* ((c-parser (treesit-parser-create 'c))
+ (old-ranges c-ts-mode--for-each-tail-ranges)
+ (new-ranges (treesit-query-range
+ 'emacs-c c-ts-mode--emacs-c-range-query beg end))
+ (set-ranges (treesit--clip-ranges
+ (treesit--merge-ranges
+ old-ranges new-ranges beg end)
+ (point-min) (point-max)))
+ (reversed-ranges (c-ts-mode--reverse-ranges
+ set-ranges (point-min) (point-max))))
+ (setq-local c-ts-mode--for-each-tail-ranges set-ranges)
+ (treesit-parser-set-included-ranges c-parser reversed-ranges)))
+
;;; Modes
(defvar-keymap c-ts-base-mode-map
@@ -1101,6 +1178,17 @@ in your configuration."
:after-hook (c-ts-mode-set-modeline)
(when (treesit-ready-p 'c)
+ ;; Add a fake "emacs-c" language which is just C. Used for
+ ;; skipping FOR_EACH_TAIL, see `c-ts-mode--emacs-set-ranges'.
+ (setf (alist-get 'emacs-c treesit-load-name-override-list)
+ '("libtree-sitter-c" "tree_sitter_c"))
+ ;; If Emacs source support is enabled, make sure emacs-c parser is
+ ;; after c parser in the parser list. This way various tree-sitter
+ ;; functions will automatically use the c parser rather than the
+ ;; emacs-c parser.
+ (when c-ts-mode-emacs-sources-support
+ (treesit-parser-create 'emacs-c))
+
(treesit-parser-create 'c)
;; Comments.
(setq-local comment-start "/* ")
@@ -1114,9 +1202,16 @@ in your configuration."
(setq-local treesit-defun-tactic 'top-level)
(treesit-major-mode-setup)
+ ;; Emacs source support: handle DEFUN and FOR_EACH_TAIL gracefully.
(when c-ts-mode-emacs-sources-support
(setq-local add-log-current-defun-function
- #'c-ts-mode--emacs-current-defun-name))))
+ #'c-ts-mode--emacs-current-defun-name)
+
+ (setq-local treesit-range-settings
+ (treesit-range-rules 'c-ts-mode--emacs-set-ranges))
+
+ (setq-local treesit-language-at-point-function
+ (lambda (_pos) 'c)))))
;;;###autoload
(define-derived-mode c++-ts-mode c-ts-base-mode "C++"
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 3134d55fc08..6ae27a13845 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -2002,6 +2002,16 @@ If it is activated, also signal textDocument/didOpen."
(declare (obsolete info "1.10"))
(interactive) (info "(eglot)"))
+;;;###autoload
+(defun eglot-update (&rest _) "Update Eglot."
+ (interactive)
+ (with-no-warnings
+ (require 'package)
+ (unless package-archive-contents (package-refresh-contents))
+ (when-let ((existing (cadr (assoc 'eglot package-alist))))
+ (package-delete existing t))
+ (package-install (cadr (assoc 'eglot package-archive-contents)))))
+
(easy-menu-define eglot-menu nil "Eglot"
`("Eglot"
;; Commands for getting information and customization.
@@ -3129,8 +3139,7 @@ for which LSP on-type-formatting should be requested."
(funcall snippet-fn (or insertText label))))
(when (cl-plusp (length additionalTextEdits))
(eglot--apply-text-edits additionalTextEdits)))
- (eglot--signal-textDocument/didChange)
- (eldoc)))))))))
+ (eglot--signal-textDocument/didChange)))))))))
(defun eglot--hover-info (contents &optional _range)
(mapconcat #'eglot--format-markup
@@ -3743,7 +3752,19 @@ If NOERROR, return predicate, else erroring function."
:success-fn (lambda (hints)
(eglot--when-live-buffer buf
(eglot--widening
- (remove-overlays from to 'eglot--inlay-hint t)
+ ;; Overlays ending right at FROM with an
+ ;; `after-string' property logically belong to
+ ;; the (FROM TO) region. Likewise, such
+ ;; overlays ending at TO don't logically belong
+ ;; to it.
+ (dolist (o (overlays-in (1- from) to))
+ (when (and (overlay-get o 'eglot--inlay-hint)
+ (cond ((eq (overlay-end o) from)
+ (overlay-get o 'after-string))
+ ((eq (overlay-end o) to)
+ (overlay-get o 'before-string))
+ (t)))
+ (delete-overlay o)))
(mapc paint-hint hints))))
:deferred 'eglot--update-hints-1)))
diff --git a/lisp/treesit.el b/lisp/treesit.el
index b7af64ee8b5..1750929cc85 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -421,13 +421,16 @@ See `treesit-query-capture' for QUERY."
(defun treesit-query-range (node query &optional beg end)
"Query the current buffer and return ranges of captured nodes.
-QUERY, NODE, BEG, END are the same as in
-`treesit-query-capture'. This function returns a list
-of (START . END), where START and END specifics the range of each
-captured node. Capture names don't matter."
+QUERY, NODE, BEG, END are the same as in `treesit-query-capture'.
+This function returns a list of (START . END), where START and
+END specifics the range of each captured node. Capture names
+generally don't matter, but names that starts with an underscore
+are ignored."
(cl-loop for capture
in (treesit-query-capture node query beg end)
+ for name = (car capture)
for node = (cdr capture)
+ if (not (string-prefix-p "_" (symbol-name name)))
collect (cons (treesit-node-start node)
(treesit-node-end node))))
@@ -442,6 +445,9 @@ When updating the range of each parser in the buffer,
range to the range spanned by captured nodes. QUERY must be a
compiled query.
+Capture names generally don't matter, but names that starts with
+an underscore are ignored.
+
QUERY can also be a function, in which case it is called with 2
arguments, START and END. It should ensure parsers' ranges are
correct in the region between START and END.
@@ -461,6 +467,9 @@ like this:
Each QUERY is a tree-sitter query in either the string,
s-expression or compiled form.
+Capture names generally don't matter, but names that starts with
+an underscore are ignored.
+
For each QUERY, :KEYWORD and VALUE pairs add meta information to
it. For example,