Support Emmet's wrap with abbreviation (#63383)

Closes https://github.com/zed-industries/zed/issues/15588


https://github.com/user-attachments/assets/2813d235-6dac-4fe6-9ae0-2783e16270ac

Release Notes:

- Added Emmet's wrap with abbreviation support
This commit is contained in:
Kirill Bulatov authored and GitHub committed 2026-09-02 18:21:02 +00:00
1 parent 810c6a04a6
commit 769d0befa7
26 files changed
+2581 -40

No files matched your search

+33
View File
@@ -11,6 +11,39 @@ Emmet support is available through the [Emmet extension](https://github.com/zed-
- Language Server: [olrtg/emmet-language-server](https://github.com/olrtg/emmet-language-server)
## Wrap with abbreviation
With the Emmet extension installed, you can wrap the current selections in an expanded [Emmet abbreviation](https://docs.emmet.io/abbreviations/):
1. Select the text to wrap. With an empty selection, the enclosing HTML element is wrapped; if no enclosing element can be determined, the current line is wrapped instead.
2. Run `editor: wrap with abbreviation` from the command palette. The last used abbreviation is prefilled and selected, so typing replaces it; `up` and `down` cycle through previously used abbreviations.
3. Type an abbreviation, for example `div.wrapper>ul>li*3`, into the input that appears below the selection. A preview of the expansion is shown under the input as you type.
4. Press `enter` to apply, or `escape` to cancel. If the abbreviation produces no expansion, the error is shown next to the input and the input stays open so you can correct it.
For a single selection, the expansion is inserted as a snippet and the cursor is placed at the end of the expansion. With multiple selections, each selection is wrapped separately; overlapping selections are merged and wrapped once.
The [documented wrap behaviors](https://docs.emmet.io/actions/wrap-with-abbreviation/) are supported:
- Wrapping individual lines: mark the repeating element with `*` (without a number), for example `ul>li*`, and each selected line is wrapped in its own element. `$` numbering works too: `ul>li.item$*>a`.
- Removing list markers: append the trim filter `|t`, for example `ul>li*|t`, to strip list markers such as `*`, `-`, or `1.` from the wrapped lines.
- Controlling output position: use the `$#` placeholder inside attribute values or text nodes, for example `ul>li[title=$#]*>{$#}`.
- The [comment filter](https://docs.emmet.io/filters/comment/) `|c` and the [BEM filter](https://docs.emmet.io/filters/bem/) `|bem` are also supported and can be combined, for example `div#page>p.intro|c|bem`.
Selections that partially cover an opening or closing tag are expanded to the whole element before wrapping. Wrapping is a markup action: it is not offered in stylesheets, where Emmet provides completions instead.
The action has no default keybinding. To add one, bind it in your keymap:
```json [keymap]
[
{
"context": "Editor && mode == full",
"bindings": {
"ctrl-alt-w": "editor::WrapWithAbbreviation"
}
}
]
```
<!--
TBD: Document Emmet usage in zed with: HTML, PHP, ERB, Javascript, TSX, CSS
-->