diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index a5e1689b6c7..37da6b5956d 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -2745,10 +2745,12 @@ desktop reloading, since it bypasses the init file, where @findex desktop-revert You can have separate saved desktop configurations in different directories; starting Emacs from a directory where you have a saved -desktop configuration will restore that configuration. You can save -the current desktop and reload the one saved in another directory by -typing @kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert} -reverts to the previously reloaded desktop. +desktop configuration will restore that configuration, provided that +you customize @code{desktop-path} to prepend @file{.} (the current +directory) to the other directories there. You can save the current +desktop and reload the one saved in another directory by typing +@kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert} reverts +to the previously reloaded desktop. @vindex desktop-load-locked-desktop The file in which Emacs saves the desktop is locked while the diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 4c40f414ca0..fedb2804f26 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3688,8 +3688,8 @@ default, from @code{font-lock-function-name-face}. @vindex font-lock-variable-name-face for the name of a variable being defined or declared. -@item font-lock-variable-ref-face -@vindex font-lock-variable-ref-face +@item font-lock-variable-use-face +@vindex font-lock-variable-use-face for the name of a variable being referenced. This face inherits, by default, from @code{font-lock-variable-name-face}. @@ -3772,8 +3772,8 @@ for properties of an object, such as the declaration of fields in a struct. This face inherits, by default, from @code{font-lock-variable-name-face}. -@item font-lock-property-ref-face -@vindex font-lock-property-ref-face +@item font-lock-property-use-face +@vindex font-lock-property-use-face for properties of an object, such as use of fields in a struct. This face inherits, by default, from @code{font-lock-property-name-face}. @@ -5093,7 +5093,15 @@ This anchor is a function that is called with 3 arguments: @var{node}, @item parent-bol This anchor is a function that is called with 3 arguments: @var{node}, @var{parent}, and @var{bol}, and returns the first non-space character -on the line of @var{parent}. +on the line which @var{parent}'s start is on. + +@item parent-bol +This anchor is a function that is called with 3 arguments: @var{node}, +@var{parent}, and @var{bol}. It finds the first ancestor node +(parent, grandparent, etc) of @var{node} that starts on its own line, +and return the start of that node. ``Starting on its own line'' means +there is only whitespace character before the node on the line which +the node's start is on. @item prev-sibling This anchor is a function that is called with 3 arguments: @var{node}, diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index d513726979b..f0d3c75d055 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -14509,13 +14509,23 @@ Here's an example method that's more complex: @end example @table @code +@vindex nnimap-address @item nnimap-address The address of the server, like @samp{imap.gmail.com}. +@vindex nnimap-user +@item nnimap-user +Username to use for authentication to the @acronym{IMAP} server. This +corresponds to the value of the @samp{login} token in your +@file{~/.authinfo} file. Set this variable if you want to access +multiple accounts from the same @acronym{IMAP} server. + +@vindex nnimap-server-port @item nnimap-server-port If the server uses a non-standard port, that can be specified here. A typical port would be @code{"imap"} or @code{"imaps"}. +@vindex nnimap-stream @item nnimap-stream How @code{nnimap} should connect to the server. Possible values are: @@ -14546,6 +14556,7 @@ Non-encrypted and unsafe straight socket connection. @end table +@vindex nnimap-authenticator @item nnimap-authenticator Some @acronym{IMAP} servers allow anonymous logins. In that case, this should be set to @code{anonymous}. If this variable isn't set, @@ -14555,6 +14566,7 @@ specific login method to be used, you can set this variable to either @code{plain}, @code{cram-md5} or @code{xoauth2}. (The latter method requires using the @file{oauth2.el} library.) +@vindex nnimap-expunge @item nnimap-expunge When to expunge deleted messages. If @code{never}, deleted articles are marked with the IMAP @code{\\Delete} flag but not automatically @@ -14570,27 +14582,32 @@ EXPUNGE nil is equivalent to @code{never}, while t will immediately expunge ALL articles that are currently flagged as deleted (i.e., potentially not only the article that was just deleted). +@vindex nnimap-streaming @item nnimap-streaming Virtually all @acronym{IMAP} server support fast streaming of data. If you have problems connecting to the server, try setting this to @code{nil}. +@vindex nnimap-fetch-partial-articles @item nnimap-fetch-partial-articles If non-@code{nil}, fetch partial articles from the server. If set to a string, then it's interpreted as a regexp, and parts that have matching types will be fetched. For instance, @samp{"text/"} will fetch all textual parts, while leaving the rest on the server. +@vindex nnimap-record-commands @item nnimap-record-commands If non-@code{nil}, record all @acronym{IMAP} commands in the @samp{"*imap log*"} buffer. +@vindex nnimap-use-namespaces @item nnimap-use-namespaces If non-@code{nil}, omit the IMAP namespace prefix in nnimap group names. If your IMAP mailboxes are called something like @samp{INBOX} and @samp{INBOX.Lists.emacs}, but you'd like the nnimap group names to be @samp{INBOX} and @samp{Lists.emacs}, you should enable this option. +@vindex nnimap-keepalive-intervals @item nnimap-keepalive-intervals By default, nnimap will send occasional @samp{NOOP} (keepalive) commands to the server, to keep the connection alive. This option diff --git a/etc/NEWS.29 b/etc/NEWS.29 index 5a244285efa..b5e67d47037 100644 --- a/etc/NEWS.29 +++ b/etc/NEWS.29 @@ -832,8 +832,8 @@ These faces are primarily meant for use with tree-sitter. They are: 'font-lock-escape-face', 'font-lock-function-call-face', 'font-lock-misc-punctuation-face', 'font-lock-number-face', 'font-lock-operator-face', 'font-lock-property-name-face', -'font-lock-property-ref-face', 'font-lock-punctuation-face', -'font-lock-regexp-face', and 'font-lock-variable-ref-face'. +'font-lock-property-use-face', 'font-lock-punctuation-face', +'font-lock-regexp-face', and 'font-lock-variable-use-face'. +++ ** New face 'variable-pitch-text'. diff --git a/lisp/cus-theme.el b/lisp/cus-theme.el index 46e41dd046c..5d3f2585976 100644 --- a/lisp/cus-theme.el +++ b/lisp/cus-theme.el @@ -73,11 +73,11 @@ Do not call this mode function yourself. It is meant for internal use." font-lock-keyword-face font-lock-negation-char-face font-lock-number-face font-lock-misc-punctuation-face font-lock-operator-face font-lock-preprocessor-face - font-lock-property-name-face font-lock-property-ref-face + font-lock-property-name-face font-lock-property-use-face font-lock-punctuation-face font-lock-regexp-grouping-backslash font-lock-regexp-grouping-construct font-lock-string-face font-lock-type-face font-lock-variable-name-face - font-lock-variable-ref-face + font-lock-variable-use-face font-lock-warning-face button link link-visited fringe header-line tooltip mode-line mode-line-buffer-id mode-line-emphasis mode-line-highlight mode-line-inactive diff --git a/lisp/font-lock.el b/lisp/font-lock.el index b82b7648797..f8815c1698a 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -2046,7 +2046,7 @@ as the constructs of Haddock, Javadoc and similar systems." "Font Lock mode face used to highlight variable names." :group 'font-lock-faces) -(defface font-lock-variable-ref-face +(defface font-lock-variable-use-face '((t :inherit font-lock-variable-name-face)) "Font Lock mode face used to highlight variable references." :group 'font-lock-faces @@ -2134,7 +2134,7 @@ For example, the declaration of fields in a struct." :group 'font-lock-faces :version "29.1") -(defface font-lock-property-ref-face +(defface font-lock-property-use-face '((t :inherit font-lock-property-name-face)) "Font Lock mode face used to highlight property references. For example, property lookup of fields in a struct." diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 035df909eb2..8122115c102 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -77,6 +77,7 @@ (declare-function treesit-node-child "treesit.c") (declare-function treesit-node-child-by-field-name "treesit.c") (declare-function treesit-node-type "treesit.c") +(declare-function treesit-node-prev-sibling "treesit.c") ;;; Custom variables @@ -279,6 +280,12 @@ doesn't have a child." ;; prev-sibling doesn't have a child. (treesit-node-start prev-sibling))) +(defun c-ts-mode--standalone-grandparent (_node parent bol &rest args) + "Like the standalone-parent anchor but pass it the grandparent. +PARENT, BOL, ARGS are the same as other anchor functions." + (apply (alist-get 'standalone-parent treesit-simple-indent-presets) + parent (treesit-node-parent parent) bol args)) + (defun c-ts-mode--indent-styles (mode) "Indent rules supported by `c-ts-mode'. MODE is either `c' or `cpp'." @@ -300,9 +307,9 @@ MODE is either `c' or `cpp'." ((parent-is "comment") prev-adaptive-prefix 0) ;; Labels. - ((node-is "labeled_statement") parent-bol 0) + ((node-is "labeled_statement") standalone-parent 0) ((parent-is "labeled_statement") - point-min c-ts-common-statement-offset) + c-ts-mode--standalone-grandparent c-ts-mode-indent-offset) ((node-is "preproc") point-min 0) ((node-is "#endif") point-min 0) @@ -330,7 +337,7 @@ MODE is either `c' or `cpp'." ;; Closing bracket. This should be before initializer_list ;; (and probably others) rule because that rule (and other ;; similar rules) will match the closing bracket. (Bug#61398) - ((node-is "}") point-min c-ts-common-statement-offset) + ((node-is "}") standalone-parent 0) ,@(when (eq mode 'cpp) '(((node-is "access_specifier") parent-bol 0) ;; Indent the body of namespace definitions. @@ -341,25 +348,25 @@ MODE is either `c' or `cpp'." ((match nil "initializer_list" nil 1 1) parent-bol c-ts-mode-indent-offset) ((match nil "initializer_list" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Statement in enum. - ((match nil "enumerator_list" nil 1 1) point-min c-ts-common-statement-offset) + ((match nil "enumerator_list" nil 1 1) standalone-parent c-ts-mode-indent-offset) ((match nil "enumerator_list" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Statement in struct and union. - ((match nil "field_declaration_list" nil 1 1) point-min c-ts-common-statement-offset) + ((match nil "field_declaration_list" nil 1 1) standalone-parent c-ts-mode-indent-offset) ((match nil "field_declaration_list" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Statement in {} blocks. - ((match nil "compound_statement" nil 1 1) point-min c-ts-common-statement-offset) + ((match nil "compound_statement" nil 1 1) standalone-parent c-ts-mode-indent-offset) ((match nil "compound_statement" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Opening bracket. - ((node-is "compound_statement") point-min c-ts-common-statement-offset) + ((node-is "compound_statement") standalone-parent c-ts-mode-indent-offset) ;; Bug#61291. - ((match "expression_statement" nil "body") point-min c-ts-common-statement-offset) + ((match "expression_statement" nil "body") standalone-parent c-ts-mode-indent-offset) ;; These rules are for cases where the body is bracketless. ;; Tested by the "Bracketless Simple Statement" test. - ((parent-is "if_statement") point-min c-ts-common-statement-offset) - ((parent-is "for_statement") point-min c-ts-common-statement-offset) - ((parent-is "while_statement") point-min c-ts-common-statement-offset) - ((parent-is "do_statement") point-min c-ts-common-statement-offset) + ((parent-is "if_statement") standalone-parent c-ts-mode-indent-offset) + ((parent-is "for_statement") standalone-parent c-ts-mode-indent-offset) + ((parent-is "while_statement") standalone-parent c-ts-mode-indent-offset) + ((parent-is "do_statement") standalone-parent c-ts-mode-indent-offset) ,@(when (eq mode 'cpp) `(((node-is "field_initializer_list") parent-bol ,(* c-ts-mode-indent-offset 2))))))) @@ -388,16 +395,13 @@ MODE is either `c' or `cpp'." ((parent-is "do_statement") parent-bol 0) ,@common)))) -(defun c-ts-mode--top-level-label-matcher (node &rest _) +(defun c-ts-mode--top-level-label-matcher (node parent &rest _) "A matcher that matches a top-level label. -NODE should be a labeled_statement." - (let ((func (treesit-parent-until - node (lambda (n) - (equal (treesit-node-type n) - "compound_statement"))))) - (and (equal (treesit-node-type node) - "labeled_statement") - (not (treesit-node-top-level func "compound_statement"))))) +NODE should be a labeled_statement. PARENT is its parent." + (and (equal (treesit-node-type node) + "labeled_statement") + (equal "function_definition" + (treesit-node-type (treesit-node-parent parent))))) ;;; Font-lock @@ -543,7 +547,7 @@ MODE is either `c' or `cpp'." '((assignment_expression left: (identifier) @font-lock-variable-name-face) (assignment_expression - left: (field_expression field: (_) @font-lock-property-ref-face)) + left: (field_expression field: (_) @font-lock-property-use-face)) (assignment_expression left: (pointer_expression (identifier) @font-lock-variable-name-face)) @@ -579,7 +583,7 @@ MODE is either `c' or `cpp'." :language mode :feature 'property - '((field_identifier) @font-lock-property-ref-face) + '((field_identifier) @font-lock-property-use-face) :language mode :feature 'bracket @@ -656,7 +660,7 @@ OVERRIDE, START, END, and ARGS, see `treesit-font-lock-rules'." "call_expression")) (treesit-fontify-with-override (treesit-node-start node) (treesit-node-end node) - 'font-lock-variable-ref-face override start end))) + 'font-lock-variable-use-face override start end))) (defun c-ts-mode--fontify-defun (node override start end &rest _) "Correctly fontify the DEFUN macro. @@ -867,6 +871,8 @@ the semicolon. This function skips the semicolon." (when (eq c-ts-mode-indent-style 'linux) (setq-local indent-tabs-mode t)) (setq-local c-ts-common-indent-offset 'c-ts-mode-indent-offset) + ;; This setup is not needed anymore, but we might find uses for it + ;; later, so I'm keeping it. (setq-local c-ts-common-indent-type-regexp-alist `((block . ,(rx (or "compound_statement" "field_declaration_list" diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el index a3f9279ec1c..d83a956af21 100644 --- a/lisp/progmodes/cmake-ts-mode.el +++ b/lisp/progmodes/cmake-ts-mode.el @@ -154,7 +154,7 @@ :language 'cmake :feature 'variable :override t - '((variable) @font-lock-variable-ref-face) + '((variable) @font-lock-variable-use-face) :language 'cmake :feature 'error diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 4ed8b0368b5..ea4977254ce 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -708,9 +708,9 @@ compilation and evaluation time conflicts." (treesit-font-lock-rules :language 'c-sharp :feature 'expression - '((conditional_expression (identifier) @font-lock-variable-ref-face) - (postfix_unary_expression (identifier)* @font-lock-variable-ref-face) - (initializer_expression (assignment_expression left: (identifier) @font-lock-variable-ref-face))) + '((conditional_expression (identifier) @font-lock-variable-use-face) + (postfix_unary_expression (identifier)* @font-lock-variable-use-face) + (initializer_expression (assignment_expression left: (identifier) @font-lock-variable-use-face))) :language 'c-sharp :feature 'bracket @@ -739,8 +739,8 @@ compilation and evaluation time conflicts." :language 'c-sharp :override t :feature 'property - `((attribute (identifier) @font-lock-property-ref-face (attribute_argument_list)) - (attribute (identifier) @font-lock-property-ref-face)) + `((attribute (identifier) @font-lock-property-use-face (attribute_argument_list)) + (attribute (identifier) @font-lock-property-use-face)) :language 'c-sharp :override t @@ -878,23 +878,23 @@ compilation and evaluation time conflicts." :override t '((if_directive "if" @font-lock-preprocessor-face - (identifier) @font-lock-variable-ref-face) + (identifier) @font-lock-variable-use-face) (elif_directive "elif" @font-lock-preprocessor-face - (identifier) @font-lock-variable-ref-face) + (identifier) @font-lock-variable-use-face) (else_directive) @font-lock-preprocessor-face (endif_directive) @font-lock-preprocessor-face (define_directive "define" @font-lock-preprocessor-face - (identifier) @font-lock-variable-ref-face) + (identifier) @font-lock-variable-use-face) (nullable_directive) @font-lock-preprocessor-face (pragma_directive) @font-lock-preprocessor-face (region_directive) @font-lock-preprocessor-face (endregion_directive) @font-lock-preprocessor-face (region_directive - (preproc_message) @font-lock-variable-ref-face) + (preproc_message) @font-lock-variable-use-face) (endregion_directive - (preproc_message) @font-lock-variable-ref-face)))) + (preproc_message) @font-lock-variable-use-face)))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode)) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 4203e4a336e..0a3189a0263 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -486,7 +486,8 @@ This can be useful when using docker to run a language server.") (WorkspaceEdit () (:changes :documentChanges)) (WorkspaceSymbol (:name :kind) (:containerName :location :data)) (InlayHint (:position :label) (:kind :textEdits :tooltip :paddingLeft - :paddingRight :data))) + :paddingRight :data)) + (InlayHintLabelPart (:value) (:tooltip :location :command))) "Alist (INTERFACE-NAME . INTERFACE) of known external LSP interfaces. INTERFACE-NAME is a symbol designated by the spec as @@ -641,7 +642,7 @@ Honor `eglot-strict-mode'." Honor `eglot-strict-mode'." (declare (indent 1) (debug (sexp &rest form))) (let ((e (cl-gensym "jsonrpc-lambda-elem"))) - `(lambda (,e) (eglot--dbind ,cl-lambda-list ,e ,@body)))) + `(lambda (,e) (cl-block nil (eglot--dbind ,cl-lambda-list ,e ,@body))))) (cl-defmacro eglot--dcase (obj &rest clauses) "Like `pcase', but for the LSP object OBJ. @@ -1440,6 +1441,12 @@ CONNECT-ARGS are passed as additional arguments to (let ((warning-minimum-level :error)) (display-warning 'eglot (apply #'format format args) :warning))) +(defalias 'eglot--bol + (if (fboundp 'pos-bol) #'pos-bol + (lambda (&optional n) (let ((inhibit-field-text-motion t)) + (line-beginning-position n)))) + "Return position of first character in current line.") + ;;; Encoding fever ;;; @@ -1453,21 +1460,24 @@ CONNECT-ARGS are passed as additional arguments to (defvar eglot-current-linepos-function #'eglot-utf-16-linepos "Function calculating position relative to line beginning. -This is the inverse of `eglot-move-to-linepos-function' (which see). -It is a function of no arguments returning the number of code units -or bytes or codepoints corresponding to the current position of point, -relative to line beginning, as expected by the function that is the -value of `eglot-move-to-linepos-function'.") +It is a function of no arguments considering the text from line +beginning up to current point. The return value is the number of +UTF code units needed to encode that text from the LSP server's +perspective. This may be a number of octets, 16-bit words or +Unicode code points, depending on whether the LSP server's +`positionEncoding' capability is UTF-8, UTF-16 or UTF-32, +respectively. Position of point should remain unaltered if that +return value is fed through the corresponding inverse function +`eglot-move-to-linepos-function' (which see).") (defun eglot-utf-8-linepos () "Calculate number of UTF-8 bytes from line beginning." - (length (encode-coding-region (line-beginning-position) (point) - 'utf-8-unix t))) + (length (encode-coding-region (eglot--bol) (point) 'utf-8-unix t))) (defun eglot-utf-16-linepos (&optional lbp) "Calculate number of UTF-16 code units from position given by LBP. -LBP defaults to `line-beginning-position'." - (/ (- (length (encode-coding-region (or lbp (line-beginning-position)) +LBP defaults to `eglot--bol'." + (/ (- (length (encode-coding-region (or lbp (eglot--bol)) ;; Fix github#860 (min (point) (point-max)) 'utf-16 t)) 2) @@ -1475,7 +1485,7 @@ LBP defaults to `line-beginning-position'." (defun eglot-utf-32-linepos () "Calculate number of Unicode codepoints from line beginning." - (- (point) (line-beginning-position))) + (- (point) (eglot--bol))) (defun eglot--pos-to-lsp-position (&optional pos) "Convert point POS to LSP position." @@ -1509,7 +1519,7 @@ encoding and Eglot will set this variable automatically.") (defun eglot-move-to-utf-8-linepos (n) "Move to line's Nth byte as computed by LSP's UTF-8 criterion." - (let* ((bol (line-beginning-position)) + (let* ((bol (eglot--bol)) (goal-byte (+ (position-bytes bol) n)) (eol (line-end-position))) (goto-char bol) @@ -1520,7 +1530,7 @@ encoding and Eglot will set this variable automatically.") (defun eglot-move-to-utf-16-linepos (n) "Move to line's Nth code unit as computed by LSP's UTF-16 criterion." - (let* ((bol (line-beginning-position)) + (let* ((bol (eglot--bol)) (goal-char (+ bol n)) (eol (line-end-position))) (goto-char bol) @@ -1535,8 +1545,7 @@ encoding and Eglot will set this variable automatically.") ;; columns, which can be different from LSP characters in case of ;; `whitespace-mode', `prettify-symbols-mode', etc. (github#296, ;; github#297) - (goto-char (min (+ (line-beginning-position) n) - (line-end-position)))) + (goto-char (min (+ (eglot--bol) n) (line-end-position)))) (defun eglot--lsp-position-to-point (pos-plist &optional marker) "Convert LSP position POS-PLIST to Emacs point. @@ -2186,7 +2195,7 @@ COMMAND is a symbol naming the command." (eglot--widening (goto-char (point-min)) (setq beg - (line-beginning-position + (eglot--bol (1+ (plist-get (plist-get range :start) :line)))) (setq end (line-end-position @@ -2626,7 +2635,7 @@ Try to visit the target file for a richer summary line." (collect (lambda () (eglot--widening (pcase-let* ((`(,beg . ,end) (eglot--range-region range)) - (bol (progn (goto-char beg) (line-beginning-position))) + (bol (progn (goto-char beg) (eglot--bol))) (substring (buffer-substring bol (line-end-position))) (hi-beg (- beg bol)) (hi-end (- (min (line-end-position) end) bol))) @@ -2977,7 +2986,7 @@ for which LSP on-type-formatting should be requested." (looking-back (regexp-opt (cl-coerce (cl-getf completion-capability :triggerCharacters) 'list)) - (line-beginning-position)))) + (eglot--bol)))) :exit-function (lambda (proxy status) (when (memq status '(finished exact)) @@ -3587,20 +3596,30 @@ If NOERROR, return predicate, else erroring function." (paint-hint (eglot--lambda ((InlayHint) position kind label paddingLeft paddingRight) (goto-char (eglot--lsp-position-to-point position)) - (let ((ov (make-overlay (point) (point))) - (left-pad (and paddingLeft (not (memq (char-before) '(32 9))))) - (right-pad (and paddingRight (not (memq (char-after) '(32 9))))) - (text (if (stringp label) - label (plist-get (elt label 0) :value)))) - (overlay-put ov 'before-string - (propertize - (concat (and left-pad " ") text (and right-pad " ")) - 'face (pcase kind - (1 'eglot-type-hint-face) - (2 'eglot-parameter-hint-face) - (_ 'eglot-inlay-hint-face)))) - (overlay-put ov 'eglot--inlay-hint t) - (overlay-put ov 'eglot--overlay t))))) + (when (or (> (point) to) (< (point) from)) (cl-return)) + (let ((left-pad (and paddingLeft + (not (memq (char-before) '(32 9))) " ")) + (right-pad (and paddingRight + (not (memq (char-after) '(32 9))) " "))) + (cl-flet + ((do-it (text lpad rpad) + (let ((ov (make-overlay (point) (point)))) + (overlay-put ov 'before-string + (propertize + (concat lpad text rpad) + 'face (pcase kind + (1 'eglot-type-hint-face) + (2 'eglot-parameter-hint-face) + (_ 'eglot-inlay-hint-face)))) + (overlay-put ov 'eglot--inlay-hint t) + (overlay-put ov 'eglot--overlay t)))) + (if (stringp label) (do-it label left-pad right-pad) + (cl-loop + for i from 0 for ldetail across label + do (eglot--dbind ((InlayHintLabelPart) value) ldetail + (do-it value + (and (zerop i) left-pad) + (and (= i (1- (length label))) right-pad)))))))))) (jsonrpc-async-request (eglot--current-server-or-lose) :textDocument/inlayHint diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index 0e019f5bad9..ce77cc3973d 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -178,12 +178,12 @@ :language 'go :feature 'property - '((selector_expression field: (field_identifier) @font-lock-property-ref-face) - (keyed_element (_ (identifier) @font-lock-property-ref-face))) + '((selector_expression field: (field_identifier) @font-lock-property-use-face) + (keyed_element (_ (identifier) @font-lock-property-use-face))) :language 'go :feature 'variable - '((identifier) @font-lock-variable-ref-face) + '((identifier) @font-lock-variable-use-face) :language 'go :feature 'escape-sequence diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 54ed8b4277d..d31d2d71c38 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -244,7 +244,7 @@ name: (identifier) @font-lock-variable-name-face) (element_value_pair - key: (identifier) @font-lock-property-ref-face) + key: (identifier) @font-lock-property-use-face) (formal_parameter name: (identifier) @font-lock-variable-name-face) @@ -255,14 +255,14 @@ :override t :feature 'expression '((method_invocation - object: (identifier) @font-lock-variable-ref-face) + object: (identifier) @font-lock-variable-use-face) (method_invocation name: (identifier) @font-lock-function-call-face) (argument_list (identifier) @font-lock-variable-name-face) - (expression_statement (identifier) @font-lock-variable-ref-face)) + (expression_statement (identifier) @font-lock-variable-use-face)) :language 'java :feature 'bracket diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 93298f4fb6e..f68ecb6fa6c 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3563,13 +3563,13 @@ This function is intended for use in `after-change-functions'." :language 'javascript :feature 'property - '(((property_identifier) @font-lock-property-ref-face + '(((property_identifier) @font-lock-property-use-face (:pred js--treesit-property-not-function-p - @font-lock-property-ref-face)) + @font-lock-property-use-face)) - (pair value: (identifier) @font-lock-variable-ref-face) + (pair value: (identifier) @font-lock-variable-use-face) - ((shorthand_property_identifier) @font-lock-property-ref-face)) + ((shorthand_property_identifier) @font-lock-property-use-face)) :language 'javascript :feature 'assignment @@ -3681,8 +3681,8 @@ For OVERRIDE, START, END, see `treesit-font-lock-rules'." (treesit-fontify-with-override (treesit-node-start node) (treesit-node-end node) (pcase (treesit-node-type node) - ("identifier" 'font-lock-variable-ref-face) - ("property_identifier" 'font-lock-property-ref-face)) + ("identifier" 'font-lock-variable-use-face) + ("property_identifier" 'font-lock-property-use-face)) override start end))) (defun js--treesit-defun-name (node) diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el index c5979b9a14c..f56d118c0fe 100644 --- a/lisp/progmodes/json-ts-mode.el +++ b/lisp/progmodes/json-ts-mode.el @@ -101,7 +101,7 @@ :language 'json :feature 'pair :override t ; Needed for overriding string face on keys. - '((pair key: (_) @font-lock-property-ref-face)) + '((pair key: (_) @font-lock-property-use-face)) :language 'json :feature 'error :override t diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 5aab31c3ea8..1f970633bfc 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1147,7 +1147,7 @@ fontified." @font-lock-variable-name-face) (assignment left: (attribute attribute: (identifier) - @font-lock-property-ref-face)) + @font-lock-property-use-face)) (pattern_list (identifier) @font-lock-variable-name-face) (tuple_pattern (identifier) @@ -1184,12 +1184,12 @@ fontified." :feature 'property :language 'python '((attribute - attribute: (identifier) @font-lock-property-ref-face) + attribute: (identifier) @font-lock-property-use-face) (class_definition body: (block (expression_statement (assignment left: - (identifier) @font-lock-property-ref-face))))) + (identifier) @font-lock-property-use-face))))) :feature 'operator :language 'python diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index f70c0279d3d..4530b162e6e 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -292,11 +292,11 @@ values of OVERRIDE" :language language :feature 'global - '((global_variable) @font-lock-variable-ref-face) + '((global_variable) @font-lock-variable-use-face) :language language :feature 'instance - '((instance_variable) @font-lock-variable-ref-face) + '((instance_variable) @font-lock-variable-use-face) :language language :feature 'method-definition diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index a46d442a0e5..2d5c3211c1a 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -239,8 +239,8 @@ :language 'rust :feature 'property - '((field_identifier) @font-lock-property-ref-face - (shorthand_field_initializer (identifier) @font-lock-property-ref-face)) + '((field_identifier) @font-lock-property-use-face + (shorthand_field_initializer (identifier) @font-lock-property-use-face)) ;; Must be under type, otherwise some imports can be highlighted as constants. :language 'rust @@ -251,25 +251,25 @@ :language 'rust :feature 'variable - '((arguments (identifier) @font-lock-variable-ref-face) - (array_expression (identifier) @font-lock-variable-ref-face) - (assignment_expression right: (identifier) @font-lock-variable-ref-face) - (binary_expression left: (identifier) @font-lock-variable-ref-face) - (binary_expression right: (identifier) @font-lock-variable-ref-face) - (block (identifier) @font-lock-variable-ref-face) - (compound_assignment_expr right: (identifier) @font-lock-variable-ref-face) - (field_expression value: (identifier) @font-lock-variable-ref-face) - (field_initializer value: (identifier) @font-lock-variable-ref-face) - (if_expression condition: (identifier) @font-lock-variable-ref-face) - (let_condition value: (identifier) @font-lock-variable-ref-face) - (let_declaration value: (identifier) @font-lock-variable-ref-face) - (match_arm value: (identifier) @font-lock-variable-ref-face) - (match_expression value: (identifier) @font-lock-variable-ref-face) - (reference_expression value: (identifier) @font-lock-variable-ref-face) - (return_expression (identifier) @font-lock-variable-ref-face) - (tuple_expression (identifier) @font-lock-variable-ref-face) - (unary_expression (identifier) @font-lock-variable-ref-face) - (while_expression condition: (identifier) @font-lock-variable-ref-face)) + '((arguments (identifier) @font-lock-variable-use-face) + (array_expression (identifier) @font-lock-variable-use-face) + (assignment_expression right: (identifier) @font-lock-variable-use-face) + (binary_expression left: (identifier) @font-lock-variable-use-face) + (binary_expression right: (identifier) @font-lock-variable-use-face) + (block (identifier) @font-lock-variable-use-face) + (compound_assignment_expr right: (identifier) @font-lock-variable-use-face) + (field_expression value: (identifier) @font-lock-variable-use-face) + (field_initializer value: (identifier) @font-lock-variable-use-face) + (if_expression condition: (identifier) @font-lock-variable-use-face) + (let_condition value: (identifier) @font-lock-variable-use-face) + (let_declaration value: (identifier) @font-lock-variable-use-face) + (match_arm value: (identifier) @font-lock-variable-use-face) + (match_expression value: (identifier) @font-lock-variable-use-face) + (reference_expression value: (identifier) @font-lock-variable-use-face) + (return_expression (identifier) @font-lock-variable-use-face) + (tuple_expression (identifier) @font-lock-variable-use-face) + (unary_expression (identifier) @font-lock-variable-use-face) + (while_expression condition: (identifier) @font-lock-variable-use-face)) :language 'rust :feature 'escape-sequence diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index d907608d0db..ca6fd2c09da 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -249,9 +249,9 @@ Argument LANGUAGE is either `typescript' or `tsx'." (public_field_definition name: (property_identifier) @font-lock-property-name-face) - (pair key: (property_identifier) @font-lock-property-ref-face) + (pair key: (property_identifier) @font-lock-property-use-face) - ((shorthand_property_identifier) @font-lock-property-ref-face)) + ((shorthand_property_identifier) @font-lock-property-use-face)) :language language :feature 'expression @@ -272,7 +272,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." :language language :feature 'pattern `((pair_pattern - key: (property_identifier) @font-lock-property-ref-face + key: (property_identifier) @font-lock-property-use-face value: [(identifier) @font-lock-variable-name-face (assignment_pattern left: (identifier) @font-lock-variable-name-face)]) diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 39e38179359..f51edfb4c80 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -1399,8 +1399,8 @@ for determining whether point is within a selector." :feature 'query :language 'css - '((keyword_query) @font-lock-property-ref-face - (feature_name) @font-lock-property-ref-face) + '((keyword_query) @font-lock-property-use-face + (feature_name) @font-lock-property-use-face) :feature 'bracket :language 'css diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el index 2ff9d07d13b..2c491034372 100644 --- a/lisp/textmodes/toml-ts-mode.el +++ b/lisp/textmodes/toml-ts-mode.el @@ -92,8 +92,8 @@ :language 'toml :feature 'pair :override t ; Needed for overriding string face on keys. - '((bare_key) @font-lock-property-ref-face - (quoted_key) @font-lock-property-ref-face + '((bare_key) @font-lock-property-use-face + (quoted_key) @font-lock-property-use-face (table ("[" @font-lock-bracket-face (_) @font-lock-type-face "]" @font-lock-bracket-face)) diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el index dc0fa00df27..dfa8d22fb34 100644 --- a/lisp/textmodes/yaml-ts-mode.el +++ b/lisp/textmodes/yaml-ts-mode.el @@ -94,22 +94,22 @@ :feature 'property :override t '((block_mapping_pair - key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face))) + key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face))) (block_mapping_pair key: (flow_node - [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face)) + [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face)) (flow_mapping - (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face)))) + (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face)))) (flow_mapping (_ key: (flow_node - [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face))) + [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face))) (flow_sequence - (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face)))) + (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face)))) (flow_sequence (_ key: (flow_node - [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face)))) + [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face)))) :language 'yaml :feature 'error diff --git a/lisp/treesit.el b/lisp/treesit.el index a413311e824..9e639149ce0 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1227,6 +1227,16 @@ See `treesit-simple-indent-presets'.") (goto-char (treesit-node-start parent)) (back-to-indentation) (point)))) + (cons 'standalone-parent + (lambda (_n parent &rest _) + (save-excursion + (catch 'term + (while parent + (goto-char (treesit-node-start parent)) + (when (looking-back (rx bol (* whitespace)) + (line-beginning-position)) + (throw 'term (point))) + (setq parent (treesit-node-parent parent))))))) (cons 'prev-sibling (lambda (node &rest _) (treesit-node-start (treesit-node-prev-sibling node)))) @@ -1323,6 +1333,11 @@ parent-bol Returns the beginning of non-space characters on the line where PARENT is on. +standalone-parent + + Finds the first ancestor node (parent, grandparent, etc) that + starts on its own line, and return the start of that node. + prev-sibling Returns the start of NODE's previous sibling. @@ -1854,10 +1869,23 @@ This is a tree-sitter equivalent of `beginning-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and `treesit-defun-skipper'." (interactive "^p") - (when (treesit-beginning-of-thing treesit-defun-type-regexp arg) - (when treesit-defun-skipper - (funcall treesit-defun-skipper)) - t)) + (let ((orig-point (point)) + (success nil)) + (catch 'done + (dotimes (_ 2) + + (when (treesit-beginning-of-thing treesit-defun-type-regexp arg) + (when treesit-defun-skipper + (funcall treesit-defun-skipper) + (setq success t))) + + ;; If we end up at the same point, it means we went to the + ;; next beg-of-defun, but defun skipper moved point back to + ;; where we started, in this case we just move one step + ;; further. + (if (or (eq arg 0) (not (eq orig-point (point)))) + (throw 'done success) + (setq arg (if (> arg 0) (1+ arg) (1- arg)))))))) (defun treesit-end-of-defun (&optional arg _) "Move forward to next end of defun. @@ -1869,9 +1897,21 @@ This is a tree-sitter equivalent of `end-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and `treesit-defun-skipper'." (interactive "^p\nd") - (when (treesit-end-of-thing treesit-defun-type-regexp arg) - (when treesit-defun-skipper - (funcall treesit-defun-skipper)))) + (let ((orig-point (point))) + (catch 'done + (dotimes (_ 2) ; Not making progress is better than infloop. + + (when (treesit-end-of-thing treesit-defun-type-regexp arg) + (when treesit-defun-skipper + (funcall treesit-defun-skipper))) + + ;; If we end up at the same point, it means we went to the + ;; prev end-of-defun, but defun skipper moved point back to + ;; where we started, in this case we just move one step + ;; further. + (if (or (eq arg 0) (not (eq orig-point (point)))) + (throw 'done nil) + (setq arg (if (> arg 0) (1+ arg) (1- arg)))))))) (defvar-local treesit-text-type-regexp "\\`comment\\'" "A regexp that matches the node type of textual nodes. @@ -2027,9 +2067,9 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'." ;; ;; prev-end (tricky): ;; 1. prev-sibling exists -;; -> If you think about it, we are already at prev-sibling's end! -;; So we need to go one step further, either to -;; prev-prev-sibling's end, or parent's prev-sibling's end, etc. +;; -> If we are already at prev-sibling's end, we need to go one +;; step further, either to prev-prev-sibling's end, or parent's +;; prev-sibling's end, etc. ;; 2. prev-sibling is nil but parent exists ;; -> Obviously we don't want to go to parent's end, instead, we ;; want to go to parent's prev-sibling's end. Again, we recurse @@ -2079,18 +2119,24 @@ function is called recursively." ;; ...forward. (if (and (eq side 'beg) ;; Should we skip the defun (recurse)? - (cond (next (not recursing)) ; [1] (see below) - (parent t) ; [2] - (t nil))) - ;; Special case: go to next beg-of-defun. Set POS - ;; to the end of next-sib/parent defun, and run one - ;; more step. If there is a next-sib defun, we only - ;; need to recurse once, so we don't need to recurse - ;; if we are already recursing [1]. If there is no + (cond (next (and (not recursing) ; [1] (see below) + (eq pos (funcall advance next)))) + (parent t))) ; [2] + ;; Special case: go to next beg-of-defun, but point + ;; is already on beg-of-defun. Set POS to the end + ;; of next-sib/parent defun, and run one more step. + ;; If there is a next-sib defun, we only need to + ;; recurse once, so we don't need to recurse if we + ;; are already recursing [1]. If there is no ;; next-sib but a parent, keep stepping out ;; (recursing) until we got out of the parents until ;; (1) there is a next sibling defun, or (2) no more ;; parents [2]. + ;; + ;; If point on beg-of-defun but we are already + ;; recurring, that doesn't count as special case, + ;; because we have already made progress (by moving + ;; the end of next before recurring.) (setq pos (or (treesit--navigate-thing (treesit-node-end (or next parent)) 1 'beg regexp pred t) @@ -2099,9 +2145,9 @@ function is called recursively." (setq pos (funcall advance (or next parent)))) ;; ...backward. (if (and (eq side 'end) - (cond (prev (not recursing)) - (parent t) - (t nil))) + (cond (prev (and (not recursing) + (eq pos (funcall advance prev)))) + (parent t))) ;; Special case: go to prev end-of-defun. (setq pos (or (treesit--navigate-thing (treesit-node-start (or prev parent)) diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el index 5aa12e8aa0e..468cd221ef9 100644 --- a/test/src/treesit-tests.el +++ b/test/src/treesit-tests.el @@ -977,22 +977,22 @@ and \"]\"." (defvar treesit--ert-defun-navigation-nested-master ;; START PREV-BEG NEXT-END PREV-END NEXT-BEG - '((0 103 105 102 106) ; Between Beg of parent & 1st sibling. + '((0 103 105 102 104) ; Between Beg of parent & 1st sibling. (1 103 105 102 106) ; Beg of 1st sibling. (2 104 105 102 106) ; Inside 1st sibling. - (3 104 107 102 109) ; End of 1st sibling. - (4 104 107 102 109) ; Between 1st sibling & 2nd sibling. - (5 104 107 102 109) ; Beg of 2nd sibling. + (3 104 107 102 106) ; End of 1st sibling. + (4 104 107 105 106) ; Between 1st sibling & 2nd sibling. + (5 104 107 105 109) ; Beg of 2nd sibling. (6 106 107 105 109) ; Inside 2nd sibling. (7 106 108 105 109) ; End of 2nd sibling. - (8 106 108 105 109) ; Between 2nd sibling & end of parent. - (9 103 110 102 nil) ; End of parent. + (8 106 108 107 109) ; Between 2nd sibling & end of parent. + (9 103 110 102 109) ; End of parent. - (100 nil 102 nil 103) ; Before 1st parent. + (100 nil 102 nil 101) ; Before 1st parent. (101 nil 102 nil 103) ; Beg of 1st parent. - (102 101 108 nil 109) ; Between 1st & 2nd parent. - (103 101 108 nil 109) ; Beg of 2nd parent. - (110 109 nil 108 nil) ; After 3rd parent. + (102 101 108 102 103) ; Between 1st & 2nd parent. + (103 101 108 102 109) ; Beg of 2nd parent. + (110 109 nil 110 nil) ; After 3rd parent. ) "Master of nested navigation test. @@ -1000,7 +1000,7 @@ This basically says, e.g., \"start with point on marker 0, go to the prev-beg, now point should be at marker 103\", etc.") (defvar treesit--ert-defun-navigation-top-level-master - ;; START PREV-BEG NEXT-END NEXT-BEG PREV-END + ;; START PREV-BEG NEXT-END PREV-END NEXT-BEG '((0 103 108 102 109) ; Between Beg of parent & 1st sibling. (1 103 108 102 109) ; Beg of 1st sibling. (2 103 108 102 109) ; Inside 1st sibling. @@ -1010,14 +1010,14 @@ the prev-beg, now point should be at marker 103\", etc.") (6 103 108 102 109) ; Inside 2nd sibling. (7 103 108 102 109) ; End of 2nd sibling. (8 103 108 102 109) ; Between 2nd sibling & end of parent. - (9 103 110 102 nil) ; End of parent. + (9 103 110 102 109) ; End of parent. ;; Top-level defuns should be identical to the nested test. - (100 nil 102 nil 103) ; Before 1st parent. + (100 nil 102 nil 101) ; Before 1st parent. (101 nil 102 nil 103) ; Beg of 1st parent. - (102 101 108 nil 109) ; Between 1st & 2nd parent. - (103 101 108 nil 109) ; Beg of 2nd parent. - (110 109 nil 108 nil) ; After 3rd parent. + (102 101 108 102 103) ; Between 1st & 2nd parent. + (103 101 108 102 109) ; Beg of 2nd parent. + (110 109 nil 110 nil) ; After 3rd parent. ) "Master of top-level navigation test.")