fix: route pane focus bindings past the file explorer
This commit is contained in:
@@ -199,6 +199,8 @@ Closing a pane gives its space to its sibling:
|
|||||||
|
|
||||||
There is no default close-pane binding. Option must send Alt/Meta in the terminal; on macOS, configure the terminal's Option-key behavior if it instead produces special characters. These bindings do not replace existing Ctrl+j or uppercase motion/edit bindings.
|
There is no default close-pane binding. Option must send Alt/Meta in the terminal; on macOS, configure the terminal's Option-key behavior if it instead produces special characters. These bindings do not replace existing Ctrl+j or uppercase motion/edit bindings.
|
||||||
|
|
||||||
|
Pane-focus bindings also work while the ordinary file explorer or picker has focus. Moving to a neighboring pane returns keyboard focus to its document; a floating picker closes, while a docked explorer remains visible. Explicit `tree` or `selection` navigation overrides and disabled keys take precedence over pane-focus bindings.
|
||||||
|
|
||||||
Diff comparisons reuse the split geometry and directional-focus engine. Option/Alt navigation moves between Before, After, and Files first, then to a neighboring workspace pane when there is no internal target in that direction. Splitting a diff text view creates an ordinary sibling showing the same buffer; historical snapshots remain read-only, including after the comparison closes.
|
Diff comparisons reuse the split geometry and directional-focus engine. Option/Alt navigation moves between Before, After, and Files first, then to a neighboring workspace pane when there is no internal target in that direction. Splitting a diff text view creates an ordinary sibling showing the same buffer; historical snapshots remain read-only, including after the comparison closes.
|
||||||
|
|
||||||
## Buffers
|
## Buffers
|
||||||
|
|||||||
@@ -1662,6 +1662,9 @@ impl Editor {
|
|||||||
.neighbor(self.pane_id, direction, self.pane_bounds)
|
.neighbor(self.pane_id, direction, self.pane_bounds)
|
||||||
{
|
{
|
||||||
self.finish_pane_interaction();
|
self.finish_pane_interaction();
|
||||||
|
if self.diff.is_none() {
|
||||||
|
self.blur_file_picker();
|
||||||
|
}
|
||||||
self.select_pane(id);
|
self.select_pane(id);
|
||||||
if self.active.view.mode == Mode::Insert {
|
if self.active.view.mode == Mode::Insert {
|
||||||
self.begin_insert();
|
self.begin_insert();
|
||||||
@@ -4260,6 +4263,28 @@ impl Editor {
|
|||||||
if (picker_focused || self.palette.is_some()) && self.handle_selection_binding(&input) {
|
if (picker_focused || self.palette.is_some()) && self.handle_selection_binding(&input) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
if picker_focused
|
||||||
|
&& let Some(Binding::Action(action)) =
|
||||||
|
self.bindings.get(&mode).and_then(|keys| keys.get(&input))
|
||||||
|
&& matches!(
|
||||||
|
action,
|
||||||
|
Action::PaneFocusLeft
|
||||||
|
| Action::PaneFocusDown
|
||||||
|
| Action::PaneFocusUp
|
||||||
|
| Action::PaneFocusRight
|
||||||
|
)
|
||||||
|
{
|
||||||
|
let action = *action;
|
||||||
|
if self
|
||||||
|
.file_picker
|
||||||
|
.as_mut()
|
||||||
|
.expect("focused picker exists")
|
||||||
|
.handle_filter_input(&input)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
return self.act(action);
|
||||||
|
}
|
||||||
if picker_focused {
|
if picker_focused {
|
||||||
self.handle_file_picker(input);
|
self.handle_file_picker(input);
|
||||||
return None;
|
return None;
|
||||||
@@ -8040,6 +8065,65 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pane_focus_remaps_do_not_steal_printable_picker_filter_input() {
|
||||||
|
let directory = Directory::new();
|
||||||
|
fs::write(directory.path("hello.txt"), "alpha").unwrap();
|
||||||
|
let mut editor = editor();
|
||||||
|
editor.project_root = directory.0.clone();
|
||||||
|
editor.handle(Input::Char('|'));
|
||||||
|
editor
|
||||||
|
.bind("normal", "h", Some("core.pane.focus_left".into()))
|
||||||
|
.unwrap();
|
||||||
|
editor.open_file_picker(FilePresentation::Floating);
|
||||||
|
editor.handle(Input::Char('h'));
|
||||||
|
assert_eq!(editor.pane_id(), 2);
|
||||||
|
assert_eq!(editor.file_picker().unwrap().query, "h");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pane_focus_bindings_escape_focused_explorer_without_changing_documents() {
|
||||||
|
let directory = Directory::new();
|
||||||
|
fs::write(directory.path("a.txt"), "alpha").unwrap();
|
||||||
|
fs::write(directory.path("b.txt"), "beta").unwrap();
|
||||||
|
let mut editor = editor();
|
||||||
|
editor.project_root = directory.0.clone();
|
||||||
|
editor.handle(Input::Char('|'));
|
||||||
|
editor.handle(Input::Char('_'));
|
||||||
|
let original = editor.lines().to_vec();
|
||||||
|
for (key, pane) in [('k', 2), ('h', 1), ('l', 2), ('j', 3)] {
|
||||||
|
editor.open_file_picker(FilePresentation::Docked);
|
||||||
|
assert!(editor.file_picker().unwrap().focused);
|
||||||
|
editor.handle(Input::Alt(key));
|
||||||
|
assert_eq!(editor.pane_id(), pane);
|
||||||
|
assert!(!editor.file_picker().unwrap().focused);
|
||||||
|
assert_eq!(editor.lines(), original);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn explorer_navigation_overrides_take_precedence_over_pane_focus() {
|
||||||
|
for context in ["tree", "selection"] {
|
||||||
|
for target in [None, Some("core.down")] {
|
||||||
|
let directory = Directory::new();
|
||||||
|
fs::write(directory.path("a.txt"), "alpha").unwrap();
|
||||||
|
fs::write(directory.path("b.txt"), "beta").unwrap();
|
||||||
|
let mut editor = editor();
|
||||||
|
editor.project_root = directory.0.clone();
|
||||||
|
editor.handle(Input::Char('|'));
|
||||||
|
editor
|
||||||
|
.bind(context, "alt+h", target.map(str::to_owned))
|
||||||
|
.unwrap();
|
||||||
|
editor.open_file_picker(FilePresentation::Docked);
|
||||||
|
editor.handle(Input::Alt('h'));
|
||||||
|
assert_eq!(editor.pane_id(), 2);
|
||||||
|
let picker = editor.file_picker().unwrap();
|
||||||
|
assert!(picker.focused);
|
||||||
|
assert_eq!(picker.selected, usize::from(target.is_some()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nested_panes_inherit_views_and_focus_geometrically_without_touching_ctrl_j() {
|
fn nested_panes_inherit_views_and_focus_geometrically_without_touching_ctrl_j() {
|
||||||
let mut editor = editor();
|
let mut editor = editor();
|
||||||
|
|||||||
Reference in New Issue
Block a user