diff options
author | Po Lu <luangruo@yahoo.com> | 2023-04-28 11:51:01 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2023-04-28 11:51:01 +0800 |
commit | a97c382682b483b34351c6757e54e3139fa27f89 (patch) | |
tree | 497b1b52dd955f593a0a39f1032e3fd55aabcc35 /lisp | |
parent | dbd74657908e67e2a5001fbe440fb2a01a2f01af (diff) | |
parent | a40f18162377d2f9a78d7443fd0f8106c8c28c3d (diff) | |
download | emacs-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.el | 18 | ||||
-rw-r--r-- | lisp/emacs-lisp/package.el | 44 | ||||
-rw-r--r-- | lisp/leim/quail/greek.el | 1 | ||||
-rw-r--r-- | lisp/progmodes/c-ts-mode.el | 99 | ||||
-rw-r--r-- | lisp/progmodes/eglot.el | 27 | ||||
-rw-r--r-- | lisp/treesit.el | 17 |
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, |