]> git.eshelyaron.com Git - emacs.git/commitdiff
"Separate" tree-sitter parser list for indirect buffers
authorYuan Fu <casouri@gmail.com>
Sat, 27 Jul 2024 05:33:17 +0000 (22:33 -0700)
committerEshel Yaron <me@eshelyaron.com>
Wed, 31 Jul 2024 14:33:08 +0000 (16:33 +0200)
When create a parser for the indirect buffer, set the buffer field of
the parser to the indirect buffer, but add the parser to the base
buffer's parser list.  This way, all the parsers still get buffer
updates, but indirect buffer's parsers can have different narrowing than
the parsers of the base buffer.

When returning the parser list of a buffer, do filtering and only return
the parser for that buffer.

From user's POV, indirect buffers appear to have their own parser list.

* doc/lispref/parsing.texi (Using Parser): Remove the text describing
indirect buffer's special case.
* src/treesit.c (Ftreesit_parser_create): When create a parser for the
indirect buffer, set the buffer field of the parser to the indirect
buffer, but add the parser to the base buffer's parser list.
(Ftreesit_parser_list): Filter parser list, only return parsers for this
buffer.

xx

(cherry picked from commit e4cd26defc0e1a6deafbe4b2310ebdb3ffa4578f)

doc/lispref/parsing.texi
etc/NEWS
src/treesit.c

index 65549505b1e912f1384b1a70a26d19cdd464e02b..a3d2a5ac71cc87ba8cb5b8424184c9d41671325e 100644 (file)
@@ -413,13 +413,6 @@ is non-@code{nil}, this function always creates a new parser.
 
 @var{tag} can be any symbol except @code{t}, and defaults to
 @code{nil}.  Different parsers can have the same tag.
-
-If that buffer is an indirect buffer, its base buffer is used instead.
-That is, indirect buffers use their base buffer's parsers.  If the
-base buffer is narrowed, an indirect buffer might not be able to
-retrieve information of the portion of the buffer text that is
-invisible in the base buffer.  Lisp programs should widen as necessary
-should they want to use a parser in an indirect buffer.
 @end defun
 
 Given a parser, we can query information about it.
@@ -458,9 +451,7 @@ tree incrementally.
 @defun treesit-parser-list &optional buffer language tag
 This function returns the parser list of @var{buffer}, filtered by
 @var{language} and @var{tag}.  If @var{buffer} is @code{nil} or
-omitted, it defaults to the current buffer.  If that buffer is an
-indirect buffer, its base buffer is used instead.  That is, indirect
-buffers use their base buffer's parsers.
+omitted, it defaults to the current buffer.
 
 If @var{language} is non-@var{nil}, only include parsers for that
 language, and only include parsers with @var{tag}.  @var{tag} defaults
index 37a5524283afc96bacb632a92c99ca6fb646e5ae..dbfca3fa8c5670390bee7c8a4be29e0d8f81934e 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -188,6 +188,23 @@ authorize the invoked D-Bus method (for example via polkit).
 ** The customization group 'wp' has been removed.
 It has been obsolete since Emacs 26.1.  Use the group 'text' instead.
 
+** Tree-sitter changes
+
++++
+*** Indirect buffers can have their own parser list.
+Before, indirect buffers share their base buffer’s parser list and
+parsers.  Now they can have their own parser list.
+
++++
+*** New variable 'treesit-language-remap-alist'.
+This variable allows a user to remap one language into another, such
+that creating a parser for language A actually creates a parser for
+language B.  By extension, any font-lock rules or indentation rules for
+language A will be applied to language B instead.
+
+This is useful for reusing font-lock rules and indentation rules of
+language A for language B, when language B is a strict superset of
+language A.
 \f
 * Changes in Emacs 31.1 on Non-Free Operating Systems
 
index 45db71bb5fdafc95d83845a0f166da1bc5c7a52c..513d0d22c7faef55651554c687a007a0dd00790c 100644 (file)
@@ -392,16 +392,20 @@ init_treesit_functions (void)
    These are all imaginary scenarios but they are not impossible
    :-)
 
-   Parsers in indirect buffers: We make indirect buffers to share the
-   parser of its base buffer.  Indirect buffers and their base buffer
+   Parsers in indirect buffers: We make indirect buffers share the
+   parser of their base buffer.  Indirect buffers and their base buffer
    share the same buffer content but not other buffer attributes.  If
    they have separate parser lists, changes made in an indirect buffer
-   will only update parsers of that indirect buffer, and not parsers
-   in the base buffer or other indirect buffers, and vice versa.  We
-   could keep track of all the base and indirect buffers, and update
-   all of their parsers, but ultimately decide to take a simpler
-   approach, which is to make indirect buffers share their base
-   buffer's parser list.  The discussion can be found in bug#59693.  */
+   will only update parsers of that indirect buffer, and not parsers in
+   the base buffer or other indirect buffers, and vice versa.  For that
+   reason, the base buffer and all ot its indirect buffers share a
+   single parser list.  But each parser in this shared parser list still
+   points to their own buffer.  On top of that, treesit-parser-list only
+   return parsers that belongs to the calling buffer.  So ultimately,
+   from the user's POV, each buffer, regardless of indirect or not,
+   appears to have their own parser list.  A discussion can be found in
+   bug#59693.  Note that that discussion led to an earlier design, which
+   is different from the current one.  */
 
 \f
 /*** Initialization  */
@@ -1416,13 +1420,20 @@ an indirect buffer.  */)
   CHECK_SYMBOL (language);
   CHECK_SYMBOL (tag);
   struct buffer *buf;
+  Lisp_Object buf_orig;
+
   if (NILP (buffer))
-    buf = current_buffer;
+    {
+      buf = current_buffer;
+      XSETBUFFER (buf_orig, current_buffer);
+    }
   else
     {
       CHECK_BUFFER (buffer);
       buf = XBUFFER (buffer);
+      buf_orig = buffer;
     }
+
   if (buf->base_buffer)
     buf = buf->base_buffer;
 
@@ -1457,9 +1468,7 @@ an indirect buffer.  */)
   ts_parser_set_language (parser, lang);
 
   /* Create parser.  */
-  Lisp_Object lisp_buf;
-  XSETBUFFER (lisp_buf, buf);
-  Lisp_Object lisp_parser = make_treesit_parser (lisp_buf,
+  Lisp_Object lisp_parser = make_treesit_parser (buf_orig,
                                                 parser, NULL,
                                                 language, tag);
 
@@ -1505,13 +1514,20 @@ tag.  */)
   (Lisp_Object buffer, Lisp_Object language, Lisp_Object tag)
 {
   struct buffer *buf;
+  Lisp_Object buf_orig;
+
   if (NILP (buffer))
-    buf = current_buffer;
+    {
+      buf = current_buffer;
+      XSETBUFFER (buf_orig, current_buffer);
+    }
   else
     {
       CHECK_BUFFER (buffer);
       buf = XBUFFER (buffer);
+      buf_orig = buffer;
     }
+
   if (buf->base_buffer)
     buf = buf->base_buffer;
 
@@ -1526,7 +1542,10 @@ tag.  */)
     {
       struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail));
       if ((NILP (language) || EQ (language, parser->language_symbol))
-         && (EQ (tag, Qt) || EQ (tag, parser->tag)))
+         && (EQ (tag, Qt) || EQ (tag, parser->tag))
+         /* Indirect buffers and base buffer shares the same parser
+          * list, so we need the filtering here.  */
+         && (EQ (parser->buffer, buf_orig)))
        return_list = Fcons (XCAR (tail), return_list);
     }