1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

refactor: move split_pane logic from mux server to mux

This commit is contained in:
Wez Furlong 2022-01-14 10:59:20 -07:00
parent 3947014bad
commit 31c754f6e4
5 changed files with 87 additions and 60 deletions

2
Cargo.lock generated
View File

@ -2306,6 +2306,7 @@ dependencies = [
"metrics",
"mlua",
"ntapi",
"percent-encoding",
"portable-pty",
"procinfo",
"promise",
@ -4833,7 +4834,6 @@ dependencies = [
"lazy_static",
"log",
"mux",
"percent-encoding",
"portable-pty",
"promise",
"rangeset",

View File

@ -23,6 +23,7 @@ log = "0.4"
luahelper = { path = "../luahelper" }
metrics = { version="0.17", features=["std"]}
mlua = "0.7"
percent-encoding = "2"
portable-pty = { path = "../pty", features = ["serde_support"]}
procinfo = { path = "../procinfo" }
promise = { path = "../promise" }

View File

@ -1,6 +1,6 @@
use crate::client::{ClientId, ClientInfo};
use crate::pane::{Pane, PaneId};
use crate::tab::{Tab, TabId};
use crate::tab::{SplitDirection, Tab, TabId};
use crate::window::{Window, WindowId};
use anyhow::{anyhow, Context, Error};
use config::keyassignment::SpawnTabDomain;
@ -11,6 +11,7 @@ use filedescriptor::{socketpair, AsRawSocketDescriptor, FileDescriptor};
use libc::{SOL_SOCKET, SO_RCVBUF, SO_SNDBUF};
use log::error;
use metrics::histogram;
use percent_encoding::percent_decode_str;
use portable_pty::{CommandBuilder, ExitStatus, PtySize};
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
@ -700,6 +701,80 @@ impl Mux {
*self.banner.borrow_mut() = banner;
}
pub async fn split_pane(
&self,
// TODO: disambiguate with TabId
pane_id: PaneId,
direction: SplitDirection,
command: Option<CommandBuilder>,
command_dir: Option<String>,
domain: config::keyassignment::SpawnTabDomain,
) -> anyhow::Result<(Rc<dyn Pane>, PtySize)> {
let (pane_domain_id, _window_id, tab_id) = self
.resolve_pane_id(pane_id)
.ok_or_else(|| anyhow!("pane_id {} invalid", pane_id))?;
let domain = match domain {
SpawnTabDomain::DefaultDomain => self.default_domain(),
SpawnTabDomain::CurrentPaneDomain => self
.get_domain(pane_domain_id)
.expect("resolve_pane_id to give valid domain_id"),
SpawnTabDomain::DomainId(domain_id) => self
.get_domain(domain_id)
.ok_or_else(|| anyhow!("domain id {} is invalid", domain_id))?,
SpawnTabDomain::DomainName(name) => self
.get_domain_by_name(&name)
.ok_or_else(|| anyhow!("domain name {} is invalid", name))?,
};
let current_pane = self
.get_pane(pane_id)
.ok_or_else(|| anyhow!("pane_id {} is invalid", pane_id))?;
let term_config = current_pane.get_config();
let cwd = command_dir.or_else(|| {
self.get_pane(pane_id)
.and_then(|pane| pane.get_current_working_dir())
.and_then(|url| {
percent_decode_str(url.path())
.decode_utf8()
.ok()
.map(|path| path.into_owned())
})
.map(|path| {
// On Windows the file URI can produce a path like:
// `/C:\Users` which is valid in a file URI, but the leading slash
// is not liked by the windows file APIs, so we strip it off here.
let bytes = path.as_bytes();
if bytes.len() > 2 && bytes[0] == b'/' && bytes[2] == b':' {
path[1..].to_owned()
} else {
path
}
})
});
let pane = domain
.split_pane(command, cwd, tab_id, pane_id, direction)
.await?;
if let Some(config) = term_config {
pane.set_config(config);
}
// FIXME: clipboard
let dims = pane.get_dimensions();
let size = PtySize {
cols: dims.cols as u16,
rows: dims.viewport_rows as u16,
pixel_height: 0, // FIXME: split pane pixel dimensions
pixel_width: 0,
};
Ok((pane, size))
}
pub async fn spawn_tab_or_window(
&self,
window_id: Option<WindowId>,

View File

@ -16,7 +16,6 @@ hostname = "0.3"
lazy_static = "1.4"
log = "0.4"
mux = { path = "../mux" }
percent-encoding = "2"
portable-pty = { path = "../pty", features = ["serde_support"]}
promise = { path = "../promise" }
rangeset = { path = "../rangeset" }

View File

@ -1,14 +1,11 @@
use crate::PKI;
use anyhow::{anyhow, Context};
use codec::*;
use config::keyassignment::SpawnTabDomain;
use mux::client::ClientId;
use mux::pane::{Pane, PaneId};
use mux::renderable::{RenderableDimensions, StableCursorPosition};
use mux::tab::TabId;
use mux::Mux;
use percent_encoding::percent_decode_str;
use portable_pty::PtySize;
use promise::spawn::spawn_into_main_thread;
use std::collections::HashMap;
use std::rc::Rc;
@ -698,70 +695,25 @@ impl Clipboard for RemoteClipboard {
async fn split_pane(split: SplitPane, sender: PduSender) -> anyhow::Result<Pdu> {
let mux = Mux::get().unwrap();
let (pane_domain_id, window_id, tab_id) = mux
let (_pane_domain_id, window_id, tab_id) = mux
.resolve_pane_id(split.pane_id)
.ok_or_else(|| anyhow!("pane_id {} invalid", split.pane_id))?;
let domain = match split.domain {
SpawnTabDomain::DefaultDomain => mux.default_domain(),
SpawnTabDomain::CurrentPaneDomain => mux
.get_domain(pane_domain_id)
.expect("resolve_pane_id to give valid domain_id"),
SpawnTabDomain::DomainId(domain_id) => mux
.get_domain(domain_id)
.ok_or_else(|| anyhow!("domain id {} is invalid", domain_id))?,
SpawnTabDomain::DomainName(name) => mux
.get_domain_by_name(&name)
.ok_or_else(|| anyhow!("domain name {} is invalid", name))?,
};
let pane_id = split.pane_id;
let current_pane = mux
.get_pane(pane_id)
.ok_or_else(|| anyhow!("pane_id {} is invalid", pane_id))?;
let term_config = current_pane.get_config();
let cwd = split.command_dir.or_else(|| {
mux.get_pane(pane_id)
.and_then(|pane| pane.get_current_working_dir())
.and_then(|url| {
percent_decode_str(url.path())
.decode_utf8()
.ok()
.map(|path| path.into_owned())
})
.map(|path| {
// On Windows the file URI can produce a path like:
// `/C:\Users` which is valid in a file URI, but the leading slash
// is not liked by the windows file APIs, so we strip it off here.
let bytes = path.as_bytes();
if bytes.len() > 2 && bytes[0] == b'/' && bytes[2] == b':' {
path[1..].to_owned()
} else {
path
}
})
});
let pane = domain
.split_pane(split.command, cwd, tab_id, split.pane_id, split.direction)
let (pane, size) = mux
.split_pane(
split.pane_id,
split.direction,
split.command,
split.command_dir,
split.domain,
)
.await?;
let dims = pane.get_dimensions();
let size = PtySize {
cols: dims.cols as u16,
rows: dims.viewport_rows as u16,
pixel_height: 0,
pixel_width: 0,
};
let clip: Arc<dyn Clipboard> = Arc::new(RemoteClipboard {
pane_id: pane.pane_id(),
sender,
});
pane.set_clipboard(&clip);
if let Some(config) = term_config {
pane.set_config(config);
}
Ok::<Pdu, anyhow::Error>(Pdu::SpawnResponse(SpawnResponse {
pane_id: pane.pane_id(),