1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 22:01:47 +03:00

wezterm: add ActivatePaneDirection key assignment

This allows moving to an adjacent pane in the specified direction.

refs: https://github.com/wez/wezterm/issues/157
This commit is contained in:
Wez Furlong 2020-09-23 21:01:40 -07:00
parent 97ff359a18
commit 84753a8261
3 changed files with 114 additions and 0 deletions

View File

@ -1863,6 +1863,19 @@ impl TermWindow {
tab.adjust_pane_size(*direction, *amount);
}
}
ActivatePaneDirection(direction) => {
let mux = Mux::get().unwrap();
let tab = match mux.get_active_tab_for_window(self.mux_window_id) {
Some(tab) => tab,
None => return Ok(()),
};
let tab_id = tab.tab_id();
if self.tab_state(tab_id).overlay.is_none() {
tab.activate_pane_direction(*direction);
}
}
};
Ok(())
}

View File

@ -120,6 +120,7 @@ pub enum KeyAssignment {
CompleteSelectionOrOpenLinkAtMouseCursor,
AdjustPaneSize(PaneDirection, usize),
ActivatePaneDirection(PaneDirection),
}
impl_lua_conversion!(KeyAssignment);
@ -295,6 +296,26 @@ impl InputMap {
KeyCode::DownArrow,
AdjustPaneSize(PaneDirection::Down, 1)
],
[
ctrl_shift,
KeyCode::LeftArrow,
ActivatePaneDirection(PaneDirection::Left)
],
[
ctrl_shift,
KeyCode::RightArrow,
ActivatePaneDirection(PaneDirection::Right)
],
[
ctrl_shift,
KeyCode::UpArrow,
ActivatePaneDirection(PaneDirection::Up)
],
[
ctrl_shift,
KeyCode::DownArrow,
ActivatePaneDirection(PaneDirection::Down)
],
);
#[cfg(target_os = "macos")]

View File

@ -6,6 +6,7 @@ use async_trait::async_trait;
use bintree::PathBranch;
use downcast_rs::{impl_downcast, Downcast};
use portable_pty::PtySize;
use rangeset::range_intersection;
use serde::{Deserialize, Serialize};
use std::cell::{RefCell, RefMut};
use std::rc::Rc;
@ -566,6 +567,85 @@ impl Tab {
}
}
/// Activate an adjacent pane in the specified direction.
/// In cases where there are multiple adjacent panes in the
/// intended direction, we take the pane that has the largest
/// edge intersection.
pub fn activate_pane_direction(&self, direction: PaneDirection) {
let panes = self.iter_panes();
let active = match panes.iter().find(|pane| pane.is_active) {
Some(p) => p,
None => {
// No active pane somehow...
self.set_active_idx(0);
return;
}
};
let mut best = None;
/// Compute the edge intersection size between two touching panes
fn compute_score(
active_start: usize,
active_size: usize,
current_start: usize,
current_size: usize,
) -> usize {
range_intersection(
&(active_start..active_start + active_size),
&(current_start..current_start + current_size),
)
.unwrap_or(0..0)
.count()
}
for pane in &panes {
let score = match direction {
PaneDirection::Right => {
if pane.left == active.left + active.width + 1 {
compute_score(active.top, active.height, pane.top, pane.height)
} else {
0
}
}
PaneDirection::Left => {
if pane.left + pane.width + 1 == active.left {
compute_score(active.top, active.height, pane.top, pane.height)
} else {
0
}
}
PaneDirection::Up => {
if pane.top + pane.height + 1 == active.top {
compute_score(active.left, active.width, pane.left, pane.width)
} else {
0
}
}
PaneDirection::Down => {
if active.top + active.height + 1 == pane.top {
compute_score(active.left, active.width, pane.left, pane.width)
} else {
0
}
}
};
if score > 0 {
let target = match best.take() {
Some((best_score, best_pane)) if best_score > score => (best_score, best_pane),
_ => (score, pane),
};
best.replace(target);
}
}
if let Some((_, target)) = best.take() {
self.set_active_idx(target.index);
}
}
pub fn prune_dead_panes(&self) -> bool {
let mut dead_panes = vec![];