* lisp/progmodes/elixir-ts-mode.el (elixir-ts--range-rules):
Rename to a shorter name from 'elixir-ts--treesit-range-rules'.
(elixir-ts--font-lock-feature-list, elixir-ts--thing-settings)
(elixir-ts--range-rules): New variables with default values
extracted from 'elixir-ts-mode'.
(elixir-ts-mode): Use 'elixir-ts--font-lock-feature-list',
'elixir-ts--thing-settings', 'elixir-ts--range-rules'
and 'heex-ts--range-rules'.
Use 'treesit-merge-font-lock-feature-list' to merge
'heex-ts--font-lock-feature-list'.
* lisp/progmodes/heex-ts-mode.el
(heex-ts--font-lock-feature-list, heex-ts--range-rules):
New variables.
(heex-ts-mode): Use 'heex-ts--font-lock-feature-list',
'heex-ts--range-rules'. Merge 'elixir-ts--font-lock-settings',
'elixir-ts--font-lock-feature-list', 'elixir-ts--thing-settings'
for embedding elixir in heex. Enable the 'sexp' navigation
by default with 'treesit-cycle-sexp-type'.
* lisp/progmodes/c-ts-mode.el (c-ts-mode): Append
'treesit-range-rules' to possibly already existing list in
'treesit-range-settings'.
* lisp/treesit.el (treesit-language-at-point-default):
Optimize to use 'when-let*'.
* lisp/treesit.el (treesit-language-at-point-default): Return
nil if there's no parser in the buffer.
(treesit-parsers-at): Add docstring for parser order.
Don't add the primary parser or the first of treesit-parser-list
when non-nil 'with-host' is provided since there is no host
for the primary parser (bug#76788).
* lisp/treesit.el (treesit-parsers-at): Add treesit-primary-parser
only when it's non-nil. When the result list is still empty,
add the first parser from 'treesit-parser-list'.
https://lists.gnu.org/archive/html/emacs-devel/2025-04/msg00627.html
* test/src/treesit-tests.el (treesit-node-supplemental)
(treesit-node-at, treesit-node-check)
(treesit-search-subtree-forward-1)
(treesit-search-subtree-backward-1): Wrap test body in 'with-temp-buffer'.
* lisp/outline.el (outline-after-change-functions): New variable.
(outline--fix-buttons-after-change):
Run hook 'outline-after-change-functions'.
* lisp/treesit.el (treesit--after-change): Improve docstring.
(treesit-major-mode-setup): Simplify to just add
'treesit--after-change' to 'outline-after-change-functions' hook.
* lisp/progmodes/rust-ts-mode.el (rust-ts-mode): Add explicit
'treesit-outline-predicate' that is like
'treesit-simple-imenu-settings', but also adds "trait_item".
* lisp/treesit.el (treesit-language-at-point-function):
Change the default value from nil to 'treesit-language-at-point-default'.
(treesit-language-at): Funcall 'treesit-language-at-point-function'
unconditionally.
(treesit-language-at-point-default): New function with body from
'treesit-language-at'.
(treesit-node-at): Simplify by replacing duplicate code
with the call to 'treesit-parsers-at'.
* lisp/treesit.el (treesit-forward-sexp): Don't use
'treesit-sexp-type-regexp' reserved for list commands
to override their default 'list' thing.
(treesit-down-list, treesit-up-list): Use
'treesit-sexp-type-regexp' instead of 'list'
when it's non-nil.
(treesit-toggle-sexp-mode): New command.
* lisp/progmodes/c-ts-mode.el (c-ts-mode--thing-settings):
Improve 'sexp' thing settings to exclude the top-level
"translation_unit" that just moves to EOF and also "comment".
* lisp/progmodes/elixir-ts-mode.el (elixir-ts--sexp-regexp): Remove.
(elixir-ts--forward-sexp): Remove to use the default 'sexp' navigation.
(elixir-ts--with-parens-0-p, elixir-ts--with-parens-1-p):
New internal functions.
(elixir-ts-mode): Add 'treesit-thing-settings'
instead of 'forward-sexp-function' (bug#76788).
* lisp/progmodes/heex-ts-mode.el (heex-ts--sexp-regexp): Remove.
(heex-ts--forward-sexp): Remove to use the default 'sexp' navigation.
(heex-ts--thing-settings): New variable.
(heex-ts-mode): Use 'heex-ts--thing-settings'
instead of 'forward-sexp-function'.
* lisp/progmodes/java-ts-mode.el (java-ts-mode):
Improve 'sexp' thing to use settings like in c-ts-mode.
* lisp/progmodes/php-ts-mode.el (php-ts-mode):
Improve 'sexp' thing settings to exclude the top-level
"program" that just moves to EOF and also "comment".
* lisp/progmodes/ruby-ts-mode.el (ruby-ts-mode):
Improve 'sexp' thing to use settings like in c-ts-mode.
* lisp/textmodes/css-mode.el (css--treesit-thing-settings):
Add 'sexp' thing. Add "string_value" to 'text' thing.
* lisp/textmodes/html-ts-mode.el (html-ts-mode--treesit-things-settings):
Improve 'sexp' thing to use settings like in c-ts-mode.
Add "doctype" to the 'list' thing.
* lisp/treesit.el (treesit-outline-search): Remove
temporary arg 'recursive'. Use iteration to visit
more ranges until the next outline heading is found.
* lisp/progmodes/php-ts-mode.el (php-ts-mode):
Set 'treesit-outline-predicate' explicitly.
(treesit-major-mode-setup): Set 'outline-minor-mode-hook'
to add 'treesit--after-change' with 'treesit-update-ranges'
to 'after-change-functions' (bug#77256).
* doc/lispref/parsing.texi (Multiple Languages): The variable
'treesit-language-at-point-function' is now optional for
multi-language major modes. Add description of 'treesit-parsers-at'.
* lisp/treesit.el (treesit-language-at-point-function):
Change the the docstring to remove the dissuasion against
deriving the language from parser ranges.
(treesit-language-at): Use the first parser from
'treesit-parsers-at' as the default return value when
'treesit-language-at-point-function' is nil. Adapt the docstring.
(treesit-node-at): Use 'treesit-parsers-at'.
(treesit-parsers-at): New function.
(treesit-local-parsers-at): Use 'treesit-parsers-at'
with the most part of the body moved to it.
(treesit-local-parsers-on): Replace the overlay property
'treesit-parser' with 'treesit-parser-local-p' in the docstring.
(treesit-up-list, treesit-simple-imenu, treesit-outline-level):
Use 'treesit-parsers-at'.
* lisp/progmodes/c-ts-mode.el (c-ts-mode): Don't set
'treesit-language-at-point-function'.
* lisp/progmodes/elixir-ts-mode.el (elixir-ts--treesit-language-at-point):
Remove.
(elixir-ts-mode): Don't set 'treesit-language-at-point-function'.
* lisp/progmodes/js.el (js--treesit-language-at-point): Remove.
(js-ts-mode): Don't set 'treesit-language-at-point-function'.
* lisp/progmodes/php-ts-mode.el (php-ts-mode--html-language-at-point)
(php-ts-mode--language-at-point): Remove.
(php-ts-mode): Don't set 'treesit-language-at-point-function'.
* lisp/textmodes/mhtml-ts-mode.el (mhtml-ts-mode--language-at-point):
Remove.
(mhtml-ts-mode): Don't set 'treesit-language-at-point-function'.
Use 'treesit-language-at' for mode-line lighter.
* lisp/treesit.el (treesit-replace-font-lock-feature-settings):
Check the query language in addition to checking the feature.
(treesit-font-lock-fontify-region): Use treesit-font-lock-setting-*
accessors.
* lisp/treesit-x.el (treesit-generic-mode-setup): Append new
font-lock rules to an existing treesit-font-lock-settings
possibly inherited from the parent.
(treesit-generic-mode-setup): Use treesit-merge-font-lock-feature-list
to merge with an existing feature list inherited from the parent.
(liquid-generic-ts-mode): New treesit generic mode.
(alpinejs-generic-ts-setup): New treesit generic setup.
* lisp/treesit.el (treesit-forward-sentence): When no more
sentences are found, move to the end of the buffer or to
the range boundary at the 'treesit-parser' overlay's end.
* lisp/treesit.el (treesit-closest-parser-boundary):
Remove temporary function.
(treesit-outline-search): Use 'previous/next-single-char-property-change'
with 'treesit-parser' property to find the closest parser boundary.
(treesit-outline-level): Get the 'treesit-host-parser' overlay
and find the parent parser node with 'treesit-node-at'.
(Unrelated to the topic of the bug, but mentioned in the
thread.)
* lisp/treesit.el (treesit--explorer-refresh-1): New function.
(treesit--explorer-refresh): Handle 'treesit-parser-deleted'
error.
* lisp/treesit.el (treesit-local-parsers-at):
(treesit-local-parsers-on): Exclude non-local parsers.
(treesit--cleanup-local-range-overlays): Don't delete non-local
parsers (because those are managed by the major mode).
(treesit--update-ranges-non-local): Apply overlay for each ranges.
(treesit--update-ranges-local): Ignore
overlays with non-local parsers, and set
'treesit-parser-local-p' property to t.
(treesit--update-range-1): Additionally pass modified-tick to
treesit--update-ranges-non-local.
(treesit-major-mode-setup): Don't delete non-local parsers.
This fixes a bug where we call treesit-query-language on a
function, which happens before the QUERY in a range setting can
be either a function or a query, but we call it with
treesit-query-language before knowing whether it's a query or
function.
* lisp/treesit.el:
(treesit--update-range-1): Skip function range settings.
(treesit-update-ranges): Handle function range settings here.
Some embedded parser needs to exclude child nodes from the
range, like markdown-inline. So I added this keyword that
allows users to customize the range for the embedded parser.
This can also be potentially useful for markdown comments in
rust, for example, because we want to exclude the comment
starters (//) from the embedded markdown parser.
* lisp/treesit.el (treesit-query-range):
(treesit-query-range-by-language): Add new parameter RANGE-FN.
(treesit-range-settings): Add new field RANGE-FN.
(treesit-range-rules): Add new keyword RANGE-FN.
(treesit-range-fn-exclude-children): New function.
(treesit--update-ranges-non-local):
(treesit--update-ranges-local):
(treesit--update-range-1): Support the RANGE-FN field.
Make use of the newly added embed-level parser property, we now
iterativeLy create/update embedded parsers at each embed level,
allowing arbitrary levels of nesting.
At the beginning, we start with the primary parser. We query it
with each range settings, gets some ranges and their
corresponding language. Then we create the first level of
embedded parsers using the ranges and language we got. This is
one iteration. For the next iteration/level, we start with the
embedded parsers we create/updated in the previous
iteration/level, and query each of them with each of the range
settings, creating/updating the next level of embedded parsers.
And we keep doing this until we don't get more matches from the
queries.
We now also support the :embed keyword in 'treesit-range-rules'
to be a function that returns a language. This allows major
modes like markdown and org mode to support code blocks of which
the language isn't known ahead of time.
* lisp/treesit.el (treesit-primary-parser): Move to front.
(treesit-query-range-by-language): New function.
(treesit-range-rules): Allow :embed to be a function, update docstring.
(treesit-local-parsers-on): Update docstring.
(treesit--parser-at-level):
(treesit--update-ranges-non-local): New functions.
(treesit--update-ranges-local): Use the new logic, support
:embed being a function.
(treesit--update-range-1): New function, has the meat of
original treesit-update-ranges.
(treesit-update-ranges): Implements the iteration logic using
treesit--update-range-1 to do the actual work.
* lisp/treesit.el (treesit-outline-search): Add optional arg
'recursive' to avoid infinite recursion when it gets stuck.
* lisp/textmodes/markdown-ts-mode.el (markdown-ts-mode):
Set buffer-local 'treesit-outline-predicate' to "section".
* doc/lispref/modes.texi (Outline Minor Mode):
Add 'treesit-aggregated-outline-predicate'.
* lisp/treesit.el (treesit-aggregated-outline-predicate):
New buffer-local variable.
(treesit-outline--at-point):
Use 'treesit-aggregated-outline-predicate'.
(treesit-closest-parser-boundary): New function.
(treesit-outline-search): Use 'treesit-aggregated-outline-predicate'
and 'treesit-closest-parser-boundary'.
(treesit-outline-level): Use 'treesit-aggregated-outline-predicate'.
(treesit-major-mode-setup): Add 'treesit-aggregated-outline-predicate'.
* lisp/textmodes/html-ts-mode.el (html-ts-mode--outline-predicate):
Improve.
* lisp/textmodes/mhtml-ts-mode.el (mhtml-ts-mode):
Set 'treesit-aggregated-outline-predicate'.
* lisp/treesit.el (treesit-simple-indent-modify-rules): Rename
and fix docstring. It should be matcher, not anchor. Also
reword a little bit.
* etc/NEWS: Update.
* lisp/textmodes/mhtml-ts-mode.el:
(mhtml-ts-mode--treesit-indent-rules): Update accordingly.