1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-11 14:25:57 +03:00

fix spawning new tabs via launcher menu

I wonder how long this has been broken... rather than spawning
into domain "local" it would try to spawn into "`local`" and fail
silently because the error message wasn't logged.

So let's log it, and let's fix it.

refs: https://github.com/wez/wezterm/issues/468
This commit is contained in:
Wez Furlong 2021-03-27 19:00:55 -07:00
parent 53a13e60f5
commit 12225a099a
3 changed files with 144 additions and 130 deletions

View File

@ -103,7 +103,7 @@ pub fn launcher(
domain_id_of_current_tab: DomainId,
mut term: TermWizTerminal,
mux_window_id: WindowId,
domains: Vec<(DomainId, DomainState, String)>,
domains: Vec<(DomainId, String, DomainState, String)>,
clipboard: ClipboardHelper,
size: PtySize,
) -> anyhow::Result<()> {
@ -137,10 +137,10 @@ pub fn launcher(
}
}
for (domain_id, domain_state, domain_name) in &domains {
for (domain_id, domain_name, domain_state, domain_label) in &domains {
let entry = if *domain_state == DomainState::Attached {
Entry::Spawn {
label: format!("New Tab ({})", domain_name),
label: format!("New Tab ({})", domain_label),
command: SpawnCommand {
domain: SpawnTabDomain::DomainName(domain_name.to_string()),
..SpawnCommand::default()
@ -149,7 +149,7 @@ pub fn launcher(
}
} else {
Entry::Attach {
label: format!("Attach {}", domain_name),
label: format!("Attach {}", domain_label),
domain: *domain_id,
}
};

View File

@ -1217,7 +1217,7 @@ impl TermWindow {
a.domain_id().cmp(&b.domain_id())
});
domains.retain(|dom| dom.spawnable());
let domains: Vec<(DomainId, DomainState, String)> = domains
let domains: Vec<(DomainId, String, DomainState, String)> = domains
.iter()
.map(|dom| {
let name = dom.domain_name();
@ -1227,7 +1227,7 @@ impl TermWindow {
} else {
format!("domain `{}` - {}", name, label)
};
(dom.domain_id(), dom.state(), label)
(dom.domain_id(), name.to_string(), dom.state(), label)
})
.collect();

View File

@ -44,144 +44,158 @@ impl super::TermWindow {
let spawn = spawn.clone();
promise::spawn::spawn(async move {
let mux = Mux::get().unwrap();
let activity = Activity::new();
let mux_builder;
if let Err(err) =
Self::spawn_command_internal(spawn, spawn_where, size, src_window_id, clipboard)
.await
{
log::error!("Failed to spawn: {:#}", err);
}
})
.detach();
}
let target_window_id = if spawn_where == SpawnWhere::NewWindow {
mux_builder = mux.new_empty_window();
*mux_builder
} else {
src_window_id
};
async fn spawn_command_internal(
spawn: SpawnCommand,
spawn_where: SpawnWhere,
size: PtySize,
src_window_id: MuxWindowId,
clipboard: ClipboardHelper,
) -> anyhow::Result<()> {
let mux = Mux::get().unwrap();
let activity = Activity::new();
let mux_builder;
let (domain, cwd) = match spawn.domain {
SpawnTabDomain::DefaultDomain => {
let target_window_id = if spawn_where == SpawnWhere::NewWindow {
mux_builder = mux.new_empty_window();
*mux_builder
} else {
src_window_id
};
let (domain, cwd) = match spawn.domain {
SpawnTabDomain::DefaultDomain => {
let cwd = mux
.get_active_tab_for_window(src_window_id)
.and_then(|tab| tab.get_active_pane())
.and_then(|pane| pane.get_current_working_dir());
(mux.default_domain().clone(), cwd)
}
SpawnTabDomain::CurrentPaneDomain => {
if spawn_where == SpawnWhere::NewWindow {
// CurrentPaneDomain is the default value for the spawn domain.
// It doesn't make sense to use it when spawning a new window,
// so we treat it as DefaultDomain instead.
let cwd = mux
.get_active_tab_for_window(src_window_id)
.and_then(|tab| tab.get_active_pane())
.and_then(|pane| pane.get_current_working_dir());
(mux.default_domain().clone(), cwd)
}
SpawnTabDomain::CurrentPaneDomain => {
if spawn_where == SpawnWhere::NewWindow {
// CurrentPaneDomain is the default value for the spawn domain.
// It doesn't make sense to use it when spawning a new window,
// so we treat it as DefaultDomain instead.
let cwd = mux
.get_active_tab_for_window(src_window_id)
.and_then(|tab| tab.get_active_pane())
.and_then(|pane| pane.get_current_working_dir());
(mux.default_domain().clone(), cwd)
} else {
let tab = match mux.get_active_tab_for_window(src_window_id) {
Some(tab) => tab,
None => bail!("window has no tabs?"),
};
let pane = tab
.get_active_pane()
.ok_or_else(|| anyhow!("current tab has no pane!?"))?;
(
mux.get_domain(pane.domain_id()).ok_or_else(|| {
anyhow!("current tab has unresolvable domain id!?")
})?,
pane.get_current_working_dir(),
)
}
}
SpawnTabDomain::DomainName(name) => (
mux.get_domain_by_name(&name).ok_or_else(|| {
anyhow!("spawn_tab called with unresolvable domain name {}", name)
})?,
None,
),
};
if domain.state() == DomainState::Detached {
bail!("Cannot spawn a tab into a Detached domain");
}
let cwd = if let Some(cwd) = spawn.cwd.as_ref() {
Some(cwd.to_str().map(|s| s.to_owned()).ok_or_else(|| {
anyhow!(
"Domain::spawn requires that the cwd be unicode in {:?}",
cwd
)
})?)
} else {
match cwd {
Some(url) if url.scheme() == "file" => {
let path = url.path().to_string();
// 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':' {
Some(path[1..].to_owned())
} else {
Some(path)
}
}
Some(_) | None => None,
}
};
let cmd_builder = if let Some(args) = spawn.args {
let mut builder = CommandBuilder::from_argv(args.iter().map(Into::into).collect());
for (k, v) in spawn.set_environment_variables.iter() {
builder.env(k, v);
}
if let Some(cwd) = spawn.cwd {
builder.cwd(cwd);
}
Some(builder)
} else {
None
};
match spawn_where {
SpawnWhere::SplitPane(direction) => {
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_active_tab_for_window(target_window_id) {
let pane = tab
.get_active_pane()
.ok_or_else(|| anyhow!("tab to have a pane"))?;
log::trace!("doing split_pane");
domain
.split_pane(cmd_builder, cwd, tab.tab_id(), pane.pane_id(), direction)
.await?;
} else {
log::error!("there is no active tab while splitting pane!?");
}
}
_ => {
let tab = domain
.spawn(size, cmd_builder, cwd, target_window_id)
.await?;
let tab_id = tab.tab_id();
} else {
let tab = match mux.get_active_tab_for_window(src_window_id) {
Some(tab) => tab,
None => bail!("window has no tabs?"),
};
let pane = tab
.get_active_pane()
.ok_or_else(|| anyhow!("newly spawned tab to have a pane"))?;
.ok_or_else(|| anyhow!("current tab has no pane!?"))?;
(
mux.get_domain(pane.domain_id())
.ok_or_else(|| anyhow!("current tab has unresolvable domain id!?"))?,
pane.get_current_working_dir(),
)
}
}
SpawnTabDomain::DomainName(name) => (
mux.get_domain_by_name(&name).ok_or_else(|| {
anyhow!("spawn_tab called with unresolvable domain name {}", name)
})?,
None,
),
};
if spawn_where != SpawnWhere::NewWindow {
let clipboard: Arc<dyn wezterm_term::Clipboard> = Arc::new(clipboard);
pane.set_clipboard(&clipboard);
let mut window = mux
.get_window_mut(target_window_id)
.ok_or_else(|| anyhow!("no such window!?"))?;
if let Some(idx) = window.idx_by_id(tab_id) {
window.set_active(idx);
}
if domain.state() == DomainState::Detached {
bail!("Cannot spawn a tab into a Detached domain");
}
let cwd = if let Some(cwd) = spawn.cwd.as_ref() {
Some(cwd.to_str().map(|s| s.to_owned()).ok_or_else(|| {
anyhow!(
"Domain::spawn requires that the cwd be unicode in {:?}",
cwd
)
})?)
} else {
match cwd {
Some(url) if url.scheme() == "file" => {
let path = url.path().to_string();
// 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':' {
Some(path[1..].to_owned())
} else {
Some(path)
}
}
};
Some(_) | None => None,
}
};
drop(activity);
let cmd_builder = if let Some(args) = spawn.args {
let mut builder = CommandBuilder::from_argv(args.iter().map(Into::into).collect());
for (k, v) in spawn.set_environment_variables.iter() {
builder.env(k, v);
}
if let Some(cwd) = spawn.cwd {
builder.cwd(cwd);
}
Some(builder)
} else {
None
};
Ok(())
})
.detach();
match spawn_where {
SpawnWhere::SplitPane(direction) => {
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_active_tab_for_window(target_window_id) {
let pane = tab
.get_active_pane()
.ok_or_else(|| anyhow!("tab to have a pane"))?;
log::trace!("doing split_pane");
domain
.split_pane(cmd_builder, cwd, tab.tab_id(), pane.pane_id(), direction)
.await?;
} else {
log::error!("there is no active tab while splitting pane!?");
}
}
_ => {
let tab = domain
.spawn(size, cmd_builder, cwd, target_window_id)
.await?;
let tab_id = tab.tab_id();
let pane = tab
.get_active_pane()
.ok_or_else(|| anyhow!("newly spawned tab to have a pane"))?;
if spawn_where != SpawnWhere::NewWindow {
let clipboard: Arc<dyn wezterm_term::Clipboard> = Arc::new(clipboard);
pane.set_clipboard(&clipboard);
let mut window = mux
.get_window_mut(target_window_id)
.ok_or_else(|| anyhow!("no such window!?"))?;
if let Some(idx) = window.idx_by_id(tab_id) {
window.set_active(idx);
}
}
}
};
drop(activity);
Ok(())
}
pub fn spawn_tab(&mut self, domain: &SpawnTabDomain) {