Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for pane swapping in Key Assignment and Lua API. #4990

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions config/src/keyassignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,20 @@ impl PaneDirection {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, FromDynamic, ToDynamic)]
pub struct SwapActivePaneDirectionArguments {
pub direction: PaneDirection,
pub keep_focus: bool,
}
impl_lua_conversion_dynamic!(SwapActivePaneDirectionArguments);

#[derive(Debug, Clone, Copy, PartialEq, Eq, FromDynamic, ToDynamic)]
pub struct SwapActivePaneByIndexArguments {
pub pane_index: usize,
pub keep_focus: bool,
}
impl_lua_conversion_dynamic!(SwapActivePaneByIndexArguments);

#[derive(Debug, Copy, Clone, PartialEq, Eq, FromDynamic, ToDynamic, Serialize, Deserialize)]
pub enum ScrollbackEraseMode {
ScrollbackOnly,
Expand Down Expand Up @@ -566,6 +580,8 @@ pub enum KeyAssignment {
AdjustPaneSize(PaneDirection, usize),
ActivatePaneDirection(PaneDirection),
ActivatePaneByIndex(usize),
SwapActivePaneDirection(SwapActivePaneDirectionArguments),
SwapActivePaneByIndex(SwapActivePaneByIndexArguments),
TogglePaneZoomState,
SetPaneZoomState(bool),
CloseCurrentPane {
Expand Down
10 changes: 10 additions & 0 deletions docs/config/lua/MuxTab/swap_active_pane_by_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# `tab:swap_active_pane_by_index{ pane_index, keep_focus }`

{{since('nightly')}}

Swaps the active pane with the pane corresponding to *pane_index*.
If *keep_focus* is true, focus is retained on the currently active pane but in
its new position.

See [tab:panes_with_info](panes_with_info.md) for more information about how to
obtain pane indexes.
52 changes: 52 additions & 0 deletions docs/config/lua/MuxTab/swap_active_pane_direction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# `tab:swap_active_pane_direction{ direction, keep_focus }`

{{since('nightly')}}

Swaps the active pane with the pane adjacent to it in the direction *direction*.
If *keep_focus* is true, focus is retained on the currently active pane but in its
new position.

Valid values for *direction* are:

* `"Left"`
* `"Right"`
* `"Up"`
* `"Down"`
* `"Prev"`
* `"Next"`

An example of usage is below:

```lua
local wezterm = require 'wezterm'
local config = {}

local function swap_active_pane_action(direction)
return wezterm.action_callback(function(_window, pane)
local tab = pane:tab()
if tab ~= nil then
tab:swap_active_pane_direction {
direction = direction,
keep_focus = true,
}
end
end)
end

config.keys = {
{
key = 'LeftArrow',
mods = 'CTRL|ALT',
action = swap_active_pane_action 'Prev',
},
{
key = 'RightArrow',
mods = 'CTRL|ALT',
action = swap_active_pane_action 'Next',
},
}
return config
```

See [ActivatePaneDirection](../keyassignment/ActivatePaneDirection.md) for more information
about how panes are selected given a direction.
35 changes: 35 additions & 0 deletions docs/config/lua/keyassignment/SwapActivePaneByIndex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# `SwapActivePaneByIndex`

{{since('20220319-142410-0fcdea07')}}

`SwapActivePaneByIndex` swaps the active pane with the pane with the specified
index within the current tab. Invalid indices are ignored.

This example causes CTRL-ALT-a, CTRL-ALT-b, CTRL-ALT-c to swap the current pane
with the 0th, 1st and 2nd panes, respectively:

```lua
local wezterm = require 'wezterm'
local act = wezterm.action
local config = {}

config.keys = {
{
key = 'a',
mods = 'CTRL|ALT',
action = { SwapActivePaneByIndex = { pane_index = 0, keep_focus = true } },
},
{
key = 'b',
mods = 'CTRL|ALT',
action = { SwapActivePaneByIndex = { pane_index = 1, keep_focus = true } },
},
{
key = 'c',
mods = 'CTRL|ALT',
action = { SwapActivePaneByIndex = { pane_index = 2, keep_focus = true } },
},
}

return config
```
48 changes: 48 additions & 0 deletions docs/config/lua/keyassignment/SwapActivePaneDirection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# `SwapActivePaneDirection`

{{since('nightly')}}

`SwapActivePaneDirection` swaps the active pane with the pane adjacent to it in
a specific direction.

See [ActivatePaneDirection](../keyassignment/ActivatePaneDirection.md) for more information
about how panes are selected given a direction.

The action requires two named arguments, *direction* and *keep_focus*.

If *keep_focus* is true, focus is retained on the currently active pane but in its
new position.

Valid values for *direction* are:

* `"Left"`
* `"Right"`
* `"Up"`
* `"Down"`
* `"Prev"`
* `"Next"`

An example of usage is below:

```lua
local wezterm = require 'wezterm'
local config = {}

config.keys = {
{
key = 'LeftArrow',
mods = 'CTRL|ALT',
action = {
SwapActivePaneDirection = { direction = 'Prev', keep_focus = true },
},
},
{
key = 'RightArrow',
mods = 'CTRL|ALT',
action = {
SwapActivePaneDirection = { direction = 'Next', keep_focus = true },
},
},
}
return config
```
30 changes: 29 additions & 1 deletion lua-api-crates/mux/src/tab.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use config::keyassignment::PaneDirection;
use config::keyassignment::{
PaneDirection, SwapActivePaneByIndexArguments, SwapActivePaneDirectionArguments,
};

use super::*;
use luahelper::mlua::Value;
Expand Down Expand Up @@ -155,5 +157,31 @@ impl UserData for MuxTab {
}
Ok(())
});

methods.add_method("swap_active_pane_direction", |_, this, args: Value| {
let mux = get_mux()?;
let tab = this.resolve(&mux)?;

let SwapActivePaneDirectionArguments {
direction,
keep_focus,
} = from_lua(args)?;
if let Some(pane_index) = tab.get_pane_direction(direction, true) {
tab.swap_active_with_index(pane_index, keep_focus);
}
Ok(())
});

methods.add_method("swap_active_pane_by_index", |_, this, args: Value| {
let mux = get_mux()?;
let tab = this.resolve(&mux)?;

let SwapActivePaneByIndexArguments {
pane_index,
keep_focus,
} = from_lua(args)?;
tab.swap_active_with_index(pane_index, keep_focus);
Ok(())
});
}
}
112 changes: 109 additions & 3 deletions wezterm-gui/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,19 +1015,34 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option<Comm
menubar: &["Window", "Select Tab"],
icon: None,
}
}
},
ActivatePaneByIndex(n) => {
let n = *n;
let ordinal = english_ordinal(n as isize);
CommandDef {
brief: format!("Activate {ordinal} Pane").into(),
doc: format!("Activates the {ordinal} Pane").into(),
keys: vec![],
args: &[ArgType::ActiveWindow],
args: &[ArgType::ActiveTab],
menubar: &[],
icon: None,
}
}
},
SwapActivePaneByIndex(SwapActivePaneByIndexArguments {
pane_index,
keep_focus
}) => {
let ordinal = english_ordinal(*pane_index as isize);
let with_focus = if *keep_focus { ", keeping focus" } else { "" };
CommandDef {
brief: format!("Swap active pane with {ordinal} pane{with_focus}").into(),
doc: format!("Swaps thhe active pane with the {ordinal} pane").into(),
keys: vec![],
args: &[ArgType::ActiveTab],
menubar: &[],
icon: None,
}
},
SetPaneZoomState(true) => CommandDef {
brief: format!("Zooms the current Pane").into(),
doc: format!(
Expand Down Expand Up @@ -1587,6 +1602,65 @@ pub fn derive_command_from_key_assignment(action: &KeyAssignment) -> Option<Comm
menubar: &["Window", "Select Pane"],
icon: Some("fa_long_arrow_down"),
},
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction : PaneDirection::Next | PaneDirection::Prev, keep_focus : _
}) => return None,
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction : PaneDirection::Left, keep_focus
}) => CommandDef {
brief: if *keep_focus {
"Swap active pane with left one".into()
} else {
"Swap active pane with left one, keeping focus".into()
},
doc: "Swaps the current pane with the pane to the left of it".into(),
keys: vec![],
args: &[ArgType::ActivePane],
menubar: &["Window", "Swap Pane"],
icon: None,
},
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction : PaneDirection::Right, keep_focus
}) => CommandDef {
brief: if *keep_focus {
"Swap active pane with right one".into()
} else {
"Swap active pane with right one, keeping focus".into()
},
doc: "Swaps the current pane with the pane to the right of it".into(),
keys: vec![],
args: &[ArgType::ActivePane],
menubar: &["Window", "Swap Pane"],
icon: None,
},
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction : PaneDirection::Up, keep_focus
}) => CommandDef {
brief: if *keep_focus {
"Swap active pane with upwards one".into()
} else {
"Swap active pane with upwards one, keeping focus".into()
},
doc: "Swaps the current pane with the pane to the top of it".into(),
keys: vec![],
args: &[ArgType::ActivePane],
menubar: &["Window", "Swap Pane"],
icon: None,
},
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction : PaneDirection::Down, keep_focus
}) => CommandDef {
brief: if *keep_focus {
"Swap active pane with downwards one".into()
} else {
"Swap active pane with downwards one, keeping focus".into()
},
doc: "Swaps the current pane with the pane to the bottom of it".into(),
keys: vec![],
args: &[ArgType::ActivePane],
menubar: &["Window", "Swap Pane"],
icon: None,
},
TogglePaneZoomState => CommandDef {
brief: "Toggle Pane Zoom".into(),
doc: "Toggles the zoom state for the current pane".into(),
Expand Down Expand Up @@ -2129,6 +2203,38 @@ fn compute_default_actions() -> Vec<KeyAssignment> {
ActivatePaneDirection(PaneDirection::Right),
ActivatePaneDirection(PaneDirection::Up),
ActivatePaneDirection(PaneDirection::Down),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Left,
keep_focus: false,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Right,
keep_focus: false,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Up,
keep_focus: false,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Down,
keep_focus: false,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Left,
keep_focus: true,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Right,
keep_focus: true,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Up,
keep_focus: true,
}),
SwapActivePaneDirection(SwapActivePaneDirectionArguments {
direction: PaneDirection::Down,
keep_focus: true,
}),
TogglePaneZoomState,
ActivateLastTab,
ShowLauncher,
Expand Down
Loading