Files
zed/docs/src/snippets.md
T
Ibrahim Khan cbe92a9c1a snippets: Strip path separators from language snippet file names (#61421)
Closes #59620

## Problem

A language whose name contains a `/`, such as a custom `PL/X` extension
(`lsp_id` → `pl/x`), broke snippets end to end:

- The `snippets: configure snippets` action wrote the file to
`~/.config/zed/snippets/pl/x.json`, i.e. inside a `pl/` subdirectory.
- The snippet scanner reads `snippets/` non-recursively and skips
directories, so that file was never loaded and the snippet could never
be used.
- The completion lookup keyed off the raw `lsp_id` (`pl/x`), which
wouldn't have matched the file-stem key even if the file had been
scanned.

So Zed's own UI created a snippet file it could never read back.

## Fix

Add `LanguageName::snippet_scope_id()` (the `lsp_id` with `/` and `\`
removed) and use it everywhere a language maps to its snippet file name
or lookup key:

- the Configure Snippets writer and its "already configured" label, and
- the two completion lookups in `editor`.

`PL/X` now maps to a flat `plx.json`, as suggested in the issue. The
`editor::InsertSnippet` action is intentionally left unchanged: its
`language` field is documented to be the snippet file name stem, which
is already separator-free.

Note: files created under the old behavior (nested `foo/bar.json`)
aren't migrated; re-running Configure Snippets writes the corrected flat
file.

## Testing

- Added a `language_core` unit test asserting `snippet_scope_id()`
strips `/` and `\` (e.g. `PL/X` → `plx`).
- `cargo test -p language_core` passes.
- `./script/clippy -p language_core -p language` passes.
- Docs Prettier passes.

Release Notes:

- Fixed snippets being unusable for languages whose name contains a `/`
character
2026-07-23 04:49:39 +00:00

1.8 KiB

title, description
title description
Snippets - Zed Create and use code snippets in Zed with tab stops, placeholders, variables, and language-scoped triggers.

Snippets

Use the {#action snippets::ConfigureSnippets} action to create a new snippets file or edit an existing snippets file for a specified scope.

The snippets are located in ~/.config/zed/snippets directory to which you can navigate with the {#action snippets::OpenFolder} action.

Example configuration

{
  // Each snippet must have a name and body, but the prefix and description are optional.
  // The prefix is used to trigger the snippet, but when omitted then the name is used.
  // Use placeholders like $1, $2 or ${1:defaultValue} to define tab stops.
  // The $0 determines the final cursor position.
  // Placeholders with the same value are linked.
  // If the snippet contains the $ symbol outside of a placeholder, it must be escaped with two slashes (e.g. \\$var).
  "Log to console": {
    "prefix": "log",
    "body": ["console.info(\"Hello, ${1:World}!\")", "$0"],
    "description": "Logs to console"
  }
}

Scopes

The scope is determined by the language name in lowercase e.g. python.json for Python, shell script.json for Shell Script, but there are some exceptions to this rule:

Scope Filename
Global snippets.json
JSX javascript.json
Plain Text plaintext.json

To create JSX snippets you have to use javascript.json snippets file, instead of jsx.json, but this does not apply to TSX and TypeScript which follow the above rule.

Path separators (/ and \) are removed from the file name, so a language named PL/X uses plx.json.

Known Limitations

  • Only the first prefix is used when a list of prefixes is passed in.
  • Currently only the json snippet file format is supported.