diff options
| author | Yuan Fu | 2024-04-16 23:46:39 -0700 |
|---|---|---|
| committer | Yuan Fu | 2024-04-19 19:04:44 -0700 |
| commit | 996b9576713f9d63ea7ff7e9630a15cb0a0214eb (patch) | |
| tree | 9e64d1677b26df5b52ee0baeb8d23fae643dfb19 /src | |
| parent | 8166d9d1747648d1f457195090ad36dd333bbc52 (diff) | |
| download | emacs-996b9576713f9d63ea7ff7e9630a15cb0a0214eb.tar.gz emacs-996b9576713f9d63ea7ff7e9630a15cb0a0214eb.zip | |
New function treesit-parser-changed-ranges
- Add a new field last_changed_ranges to tree-sitter parser object.
- Add a new function treesit-parser-changed-ranges
* doc/lispref/parsing.texi (Using Parser): Add the function in
tree-sitter manual.
* src/treesit.c (treesit_get_changed_ranges): New function, refactored
out of treesit_call_after_change_functions.
(treesit_call_after_change_functions): Pull out
treesit_get_changed_ranges.
(treesit_ensure_parsed): Save the changed ranges to the parser object.
(make_treesit_parser): Initialize the new parser field
last_changed_ranges.
(Ftreesit_parser_changed_ranges): New function.
(Qtreesit_unparsed_edits): New error.
* src/treesit.h (Lisp_TS_Parser): New field.
Diffstat (limited to 'src')
| -rw-r--r-- | src/treesit.c | 49 | ||||
| -rw-r--r-- | src/treesit.h | 3 |
2 files changed, 48 insertions, 4 deletions
diff --git a/src/treesit.c b/src/treesit.c index d86ab501187..76354361284 100644 --- a/src/treesit.c +++ b/src/treesit.c | |||
| @@ -1017,9 +1017,8 @@ treesit_check_buffer_size (struct buffer *buffer) | |||
| 1017 | 1017 | ||
| 1018 | static Lisp_Object treesit_make_ranges (const TSRange *, uint32_t, struct buffer *); | 1018 | static Lisp_Object treesit_make_ranges (const TSRange *, uint32_t, struct buffer *); |
| 1019 | 1019 | ||
| 1020 | static void | 1020 | static Lisp_Object |
| 1021 | treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree, | 1021 | treesit_get_changed_ranges (TSTree *old_tree, TSTree *new_tree, Lisp_Object parser) |
| 1022 | Lisp_Object parser) | ||
| 1023 | { | 1022 | { |
| 1024 | /* If the old_tree is NULL, meaning this is the first parse, the | 1023 | /* If the old_tree is NULL, meaning this is the first parse, the |
| 1025 | changed range is the whole buffer. */ | 1024 | changed range is the whole buffer. */ |
| @@ -1039,7 +1038,13 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree, | |||
| 1039 | lisp_ranges = Fcons (Fcons (Fpoint_min (), Fpoint_max ()), Qnil); | 1038 | lisp_ranges = Fcons (Fcons (Fpoint_min (), Fpoint_max ()), Qnil); |
| 1040 | set_buffer_internal (oldbuf); | 1039 | set_buffer_internal (oldbuf); |
| 1041 | } | 1040 | } |
| 1041 | return lisp_ranges; | ||
| 1042 | } | ||
| 1042 | 1043 | ||
| 1044 | static void | ||
| 1045 | treesit_call_after_change_functions (Lisp_Object lisp_ranges, | ||
| 1046 | Lisp_Object parser) | ||
| 1047 | { | ||
| 1043 | specpdl_ref count = SPECPDL_INDEX (); | 1048 | specpdl_ref count = SPECPDL_INDEX (); |
| 1044 | 1049 | ||
| 1045 | /* let's trust the after change functions and not clone a new ranges | 1050 | /* let's trust the after change functions and not clone a new ranges |
| @@ -1091,13 +1096,17 @@ treesit_ensure_parsed (Lisp_Object parser) | |||
| 1091 | XTS_PARSER (parser)->tree = new_tree; | 1096 | XTS_PARSER (parser)->tree = new_tree; |
| 1092 | XTS_PARSER (parser)->need_reparse = false; | 1097 | XTS_PARSER (parser)->need_reparse = false; |
| 1093 | 1098 | ||
| 1099 | Lisp_Object changed_ranges; | ||
| 1100 | changed_ranges = treesit_get_changed_ranges (tree, new_tree, parser); | ||
| 1101 | XTS_PARSER (parser)->last_changed_ranges = changed_ranges; | ||
| 1102 | |||
| 1094 | /* After-change functions should run at the very end, most crucially | 1103 | /* After-change functions should run at the very end, most crucially |
| 1095 | after need_reparse is set to false, this way if the function | 1104 | after need_reparse is set to false, this way if the function |
| 1096 | calls some tree-sitter function which invokes | 1105 | calls some tree-sitter function which invokes |
| 1097 | treesit_ensure_parsed again, it returns early and do not | 1106 | treesit_ensure_parsed again, it returns early and do not |
| 1098 | recursively call the after change functions again. | 1107 | recursively call the after change functions again. |
| 1099 | (ref:notifier-inside-ensure-parsed) */ | 1108 | (ref:notifier-inside-ensure-parsed) */ |
| 1100 | treesit_call_after_change_functions (tree, new_tree, parser); | 1109 | treesit_call_after_change_functions (changed_ranges, parser); |
| 1101 | ts_tree_delete (tree); | 1110 | ts_tree_delete (tree); |
| 1102 | } | 1111 | } |
| 1103 | 1112 | ||
| @@ -1171,6 +1180,7 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser, | |||
| 1171 | lisp_parser->after_change_functions = Qnil; | 1180 | lisp_parser->after_change_functions = Qnil; |
| 1172 | lisp_parser->tag = tag; | 1181 | lisp_parser->tag = tag; |
| 1173 | lisp_parser->last_set_ranges = Qnil; | 1182 | lisp_parser->last_set_ranges = Qnil; |
| 1183 | lisp_parser->last_changed_ranges = Qnil; | ||
| 1174 | lisp_parser->buffer = buffer; | 1184 | lisp_parser->buffer = buffer; |
| 1175 | lisp_parser->parser = parser; | 1185 | lisp_parser->parser = parser; |
| 1176 | lisp_parser->tree = tree; | 1186 | lisp_parser->tree = tree; |
| @@ -1818,6 +1828,32 @@ positions. PARSER is the parser issuing the notification. */) | |||
| 1818 | return Qnil; | 1828 | return Qnil; |
| 1819 | } | 1829 | } |
| 1820 | 1830 | ||
| 1831 | DEFUN ("treesit-parser-changed-ranges", Ftreesit_parser_changed_ranges, | ||
| 1832 | Streesit_parser_changed_ranges, | ||
| 1833 | 1, 2, 0, | ||
| 1834 | doc: /* Return the buffer regions affected by the last reparse of PARSER. | ||
| 1835 | |||
| 1836 | Returns a list of cons (BEG . END), where each cons represents a region | ||
| 1837 | in which the buffer content was affected by the last reparse. | ||
| 1838 | |||
| 1839 | This function should almost always be called immediately after | ||
| 1840 | reparsing. If it's called when there are new buffer edits that hasn't | ||
| 1841 | been reparsed, Emacs signals `treesit-unparsed-edits', unless QUIET is | ||
| 1842 | non-nil. | ||
| 1843 | |||
| 1844 | Calling this function multiple times consecutively doesn't change its | ||
| 1845 | return value; it always returns the ranges affected by the last | ||
| 1846 | reparse. */) | ||
| 1847 | (Lisp_Object parser, Lisp_Object quiet) | ||
| 1848 | { | ||
| 1849 | treesit_check_parser (parser); | ||
| 1850 | |||
| 1851 | if (XTS_PARSER (parser)->need_reparse && NILP (quiet)) | ||
| 1852 | xsignal1 (Qtreesit_unparsed_edits, parser); | ||
| 1853 | |||
| 1854 | return XTS_PARSER (parser)->last_changed_ranges; | ||
| 1855 | } | ||
| 1856 | |||
| 1821 | 1857 | ||
| 1822 | /*** Node API */ | 1858 | /*** Node API */ |
| 1823 | 1859 | ||
| @@ -4010,6 +4046,7 @@ syms_of_treesit (void) | |||
| 4010 | DEFSYM (Qtreesit_query_error, "treesit-query-error"); | 4046 | DEFSYM (Qtreesit_query_error, "treesit-query-error"); |
| 4011 | DEFSYM (Qtreesit_parse_error, "treesit-parse-error"); | 4047 | DEFSYM (Qtreesit_parse_error, "treesit-parse-error"); |
| 4012 | DEFSYM (Qtreesit_range_invalid, "treesit-range-invalid"); | 4048 | DEFSYM (Qtreesit_range_invalid, "treesit-range-invalid"); |
| 4049 | DEFSYM (Qtreesit_unparsed_edits, "treesit-unparsed_edits"); | ||
| 4013 | DEFSYM (Qtreesit_buffer_too_large, | 4050 | DEFSYM (Qtreesit_buffer_too_large, |
| 4014 | "treesit-buffer-too-large"); | 4051 | "treesit-buffer-too-large"); |
| 4015 | DEFSYM (Qtreesit_load_language_error, | 4052 | DEFSYM (Qtreesit_load_language_error, |
| @@ -4038,6 +4075,8 @@ syms_of_treesit (void) | |||
| 4038 | define_error (Qtreesit_range_invalid, | 4075 | define_error (Qtreesit_range_invalid, |
| 4039 | "RANGES are invalid: they have to be ordered and should not overlap", | 4076 | "RANGES are invalid: they have to be ordered and should not overlap", |
| 4040 | Qtreesit_error); | 4077 | Qtreesit_error); |
| 4078 | define_error (Qtreesit_unparsed_edits, "There are unparsed edits in the buffer", | ||
| 4079 | Qtreesit_error); | ||
| 4041 | define_error (Qtreesit_buffer_too_large, "Buffer too large (> 4GiB)", | 4080 | define_error (Qtreesit_buffer_too_large, "Buffer too large (> 4GiB)", |
| 4042 | Qtreesit_error); | 4081 | Qtreesit_error); |
| 4043 | define_error (Qtreesit_load_language_error, | 4082 | define_error (Qtreesit_load_language_error, |
| @@ -4178,6 +4217,8 @@ the symbol of that THING. For example, (or sexp sentence). */); | |||
| 4178 | defsubr (&Streesit_parser_add_notifier); | 4217 | defsubr (&Streesit_parser_add_notifier); |
| 4179 | defsubr (&Streesit_parser_remove_notifier); | 4218 | defsubr (&Streesit_parser_remove_notifier); |
| 4180 | 4219 | ||
| 4220 | defsubr (&Streesit_parser_changed_ranges); | ||
| 4221 | |||
| 4181 | defsubr (&Streesit_node_type); | 4222 | defsubr (&Streesit_node_type); |
| 4182 | defsubr (&Streesit_node_start); | 4223 | defsubr (&Streesit_node_start); |
| 4183 | defsubr (&Streesit_node_end); | 4224 | defsubr (&Streesit_node_end); |
diff --git a/src/treesit.h b/src/treesit.h index bb81bf0e2b3..aa71933fe8d 100644 --- a/src/treesit.h +++ b/src/treesit.h | |||
| @@ -49,6 +49,9 @@ struct Lisp_TS_Parser | |||
| 49 | ranges the users wants to set, and avoid reparse if the new | 49 | ranges the users wants to set, and avoid reparse if the new |
| 50 | ranges is the same as the last set one. */ | 50 | ranges is the same as the last set one. */ |
| 51 | Lisp_Object last_set_ranges; | 51 | Lisp_Object last_set_ranges; |
| 52 | /* The range of buffer content that was affected by the last | ||
| 53 | re-parse. */ | ||
| 54 | Lisp_Object last_changed_ranges; | ||
| 52 | /* The buffer associated with this parser. */ | 55 | /* The buffer associated with this parser. */ |
| 53 | Lisp_Object buffer; | 56 | Lisp_Object buffer; |
| 54 | /* The pointer to the tree-sitter parser. Never NULL. */ | 57 | /* The pointer to the tree-sitter parser. Never NULL. */ |