summaryrefslogtreecommitdiff
path: root/admin/notes/tree-sitter/html-manual/Multiple-Languages.html
diff options
context:
space:
mode:
Diffstat (limited to 'admin/notes/tree-sitter/html-manual/Multiple-Languages.html')
-rw-r--r--admin/notes/tree-sitter/html-manual/Multiple-Languages.html328
1 files changed, 328 insertions, 0 deletions
diff --git a/admin/notes/tree-sitter/html-manual/Multiple-Languages.html b/admin/notes/tree-sitter/html-manual/Multiple-Languages.html
new file mode 100644
index 00000000000..46985649a82
--- /dev/null
+++ b/admin/notes/tree-sitter/html-manual/Multiple-Languages.html
@@ -0,0 +1,328 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!-- Created by GNU Texinfo 6.8, https://www.gnu.org/software/texinfo/ -->
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<!-- This is the GNU Emacs Lisp Reference Manual
+corresponding to Emacs version 29.0.50.
+
+Copyright © 1990-1996, 1998-2022 Free Software Foundation,
+Inc.
+
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with the
+Invariant Sections being "GNU General Public License," with the
+Front-Cover Texts being "A GNU Manual," and with the Back-Cover
+Texts as in (a) below. A copy of the license is included in the
+section entitled "GNU Free Documentation License."
+
+(a) The FSF's Back-Cover Text is: "You have the freedom to copy and
+modify this GNU manual. Buying copies from the FSF supports it in
+developing GNU and promoting software freedom." -->
+<title>Multiple Languages (GNU Emacs Lisp Reference Manual)</title>
+
+<meta name="description" content="Multiple Languages (GNU Emacs Lisp Reference Manual)">
+<meta name="keywords" content="Multiple Languages (GNU Emacs Lisp Reference Manual)">
+<meta name="resource-type" content="document">
+<meta name="distribution" content="global">
+<meta name="Generator" content="makeinfo">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+
+<link href="index.html" rel="start" title="Top">
+<link href="Index.html" rel="index" title="Index">
+<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
+<link href="Parsing-Program-Source.html" rel="up" title="Parsing Program Source">
+<link href="Tree_002dsitter-major-modes.html" rel="next" title="Tree-sitter major modes">
+<link href="Pattern-Matching.html" rel="prev" title="Pattern Matching">
+<style type="text/css">
+<!--
+a.copiable-anchor {visibility: hidden; text-decoration: none; line-height: 0em}
+a.summary-letter {text-decoration: none}
+blockquote.indentedblock {margin-right: 0em}
+div.display {margin-left: 3.2em}
+div.example {margin-left: 3.2em}
+kbd {font-style: oblique}
+pre.display {font-family: inherit}
+pre.format {font-family: inherit}
+pre.menu-comment {font-family: serif}
+pre.menu-preformatted {font-family: serif}
+span.nolinebreak {white-space: nowrap}
+span.roman {font-family: initial; font-weight: normal}
+span.sansserif {font-family: sans-serif; font-weight: normal}
+span:hover a.copiable-anchor {visibility: visible}
+ul.no-bullet {list-style: none}
+-->
+</style>
+<link rel="stylesheet" type="text/css" href="./manual.css">
+
+
+</head>
+
+<body lang="en">
+<div class="section" id="Multiple-Languages">
+<div class="header">
+<p>
+Next: <a href="Tree_002dsitter-major-modes.html" accesskey="n" rel="next">Developing major modes with tree-sitter</a>, Previous: <a href="Pattern-Matching.html" accesskey="p" rel="prev">Pattern Matching Tree-sitter Nodes</a>, Up: <a href="Parsing-Program-Source.html" accesskey="u" rel="up">Parsing Program Source</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Index.html" title="Index" rel="index">Index</a>]</p>
+</div>
+<hr>
+<span id="Parsing-Text-in-Multiple-Languages"></span><h3 class="section">37.6 Parsing Text in Multiple Languages</h3>
+<span id="index-multiple-languages_002c-parsing-with-tree_002dsitter"></span>
+<span id="index-parsing-multiple-languages-with-tree_002dsitter"></span>
+<p>Sometimes, the source of a programming language could contain snippets
+of other languages; <acronym>HTML</acronym> + <acronym>CSS</acronym> + JavaScript is one
+example. In that case, text segments written in different languages
+need to be assigned different parsers. Traditionally, this is
+achieved by using narrowing. While tree-sitter works with narrowing
+(see <a href="Using-Parser.html#tree_002dsitter-narrowing">narrowing</a>), the recommended way is
+instead to set regions of buffer text (i.e., ranges) in which a parser
+will operate. This section describes functions for setting and
+getting ranges for a parser.
+</p>
+<p>Lisp programs should call <code>treesit-update-ranges</code> to make sure
+the ranges for each parser are correct before using parsers in a
+buffer, and call <code>treesit-language-at</code> to figure out the language
+responsible for the text at some position. These two functions don&rsquo;t
+work by themselves, they need major modes to set
+<code>treesit-range-settings</code> and
+<code>treesit-language-at-point-function</code>, which do the actual work.
+These functions and variables are explained in more detail towards the
+end of the section.
+</p>
+<span id="Getting-and-setting-ranges"></span><h3 class="heading">Getting and setting ranges</h3>
+
+<dl class="def">
+<dt id="index-treesit_002dparser_002dset_002dincluded_002dranges"><span class="category">Function: </span><span><strong>treesit-parser-set-included-ranges</strong> <em>parser ranges</em><a href='#index-treesit_002dparser_002dset_002dincluded_002dranges' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This function sets up <var>parser</var> to operate on <var>ranges</var>. The
+<var>parser</var> will only read the text of the specified ranges. Each
+range in <var>ranges</var> is a list of the form <code>(<var>beg</var>&nbsp;.&nbsp;<var>end</var>)</code><!-- /@w -->.
+</p>
+<p>The ranges in <var>ranges</var> must come in order and must not overlap.
+That is, in pseudo code:
+</p>
+<div class="example">
+<pre class="example">(cl-loop for idx from 1 to (1- (length ranges))
+ for prev = (nth (1- idx) ranges)
+ for next = (nth idx ranges)
+ should (&lt;= (car prev) (cdr prev)
+ (car next) (cdr next)))
+</pre></div>
+
+<span id="index-treesit_002drange_002dinvalid"></span>
+<p>If <var>ranges</var> violates this constraint, or something else went
+wrong, this function signals the <code>treesit-range-invalid</code> error.
+The signal data contains a specific error message and the ranges we
+are trying to set.
+</p>
+<p>This function can also be used for disabling ranges. If <var>ranges</var>
+is <code>nil</code>, the parser is set to parse the whole buffer.
+</p>
+<p>Example:
+</p>
+<div class="example">
+<pre class="example">(treesit-parser-set-included-ranges
+ parser '((1 . 9) (16 . 24) (24 . 25)))
+</pre></div>
+</dd></dl>
+
+<dl class="def">
+<dt id="index-treesit_002dparser_002dincluded_002dranges"><span class="category">Function: </span><span><strong>treesit-parser-included-ranges</strong> <em>parser</em><a href='#index-treesit_002dparser_002dincluded_002dranges' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This function returns the ranges set for <var>parser</var>. The return
+value is the same as the <var>ranges</var> argument of
+<code>treesit-parser-included-ranges</code>: a list of cons cells of the form
+<code>(<var>beg</var>&nbsp;.&nbsp;<var>end</var>)</code><!-- /@w -->. If <var>parser</var> doesn&rsquo;t have any
+ranges, the return value is <code>nil</code>.
+</p>
+<div class="example">
+<pre class="example">(treesit-parser-included-ranges parser)
+ &rArr; ((1 . 9) (16 . 24) (24 . 25))
+</pre></div>
+</dd></dl>
+
+<dl class="def">
+<dt id="index-treesit_002dquery_002drange"><span class="category">Function: </span><span><strong>treesit-query-range</strong> <em>source query &amp;optional beg end</em><a href='#index-treesit_002dquery_002drange' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This function matches <var>source</var> with <var>query</var> and returns the
+ranges of captured nodes. The return value is a list of cons cells of
+the form <code>(<var>beg</var>&nbsp;.&nbsp;<var>end</var>)</code><!-- /@w -->, where <var>beg</var> and
+<var>end</var> specify the beginning and the end of a region of text.
+</p>
+<p>For convenience, <var>source</var> can be a language symbol, a parser, or a
+node. If it&rsquo;s a language symbol, this function matches in the root
+node of the first parser using that language; if a parser, this
+function matches in the root node of that parser; if a node, this
+function matches in that node.
+</p>
+<p>The argument <var>query</var> is the query used to capture nodes
+(see <a href="Pattern-Matching.html">Pattern Matching Tree-sitter Nodes</a>). The capture names don&rsquo;t matter. The
+arguments <var>beg</var> and <var>end</var>, if both non-<code>nil</code>, limit the
+range in which this function queries.
+</p>
+<p>Like other query functions, this function raises the
+<code>treesit-query-error</code> error if <var>query</var> is malformed.
+</p></dd></dl>
+
+<span id="Supporting-multiple-languages-in-Lisp-programs"></span><h3 class="heading">Supporting multiple languages in Lisp programs</h3>
+
+<p>It should suffice for general Lisp programs to call the following two
+functions in order to support program sources that mixes multiple
+languages.
+</p>
+<dl class="def">
+<dt id="index-treesit_002dupdate_002dranges"><span class="category">Function: </span><span><strong>treesit-update-ranges</strong> <em>&amp;optional beg end</em><a href='#index-treesit_002dupdate_002dranges' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This function updates ranges for parsers in the buffer. It makes sure
+the parsers&rsquo; ranges are set correctly between <var>beg</var> and <var>end</var>,
+according to <code>treesit-range-settings</code>. If omitted, <var>beg</var>
+defaults to the beginning of the buffer, and <var>end</var> defaults to the
+end of the buffer.
+</p>
+<p>For example, fontification functions use this function before querying
+for nodes in a region.
+</p></dd></dl>
+
+<dl class="def">
+<dt id="index-treesit_002dlanguage_002dat"><span class="category">Function: </span><span><strong>treesit-language-at</strong> <em>pos</em><a href='#index-treesit_002dlanguage_002dat' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This function returns the language of the text at buffer position
+<var>pos</var>. Under the hood it calls
+<code>treesit-language-at-point-function</code> and returns its return
+value. If <code>treesit-language-at-point-function</code> is <code>nil</code>,
+this function returns the language of the first parser in the returned
+value of <code>treesit-parser-list</code>. If there is no parser in the
+buffer, it returns <code>nil</code>.
+</p></dd></dl>
+
+<span id="Supporting-multiple-languages-in-major-modes"></span><h3 class="heading">Supporting multiple languages in major modes</h3>
+
+<span id="index-host-language_002c-tree_002dsitter"></span>
+<span id="index-tree_002dsitter-host-and-embedded-languages"></span>
+<span id="index-embedded-language_002c-tree_002dsitter"></span>
+<p>Normally, in a set of languages that can be mixed together, there is a
+<em>host language</em> and one or more <em>embedded languages</em>. A Lisp
+program usually first parses the whole document with the host
+language&rsquo;s parser, retrieves some information, sets ranges for the
+embedded languages with that information, and then parses the embedded
+languages.
+</p>
+<p>Take a buffer containing <acronym>HTML</acronym>, <acronym>CSS</acronym> and JavaScript
+as an example. A Lisp program will first parse the whole buffer with
+an <acronym>HTML</acronym> parser, then query the parser for
+<code>style_element</code> and <code>script_element</code> nodes, which
+correspond to <acronym>CSS</acronym> and JavaScript text, respectively. Then
+it sets the range of the <acronym>CSS</acronym> and JavaScript parser to the
+ranges in which their corresponding nodes span.
+</p>
+<p>Given a simple <acronym>HTML</acronym> document:
+</p>
+<div class="example">
+<pre class="example">&lt;html&gt;
+ &lt;script&gt;1 + 2&lt;/script&gt;
+ &lt;style&gt;body { color: &quot;blue&quot;; }&lt;/style&gt;
+&lt;/html&gt;
+</pre></div>
+
+<p>a Lisp program will first parse with a <acronym>HTML</acronym> parser, then set
+ranges for <acronym>CSS</acronym> and JavaScript parsers:
+</p>
+<div class="example">
+<pre class="example">;; Create parsers.
+(setq html (treesit-get-parser-create 'html))
+(setq css (treesit-get-parser-create 'css))
+(setq js (treesit-get-parser-create 'javascript))
+</pre><pre class="example">
+
+</pre><pre class="example">;; Set CSS ranges.
+(setq css-range
+ (treesit-query-range
+ 'html
+ &quot;(style_element (raw_text) @capture)&quot;))
+(treesit-parser-set-included-ranges css css-range)
+</pre><pre class="example">
+
+</pre><pre class="example">;; Set JavaScript ranges.
+(setq js-range
+ (treesit-query-range
+ 'html
+ &quot;(script_element (raw_text) @capture)&quot;))
+(treesit-parser-set-included-ranges js js-range)
+</pre></div>
+
+<p>Emacs automates this process in <code>treesit-update-ranges</code>. A
+multi-language major mode should set <code>treesit-range-settings</code> so
+that <code>treesit-update-ranges</code> knows how to perform this process
+automatically. Major modes should use the helper function
+<code>treesit-range-rules</code> to generate a value that can be assigned to
+<code>treesit-range-settings</code>. The settings in the following example
+directly translate into operations shown above.
+</p>
+<div class="example">
+<pre class="example">(setq-local treesit-range-settings
+ (treesit-range-rules
+ :embed 'javascript
+ :host 'html
+ '((script_element (raw_text) @capture))
+</pre><pre class="example">
+
+</pre><pre class="example"> :embed 'css
+ :host 'html
+ '((style_element (raw_text) @capture))))
+</pre></div>
+
+<dl class="def">
+<dt id="index-treesit_002drange_002drules"><span class="category">Function: </span><span><strong>treesit-range-rules</strong> <em>&amp;rest query-specs</em><a href='#index-treesit_002drange_002drules' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This function is used to set <var>treesit-range-settings</var>. It
+takes care of compiling queries and other post-processing, and outputs
+a value that <var>treesit-range-settings</var> can have.
+</p>
+<p>It takes a series of <var>query-spec</var>s, where each <var>query-spec</var> is
+a <var>query</var> preceded by zero or more <var>keyword</var>/<var>value</var>
+pairs. Each <var>query</var> is a tree-sitter query in either the
+string, s-expression or compiled form, or a function.
+</p>
+<p>If <var>query</var> is a tree-sitter query, it should be preceded by two
+<var>:keyword</var>/<var>value</var> pairs, where the <code>:embed</code> keyword
+specifies the embedded language, and the <code>:host</code> keyword
+specified the host language.
+</p>
+<p><code>treesit-update-ranges</code> uses <var>query</var> to figure out how to set
+the ranges for parsers for the embedded language. It queries
+<var>query</var> in a host language parser, computes the ranges in which
+the captured nodes span, and applies these ranges to embedded
+language parsers.
+</p>
+<p>If <var>query</var> is a function, it doesn&rsquo;t need any <var>:keyword</var> and
+<var>value</var> pair. It should be a function that takes 2 arguments,
+<var>start</var> and <var>end</var>, and sets the ranges for parsers in the
+current buffer in the region between <var>start</var> and <var>end</var>. It is
+fine for this function to set ranges in a larger region that
+encompasses the region between <var>start</var> and <var>end</var>.
+</p></dd></dl>
+
+<dl class="def">
+<dt id="index-treesit_002drange_002dsettings"><span class="category">Variable: </span><span><strong>treesit-range-settings</strong><a href='#index-treesit_002drange_002dsettings' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This variable helps <code>treesit-update-ranges</code> in updating the
+ranges for parsers in the buffer. It is a list of <var>setting</var>s
+where the exact format of a <var>setting</var> is considered internal. You
+should use <code>treesit-range-rules</code> to generate a value that this
+variable can have.
+</p>
+</dd></dl>
+
+
+<dl class="def">
+<dt id="index-treesit_002dlanguage_002dat_002dpoint_002dfunction"><span class="category">Variable: </span><span><strong>treesit-language-at-point-function</strong><a href='#index-treesit_002dlanguage_002dat_002dpoint_002dfunction' class='copiable-anchor'> &para;</a></span></dt>
+<dd><p>This variable&rsquo;s value should be a function that takes a single
+argument, <var>pos</var>, which is a buffer position, and returns the
+language of the buffer text at <var>pos</var>. This variable is used by
+<code>treesit-language-at</code>.
+</p></dd></dl>
+
+</div>
+<hr>
+<div class="header">
+<p>
+Next: <a href="Tree_002dsitter-major-modes.html">Developing major modes with tree-sitter</a>, Previous: <a href="Pattern-Matching.html">Pattern Matching Tree-sitter Nodes</a>, Up: <a href="Parsing-Program-Source.html">Parsing Program Source</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Index.html" title="Index" rel="index">Index</a>]</p>
+</div>
+
+
+
+</body>
+</html>