mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 05:12:40 +03:00
Add RotatePanes key assignment
This commit is contained in:
parent
da7da888cd
commit
d2d4257f79
@ -459,6 +459,40 @@ impl<L, N> Cursor<L, N> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Move the current position to the next in a postorder traversal.
|
||||
/// Returns the modified cursor position.
|
||||
///
|
||||
/// In the case where there are no more nodes in the postorder traversal,
|
||||
/// yields `Err` with the newly adjusted cursor; calling `postorder_next`
|
||||
/// after it has yielded `Err` can potentially yield `Ok` with previously
|
||||
/// visited nodes, so the caller must take care to stop iterating when
|
||||
/// `Err` is received!
|
||||
pub fn postorder_next(mut self) -> Result<Self, Self> {
|
||||
// Since we are a "proper" binary tree, we know we cannot have
|
||||
// difficult cases such as a left without a right or vice versa.
|
||||
|
||||
if self.is_leaf() {
|
||||
if self.is_right() {
|
||||
return self.go_up()?.go_left();
|
||||
}
|
||||
|
||||
// while (We were on the left)
|
||||
loop {
|
||||
self = self.go_up()?;
|
||||
|
||||
if self.is_top() {
|
||||
return Err(self);
|
||||
}
|
||||
|
||||
if self.is_right() {
|
||||
return self.go_up()?.go_left();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.go_right()
|
||||
}
|
||||
}
|
||||
|
||||
/// Move to the nth (preorder) leaf from the current position.
|
||||
pub fn go_to_nth_leaf(mut self, n: usize) -> Result<Self, Self> {
|
||||
let mut next = 0;
|
||||
|
@ -370,9 +370,16 @@ pub enum KeyAssignment {
|
||||
AttachDomain(String),
|
||||
|
||||
CopyMode(CopyModeAssignment),
|
||||
RotatePanes(RotationDirection),
|
||||
}
|
||||
impl_lua_conversion_dynamic!(KeyAssignment);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||
pub enum RotationDirection {
|
||||
Clockwise,
|
||||
CounterClockwise,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, FromDynamic, ToDynamic)]
|
||||
pub enum CopyModeAssignment {
|
||||
MoveToViewportBottom,
|
||||
|
@ -34,6 +34,7 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
* In the Launcher Menu, you may now use `CTRL-G` to cancel/exit the launcher [#1977](https://github.com/wez/wezterm/issues/1977)
|
||||
* [cell_width](config/lua/config/cell_width.md) option to adjust the horizontal spacing when the availble font stretches are insufficient. [#1979](https://github.com/wez/wezterm/issues/1979)
|
||||
* [min_scroll_bar_height](config/lua/config/min_scroll_bar_height.md) to control the minimum size of the scroll bar thumb [#1936](https://github.com/wez/wezterm/issues/1936)
|
||||
* [RotatePanes](config/lua/keyassignment/RotatePanes.md) key assignment for re-arranging the panes in a tab
|
||||
|
||||
|
||||
#### Updated
|
||||
|
50
docs/config/lua/keyassignment/RotatePanes.md
Normal file
50
docs/config/lua/keyassignment/RotatePanes.md
Normal file
@ -0,0 +1,50 @@
|
||||
# RotatePanes
|
||||
|
||||
*Since: nightly builds only*
|
||||
|
||||
Rotates the sequence of panes within the active tab, preserving the sizes based on the tab positions.
|
||||
|
||||
Panes within a tab have an ordering that follows the creation order of the splits.
|
||||
|
||||
As an example, if you have three panes created in sequence using horizontal
|
||||
splits, their indices from left to right are `0, 1, 2`:
|
||||
|
||||
```
|
||||
|--------|----|----|
|
||||
| 0 | 1 | 2 |
|
||||
|--------|----|----|
|
||||
```
|
||||
|
||||
If you perform a clockwise rotation on that tab, the indices are rearranged
|
||||
so that the panes are now `2, 0, 1`.
|
||||
|
||||
```
|
||||
|--------|----|----|
|
||||
| 2 | 0 | 1 |
|
||||
|--------|----|----|
|
||||
```
|
||||
|
||||
If you instead perform a counter-clockwise rotation then the indices are rearranged
|
||||
so that the panes are now `1, 2, 0`
|
||||
|
||||
```
|
||||
|--------|----|----|
|
||||
| 1 | 2 | 0 |
|
||||
|--------|----|----|
|
||||
```
|
||||
|
||||
The sizes of original positions are preserved; as you can see from the examples
|
||||
above, the left-most pane is still the largest of the panes despite rotating
|
||||
the panes withing those placements.
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
|
||||
return {
|
||||
keys = {
|
||||
{key="b", mods="CTRL", action=wezterm.action{RotatePanes="CounterClockwise"}},
|
||||
{key="n", mods="CTRL", action=wezterm.action{RotatePanes="Clockwise"}},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
@ -594,6 +594,70 @@ impl Tab {
|
||||
self.iter_panes_impl(false)
|
||||
}
|
||||
|
||||
pub fn rotate_counter_clockwise(&self) {
|
||||
let panes = self.iter_panes_ignoring_zoom();
|
||||
if panes.is_empty() {
|
||||
// Shouldn't happen, but we check for this here so that the
|
||||
// expect below cannot trigger a panic
|
||||
return;
|
||||
}
|
||||
let mut pane_to_swap = panes
|
||||
.first()
|
||||
.map(|p| p.pane.clone())
|
||||
.expect("at least one pane");
|
||||
|
||||
let mut root = self.pane.borrow_mut();
|
||||
let mut cursor = root.take().unwrap().cursor();
|
||||
|
||||
loop {
|
||||
if cursor.is_leaf() {
|
||||
std::mem::swap(&mut pane_to_swap, cursor.leaf_mut().unwrap());
|
||||
}
|
||||
|
||||
match cursor.postorder_next() {
|
||||
Ok(c) => cursor = c,
|
||||
Err(c) => {
|
||||
root.replace(c.tree());
|
||||
let size = *self.size.borrow();
|
||||
apply_sizes_from_splits(root.as_mut().unwrap(), &size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rotate_clockwise(&self) {
|
||||
let panes = self.iter_panes_ignoring_zoom();
|
||||
if panes.is_empty() {
|
||||
// Shouldn't happen, but we check for this here so that the
|
||||
// expect below cannot trigger a panic
|
||||
return;
|
||||
}
|
||||
let mut pane_to_swap = panes
|
||||
.last()
|
||||
.map(|p| p.pane.clone())
|
||||
.expect("at least one pane");
|
||||
|
||||
let mut root = self.pane.borrow_mut();
|
||||
let mut cursor = root.take().unwrap().cursor();
|
||||
|
||||
loop {
|
||||
if cursor.is_leaf() {
|
||||
std::mem::swap(&mut pane_to_swap, cursor.leaf_mut().unwrap());
|
||||
}
|
||||
|
||||
match cursor.preorder_next() {
|
||||
Ok(c) => cursor = c,
|
||||
Err(c) => {
|
||||
root.replace(c.tree());
|
||||
let size = *self.size.borrow();
|
||||
apply_sizes_from_splits(root.as_mut().unwrap(), &size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_panes_impl(&self, respect_zoom_state: bool) -> Vec<PositionedPane> {
|
||||
let mut panes = vec![];
|
||||
|
||||
|
@ -23,7 +23,7 @@ use ::window::*;
|
||||
use anyhow::{anyhow, ensure, Context};
|
||||
use config::keyassignment::{
|
||||
ClipboardCopyDestination, ClipboardPasteSource, KeyAssignment, Pattern, QuickSelectArguments,
|
||||
SpawnCommand,
|
||||
RotationDirection, SpawnCommand,
|
||||
};
|
||||
use config::{
|
||||
configuration, AudibleBell, ConfigHandle, Dimension, DimensionContext, GradientOrientation,
|
||||
@ -2477,6 +2477,17 @@ impl TermWindow {
|
||||
CopyMode(_) => {
|
||||
// NOP here; handled by the overlay directly
|
||||
}
|
||||
RotatePanes(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(()),
|
||||
};
|
||||
match direction {
|
||||
RotationDirection::Clockwise => tab.rotate_clockwise(),
|
||||
RotationDirection::CounterClockwise => tab.rotate_counter_clockwise(),
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user