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)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||||
pub struct PaneSelectArguments {
|
pub struct PaneSelectArguments {
|
||||||
/// Overrides the main quick_select_alphabet config
|
/// Overrides the main quick_select_alphabet config
|
||||||
#[dynamic(default)]
|
#[dynamic(default)]
|
||||||
pub alphabet: String,
|
pub alphabet: String,
|
||||||
|
|
||||||
|
#[dynamic(default)]
|
||||||
|
pub mode: PaneSelectMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||||
|
@ -1470,6 +1470,58 @@ impl Tab {
|
|||||||
cell_dimensions(&*self.size.borrow())
|
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
|
/// Computes the size of the pane that would result if the specified
|
||||||
/// pane was split in a particular direction.
|
/// pane was split in a particular direction.
|
||||||
/// The intent is to call this prior to spawning the new pane so that
|
/// 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::termwindow::DimensionContext;
|
||||||
use crate::utilsprites::RenderMetrics;
|
use crate::utilsprites::RenderMetrics;
|
||||||
use crate::TermWindow;
|
use crate::TermWindow;
|
||||||
use config::keyassignment::{KeyAssignment, PaneSelectArguments};
|
use config::keyassignment::{KeyAssignment, PaneSelectArguments, PaneSelectMode};
|
||||||
use config::{Dimension, TabBarColors};
|
use config::{Dimension, TabBarColors};
|
||||||
use mux::Mux;
|
use mux::Mux;
|
||||||
use std::cell::{Ref, RefCell};
|
use std::cell::{Ref, RefCell};
|
||||||
@ -18,6 +18,7 @@ pub struct PaneSelector {
|
|||||||
labels: RefCell<Vec<String>>,
|
labels: RefCell<Vec<String>>,
|
||||||
selection: RefCell<String>,
|
selection: RefCell<String>,
|
||||||
alphabet: String,
|
alphabet: String,
|
||||||
|
mode: PaneSelectMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaneSelector {
|
impl PaneSelector {
|
||||||
@ -32,6 +33,7 @@ impl PaneSelector {
|
|||||||
labels: RefCell::new(vec![]),
|
labels: RefCell::new(vec![]),
|
||||||
selection: RefCell::new(String::new()),
|
selection: RefCell::new(String::new()),
|
||||||
alphabet,
|
alphabet,
|
||||||
|
mode: args.mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +145,38 @@ impl PaneSelector {
|
|||||||
|
|
||||||
Ok((elements, labels))
|
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 {
|
impl Modal for PaneSelector {
|
||||||
@ -176,22 +210,7 @@ impl Modal for PaneSelector {
|
|||||||
// and if we have a complete match, activate that pane
|
// and if we have a complete match, activate that pane
|
||||||
if let Some(pane_index) = self.labels.borrow().iter().position(|s| s == &*selection)
|
if let Some(pane_index) = self.labels.borrow().iter().position(|s| s == &*selection)
|
||||||
{
|
{
|
||||||
let mux = Mux::get().unwrap();
|
return self.perform_selection(pane_index, term_window);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(KeyCode::Backspace, KeyModifiers::NONE) => {
|
(KeyCode::Backspace, KeyModifiers::NONE) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user