@cindex nested defuns
@vindex treesit-defun-tactic
Some programming languages supported @dfn{nested defuns}, whereby a
-defun (such as a function or a method or a class) can be defined
-inside (i.e., as part of the body) of another defun. The commands
-described above by default find the beginning and the end of the
-@emph{innermost} defun around point. Major modes based on the
-tree-sitter library provide control of this behavior: if the variable
-@code{treesit-defun-tactic} is set to the value @code{top-level}, the
-defun commands will find the @emph{outermost} defuns instead.
+defun (such as a function or a method or a class) can be defined inside
+(i.e., as part of the body) of another defun. The commands described
+above by default find the beginning and the end of the @emph{innermost}
+defun around point. Major modes based on the tree-sitter library
+provide control of this behavior: by default, the value of
+@code{treesit-defun-tactic} is set to @code{nested}; if it's set
+to@code{top-level}, the defun commands will find the @emph{outermost}
+defuns instead; if the value is set to @code{parent-first}, the defun
+command always tries to move out of the current enclosing defun rather
+than moving to the previous or next defun around point; if there's no
+enclosing defun, it moves to the previous or next defun.
@node Moving by Sentences
@subsection Moving by Sentences
defined in @code{treesit-thing-settings}, or a predicate.
@var{tactic} determines how this function moves between things. It can
-be @code{nested}, @code{top-level}, @code{restricted}, or @code{nil}.
-@code{nested} or @code{nil} means normal nested navigation: first try to
-move across siblings; if there aren't any siblings left in the current
-level, move to the parent, then its siblings, and so on.
-@code{top-level} means only navigate across top-level things and ignore
-nested things. @code{restricted} means movement is restricted within
-the thing that encloses @var{position}, if there is such a thing. This
-tactic is useful for commands that want to stop at the current nesting
-level and not move up.
+be @code{nested}, @code{top-level}, @code{restricted},
+@code{parent-first}, or @code{nil}. @code{nested} or @code{nil} means
+normal nested navigation: first try to move across siblings; if there
+aren't any siblings left in the current level, move to the parent, then
+its siblings, and so on. @code{top-level} means only navigate across
+top-level things and ignore nested things. @code{restricted} means
+movement is restricted within the thing that encloses @var{position}, if
+there is such a thing. This tactic is useful for commands that want to
+stop at the current nesting level and not move up. @var{parent-first}
+means move to the parent if there is one; and move to siblings if
+there's no parent.
@end defun
@defun treesit-thing-at position thing &optional strict
THING can be a regexp, a predicate function, and more. See
`treesit-thing-settings' for details.
-TACTIC determines how does this function move between things. It
-can be `nested', `top-level', `restricted', or nil. `nested'
-means normal nested navigation: try to move to siblings first,
-and if there aren't enough siblings, move to the parent and its
-siblings. `top-level' means only consider top-level things, and
-nested things are ignored. `restricted' means movement is
-restricted inside the thing that encloses POS (i.e., parent),
-should there be one. If omitted, TACTIC is considered to be
-`nested'.
+TACTIC determines how does this function move between things. It can be
+`nested', `top-level', `restricted', `parent-first' or nil. `nested'
+means normal nested navigation: try to move to siblings first, and if
+there aren't enough siblings, move to the parent and its siblings.
+`top-level' means only consider top-level things, and nested things are
+ignored. `restricted' means movement is restricted inside the thing
+that encloses POS (i.e., parent), should there be one. `parent' means
+move to the parent if there is one; and move to siblings if there's no
+parent. If omitted, TACTIC is considered to be `nested'.
RECURSING is an internal parameter, if non-nil, it means this
function is called recursively."
(setq parent (treesit-node-top-level parent thing t)
prev nil
next nil))
+ ;; When PARENT is nil, `nested' and `parent-first' are the
+ ;; same, if there is a PARENT, pretend there is no nested PREV
+ ;; and NEXT so the following code moves to the parent.
+ (when (and (eq tactic 'parent-first) parent)
+ (setq prev nil next nil))
;; If TACTIC is `restricted', the implementation is simple.
;; In principle we don't go to parent's beg/end for
;; `restricted' tactic, but if the parent is a "leaf thing"