mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 21:32:13 +03:00
paneselect: add mode parameter and a mode for swapping panes
Extends the pane selector to allow: ``` wezterm --config 'keys={{key="p", mods="CTRL", action=wezterm.action{PaneSelect={mode="SwapWithActive"}}}}' ``` to swap the active pane with the selected pane. Similar to https://wezfurlong.org/wezterm/config/lua/keyassignment/RotatePanes.html except that only the active and the selected panes have their positions adjusted. refs: https://github.com/wez/wezterm/issues/1842 refs: https://github.com/wez/wezterm/issues/1975
This commit is contained in:
parent
e114534bee
commit
2725559fc0
@ -264,11 +264,26 @@ impl Default for ClipboardPasteSource {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||
pub enum PaneSelectMode {
|
||||
Activate,
|
||||
SwapWithActive,
|
||||
}
|
||||
|
||||
impl Default for PaneSelectMode {
|
||||
fn default() -> Self {
|
||||
Self::Activate
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||
pub struct PaneSelectArguments {
|
||||
/// Overrides the main quick_select_alphabet config
|
||||
#[dynamic(default)]
|
||||
pub alphabet: String,
|
||||
|
||||
#[dynamic(default)]
|
||||
pub mode: PaneSelectMode,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||
|
@ -1470,6 +1470,58 @@ impl Tab {
|
||||
cell_dimensions(&*self.size.borrow())
|
||||
}
|
||||
|
||||
/// Swap the active pane with the specified pane_index
|
||||
pub fn swap_active_with_index(&self, pane_index: usize) -> Option<()> {
|
||||
let active_idx = self.get_active_idx();
|
||||
let mut pane = self.get_active_pane()?;
|
||||
log::trace!(
|
||||
"swap_active_with_index: pane_index {} active {}",
|
||||
pane_index,
|
||||
active_idx
|
||||
);
|
||||
|
||||
{
|
||||
let mut root = self.pane.borrow_mut();
|
||||
let mut cursor = root.take().unwrap().cursor();
|
||||
|
||||
// locate the requested index
|
||||
match cursor.go_to_nth_leaf(pane_index) {
|
||||
Ok(c) => cursor = c,
|
||||
Err(c) => {
|
||||
log::trace!("didn't find pane {pane_index}");
|
||||
root.replace(c.tree());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
std::mem::swap(&mut pane, cursor.leaf_mut().unwrap());
|
||||
|
||||
// re-position to the root
|
||||
cursor = cursor.tree().cursor();
|
||||
|
||||
// and now go and update the active idx
|
||||
match cursor.go_to_nth_leaf(active_idx) {
|
||||
Ok(c) => cursor = c,
|
||||
Err(c) => {
|
||||
root.replace(c.tree());
|
||||
log::trace!("didn't find active {active_idx}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
std::mem::swap(&mut pane, cursor.leaf_mut().unwrap());
|
||||
root.replace(cursor.tree());
|
||||
|
||||
// Advise the panes of their new sizes
|
||||
let size = *self.size.borrow();
|
||||
apply_sizes_from_splits(root.as_mut().unwrap(), &size);
|
||||
}
|
||||
|
||||
// And update focus
|
||||
self.advise_focus_change(Some(pane));
|
||||
None
|
||||
}
|
||||
|
||||
/// Computes the size of the pane that would result if the specified
|
||||
/// pane was split in a particular direction.
|
||||
/// The intent is to call this prior to spawning the new pane so that
|
||||
|
@ -7,7 +7,7 @@ use crate::termwindow::render::{
|
||||
use crate::termwindow::DimensionContext;
|
||||
use crate::utilsprites::RenderMetrics;
|
||||
use crate::TermWindow;
|
||||
use config::keyassignment::{KeyAssignment, PaneSelectArguments};
|
||||
use config::keyassignment::{KeyAssignment, PaneSelectArguments, PaneSelectMode};
|
||||
use config::{Dimension, TabBarColors};
|
||||
use mux::Mux;
|
||||
use std::cell::{Ref, RefCell};
|
||||
@ -18,6 +18,7 @@ pub struct PaneSelector {
|
||||
labels: RefCell<Vec<String>>,
|
||||
selection: RefCell<String>,
|
||||
alphabet: String,
|
||||
mode: PaneSelectMode,
|
||||
}
|
||||
|
||||
impl PaneSelector {
|
||||
@ -32,6 +33,7 @@ impl PaneSelector {
|
||||
labels: RefCell::new(vec![]),
|
||||
selection: RefCell::new(String::new()),
|
||||
alphabet,
|
||||
mode: args.mode,
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +145,38 @@ impl PaneSelector {
|
||||
|
||||
Ok((elements, labels))
|
||||
}
|
||||
|
||||
fn perform_selection(
|
||||
&self,
|
||||
pane_index: usize,
|
||||
term_window: &mut TermWindow,
|
||||
) -> anyhow::Result<()> {
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(term_window.mux_window_id) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let tab_id = tab.tab_id();
|
||||
|
||||
if term_window.tab_state(tab_id).overlay.is_none() {
|
||||
let panes = tab.iter_panes();
|
||||
|
||||
match self.mode {
|
||||
PaneSelectMode::Activate => {
|
||||
if panes.iter().position(|p| p.index == pane_index).is_some() {
|
||||
tab.set_active_idx(pane_index);
|
||||
}
|
||||
}
|
||||
PaneSelectMode::SwapWithActive => {
|
||||
tab.swap_active_with_index(pane_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
term_window.cancel_modal();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Modal for PaneSelector {
|
||||
@ -176,22 +210,7 @@ impl Modal for PaneSelector {
|
||||
// and if we have a complete match, activate that pane
|
||||
if let Some(pane_index) = self.labels.borrow().iter().position(|s| s == &*selection)
|
||||
{
|
||||
let mux = Mux::get().unwrap();
|
||||
let tab = match mux.get_active_tab_for_window(term_window.mux_window_id) {
|
||||
Some(tab) => tab,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let tab_id = tab.tab_id();
|
||||
|
||||
if term_window.tab_state(tab_id).overlay.is_none() {
|
||||
let panes = tab.iter_panes();
|
||||
if panes.iter().position(|p| p.index == pane_index).is_some() {
|
||||
tab.set_active_idx(pane_index);
|
||||
}
|
||||
}
|
||||
|
||||
term_window.cancel_modal();
|
||||
return self.perform_selection(pane_index, term_window);
|
||||
}
|
||||
}
|
||||
(KeyCode::Backspace, KeyModifiers::NONE) => {
|
||||
|
Loading…
Reference in New Issue
Block a user