Reproduction steps
- Start Zed.
- Open the command palette and run snippets: configure snippets → "New Snippets File...". This opens a snippets file in ~/.config/zed/snippets/.
- Paste the following and save:
{
"Choice bug repro": {
"prefix": "tchoice",
"body": "${1|a,b\,c|}"
}
}
- Restart Zed (the snippet may not be picked up if the snippets directory was just created).
- In a buffer, type tchoice and accept the snippet completion (press ctrl-space if the menu doesn't open automatically).
- Look at the choice dropdown that opens for the first tabstop.
Current vs. Expected behavior
Current: the dropdown offers a and bc — the backslash-escaped comma in the second choice is silently dropped
Expected: a and b,c.
The snippet body ${1|a,b,c|} has two choices, where , is an escaped literal comma.
Per the LSP snippet grammar (choice ::= '${' int '|' text (',' text)* '|}'): "Within choice elements, the backslash also escapes comma and pipe characters."
VS Code offers a and b,c for the same snippet body.
Escapes in the first choice work correctly (e.g. ${1|x,y,z|} correctly offers x,y). The bug affects every choice after the first, for any escaped character (,, |, \).
Cause
In crates/snippet/src/snippet.rs, parse_choices handles escape sequences like this:
Some('\') => {
source = &source[1..];
if let Some(c) = source.chars().next() {
if !found_default_choice {
current_choice.push(c);
text.push(c);
}
source = &source[c.len_utf8()..];
}
}
current_choice.push(c) is inside the !found_default_choice guard, so once the first choice has been parsed, escaped characters in later choices are skipped entirely. The guard should only apply to text (the default value inserted into the buffer) - the plain-text branch a few lines below does this correctly, appending to current_choice unconditionally and only gating text.
The existing test (test_snippet_with_choice_placeholders) only covers escapes in the first choice, which is why it doesn't catch this.
I'd like to submit a PR fixing this (move current_choice.push(c) out of the guard) along with a regression test.
Zed version and system specs
Zed: v1.11.3+stable.326.952d712dac48a4af2c54fb22c82d82a9d69b72d4 (Zed)
OS: Linux Wayland fedora 44
Memory: 15 GiB
Architecture: x86_64
GPU: AMD Radeon Graphics (RADV RENOIR) || radv || Mesa 26.1.4
Attach Zed log file
Zed.log
Relevant Zed settings
settings.json
Relevant Keymap
keymap.json
(for AI issues) Model provider details
No response
If you are using WSL on Windows, what flavor of Linux are you using?
None
Reproduction steps
{
"Choice bug repro": {
"prefix": "tchoice",
"body": "${1|a,b\,c|}"
}
}
Current vs. Expected behavior
Current: the dropdown offers a and bc — the backslash-escaped comma in the second choice is silently dropped
Expected: a and b,c.
The snippet body ${1|a,b,c|} has two choices, where , is an escaped literal comma.
Per the LSP snippet grammar (choice ::= '${' int '|' text (',' text)* '|}'): "Within choice elements, the backslash also escapes comma and pipe characters."
VS Code offers a and b,c for the same snippet body.
Escapes in the first choice work correctly (e.g. ${1|x,y,z|} correctly offers x,y). The bug affects every choice after the first, for any escaped character (,, |, \).
Cause
In crates/snippet/src/snippet.rs, parse_choices handles escape sequences like this:
Some('\') => {
source = &source[1..];
if let Some(c) = source.chars().next() {
if !found_default_choice {
current_choice.push(c);
text.push(c);
}
source = &source[c.len_utf8()..];
}
}
current_choice.push(c) is inside the !found_default_choice guard, so once the first choice has been parsed, escaped characters in later choices are skipped entirely. The guard should only apply to text (the default value inserted into the buffer) - the plain-text branch a few lines below does this correctly, appending to current_choice unconditionally and only gating text.
The existing test (test_snippet_with_choice_placeholders) only covers escapes in the first choice, which is why it doesn't catch this.
I'd like to submit a PR fixing this (move current_choice.push(c) out of the guard) along with a regression test.
Zed version and system specs
Zed: v1.11.3+stable.326.952d712dac48a4af2c54fb22c82d82a9d69b72d4 (Zed)
OS: Linux Wayland fedora 44
Memory: 15 GiB
Architecture: x86_64
GPU: AMD Radeon Graphics (RADV RENOIR) || radv || Mesa 26.1.4
Attach Zed log file
Zed.log
Relevant Zed settings
settings.json
Relevant Keymap
keymap.json
(for AI issues) Model provider details
No response
If you are using WSL on Windows, what flavor of Linux are you using?
None