From 01e7d4b2a1e7c3299ac73ade27b5efa46b12742b Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Wed, 30 Nov 2022 15:05:07 -0800 Subject: [PATCH] Make treesit-defun-prefer-top-level more flexible * doc/lispref/positions.texi (List Motion): Update manual. * lisp/treesit.el (treesit-defun-prefer-top-level): Update docstring. (treesit--defun-maybe-top-level): Change to accept new format. --- doc/lispref/positions.texi | 17 +++++++++++++++++ lisp/treesit.el | 30 +++++++++++++++--------------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index a01e568de07..c065cc11e25 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -850,6 +850,23 @@ For example, @code{python-mode} sets this variable to a regexp that matches either @code{function_definition} or @code{class_definition}. @end defvar +@defvar treesit-defun-prefer-top-level +If this variable is non-@code{nil}, Emacs skips nested defun and +prefers the top-level defun. + +In some languages, a defun could be nested in another one. Normally +Emacs stops at the first defun it encounters. If this variable's +value is @code{t}, whenever Emacs finds a defun node, it tries to go +up the parse tree and find the top-level defun. + +This variable can also be a list of cons cells of the form +@w{@code{(@var{from} . @var{to}))}}, where @var{from} and @var{to} are +regexp matching tree-sitter node types. When Emacs finds a defun node +whose type matches any of the @var{from} regexp in the list, Emacs +then tries to go up the parse tree to find the top-level node matching +the corresponding @var{to} regexp. +@end defvar + @node Skipping Characters @subsection Skipping Characters @cindex skipping characters diff --git a/lisp/treesit.el b/lisp/treesit.el index 8f092f475de..dd7895683ff 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1554,20 +1554,18 @@ For example, \"(function|class)_definition\". This is used by `treesit-beginning-of-defun' and friends.") (defvar-local treesit-defun-prefer-top-level nil - "When non-nil, `treesit-beginning-of-defun' prefers top-level defun. + "When non-nil, Emacs prefers top-level defun. -In some languages, a defun (function, class, struct) could be -nested in another one. Normally `treesit-beginning-of-defun' -just finds the first defun it encounter. If this variable's -value is t, `treesit-beginning-of-defun' tries to find the -top-level defun, and ignores nested ones. +In some languages, a defun could be nested in another one. +Normally Emacs stops at the first defun it encounters. If this +variable's value is t, Emacs tries to find the top-level defun, +and ignores nested ones. -This variable can also be a list of tree-sitter node type -regexps. Then, when `treesit-beginning-of-defun' finds a defun -node and that node's type matches one in the list, -`treesit-beginning-of-defun' finds the top-level node matching -that particular regexp (as opposed to any node matched by -`treesit-defun-type-regexp').") +This variable can also be a list of cons cells of the form (FROM +. TO), where FROM and TO are tree-sitter node type regexps. When +Emacs finds a defun node whose type matches any of the FROM +regexp in the list, Emacs then tries to find the top-level node +matching the corresponding TO regexp.") (defun treesit--defun-maybe-top-level (node) "Maybe return the top-level equivalent of NODE. @@ -1579,9 +1577,11 @@ For the detailed semantic see `treesit-defun-prefer-top-level'." node)) ((pred consp) (cl-loop - for re in treesit-defun-prefer-top-level - if (string-match-p re (treesit-node-type node)) - return (or (treesit-node-top-level node re) + for con in treesit-defun-prefer-top-level + for from = (car con) + for to = (cdr con) + if (string-match-p from (treesit-node-type node)) + return (or (treesit-node-top-level node to) node) finally return node)))) -- 2.39.2