editor: Add action to move between snippet tabstop positions v2 (#42127)

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

This PR fixes the issues that caused #41407 to be reverted in #42008.
Namely that the action context didn't take into account if a snippet
could move backwards or forwards, and the action shared the same key
mapping as `editor::MoveToPreviousWordStart` and
`editor::MoveToNextWordEnd`.

I changed the default key mapping for the move to snippet tabstop to tab
and shift-tab to match the default behavior of other editors.

Release Notes:

- Editor: Add actions to move between snippet tabstop positions
This commit is contained in:
Anthony Eid
2025-11-06 18:49:39 +00:00
committed by GitHub
parent 2d45c23fb0
commit ba136abf6c
7 changed files with 219 additions and 0 deletions
+48
View File
@@ -2511,6 +2511,18 @@ impl Editor {
key_context.add("renaming");
}
if let Some(snippet_stack) = self.snippet_stack.last() {
key_context.add("in_snippet");
if snippet_stack.active_index > 0 {
key_context.add("has_previous_tabstop");
}
if snippet_stack.active_index < snippet_stack.ranges.len().saturating_sub(1) {
key_context.add("has_next_tabstop");
}
}
match self.context_menu.borrow().as_ref() {
Some(CodeContextMenu::Completions(menu)) => {
if menu.visible() {
@@ -10046,6 +10058,42 @@ impl Editor {
self.outdent(&Outdent, window, cx);
}
pub fn next_snippet_tabstop(
&mut self,
_: &NextSnippetTabstop,
window: &mut Window,
cx: &mut Context<Self>,
) {
if self.mode.is_single_line() || self.snippet_stack.is_empty() {
cx.propagate();
return;
}
if self.move_to_next_snippet_tabstop(window, cx) {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
return;
}
cx.propagate();
}
pub fn previous_snippet_tabstop(
&mut self,
_: &PreviousSnippetTabstop,
window: &mut Window,
cx: &mut Context<Self>,
) {
if self.mode.is_single_line() || self.snippet_stack.is_empty() {
cx.propagate();
return;
}
if self.move_to_prev_snippet_tabstop(window, cx) {
self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
return;
}
cx.propagate();
}
pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
if self.mode.is_single_line() {
cx.propagate();