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 zoom-pane subcommand #4160

Merged
merged 3 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions mux/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,10 @@ impl Tab {
.lock()
.split_and_insert(pane_index, request, pane)
}

pub fn get_zoomed_pane(&self) -> Option<Arc<dyn Pane>> {
self.inner.lock().get_zoomed_pane()
}
}

impl TabInner {
Expand Down Expand Up @@ -2051,6 +2055,10 @@ impl TabInner {
pane_index
})
}

fn get_zoomed_pane(&self) -> Option<Arc<dyn Pane>> {
self.zoomed.clone()
}
}

/// This type is used directly by the codec, take care to bump
Expand Down
9 changes: 6 additions & 3 deletions wezterm-mux-server-impl/src/sessionhandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,11 @@ impl SessionHandler {
let tab = mux
.get_tab(containing_tab_id)
.ok_or_else(|| anyhow!("no such tab {}", containing_tab_id))?;
tab.set_active_pane(&pane);
tab.set_zoomed(zoomed);
tab.set_zoomed(false);
wez marked this conversation as resolved.
Show resolved Hide resolved
if zoomed {
tab.set_active_pane(&pane);
tab.set_zoomed(zoomed);
}
Ok(Pdu::UnitResponse(UnitResponse {}))
},
send_response,
Expand Down Expand Up @@ -1021,7 +1024,7 @@ async fn split_pane(split: SplitPane, client_id: Option<Arc<ClientId>>) -> anyho

Ok::<Pdu, anyhow::Error>(Pdu::SpawnResponse(SpawnResponse {
pane_id: pane.pane_id(),
tab_id: tab_id,
tab_id,
window_id,
size,
}))
Expand Down
6 changes: 6 additions & 0 deletions wezterm/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod set_window_title;
mod spawn_command;
mod split_pane;
mod tls_creds;
mod zoom_pane;

#[derive(Debug, Parser, Clone, Copy)]
enum CliOutputFormatKind {
Expand Down Expand Up @@ -159,6 +160,10 @@ Outputs the pane-id for the newly created pane on success"
/// Rename a workspace
#[command(name = "rename-workspace", rename_all = "kebab")]
RenameWorkspace(rename_workspace::RenameWorkspace),

/// Zoom, unzoom, or toggle zoom state
#[command(name = "zoom-pane", rename_all = "kebab")]
ZoomPane(zoom_pane::ZoomPane),
}

async fn run_cli_async(opts: &crate::Opt, cli: CliCommand) -> anyhow::Result<()> {
Expand Down Expand Up @@ -194,6 +199,7 @@ async fn run_cli_async(opts: &crate::Opt, cli: CliCommand) -> anyhow::Result<()>
CliSubCommand::SetTabTitle(cmd) => cmd.run(client).await,
CliSubCommand::SetWindowTitle(cmd) => cmd.run(client).await,
CliSubCommand::RenameWorkspace(cmd) => cmd.run(client).await,
CliSubCommand::ZoomPane(cmd) => cmd.run(client).await,
}
}

Expand Down
109 changes: 109 additions & 0 deletions wezterm/src/cli/zoom_pane.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::cli::resolve_pane_id;
use anyhow::{anyhow, Result};
use clap::Parser;
use codec::SetPaneZoomed;
use mux::pane::PaneId;
use std::collections::HashMap;
use wezterm_client::client::Client;

#[derive(Debug, Parser, Clone)]
pub struct ZoomPane {
/// Specify the target pane.
/// The default is to use the current pane based on the
/// environment variable WEZTERM_PANE.
#[arg(long)]
pane_id: Option<PaneId>,

/// Zooms the pane if it wasn't already zoomed
#[arg(long, default_value = "true", conflicts_with_all=&["unzoom", "toggle"])]
zoom: bool,

/// Unzooms the pane if it was zoomed
#[arg(long, conflicts_with_all=&["zoom", "toggle"])]
unzoom: bool,

/// Toggles the zoom state of the pane
#[arg(long, conflicts_with_all=&["zoom", "unzoom"])]
toggle: bool,
}

impl ZoomPane {
pub async fn run(&self, client: Client) -> Result<()> {
let panes = client.list_panes().await?;

let mut pane_id_to_tab_id = HashMap::new();
let mut tab_id_to_active_zoomed_pane_id = HashMap::new();

for tabroot in panes.tabs {
let mut cursor = tabroot.into_tree().cursor();

loop {
if let Some(entry) = cursor.leaf_mut() {
pane_id_to_tab_id.insert(entry.pane_id, entry.tab_id);
if entry.is_active_pane && entry.is_zoomed_pane {
tab_id_to_active_zoomed_pane_id.insert(entry.tab_id, entry.pane_id);
}
}
match cursor.preorder_next() {
Ok(c) => cursor = c,
Err(_) => break,
}
}
}

let pane_id = resolve_pane_id(&client, self.pane_id).await?;
let containing_tab_id = pane_id_to_tab_id
.get(&pane_id)
.copied()
.ok_or_else(|| anyhow!("unable to resolve current tab"))?;

if self.zoom {
client
.set_zoomed(SetPaneZoomed {
containing_tab_id,
pane_id,
zoomed: true,
})
.await?;
}

if self.unzoom {
client
.set_zoomed(SetPaneZoomed {
containing_tab_id,
pane_id,
zoomed: false,
})
.await?;
}
wez marked this conversation as resolved.
Show resolved Hide resolved

if self.toggle {
if tab_id_to_active_zoomed_pane_id.contains_key(&containing_tab_id) {
let target_pane = tab_id_to_active_zoomed_pane_id
.get(&containing_tab_id)
.copied()
.ok_or_else(|| {
anyhow!("could not determine which pane should be active for tab {containing_tab_id}")
})?;
if target_pane == pane_id {
client
.set_zoomed(SetPaneZoomed {
containing_tab_id,
pane_id,
zoomed: false,
})
.await?;
}
} else {
client
.set_zoomed(SetPaneZoomed {
containing_tab_id,
pane_id,
zoomed: true,
})
.await?;
}
}
wez marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}
}
Loading