Rewrite and refactor the guides

pull/5534/head
David-Else 1 year ago
parent 421b5ebace
commit dc6a0e3064

@ -1,4 +1,4 @@
# Guides # Guides
This section contains guides for adding new language server configurations, This section contains guides for adding new language server configurations,
tree-sitter grammars, textobject queries, etc. tree-sitter grammars, textobject queries, and other similar items.

@ -1,45 +1,59 @@
# Adding languages # Adding new languages to Helix
In order to add a new language to Helix, you will need to follow the steps
below.
## Language configuration ## Language configuration
To add a new language, you need to add a `[[language]]` entry to the 1. Add a new `[[language]]` entry in the `languages.toml` file and provide the
`languages.toml` (see the [language configuration section]). necessary configuration for the new language. For more information on
language configuration, refer to the
[language configuration section](../languages.md) of the documentation.
2. If you are adding a new language or updating an existing language server
configuration, run the command `cargo xtask docgen` to update the
[Language Support](../lang-support.md) documentation.
When adding a new language or Language Server configuration for an existing > 💡 If you are adding a new Language Server configuration, make sure to update
language, run `cargo xtask docgen` to add the new configuration to the > the
[Language Support][lang-support] docs before creating a pull request. > [Language Server Wiki](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers)
When adding a Language Server configuration, be sure to update the > with the installation instructions.
[Language Server Wiki][install-lsp-wiki] with installation notes.
## Grammar configuration ## Grammar configuration
If a tree-sitter grammar is available for the language, add a new `[[grammar]]` 1. If a tree-sitter grammar is available for the new language, add a new
entry to `languages.toml`. `[[grammar]]` entry to the `languages.toml` file.
2. If you are testing the grammar locally, you can use the `source.path` key
You may use the `source.path` key rather than `source.git` with an absolute path with an absolute path to the grammar. However, before submitting a pull
to a locally available grammar for testing, but switch to `source.git` before request, make sure to switch to using `source.git`.
submitting a pull request.
## Queries ## Queries
For a language to have syntax-highlighting and indentation among 1. In order to provide syntax highlighting and indentation for the new language,
other things, you have to add queries. Add a directory for your you will need to add queries.
language with the path `runtime/queries/<name>/`. The tree-sitter 2. Create a new directory for the language with the path
[website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries) `runtime/queries/<name>/`.
gives more info on how to write queries. 3. Refer to the
[tree-sitter website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries)
> NOTE: When evaluating queries, the first matching query takes for more information on writing queries.
precedence, which is different from other editors like Neovim where
the last matching query supersedes the ones before it. See > 💡 In Helix, the first matching query takes precedence when evaluating
[this issue][neovim-query-precedence] for an example. > queries, which is different from other editors such as Neovim where the last
> matching query supersedes the ones before it. See
## Common Issues > [this issue](https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090)
> for an example.
- If you get errors when running after switching branches, you may have to update the tree-sitter grammars. Run `hx --grammar fetch` to fetch the grammars and `hx --grammar build` to build any out-of-date grammars.
## Common issues
- If a parser is segfaulting or you want to remove the parser, make sure to remove the compiled parser in `runtime/grammar/<name>.so`
- If you encounter errors when running Helix after switching branches, you may
need to update the tree-sitter grammars. Run the command `hx --grammar fetch`
to fetch the grammars and `hx --grammar build` to build any out-of-date
grammars.
- If a parser is causing a segfault or you want to remove it, make sure to
remove the compiled parser located at `runtime/grammar/<name>.so`.
[language configuration section]: ../languages.md [language configuration section]: ../languages.md
[neovim-query-precedence]: https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090 [neovim-query-precedence]:
[install-lsp-wiki]: https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090
[install-lsp-wiki]:
https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers
[lang-support]: ../lang-support.md [lang-support]: ../lang-support.md

@ -1,35 +1,33 @@
# Adding Indent Queries # Adding Indent Queries
Helix uses tree-sitter to correctly indent new lines. This requires Helix uses tree-sitter to correctly indent new lines. This requires a
a tree-sitter grammar and an `indent.scm` query file placed in tree-sitter grammar and an `indent.scm` query file placed in
`runtime/queries/{language}/indents.scm`. The indentation for a line `runtime/queries/{language}/indents.scm`. The indentation for a line is
is calculated by traversing the syntax tree from the lowest node at the calculated by traversing the syntax tree from the lowest node at the beginning
beginning of the new line. Each of these nodes contributes to the total of the new line. Each of these nodes contributes to the total indent when it is
indent when it is captured by the query (in what way depends on the name captured by the query (in what way depends on the name of the capture).
of the capture).
Note that it matters where these added indents begin. For example, multiple
Note that it matters where these added indents begin. For example, indent level increases that start on the same line only increase the total
multiple indent level increases that start on the same line only increase indent level by 1.
the total indent level by 1.
## Scopes ## Scopes
Added indents don't always apply to the whole node. For example, in most Added indents don't always apply to the whole node. For example, in most cases
cases when a node should be indented, we actually only want everything when a node should be indented, we actually only want everything except for its
except for its first line to be indented. For this, there are several first line to be indented. For this, there are several scopes (more scopes may
scopes (more scopes may be added in the future if required): be added in the future if required):
- `all`: This scope applies to the whole captured node. This is only different
from `tail` when the captured node is the first node on its line.
- `all`: - `tail`: This scope applies to everything except for the first line of the
This scope applies to the whole captured node. This is only different from captured node.
`tail` when the captured node is the first node on its line.
- `tail`: Every capture type has a default scope which should do the right thing in most
This scope applies to everything except for the first line of the situations. When a different scope is required, this can be changed by using a
captured node. `#set!` declaration anywhere in the pattern:
Every capture type has a default scope which should do the right thing
in most situations. When a different scope is required, this can be
changed by using a `#set!` declaration anywhere in the pattern:
```scm ```scm
(assignment_expression (assignment_expression
right: (_) @indent right: (_) @indent
@ -38,56 +36,54 @@ changed by using a `#set!` declaration anywhere in the pattern:
## Capture Types ## Capture Types
- `@indent` (default scope `tail`): - `@indent` (default scope `tail`): Increase the indent level by 1. Multiple
Increase the indent level by 1. Multiple occurrences in the same line occurrences in the same line don't stack. If there is at least one `@indent`
don't stack. If there is at least one `@indent` and one `@outdent` and one `@outdent` capture on the same line, the indent level isn't changed at
capture on the same line, the indent level isn't changed at all. all.
- `@outdent` (default scope `all`):
Decrease the indent level by 1. The same rules as for `@indent` apply.
- `@extend`: - `@outdent` (default scope `all`): Decrease the indent level by 1. The same
Extend the range of this node to the end of the line and to lines that rules as for `@indent` apply.
are indented more than the line that this node starts on. This is useful
for languages like Python, where for the purpose of indentation some nodes
(like functions or classes) should also contain indented lines that follow them.
- `@extend.prevent-once`: - `@extend`: Extend the range of this node to the end of the line and to lines
Prevents the first extension of an ancestor of this node. For example, in Python that are indented more than the line that this node starts on. This is useful
a return expression always ends the block that it is in. Note that this only stops the for languages like Python, where for the purpose of indentation some nodes
extension of the next `@extend` capture. If multiple ancestors are captured, (like functions or classes) should also contain indented lines that follow
only the extension of the innermost one is prevented. All other ancestors are unaffected them.
(regardless of whether the innermost ancestor would actually have been extended).
- `@extend.prevent-once`: Prevents the first extension of an ancestor of this
node. For example, in Python a return expression always ends the block that it
is in. Note that this only stops the extension of the next `@extend` capture.
If multiple ancestors are captured, only the extension of the innermost one is
prevented. All other ancestors are unaffected (regardless of whether the
innermost ancestor would actually have been extended).
## Predicates ## Predicates
In some cases, an S-expression cannot express exactly what pattern should be matched. In some cases, an S-expression cannot express exactly what pattern should be
For that, tree-sitter allows for predicates to appear anywhere within a pattern, matched. For that, tree-sitter allows for predicates to appear anywhere within a
similar to how `#set!` declarations work: pattern, similar to how `#set!` declarations work:
```scm ```scm
(some_kind (some_kind
(child_kind) @indent (child_kind) @indent
(#predicate? arg1 arg2 ...) (#predicate? arg1 arg2 ...)
) )
``` ```
The number of arguments depends on the predicate that's used.
Each argument is either a capture (`@name`) or a string (`"some string"`).
The following predicates are supported by tree-sitter:
- `#eq?`/`#not-eq?`: The number of arguments depends on the predicate that's used. Each argument is
The first argument (a capture) must/must not be equal to the second argument either a capture (`@name`) or a string (`"some string"`). The following
(a capture or a string). predicates are supported by tree-sitter:
- `#eq?`/`#not-eq?`: The first argument (a capture) must/must not be equal to
the second argument (a capture or a string).
- `#match?`/`#not-match?`: - `#match?`/`#not-match?`: The first argument (a capture) must/must not match
The first argument (a capture) must/must not match the regex given in the the regex given in the second argument (a string).
second argument (a string).
Additionally, we support some custom predicates for indent queries: Additionally, we support some custom predicates for indent queries:
- `#not-kind-eq?`: - `#not-kind-eq?`: The kind of the first argument (a capture) must not be equal
The kind of the first argument (a capture) must not be equal to the second to the second argument (a string).
argument (a string).
- `#same-line?`/`#not-same-line?`: - `#same-line?`/`#not-same-line?`: The captures given by the 2 arguments
The captures given by the 2 arguments must/must not start on the same line. must/must not start on the same line.

@ -1,21 +1,21 @@
# Adding Textobject Queries # Adding Textobject Queries
Textobjects that are language specific ([like functions, classes, etc][textobjects]) Helix supports textobjects that are language specific, such as functions,
require an accompanying tree-sitter grammar and a `textobjects.scm` query file classes, etc. These textobjects require an accompanying tree-sitter grammar and
to work properly. Tree-sitter allows us to query the source code syntax tree a `textobjects.scm` query file to work properly. Tree-sitter allows us to query
and capture specific parts of it. The queries are written in a lisp dialect. the source code syntax tree and capture specific parts of it. The queries are
More information on how to write queries can be found in the [official tree-sitter written in a lisp dialect. More information on how to write queries can be found
documentation][tree-sitter-queries]. in the [official tree-sitter documentation][tree-sitter-queries].
Query files should be placed in `runtime/queries/{language}/textobjects.scm` Query files should be placed in `runtime/queries/{language}/textobjects.scm`
when contributing. Note that to test the query files locally you should put when contributing to Helix. Note that to test the query files locally you should
them under your local runtime directory (`~/.config/helix/runtime` on Linux put them under your local runtime directory (`~/.config/helix/runtime` on Linux
for example). for example).
The following [captures][tree-sitter-captures] are recognized: The following [captures][tree-sitter-captures] are recognized:
| Capture Name | | Capture Name |
| --- | | ------------------ |
| `function.inside` | | `function.inside` |
| `function.around` | | `function.around` |
| `class.inside` | | `class.inside` |
@ -26,24 +26,28 @@ The following [captures][tree-sitter-captures] are recognized:
| `comment.inside` | | `comment.inside` |
| `comment.around` | | `comment.around` |
[Example query files][textobject-examples] can be found in the helix GitHub repository. [Example query files][textobject-examples] can be found in the Helix GitHub
repository.
## Queries for Textobject Based Navigation ## Queries for Textobject Based Navigation
[Tree-sitter based navigation][textobjects-nav] is done using captures in the Tree-sitter based navigation in Helix is done using captures in the following
following order: order:
- `object.movement` - `object.movement`
- `object.around` - `object.around`
- `object.inside` - `object.inside`
For example if a `function.around` capture has been already defined for a language For example if a `function.around` capture has been already defined for a
in it's `textobjects.scm` file, function navigation should also work automatically. language in its `textobjects.scm` file, function navigation should also work
`function.movement` should be defined only if the node captured by `function.around` automatically. `function.movement` should be defined only if the node captured
doesn't make sense in a navigation context. by `function.around` doesn't make sense in a navigation context.
[textobjects]: ../usage.md#textobjects [textobjects]: ../usage.md#textobjects
[textobjects-nav]: ../usage.md#tree-sitter-textobject-based-navigation [textobjects-nav]: ../usage.md#tree-sitter-textobject-based-navigation
[tree-sitter-queries]: https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax [tree-sitter-queries]:
[tree-sitter-captures]: https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax
[textobject-examples]: https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&type=Code&ref=advsearch&l=&l= [tree-sitter-captures]:
https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes
[textobject-examples]:
https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&type=Code&ref=advsearch&l=&l=

Loading…
Cancel
Save