From: Yuan Fu Date: Sat, 2 Sep 2023 00:14:44 +0000 (-0700) Subject: Obsolete treesit-block/sexp/sentence/text-type-regexp X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=2547fbe9c44c0c4642426c008db8f1b4d6867f4c;p=emacs.git Obsolete treesit-block/sexp/sentence/text-type-regexp And replace them with treesit-thing-settings. * doc/lispref/positions.texi (List Motion): Remove mention of treesit-sexp/sentence-type-regexp. * lisp/progmodes/c-ts-mode.el (c-ts-base-mode) * lisp/progmodes/dockerfile-ts-mode.el (dockerfile-ts-mode) * lisp/progmodes/java-ts-mode.el (java-ts-mode) * lisp/progmodes/js.el (js-ts-mode) * lisp/progmodes/json-ts-mode.el (json-ts-mode) * lisp/progmodes/ruby-ts-mode.el (ruby-ts-mode) * lisp/progmodes/typescript-ts-mode.el (typescript-ts-base-mode) (tsx-ts-mode) * lisp/progmodes/heex-ts-mode.el (heex-ts-mode) * lisp/progmodes/sh-script.el (bash-ts-mode) * lisp/progmodes/prog-mode.el (prog-fill-reindent-defun) * lisp/textmodes/html-ts-mode.el (html-ts-mode): Replace treesit-sexp/sentence/text-type-regexp with treesit-thing-settings. * lisp/treesit.el (treesit-sexp-type-regexp) (treesit-sentence-type-regexp): Mark obsolete. (treesit-block-type-regexp): Remove. * lisp/treesit.el (treesit-forward-sexp) (treesit-transpose-sexps) (treesit-beginning-of-defun) (treesit-end-of-defun) (treesit-forward-sentence) (treesit-defun-at-point): Make use of treesit-thing-settings. (treesit-thing-definition) (treesit-thing-defined-p): New functions. (treesit-major-mode-setup): Replace treesit-sexp/sentence-type-regexp with treesit-thing-settings. --- diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index 98cf81be107..5ff89e992d9 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -872,36 +872,25 @@ defuns. If the value is @code{nested}, navigation functions recognize nested defuns. @end defvar -@defvar treesit-sentence-type-regexp -The value of this variable is a regexp matching the node type of sentence -nodes. (For ``node'' and ``node type'', @pxref{Parsing Program Source}.) -@end defvar - @findex treesit-forward-sentence @findex forward-sentence @findex backward-sentence If Emacs is compiled with tree-sitter, it can use the tree-sitter parser information to move across syntax constructs. Since what exactly is considered a sentence varies between languages, a major -mode should set @code{treesit-sentence-type-regexp} to determine that. +mode should set @code{treesit-thing-settings} to determine that. Then the mode can get navigation-by-sentence functionality for free, by using @code{forward-sentence} and @code{backward-sentence}(@pxref{Moving by Sentences,,, emacs, The extensible self-documenting text editor}). -@defvar treesit-sexp-type-regexp -The value of this variable is a regexp matching the node type of sexp -nodes. (For ``node'' and ``node type'', @pxref{Parsing Program -Source}.) -@end defvar - @findex treesit-forward-sexp @findex forward-sexp@r{, and tree-sitter} @findex backward-sexp@r{, and tree-sitter} If Emacs is compiled with tree-sitter, it can use the tree-sitter parser information to move across syntax constructs. Since what exactly is considered a sexp varies between languages, a major mode -should set @code{treesit-sexp-type-regexp} to determine that. Then +should set @code{treesit-thing-settings} to determine that. Then the mode can get navigation-by-sexp functionality for free, by using @code{forward-sexp} and @code{backward-sexp}(@pxref{Moving by Sentences,,, emacs, The extensible self-documenting text editor}). diff --git a/etc/NEWS b/etc/NEWS index f965cf10561..5c11b6b9ac7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -936,24 +936,17 @@ Major modes can now set this variable to customize the behavior of the The previous implementation of 'forward-sentence' is moved into its own function, to be bound by 'forward-sentence-function'. -*** New buffer-local variable 'treesit-sentence-type-regexp'. -Similarly to 'treesit-defun-type-regexp', this variable is used to -define "sentences" in tree-sitter enabled modes. - *** New function 'treesit-forward-sentence'. -All tree-sitter enabled modes that define 'treesit-sentence-type-regexp' -now set 'forward-sentence-function' to call 'treesit-forward-sentence'. +All tree-sitter enabled modes that define 'sentence' in +'treesit-thing-settings' now set 'forward-sentence-function' to call +'treesit-forward-sentence'. ** Functions and variables to move by program sexps -*** New buffer-local variable 'treesit-sexp-type-regexp'. -Similarly to 'treesit-defun-type-regexp', this variable is used to -define "sexps" in tree-sitter enabled modes. - *** New function 'treesit-forward-sexp'. Tree-sitter conditionally sets 'forward-sexp-function' for major modes -that have defined 'treesit-sexp-type-regexp' to enable sexp-related -motion commands. +that have defined 'sexp' in 'treesit-thing-settings' to enable +sexp-related motion commands. ** New or changed byte-compilation warnings diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index b3c48eb2c65..165bdd668c3 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -1127,34 +1127,36 @@ BEG and END are described in `treesit-range-rules'." (setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper) (setq-local treesit-defun-name-function #'c-ts-mode--defun-name) - (setq-local treesit-sentence-type-regexp - ;; compound_statement makes us jump over too big units - ;; of code, so skip that one, and include the other - ;; statements. - (regexp-opt '("preproc" - "declaration" - "specifier" - "attributed_statement" - "labeled_statement" - "expression_statement" - "if_statement" - "switch_statement" - "do_statement" - "while_statement" - "for_statement" - "return_statement" - "break_statement" - "continue_statement" - "goto_statement" - "case_statement"))) - ;; IMO it makes more sense to define what's NOT sexp, since sexp by ;; spirit, especially when used for movement, is like "expression" ;; or "syntax unit". --yuan - (setq-local treesit-sexp-type-regexp - ;; It more useful to include semicolons as sexp so that - ;; users can move to the end of a statement. - (rx (not (or "{" "}" "[" "]" "(" ")" ",")))) + (setq-local treesit-thing-settings + `((c + ;; It's more useful to include semicolons as sexp so + ;; that users can move to the end of a statement. + (sexp (not ,(rx (or "{" "}" "[" "]" "(" ")" ",")))) + ;; compound_statement makes us jump over too big units + ;; of code, so skip that one, and include the other + ;; statements. + (sentence + ,(regexp-opt '("preproc" + "declaration" + "specifier" + "attributed_statement" + "labeled_statement" + "expression_statement" + "if_statement" + "switch_statement" + "do_statement" + "while_statement" + "for_statement" + "return_statement" + "break_statement" + "continue_statement" + "goto_statement" + "case_statement"))) + (text ,(regexp-opt '("comment" + "raw_string_literal")))))) ;; Nodes like struct/enum/union_specifier can appear in ;; function_definitions, so we need to find the top-level node. @@ -1291,9 +1293,6 @@ recommended to enable `electric-pair-mode' with this mode." :after-hook (c-ts-mode-set-modeline) (when (treesit-ready-p 'cpp) - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" - "raw_string_literal"))) (treesit-parser-create 'cpp) diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 37bb84ab5ba..866c802ca43 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -959,10 +959,12 @@ Key bindings: ;; Comments. (c-ts-common-comment-setup) - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" - "verbatim_string-literal" - "interpolated_verbatim_string-text"))) + (setq-local treesit-thing-settings + `((c-sharp + (text + ,(regexp-opt '("comment" + "verbatim_string-literal" + "interpolated_verbatim_string-text")))))) ;; Indent. (setq-local treesit-simple-indent-rules csharp-ts-mode--indent-rules) diff --git a/lisp/progmodes/dockerfile-ts-mode.el b/lisp/progmodes/dockerfile-ts-mode.el index 333158e20f6..0305bea5182 100644 --- a/lisp/progmodes/dockerfile-ts-mode.el +++ b/lisp/progmodes/dockerfile-ts-mode.el @@ -175,8 +175,9 @@ the subtrees." dockerfile-ts-mode--indent-rules) ;; Navigation - (setq-local treesit-sentence-type-regexp - "instruction") + (setq-local treesit-thing-settings + `((dockerfile + (sentence "instruction")))) ;; Font-lock. (setq-local treesit-font-lock-settings diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el index 68a537b9229..5237c767330 100644 --- a/lisp/progmodes/heex-ts-mode.el +++ b/lisp/progmodes/heex-ts-mode.el @@ -149,8 +149,9 @@ With ARG, do it many times. Negative ARG means move backward." (treesit-parser-create 'heex) ;; Comments - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" "text"))) + (setq-local treesit-thing-settings + `((heex + (text ,(regexp-opt '("comment" "text")))))) (setq-local forward-sexp-function #'heex-ts--forward-sexp) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 121c8550be0..863adeb9245 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -317,11 +317,6 @@ Return nil if there is no name or if NODE is not a defun node." ;; Comments. (c-ts-common-comment-setup) - (setq-local treesit-text-type-regexp - (regexp-opt '("line_comment" - "block_comment" - "text_block"))) - ;; Indent. (setq-local c-ts-common-indent-type-regexp-alist `((block . ,(rx (or "class_body" @@ -360,28 +355,30 @@ Return nil if there is no name or if NODE is not a defun node." "constructor_declaration"))) (setq-local treesit-defun-name-function #'java-ts-mode--defun-name) - (setq-local treesit-sentence-type-regexp - (regexp-opt '("statement" - "local_variable_declaration" - "field_declaration" - "module_declaration" - "package_declaration" - "import_declaration"))) - - (setq-local treesit-sexp-type-regexp - (regexp-opt '("annotation" - "parenthesized_expression" - "argument_list" - "identifier" - "modifiers" - "block" - "body" - "literal" - "access" - "reference" - "_type" - "true" - "false"))) + (setq-local treesit-thing-settings + `(java + (sexp ,(rx (or "annotation" + "parenthesized_expression" + "argument_list" + "identifier" + "modifiers" + "block" + "body" + "literal" + "access" + "reference" + "_type" + "true" + "false"))) + (sentence ,(rx (or "statement" + "local_variable_declaration" + "field_declaration" + "module_declaration" + "package_declaration" + "import_declaration"))) + (text ,(regexp-opt '("line_comment" + "block_comment" + "text_block"))))) ;; Font-lock. (setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 1d89b35aa2d..60f50f7e15e 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3831,7 +3831,7 @@ Currently there are `js-mode' and `js-ts-mode'." "jsx_element" "jsx_self_closing_element") "Nodes that designate sentences in JavaScript. -See `treesit-sentence-type-regexp' for more information.") +See `treesit-thing-settings' for more information.") (defvar js--treesit-sexp-nodes '("expression" @@ -3873,10 +3873,6 @@ See `treesit-sexp-type-regexp' for more information.") (c-ts-common-comment-setup) (setq-local comment-multi-line t) - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" - "template_string"))) - ;; Electric-indent. (setq-local electric-indent-chars (append "{}():;,<>/" electric-indent-chars)) ;FIXME: js2-mode adds "[]*". @@ -3896,11 +3892,12 @@ See `treesit-sexp-type-regexp' for more information.") "lexical_declaration"))) (setq-local treesit-defun-name-function #'js--treesit-defun-name) - (setq-local treesit-sentence-type-regexp - (regexp-opt js--treesit-sentence-nodes)) - - (setq-local treesit-sexp-type-regexp - (regexp-opt js--treesit-sexp-nodes)) + (setq-local treesit-thing-settings + `((javascript + (sexp ,(regexp-opt js--treesit-sexp-nodes)) + (sentence ,(regexp-opt js--treesit-sentence-nodes)) + (text ,(regexp-opt '("comment" + "template_string")))))) ;; Fontification. (setq-local treesit-font-lock-settings js--treesit-font-lock-settings) diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el index f56d118c0fe..78117356821 100644 --- a/lisp/progmodes/json-ts-mode.el +++ b/lisp/progmodes/json-ts-mode.el @@ -147,7 +147,9 @@ Return nil if there is no name or if NODE is not a defun node." (rx (or "pair" "object"))) (setq-local treesit-defun-name-function #'json-ts-mode--defun-name) - (setq-local treesit-sentence-type-regexp "pair") + (setq-local treesit-thing-settings + `((json + (sentence "pair")))) ;; Font-lock. (setq-local treesit-font-lock-settings json-ts-mode--font-lock-settings) diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el index 16497097061..f5e6e117d99 100644 --- a/lisp/progmodes/prog-mode.el +++ b/lisp/progmodes/prog-mode.el @@ -37,6 +37,7 @@ (declare-function treesit-parser-list "treesit.c") (declare-function treesit-node-type "treesit.c") (declare-function treesit-node-at "treesit.c") +(declare-function treesit-node-match-p "treesit.c") (defgroup prog-mode nil "Generic programming mode, from which others derive." @@ -160,9 +161,8 @@ or follows point." (let ((treesit-text-node (and (treesit-available-p) (treesit-parser-list) - (string-match-p - treesit-text-type-regexp - (treesit-node-type (treesit-node-at (point))))))) + (treesit-node-match-p + (treesit-node-at (point)) 'text t)))) (if (or treesit-text-node (nth 8 (syntax-ppss)) (re-search-forward "\\s-*\\s<" (line-end-position) t)) diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index adbf18786cb..fabe5859779 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -1122,44 +1122,45 @@ leading double colon is not added." ;; Navigation. (setq-local treesit-defun-type-regexp ruby-ts--method-regex) - (setq-local treesit-sexp-type-regexp - (cons (rx - bol - (or - "class" - "module" - "method" - "array" - "hash" - "parenthesized_statements" - "method_parameters" - "array_pattern" - "hash_pattern" - "if" - "unless" - "case" - "case_match" - "when" - "block" - "do_block" - "begin" - "integer" - "identifier" - "constant" - "simple_symbol" - "hash_key_symbol" - "symbol_array" - "string" - "string_array" - "heredoc_body" - "regex" - "argument_list" - "interpolation" - "instance_variable" - "global_variable" - ) - eol) - #'ruby-ts--sexp-p)) + (setq-local treesit-thing-settings + `((ruby + (sexp ,(cons (rx + bol + (or + "class" + "module" + "method" + "array" + "hash" + "parenthesized_statements" + "method_parameters" + "array_pattern" + "hash_pattern" + "if" + "unless" + "case" + "case_match" + "when" + "block" + "do_block" + "begin" + "integer" + "identifier" + "constant" + "simple_symbol" + "hash_key_symbol" + "symbol_array" + "string" + "string_array" + "heredoc_body" + "regex" + "argument_list" + "interpolation" + "instance_variable" + "global_variable" + ) + eol) + #'ruby-ts--sexp-p))))) ;; AFAIK, Ruby can not nest methods (setq-local treesit-defun-prefer-top-level nil) diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index ed4ea8e3618..cc521cb0591 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -1629,10 +1629,11 @@ not written in Bash or sh." ( bracket delimiter misc-punctuation operator))) (setq-local treesit-font-lock-settings sh-mode--treesit-settings) - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" - "heredoc_start" - "heredoc_body"))) + (setq-local treesit-thing-settings + `((bash + (sentence ,(regexp-opt '("comment" + "heredoc_start" + "heredoc_body")))))) (setq-local treesit-defun-type-regexp "function_definition") (treesit-major-mode-setup))) diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index 3f8e232b71f..441cdc1f7aa 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -387,7 +387,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." "lexical_declaration" "property_signature") "Nodes that designate sentences in TypeScript. -See `treesit-sentence-type-regexp' for more information.") +See `treesit-thing-settings' for more information.") (defvar typescript-ts-mode--sexp-nodes '("expression" @@ -409,7 +409,7 @@ See `treesit-sentence-type-regexp' for more information.") "arguments" "pair") "Nodes that designate sexps in TypeScript. -See `treesit-sexp-type-regexp' for more information.") +See `treesit-thing-settings' for more information.") ;;;###autoload (define-derived-mode typescript-ts-base-mode prog-mode "TypeScript" @@ -421,10 +421,6 @@ See `treesit-sexp-type-regexp' for more information.") (c-ts-common-comment-setup) (setq-local treesit-defun-prefer-top-level t) - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" - "template_string"))) - ;; Electric (setq-local electric-indent-chars (append "{}():;,<>/" electric-indent-chars)) @@ -438,11 +434,13 @@ See `treesit-sexp-type-regexp' for more information.") "lexical_declaration"))) (setq-local treesit-defun-name-function #'js--treesit-defun-name) - (setq-local treesit-sentence-type-regexp - (regexp-opt typescript-ts-mode--sentence-nodes)) - - (setq-local treesit-sexp-type-regexp - (regexp-opt typescript-ts-mode--sexp-nodes)) + (setq-local treesit-thing-settings + `((typescript + (sexp ,(regexp-opt typescript-ts-mode--sexp-nodes)) + (sentence ,(regexp-opt + typescript-ts-mode--sentence-nodes)) + (text ,(regexp-opt '("comment" + "template_string")))))) ;; Imenu (same as in `js-ts-mode'). (setq-local treesit-simple-imenu-settings @@ -513,17 +511,15 @@ at least 3 (which is the default value)." (setq-local treesit-simple-indent-rules (typescript-ts-mode--indent-rules 'tsx)) - ;; Navigation - (setq-local treesit-sentence-type-regexp - (regexp-opt (append - typescript-ts-mode--sentence-nodes - '("jsx_element" - "jsx_self_closing_element")))) - - (setq-local treesit-sexp-type-regexp - (regexp-opt (append - typescript-ts-mode--sexp-nodes - '("jsx")))) + (setq-local treesit-thing-settings + `((tsx + (sexp ,(regexp-opt + (append typescript-ts-mode--sexp-nodes + '("jsx")))) + (sentence ,(regexp-opt + (append typescript-ts-mode--sentence-nodes + '("jsx_element" + "jsx_self_closing_element"))))))) ;; Font-lock. (setq-local treesit-font-lock-settings diff --git a/lisp/textmodes/html-ts-mode.el b/lisp/textmodes/html-ts-mode.el index 4c1f410a7ef..d08d899c815 100644 --- a/lisp/textmodes/html-ts-mode.el +++ b/lisp/textmodes/html-ts-mode.el @@ -94,10 +94,6 @@ Return nil if there is no name or if NODE is not a defun node." (treesit-parser-create 'html) - ;; Comments. - (setq-local treesit-text-type-regexp - (regexp-opt '("comment" "text"))) - ;; Indent. (setq-local treesit-simple-indent-rules html-ts-mode--indent-rules) @@ -106,13 +102,14 @@ Return nil if there is no name or if NODE is not a defun node." (setq-local treesit-defun-name-function #'html-ts-mode--defun-name) - (setq-local treesit-sentence-type-regexp "tag") - - (setq-local treesit-sexp-type-regexp - (regexp-opt '("element" - "text" - "attribute" - "value"))) + (setq-local treesit-thing-settings + `((html + (sexp ,(regexp-opt '("element" + "text" + "attribute" + "value"))) + (sentence "tag") + (text ,(regexp-opt '("comment" "text")))))) ;; Font-lock. (setq-local treesit-font-lock-settings html-ts-mode--font-lock-settings) diff --git a/lisp/treesit.el b/lisp/treesit.el index a9761dbb38d..379f39771c5 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1799,6 +1799,8 @@ BACKWARD and ALL are the same as in `treesit-search-forward'." (goto-char current-pos))) node)) +(make-obsolete 'treesit-sexp-type-regexp "`treesit-sexp-type-regexp' will be removed in a few months, use `treesit-thing-settings' instead." "30.0.5") + (defvar-local treesit-sexp-type-regexp nil "A regexp that matches the node type of sexp nodes. @@ -1816,7 +1818,7 @@ like `forward-sexp' does. If point is already at top-level, return nil without moving point." (interactive "^p") (let ((arg (or arg 1)) - (pred treesit-sexp-type-regexp)) + (pred (or treesit-sexp-type-regexp 'sexp))) (or (if (> arg 0) (treesit-end-of-thing pred (abs arg) 'restricted) (treesit-beginning-of-thing pred (abs arg) 'restricted)) @@ -1842,7 +1844,12 @@ its sibling node ARG nodes away. Return a pair of positions as described by `transpose-sexps-function' for use in `transpose-subr' and friends." - (let* ((parent (treesit-node-parent (treesit-node-at (point)))) + ;; First arrive at the right level at where the node at point is + ;; considered a sexp. If sexp isn't defined, or we can't find any + ;; node that's a sexp, use the node at point. + (let* ((node (or (treesit-thing-at-point 'sexp 'nested) + (treesit-node-at (point)))) + (parent (treesit-node-parent node)) (child (treesit-node-child parent 0 t))) (named-let loop ((prev child) (next (treesit-node-next-sibling child t))) @@ -1900,9 +1907,6 @@ for invalid node. This is used by `treesit-beginning-of-defun' and friends.") -(defvar-local treesit-block-type-regexp nil - "Like `treesit-defun-type-regexp', but for blocks.") - (defvar-local treesit-defun-tactic 'nested "Determines how does Emacs treat nested defuns. If the value is `top-level', Emacs only moves across top-level @@ -1928,11 +1932,20 @@ nil.") "The delimiter used to connect several defun names. This is used in `treesit-add-log-current-defun'.") +(defun treesit-thing-definition (thing) + "Return the predicate for THING if it's defined. +A thing is considered defined if it has an entry in +`treesit-thing-settings'." + (alist-get thing treesit-thing-settings)) + +(defalias 'treesit-thing-defined-p 'treesit-thing-definition + "Return non-nil if THING is defined.") + (defun treesit-beginning-of-thing (pred &optional arg tactic) "Like `beginning-of-defun', but generalized into things. -PRED is like `treesit-defun-type-regexp', ARG -is the same as in `beginning-of-defun'. +PRED is a thing predicate, see `treesit-thing-settings' for more +detail. ARG is the same as in `beginning-of-defun'. TACTIC determines how does this function move between things. It can be `nested', `top-level', `restricted', or nil. `nested' @@ -1954,8 +1967,8 @@ Return non-nil if successfully moved, nil otherwise." (defun treesit-end-of-thing (pred &optional arg tactic) "Like `end-of-defun', but generalized into things. -PRED is like `treesit-defun-type-regexp', ARG is the same as -in `end-of-defun'. +PRED is a thing predicate, see `treesit-thing-settings' for more +detail. ARG is the same as in `end-of-defun'. TACTIC determines how does this function move between things. It can be `nested', `top-level', `restricted', or nil. `nested' @@ -1984,19 +1997,21 @@ If search is successful, return t, otherwise return nil. This is a tree-sitter equivalent of `beginning-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' -and `treesit-defun-skipper'." +and `treesit-defun-skipper'. If `treesit-defun-type-regexp' is +not set, Emacs also looks for definition of defun in +`treesit-thing-settings'." (interactive "^p") (or (not (eq this-command 'treesit-beginning-of-defun)) (eq last-command 'treesit-beginning-of-defun) (and transient-mark-mode mark-active) (push-mark)) (let ((orig-point (point)) - (success nil)) + (success nil) + (pred (or treesit-defun-type-regexp 'defun))) (catch 'done (dotimes (_ 2) - (when (treesit-beginning-of-thing - treesit-defun-type-regexp arg treesit-defun-tactic) + (when (treesit-beginning-of-thing pred arg treesit-defun-tactic) (when treesit-defun-skipper (funcall treesit-defun-skipper) (setq success t))) @@ -2017,9 +2032,12 @@ Negative argument -N means move back to Nth preceding end of defun. This is a tree-sitter equivalent of `end-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and -`treesit-defun-skipper'." +`treesit-defun-skipper'. If `treesit-defun-type-regexp' is not +set, Emacs also looks for definition of defun in +`treesit-thing-settings'." (interactive "^p\nd") - (let ((orig-point (point))) + (let ((orig-point (point)) + (pred (or treesit-defun-type-regexp 'defun))) (if (or (null arg) (= arg 0)) (setq arg 1)) (or (not (eq this-command 'treesit-end-of-defun)) (eq last-command 'treesit-end-of-defun) @@ -2028,8 +2046,7 @@ this function depends on `treesit-defun-type-regexp' and (catch 'done (dotimes (_ 2) ; Not making progress is better than infloop. - (when (treesit-end-of-thing - treesit-defun-type-regexp arg treesit-defun-tactic) + (when (treesit-end-of-thing pred arg treesit-defun-tactic) (when treesit-defun-skipper (funcall treesit-defun-skipper))) @@ -2041,6 +2058,8 @@ this function depends on `treesit-defun-type-regexp' and (throw 'done nil) (setq arg (if (> arg 0) (1+ arg) (1- arg)))))))) +(make-obsolete 'treesit-text-type-regexp "`treesit-text-type-regexp' will be removed in a few months, use `treesit-thing-settings' instead." "30.0.5") + (defvar-local treesit-text-type-regexp "\\`comment\\'" "A regexp that matches the node type of textual nodes. @@ -2050,6 +2069,8 @@ comments and multiline string literals. For example, \"text_block\" in the case of a string. This is used by `prog-fill-reindent-defun' and friends.") +(make-obsolete 'treesit-sentence-type-regexp "`treesit-sentence-type-regexp' will be removed in a few months, use `treesit-thing-settings' instead." "30.0.5") + (defvar-local treesit-sentence-type-regexp nil "A regexp that matches the node type of sentence nodes. @@ -2059,21 +2080,21 @@ smaller in scope than defuns. This is used by `treesit-forward-sentence' and friends.") (defun treesit-forward-sentence (&optional arg) - "Tree-sitter `forward-sentence-function' function. + "Tree-sitter `forward-sentence-function' implementation. ARG is the same as in `forward-sentence'. -If inside comment or other nodes described in -`treesit-sentence-type-regexp', use -`forward-sentence-default-function', else move across nodes as -described by `treesit-sentence-type-regexp'." - (if (string-match-p - treesit-text-type-regexp - (treesit-node-type (treesit-node-at (point)))) +If point is inside a text environment, go forward a prose +sentence using `forward-sentence-default-function'. If point is +inside code, go forward a source code sentence. + +What constitutes as text and source code sentence is determined +by `text' and `sentence' in `treesit-thing-settings'." + (if (treesit-node-match-p (treesit-node-at (point)) 'text) (funcall #'forward-sentence-default-function arg) (funcall (if (> arg 0) #'treesit-end-of-thing #'treesit-beginning-of-thing) - treesit-sentence-type-regexp (abs arg)))) + 'sentence (abs arg)))) (defun treesit-default-defun-skipper () "Skips spaces after navigating a defun. @@ -2111,8 +2132,8 @@ previous and next sibling things around POS, and PARENT is the parent thing surrounding POS. All of three could be nil if no sound things exists. -PRED can be a regexp, a predicate function, and more. See -`treesit-thing-settings' for details." +PRED should be a thing defined in `treesit-thing-settings', it +can also be a predicate, which see." (let* ((node (treesit-node-at pos)) (result (list nil nil nil))) ;; 1. Find previous and next sibling defuns. @@ -2319,10 +2340,11 @@ Respects `treesit-defun-tactic': return the top-level defun if it is `top-level', return the immediate parent defun if it is `nested'. -Return nil if `treesit-defun-type-regexp' is not set." - (when treesit-defun-type-regexp +Return nil if `treesit-defun-type-regexp' isn't set and `defun' +isn't defined in `treesit-thing-settings'." + (when (or treesit-defun-type-regexp (treesit-thing-defined-p 'defun)) (treesit-thing-at-point - treesit-defun-type-regexp treesit-defun-tactic))) + (or treesit-defun-type-regexp 'defun) treesit-defun-tactic))) (defun treesit-defun-name (node) "Return the defun name of NODE. @@ -2495,14 +2517,18 @@ and enable `font-lock-mode'. If `treesit-simple-indent-rules' is non-nil, set up indentation. -If `treesit-defun-type-regexp' is non-nil, set up -`beginning-of-defun-function' and `end-of-defun-function'. +If `treesit-defun-type-regexp' is non-nil or `defun' is defined +in `treesit-thing-settings', set up `beginning-of-defun-function' +and `end-of-defun-function'. If `treesit-defun-name-function' is non-nil, set up `add-log-current-defun'. If `treesit-simple-imenu-settings' is non-nil, set up Imenu. +If `sexp', `sentence' are defined in `treesit-thing-settings', +enable tree-sitter navigation commands for them. + Make sure necessary parsers are created for the current buffer before calling this function." ;; Font-lock. @@ -2526,7 +2552,7 @@ before calling this function." (setq-local indent-line-function #'treesit-indent) (setq-local indent-region-function #'treesit-indent-region)) ;; Navigation. - (when treesit-defun-type-regexp + (when (or treesit-defun-type-regexp (treesit-thing-defined-p 'defun)) (keymap-set (current-local-map) " " #'treesit-beginning-of-defun) (keymap-set (current-local-map) " " @@ -2545,10 +2571,10 @@ before calling this function." (setq-local add-log-current-defun-function #'treesit-add-log-current-defun)) - (when treesit-sexp-type-regexp + (when (treesit-thing-defined-p 'sexp) (setq-local forward-sexp-function #'treesit-forward-sexp)) (setq-local transpose-sexps-function #'treesit-transpose-sexps) - (when treesit-sentence-type-regexp + (when (treesit-thing-defined-p 'sentence) (setq-local forward-sentence-function #'treesit-forward-sentence)) ;; Imenu.