emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master c5d319af475: Merge from origin/emacs-29


From: Stefan Kangas
Subject: master c5d319af475: Merge from origin/emacs-29
Date: Tue, 28 Feb 2023 00:46:17 -0500 (EST)

branch: master
commit c5d319af475337beba9a0720a185e4ea3d375e07
Merge: 93f557af0ef 613de662811
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Merge from origin/emacs-29
    
    613de662811 Rename the newly added -ref- faces to -use-
    f601e9666d8 Eglot: support multiple labels in same inlay hint
    4a5eda7ed2a Eglot: don't paint hints outside requested region (bug#61...
    11c1aa1eb12 ; * doc/misc/gnus.texi: Fix last change.
    44949c292f9 ; Add `nnimap-user' to Gnus manual
    6c7078c66f4 ; * lisp/progmodes/c-ts-mode.el (treesit-node-prev-siblin...
    3d0a6c9baa6 Eglot: protect against unintended field text motion (bug#...
    647e40f4a0c ; And yet another fix to eglot-current-linepos-function's...
    9d0f856a167 Fix description of 'desktop-save-mode'
    aee10ca1cbe Adjust tree-sitter defun navigation (bug#61617)
    edf5b976869 Simplify c-ts-mode--top-level-label-matcher
    0f15286c539 New tree-sitter indent anchor standalone-parent used by c...
    
    # Conflicts:
    #       etc/NEWS
---
 doc/emacs/misc.texi                  | 10 ++--
 doc/lispref/modes.texi               | 18 ++++++--
 doc/misc/gnus.texi                   | 17 +++++++
 etc/NEWS.29                          |  4 +-
 lisp/cus-theme.el                    |  4 +-
 lisp/font-lock.el                    |  4 +-
 lisp/progmodes/c-ts-mode.el          | 54 ++++++++++++----------
 lisp/progmodes/cmake-ts-mode.el      |  2 +-
 lisp/progmodes/csharp-mode.el        | 20 ++++----
 lisp/progmodes/eglot.el              | 85 ++++++++++++++++++++--------------
 lisp/progmodes/go-ts-mode.el         |  6 +--
 lisp/progmodes/java-ts-mode.el       |  6 +--
 lisp/progmodes/js.el                 | 12 ++---
 lisp/progmodes/json-ts-mode.el       |  2 +-
 lisp/progmodes/python.el             |  6 +--
 lisp/progmodes/ruby-ts-mode.el       |  4 +-
 lisp/progmodes/rust-ts-mode.el       | 42 ++++++++---------
 lisp/progmodes/typescript-ts-mode.el |  6 +--
 lisp/textmodes/css-mode.el           |  4 +-
 lisp/textmodes/toml-ts-mode.el       |  4 +-
 lisp/textmodes/yaml-ts-mode.el       | 12 ++---
 lisp/treesit.el                      | 88 +++++++++++++++++++++++++++---------
 test/src/treesit-tests.el            | 32 ++++++-------
 23 files changed, 270 insertions(+), 172 deletions(-)

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.")
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]