summaryrefslogtreecommitdiff
path: root/admin/notes/tree-sitter/html-manual/Parser_002dbased-Indentation.html
blob: 691c8fba8c74718494e274f0dc808b95b6b0501b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!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>Parser-based Indentation (GNU Emacs Lisp Reference Manual)</title>

<meta name="description" content="Parser-based Indentation (GNU Emacs Lisp Reference Manual)">
<meta name="keywords" content="Parser-based Indentation (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="Auto_002dIndentation.html" rel="up" title="Auto-Indentation">
<link href="SMIE.html" rel="prev" title="SMIE">
<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="subsection" id="Parser_002dbased-Indentation">
<div class="header">
<p>
Previous: <a href="SMIE.html" accesskey="p" rel="prev">Simple Minded Indentation Engine</a>, Up: <a href="Auto_002dIndentation.html" accesskey="u" rel="up">Automatic Indentation of code</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="Parser_002dbased-Indentation-1"></span><h4 class="subsection">24.7.2 Parser-based Indentation</h4>


<p>When built with the tree-sitter library (see <a href="Parsing-Program-Source.html">Parsing Program Source</a>), Emacs could parse program source and produce a syntax tree.
And this syntax tree can be used for indentation.  For maximum
flexibility, we could write a custom indent function that queries the
syntax tree and indents accordingly for each language, but that would
be a lot of work.  It is more convenient to use the simple indentation
engine described below: we only need to write some indentation rules
and the engine takes care of the rest.
</p>
<p>To enable the indentation engine, set the value of
<code>indent-line-function</code> to <code>treesit-indent</code>.
</p>
<dl class="def">
<dt id="index-treesit_002dindent_002dfunction"><span class="category">Variable: </span><span><strong>treesit-indent-function</strong><a href='#index-treesit_002dindent_002dfunction' class='copiable-anchor'> &para;</a></span></dt>
<dd><p>This variable stores the actual function called by
<code>treesit-indent</code>.  By default, its value is
<code>treesit-simple-indent</code>.  In the future we might add other
more complex indentation engines.
</p></dd></dl>

<span id="Writing-indentation-rules"></span><h3 class="heading">Writing indentation rules</h3>

<dl class="def">
<dt id="index-treesit_002dsimple_002dindent_002drules"><span class="category">Variable: </span><span><strong>treesit-simple-indent-rules</strong><a href='#index-treesit_002dsimple_002dindent_002drules' class='copiable-anchor'> &para;</a></span></dt>
<dd><p>This local variable stores indentation rules for every language. It is
a list of
</p>
<div class="example">
<pre class="example">(<var>language</var> . <var>rules</var>)
</pre></div>

<p>where <var>language</var> is a language symbol, and <var>rules</var> is a list
of
</p>
<div class="example">
<pre class="example">(<var>matcher</var> <var>anchor</var> <var>offset</var>)
</pre></div>

<p>First Emacs passes the node at point to <var>matcher</var>, if it return
non-nil, this rule applies.  Then Emacs passes the node to
<var>anchor</var>, it returns a point.  Emacs takes the column number of
that point, add <var>offset</var> to it, and the result is the indent for
the current line.
</p>
<p>The <var>matcher</var> and <var>anchor</var> are functions, and Emacs provides
convenient presets for them.  You can skip over to
<code>treesit-simple-indent-presets</code> below, those presets should be
more than enough.
</p>
<p>A <var>matcher</var> or an <var>anchor</var> is a function that takes three
arguments (<var>node</var> <var>parent</var> <var>bol</var>).  Argument <var>bol</var> is
the point at where we are indenting: the position of the first
non-whitespace character from the beginning of line; <var>node</var> is the
largest (highest-in-tree) node that starts at that point; <var>parent</var>
is the parent of <var>node</var>.  A <var>matcher</var> returns nil/non-nil, and
<var>anchor</var> returns a point.
</p></dd></dl>

<dl class="def">
<dt id="index-treesit_002dsimple_002dindent_002dpresets"><span class="category">Variable: </span><span><strong>treesit-simple-indent-presets</strong><a href='#index-treesit_002dsimple_002dindent_002dpresets' class='copiable-anchor'> &para;</a></span></dt>
<dd><p>This is a list of presets for <var>matcher</var>s and <var>anchor</var>s in
<code>treesit-simple-indent-rules</code>.  Each of them represent a function
that takes <var>node</var>, <var>parent</var> and <var>bol</var> as arguments.
</p>
<div class="example">
<pre class="example">no-node
</pre></div>

<p>This matcher matches the case where <var>node</var> is nil, i.e., there is
no node that starts at <var>bol</var>.  This is the case when <var>bol</var> is
at an empty line or inside a multi-line string, etc.
</p>
<div class="example">
<pre class="example">(parent-is <var>type</var>)
</pre></div>

<p>This matcher matches if <var>parent</var>&rsquo;s type is <var>type</var>.
</p>
<div class="example">
<pre class="example">(node-is <var>type</var>)
</pre></div>

<p>This matcher matches if <var>node</var>&rsquo;s type is <var>type</var>.
</p>
<div class="example">
<pre class="example">(query <var>query</var>)
</pre></div>

<p>This matcher matches if querying <var>parent</var> with <var>query</var>
captures <var>node</var>.  The capture name does not matter.
</p>
<div class="example">
<pre class="example">(match <var>node-type</var> <var>parent-type</var>
       <var>node-field</var> <var>node-index-min</var> <var>node-index-max</var>)
</pre></div>

<p>This matcher checks if <var>node</var>&rsquo;s type is <var>node-type</var>,
<var>parent</var>&rsquo;s type is <var>parent-type</var>, <var>node</var>&rsquo;s field name in
<var>parent</var> is <var>node-field</var>, and <var>node</var>&rsquo;s index among its
siblings is between <var>node-index-min</var> and <var>node-index-max</var>.  If
the value of a constraint is nil, this matcher doesn&rsquo;t check for that
constraint.  For example, to match the first child where parent is
<code>argument_list</code>, use
</p>
<div class="example">
<pre class="example">(match nil &quot;argument_list&quot; nil nil 0 0)
</pre></div>

<div class="example">
<pre class="example">first-sibling
</pre></div>

<p>This anchor returns the start of the first child of <var>parent</var>.
</p>
<div class="example">
<pre class="example">parent
</pre></div>

<p>This anchor returns the start of <var>parent</var>.
</p>
<div class="example">
<pre class="example">parent-bol
</pre></div>

<p>This anchor returns the beginning of non-space characters on the line
where <var>parent</var> is on.
</p>
<div class="example">
<pre class="example">prev-sibling
</pre></div>

<p>This anchor returns the start of the previous sibling of <var>node</var>.
</p>
<div class="example">
<pre class="example">no-indent
</pre></div>

<p>This anchor returns the start of <var>node</var>, i.e., no indent.
</p>
<div class="example">
<pre class="example">prev-line
</pre></div>

<p>This anchor returns the first non-whitespace charater on the previous
line.
</p></dd></dl>

<span id="Indentation-utilities"></span><h3 class="heading">Indentation utilities</h3>

<p>Here are some utility functions that can help writing indentation
rules.
</p>
<dl class="def">
<dt id="index-treesit_002dcheck_002dindent"><span class="category">Function: </span><span><strong>treesit-check-indent</strong> <em>mode</em><a href='#index-treesit_002dcheck_002dindent' class='copiable-anchor'> &para;</a></span></dt>
<dd><p>This function checks current buffer&rsquo;s indentation against major mode
<var>mode</var>.  It indents the current buffer in <var>mode</var> and compares
the indentation with the current indentation.  Then it pops up a diff
buffer showing the difference.  Correct indentation (target) is in
green, current indentation is in red.
</p></dd></dl>

<p>It is also helpful to use <code>treesit-inspect-mode</code> when writing
indentation rules.
</p>
</div>
<hr>
<div class="header">
<p>
Previous: <a href="SMIE.html">Simple Minded Indentation Engine</a>, Up: <a href="Auto_002dIndentation.html">Automatic Indentation of code</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>