spans point, and its immediate parent.
This minor mode doesn't create parsers on its own. It simply uses the
-first parser in @var{treesit-parser-list} (@pxref{Using Parser}).
+first parser in @code{(treesit-parser-list)} (@pxref{Using Parser}).
@end deffn
@heading Reading the grammar definition
size exceeds that, Emacs signals @var{treesit-buffer-too-large}
with signal data being the buffer size.
-@vindex treesit-parser-list
Once a parser is created, Emacs automatically adds it to the
-buffer-local variable @var{treesit-parser-list}. Every time a
-change is made to the buffer, Emacs updates parsers in this list so
-they can update their syntax tree incrementally. Therefore, one must
-not remove parsers from this list and put the parser back in: if any
-change is made when that parser is absent, the parser will be
-permanently out-of-sync with the buffer content, and shouldn't be used
-anymore.
+buffer-local parser list. Every time a change is made to the buffer,
+Emacs updates parsers in this list so they can update their syntax
+tree incrementally.
+
+@defun treesit-parser-list &optional buffer
+This function returns the parser list of @var{buffer}. And
+@var{buffer} defaults to the current buffer.
+@end defun
+
+@defun treesit-parser-delete parser
+This function deletes @var{parser}.
+@end defun
@cindex tree-sitter narrowing
@anchor{tree-sitter narrowing} Normally, a parser ``sees'' the whole
greater than @var{point}.
When @var{parser-or-lang} is nil, this function uses the first parser
-in @var{treesit-parser-list} in the current buffer. If
+in @code{(treesit-parser-list)} in the current buffer. If
@var{parser-or-lang} is a parser object, it use that parser; if
@var{parser-or-lang} is a language, it finds the first parser using
-that language in @var{treesit-parser-list} and use that.
+that language in @code{(treesit-parser-list)} and use that.
If @var{named} is non-nil, this function looks for a named node
instead (@pxref{tree-sitter named node, named node}).
@code{treesit-node-at} instead.
When @var{parser-or-lang} is nil, this function uses the first parser
-in @var{treesit-parser-list} in the current buffer. If
+in @code{(treesit-parser-list)} in the current buffer. If
@var{parser-or-lang} is a parser object, it use that parser; if
@var{parser-or-lang} is a language, it finds the first parser using
-that language in @var{treesit-parser-list} and use that.
+that language in @code{(treesit-parser-list)} and use that.
If @var{named} is non-nil, this function looks for a named node
instead (@pxref{tree-sitter named node, named node}).
@defun treesit-buffer-root-node &optional language
This function finds the first parser that uses @var{language} in
-@var{treesit-parser-list} in the current buffer, and returns the
+@code{(treesit-parser-list)} in the current buffer, and returns the
root node of that buffer. If it cannot find an appropriate parser, it
returns nil.
@end defun
the ranges of @var{parser-or-lang} to @var{ranges}. Conveniently,
@var{parser-or-lang} could be either a parser or a language. If it is
a language, this function looks for the first parser in
-@var{treesit-parser-list} for that language in the current buffer,
+@code{(treesit-parser-list)} for that language in the current buffer,
and set range for it.
@end defun
@defun treesit-language-at point
This function tries to figure out which language is responsible for
the text at @var{point}. It goes over each parser in
-@var{treesit-parser-list} and see if that parser's range covers
+@code{(treesit-parser-list)} and see if that parser's range covers
@var{point}.
@end defun
(defun treesit-language-at (point)
"Return the language used at POINT."
- (cl-loop for parser in treesit-parser-list
+ (cl-loop for parser in (treesit-parser-list)
if (treesit-node-on point point parser)
return (treesit-parser-language parser)))
non-nil, only look for named node.
If PARSER-OR-LANG is nil, use the first parser in
-`treesit-parser-list'; if PARSER-OR-LANG is a parser, use
+(`treesit-parser-list'); if PARSER-OR-LANG is a parser, use
that parser; if PARSER-OR-LANG is a language, find a parser using
that language in the current buffer, and use that."
(let ((node (if (treesit-parser-p parser-or-lang)
node.
If PARSER-OR-LANG is nil, use the first parser in
-`treesit-parser-list'; if PARSER-OR-LANG is a parser, use
+(`treesit-parser-list'); if PARSER-OR-LANG is a parser, use
that parser; if PARSER-OR-LANG is a language, find a parser using
that language in the current buffer, and use that."
(let ((root (if (treesit-parser-p parser-or-lang)
(defun treesit-buffer-root-node (&optional language)
"Return the root node of the current buffer.
-Use the first parser in `treesit-parser-list', if LANGUAGE is
+Use the first parser in (`treesit-parser-list'), if LANGUAGE is
non-nil, use the first parser for LANGUAGE."
(if-let ((parser
(or (if language
(or (treesit-parser-create language)
(error "Cannot find a parser for %s" language))
- (or (car treesit-parser-list)
+ (or (car (treesit-parser-list))
(error "Buffer has no parser"))))))
(treesit-parser-root-node parser)))
(skip-chars-forward " \t")
(point)))
(smallest-node
- (cl-loop for parser in treesit-parser-list
+ (cl-loop for parser in (treesit-parser-list)
for node = (treesit-node-at bol parser)
if node return node))
(node (treesit-parent-while
QUERY has to capture the node to match. LANG specifies the
language in which we search for nodes. If LANG is nil, use the
-first parser in `treesit-parser-list'.
+first parser in (`treesit-parser-list').
Move forward/backward ARG times, positive ARG means go forward,
negative ARG means go backward.
(cl-loop for idx from 1 to (abs arg)
for parser = (if lang
(treesit-parser-create lang)
- (car treesit-parser-list))
+ (car (treesit-parser-list)))
for node =
(if-let ((starting-point (point))
(node (treesit-node-at (point) parser t)))
QUERY has to capture the node to match. LANG specifies the
language in which we search for nodes. If LANG is nil, use the
-first parser in `treesit-parser-list'.
+first parser in (`treesit-parser-list').
Move forward/backward ARG times, positive ARG means go forward,
negative ARG means go backward.
QUERY has to capture the node to match. LANG specifies the
language in which we search for nodes. If LANG is nil, use the
-first parser in `treesit-parser-list'.
+first parser in (`treesit-parser-list').
Move forward/backward ARG times, positive ARG means go forward,
negative ARG means go backward.
If called interactively, show in echo area, otherwise set
`treesit--inspect-name' (which will appear in the mode-line
if `treesit-inspect-mode' is enabled). Uses the first parser
-in `treesit-parser-list'."
+in (`treesit-parser-list')."
(interactive "p")
;; NODE-LIST contains all the node that starts at point.
(let* ((node-list
its immediate parent.
This minor mode doesn't create parsers on its own. It simply
-uses the first parser in `treesit-parser-list'."
+uses the first parser in (`treesit-parser-list')."
:lighter nil
(if treesit-inspect-mode
(progn
{
b->extra_line_spacing_ = val;
}
+#ifdef HAVE_TREE_SITTER
+static void
+bset_ts_parser_list (struct buffer *b, Lisp_Object val)
+{
+ b->ts_parser_list_ = val;
+}
+#endif
static void
bset_file_format (struct buffer *b, Lisp_Object val)
{
(b, BVAR (&buffer_defaults, enable_multibyte_characters));
bset_cursor_type (b, BVAR (&buffer_defaults, cursor_type));
bset_extra_line_spacing (b, BVAR (&buffer_defaults, extra_line_spacing));
+#ifdef HAVE_TREE_SITTER
+ bset_ts_parser_list (b, Qnil);
+#endif
b->display_error_modiff = 0;
}
XSETFASTINT (BVAR (&buffer_local_flags, tab_line_format), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, cursor_type), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, extra_line_spacing), idx); ++idx;
+#ifdef HAVE_TREE_SITTER
+ XSETFASTINT (BVAR (&buffer_local_flags, ts_parser_list), idx); ++idx;
+#endif
XSETFASTINT (BVAR (&buffer_local_flags, cursor_in_non_selected_windows), idx); ++idx;
/* buffer_local_flags contains no pointers, so it's safe to treat it
bset_bidi_paragraph_separate_re (&buffer_defaults, Qnil);
bset_cursor_type (&buffer_defaults, Qt);
bset_extra_line_spacing (&buffer_defaults, Qnil);
+#ifdef HAVE_TREE_SITTER
+ bset_ts_parser_list (&buffer_defaults, Qnil);
+#endif
bset_cursor_in_non_selected_windows (&buffer_defaults, Qt);
bset_enable_multibyte_characters (&buffer_defaults, Qt);
in the display of this buffer. */
Lisp_Object extra_line_spacing_;
+#ifdef HAVE_TREE_SITTER
+ /* A list of tree-sitter parsers for this buffer. */
+ Lisp_Object ts_parser_list_;
+#endif
/* Cursor type to display in non-selected windows.
t means to use hollow box cursor.
See `cursor-type' for other values. */
ts_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
ptrdiff_t new_end_byte)
{
- for (Lisp_Object parser_list =
- Fsymbol_value (Qtreesit_parser_list);
+ for (Lisp_Object parser_list
+ = BVAR (current_buffer, ts_parser_list);
!NILP (parser_list);
parser_list = XCDR (parser_list))
{
ts_initialize ();
CHECK_SYMBOL (language);
- struct buffer *old_buffer = current_buffer;
- if (!NILP (buffer))
+ struct buffer *buf;
+ if (NILP (buffer))
+ buf = current_buffer;
+ else
{
CHECK_BUFFER (buffer);
- set_buffer_internal (XBUFFER (buffer));
+ buf = XBUFFER (buffer);
}
- ts_check_buffer_size (current_buffer);
+ ts_check_buffer_size (buf);
/* See if we can reuse a parser. */
- for (Lisp_Object tail = Fsymbol_value (Qtreesit_parser_list);
+ for (Lisp_Object tail = BVAR (buf, ts_parser_list);
NILP (no_reuse) && !NILP (tail);
tail = XCDR (tail))
{
struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail));
if (EQ (parser->language_symbol, language))
{
- set_buffer_internal (old_buffer);
return XCAR (tail);
}
}
Lisp_Object lisp_parser
= make_ts_parser (Fcurrent_buffer (), parser, NULL, language);
- Fset (Qtreesit_parser_list,
- Fcons (lisp_parser, Fsymbol_value (Qtreesit_parser_list)));
+ BVAR (buf, ts_parser_list)
+ = Fcons (lisp_parser, BVAR (buf, ts_parser_list));
- set_buffer_internal (old_buffer);
return lisp_parser;
}
+DEFUN ("treesit-parser-delete",
+ Ftreesit_parser_delete, Streesit_parser_delete,
+ 1, 1, 0,
+ doc: /* Delete PARSER from its buffer. */)
+ (Lisp_Object parser)
+{
+ CHECK_TS_PARSER (parser);
+ Lisp_Object buffer = XTS_PARSER (parser)->buffer;
+ struct buffer *buf = XBUFFER (buffer);
+ BVAR (buf, ts_parser_list)
+ = Fdelete (parser, BVAR (buf, ts_parser_list));
+ return Qnil;
+}
+
+DEFUN ("treesit-parser-list",
+ Ftreesit_parser_list, Streesit_parser_list,
+ 0, 1, 0,
+ doc: /* Return BUFFER's parser list.
+BUFFER defaults to the current buffer. */)
+ (Lisp_Object buffer)
+{
+ struct buffer *buf;
+ if (NILP (buffer))
+ buf = current_buffer;
+ else
+ {
+ CHECK_BUFFER (buffer);
+ buf = XBUFFER (buffer);
+ }
+ /* Return a fresh list so messing with that list doesn't affect our
+ internal data. */
+ Lisp_Object return_list = Qnil;
+ for (Lisp_Object tail = BVAR (buf, ts_parser_list);
+ !NILP (tail);
+ tail = XCDR (tail))
+ {
+ return_list = Fcons (XCAR (tail), return_list);
+ }
+ return Freverse (return_list);
+}
+
DEFUN ("treesit-parser-buffer",
Ftreesit_parser_buffer, Streesit_parser_buffer,
1, 1, 0,
"This node is outdated, please retrieve a new one",
Qtreesit_error);
- DEFSYM (Qtreesit_parser_list, "treesit-parser-list");
- DEFVAR_LISP ("treesit-parser-list", Vtreesit_parser_list,
- doc: /* A list of tree-sitter parsers.
-
-If you removed a parser from this list, do not put it back in. Emacs
-keeps the parser in this list updated with any change in the buffer.
-If removed and put back in, there is no guarantee that the parser is in
-sync with the buffer's content. */);
- Vtreesit_parser_list = Qnil;
- Fmake_variable_buffer_local (Qtreesit_parser_list);
-
DEFVAR_LISP ("treesit-load-name-override-list",
Vtreesit_load_name_override_list,
doc:
defsubr (&Streesit_node_parser);
defsubr (&Streesit_parser_create);
+ defsubr (&Streesit_parser_delete);
+ defsubr (&Streesit_parser_list);
defsubr (&Streesit_parser_buffer);
defsubr (&Streesit_parser_language);
(with-temp-buffer
(let ((parser (treesit-parser-create 'json)))
(should
- (eq parser (car treesit-parser-list)))
+ (eq parser (car (treesit-parser-list))))
(should
(equal (treesit-node-string
(treesit-parser-root-node parser))