vim: Close popovers and expanded hunks on escape in Helix normal mode
In Helix normal mode escape runs `vim::SwitchToHelixNormalMode`, which only switches the mode, so the diagnostic shown by `] d`, a hunk expanded with `g o`, a hover popover and the like stayed open. Vim mode closes them because escape there is `editor::Cancel`. Binding Helix to `Cancel` isn't an option, since once nothing is open it collapses the selections. Pull the part of `Editor::cancel` that runs before it touches the selections into `Editor::dismiss_overlays`, and call it when escape is pressed in Helix normal mode. Selections are kept as before. Closes #55197
This commit is contained in:
1 parent
134c5e9f71
commit
5f70e7afe2
3 files changed
+68
-17
No files matched your search
+23
-16
@@ -3519,22 +3519,7 @@ impl Editor {
|
|||||||
self.selection_mark_mode = false;
|
self.selection_mark_mode = false;
|
||||||
self.selection_drag_state = SelectionDragState::None;
|
self.selection_drag_state = SelectionDragState::None;
|
||||||
|
|
||||||
if self.dismiss_menus_and_popups(true, window, cx) {
|
if self.dismiss_overlays(window, cx) {
|
||||||
cx.notify();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if self.clear_expanded_diff_hunks(cx) {
|
|
||||||
cx.notify();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if self.show_git_blame_gutter
|
|
||||||
&& !self
|
|
||||||
.blame
|
|
||||||
.as_ref()
|
|
||||||
.is_some_and(|blame| blame.read(cx).is_static())
|
|
||||||
{
|
|
||||||
self.show_git_blame_gutter = false;
|
|
||||||
cx.notify();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3553,6 +3538,28 @@ impl Editor {
|
|||||||
cx.propagate();
|
cx.propagate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Closes what [`Cancel`] closes before it gets to the selections: menus and popovers,
|
||||||
|
/// expanded diff hunks and the git blame gutter. Returns whether anything was closed.
|
||||||
|
pub fn dismiss_overlays(&mut self, window: &mut Window, cx: &mut Context<Self>) -> bool {
|
||||||
|
let mut dismissed =
|
||||||
|
self.dismiss_menus_and_popups(true, window, cx) || self.clear_expanded_diff_hunks(cx);
|
||||||
|
if !dismissed
|
||||||
|
&& self.show_git_blame_gutter
|
||||||
|
&& !self
|
||||||
|
.blame
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|blame| blame.read(cx).is_static())
|
||||||
|
{
|
||||||
|
self.show_git_blame_gutter = false;
|
||||||
|
dismissed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if dismissed {
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
dismissed
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dismiss_menus_and_popups(
|
pub fn dismiss_menus_and_popups(
|
||||||
&mut self,
|
&mut self,
|
||||||
is_user_requested: bool,
|
is_user_requested: bool,
|
||||||
|
|||||||
+40
-1
@@ -1879,7 +1879,7 @@ mod test {
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use std::{fmt::Write, time::Duration};
|
use std::{fmt::Write, time::Duration};
|
||||||
|
|
||||||
use editor::{HighlightKey, MultiBufferOffset};
|
use editor::{Anchor, HighlightKey, MultiBufferOffset};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Bounds, DispatchEventResult, ElementInputHandler, KeyBinding, KeyDownEvent, Keystroke,
|
Bounds, DispatchEventResult, ElementInputHandler, KeyBinding, KeyDownEvent, Keystroke,
|
||||||
PlatformInput, PlatformInputHandler, UpdateGlobal, VisualTestContext,
|
PlatformInput, PlatformInputHandler, UpdateGlobal, VisualTestContext,
|
||||||
@@ -4687,6 +4687,45 @@ mod test {
|
|||||||
assert_eq!(cx.active_operator(), None);
|
assert_eq!(cx.active_operator(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_helix_escape_collapses_expanded_hunk(cx: &mut gpui::TestAppContext) {
|
||||||
|
let mut cx = VimTestContext::new(cx, true).await;
|
||||||
|
cx.enable_helix();
|
||||||
|
|
||||||
|
let selected = indoc! {"
|
||||||
|
one
|
||||||
|
«twoˇ»
|
||||||
|
three"};
|
||||||
|
cx.set_state(selected, Mode::HelixNormal);
|
||||||
|
cx.set_head_text(indoc! {"
|
||||||
|
one
|
||||||
|
CHANGED
|
||||||
|
three"});
|
||||||
|
cx.run_until_parked();
|
||||||
|
|
||||||
|
let has_expanded_hunks = |cx: &mut VimTestContext| {
|
||||||
|
cx.update_editor(|editor, _, cx| {
|
||||||
|
editor
|
||||||
|
.buffer()
|
||||||
|
.read(cx)
|
||||||
|
.has_expanded_diff_hunks_in_ranges(&[Anchor::Min..Anchor::Max], cx)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.simulate_keystrokes("g o");
|
||||||
|
assert!(has_expanded_hunks(&mut cx));
|
||||||
|
|
||||||
|
cx.simulate_keystrokes("escape");
|
||||||
|
assert!(
|
||||||
|
!has_expanded_hunks(&mut cx),
|
||||||
|
"escape should collapse the expanded hunk"
|
||||||
|
);
|
||||||
|
cx.assert_state(selected, Mode::HelixNormal);
|
||||||
|
|
||||||
|
cx.simulate_keystrokes("escape");
|
||||||
|
cx.assert_state(selected, Mode::HelixNormal);
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_helix_rename_uses_visible_cursor_position(cx: &mut gpui::TestAppContext) {
|
async fn test_helix_rename_uses_visible_cursor_position(cx: &mut gpui::TestAppContext) {
|
||||||
let mut cx = VimTestContext::new_typescript(cx).await;
|
let mut cx = VimTestContext::new_typescript(cx).await;
|
||||||
|
|||||||
@@ -714,6 +714,11 @@ impl Vim {
|
|||||||
editor,
|
editor,
|
||||||
cx,
|
cx,
|
||||||
|vim, _: &SwitchToHelixNormalMode, window, cx| {
|
|vim, _: &SwitchToHelixNormalMode, window, cx| {
|
||||||
|
// Escape in helix normal mode lands here. Close popovers and overlays
|
||||||
|
// like `editor::Cancel` does in vim mode, but keep the selections.
|
||||||
|
if vim.mode == Mode::HelixNormal {
|
||||||
|
vim.update_editor(cx, |_, editor, cx| editor.dismiss_overlays(window, cx));
|
||||||
|
}
|
||||||
vim.switch_mode(Mode::HelixNormal, true, window, cx)
|
vim.switch_mode(Mode::HelixNormal, true, window, cx)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user