Add textobjects queries (#20924)

Co-Authored-By: Max <max@zed.dev>

Release Notes:

- vim: Added motions `[[`, `[]`, `]]`, `][` for navigating by section,
`[m`, `]m`, `[M`, `]M` for navigating by method, and `[*`, `]*`, `[/`,
`]/` for comments. These currently only work for languages built in to
Zed, as they are powered by new tree-sitter queries.
- vim: Added new text objects: `ic`, `ac` for inside/around classes,
`if`,`af` for functions/methods, and `g c` for comments. These currently
only work for languages built in to Zed, as they are powered by new
tree-sitter queries.

---------

Co-authored-by: Max <max@zed.dev>
This commit is contained in:
Conrad Irwin 2024-12-03 09:37:01 -08:00 committed by GitHub
parent c443307c19
commit 75c9dc179b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 1205 additions and 26 deletions

View file

@ -69,6 +69,7 @@ several features:
- Syntax overrides
- Text redactions
- Runnable code detection
- Selecting classes, functions, etc.
The following sections elaborate on how [Tree-sitter queries](https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax) enable these
features in Zed, using [JSON syntax](https://www.json.org/json-en.html) as a guiding example.
@ -259,6 +260,44 @@ For example, in JavaScript, we also disable auto-closing of single quotes within
(comment) @comment.inclusive
```
### Text objects
The `textobjects.scm` file defines rules for navigating by text objects. This was added in Zed v0.165 and is currently used only in Vim mode.
Vim provides two levels of granularity for navigating around files. Section-by-section with `[]` etc., and method-by-method with `]m` etc. Even languages that don't support functions and classes can work well by defining similar concepts. For example CSS defines a rule-set as a method, and a media-query as a class.
For languages with closures, these typically should not count as functions in Zed. This is best-effort however, as languages like Javascript do not syntactically differentiate syntactically between closures and top-level function declarations.
For languages with declarations like C, provide queries that match `@class.around` or `@function.around`. The `if` and `ic` text objects will default to these if there is no inside.
If you are not sure what to put in textobjects.scm, both [nvim-treesitter-textobjects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects), and the [Helix editor](https://github.com/helix-editor/helix) have queries for many languages. You can refer to the Zed [built-in languages](https://github.com/zed-industries/zed/tree/main/crates/languages/src) to see how to adapt these.
| Capture | Description | Vim mode |
| ---------------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
| @function.around | An entire function definition or equivalent small section of a file. | `[m`, `]m`, `[M`,`]M` motions. `af` text object |
| @function.inside | The function body (the stuff within the braces). | `if` text object |
| @class.around | An entire class definition or equivalent large section of a file. | `[[`, `]]`, `[]`, `][` motions. `ac` text object |
| @class.inside | The contents of a class definition. | `ic` text object |
| @comment.around | An entire comment (e.g. all adjacent line comments, or a block comment) | `gc` text object |
| @comment.inside | The contents of a comment | `igc` text object (rarely supported) |
For example:
```scheme
; include only the content of the method in the function
(method_definition
body: (_
"{"
(_)* @function.inside
"}")) @function.around
; match function.around for declarations with no body
(function_signature_item) @function.around
; join all adjacent comments into one
(comment)+ @comment.around
```
### Text redactions
The `redactions.scm` file defines text redaction rules. When collaborating and sharing your screen, it makes sure that certain syntax nodes are rendered in a redacted mode to avoid them from leaking.

View file

@ -79,12 +79,41 @@ The following commands use the language server to help you navigate and refactor
### Treesitter
Treesitter is a powerful tool that Zed uses to understand the structure of your code. These commands help you navigate your code semantically.
Treesitter is a powerful tool that Zed uses to understand the structure of your code. Zed provides motions that change the current cursor position, and text objects that can be used as the target of actions.
| Command | Default Shortcut |
| ---------------------------- | ---------------- |
| Select a smaller syntax node | `] x` |
| Select a larger syntax node | `[ x` |
| Command | Default Shortcut |
| ------------------------------- | --------------------------- |
| Go to next/previous method | `] m` / `[ m` |
| Go to next/previous method end | `] M` / `[ M` |
| Go to next/previous section | `] ]` / `[ [` |
| Go to next/previous section end | `] [` / `[ ]` |
| Go to next/previous comment | `] /`, `] *` / `[ /`, `[ *` |
| Select a larger syntax node | `[ x` |
| Select a larger syntax node | `[ x` |
| Text Objects | Default Shortcut |
| ---------------------------------------------------------- | ---------------- |
| Around a class, definition, etc. | `a c` |
| Inside a class, definition, etc. | `i c` |
| Around a function, method etc. | `a f` |
| Inside a function, method, etc. | `i f` |
| A comment | `g c` |
| An argument, or list item, etc. | `i a` |
| An argument, or list item, etc. (including trailing comma) | `a a` |
| Around an HTML-like tag | `i a` |
| Inside an HTML-like tag | `i a` |
| The current indent level, and one line before and after | `a I` |
| The current indent level, and one line before | `a i` |
| The current indent level | `i i` |
Note that the definitions for the targets of the `[m` family of motions are the same as the
boundaries defined by `af`. The targets of the `[[` are the same as those defined by `ac`, though
if there are no classes, then functions are also used. Similarly `gc` is used to find `[ /`. `g c`
The definition of functions, classes and comments is language dependent, and support can be added
to extensions by adding a [`textobjects.scm`]. The definition of arguments and tags operates at
the tree-sitter level, but looks for certain patterns in the parse tree and is not currently configurable
per language.
### Multi cursor