use super::cli::{absolute_cwd, block_is_gone, session_is_gone};
use super::policy::{Listing, created_id, split_word};
use super::session::TernBackend;
use crate::backend::*;
impl TernBackend {
pub(super) fn split_and_start(
&self,
base_pane: &str,
spec: &SpawnSpec,
placement: PanePlacement,
session_id: &str,
tab_id: &str,
) -> Result<String> {
if spec.command.is_empty() {
anyhow::bail!("tern spawn requires a command");
}
let mut args = vec![
"split".into(),
base_pane.into(),
split_word(placement.direction).into(),
"--cwd".into(),
absolute_cwd(&spec.cwd),
"--keep-open".into(),
"--json".into(),
"--".into(),
];
args.extend(launch_argv(spec));
let created = self.json(args)?;
if let Some(created_session) = created_id(&created, "session") {
if created_session != session_id {
anyhow::bail!(
"tern split answered in session {created_session}, not {session_id}: the \
TERN_WINDOW_KEY this client used addresses another window"
);
}
}
if let Some(created_tab) = created_id(&created, "tab") {
if created_tab != tab_id {
anyhow::bail!(
"tern split answered in tab {created_tab}, not {tab_id}: the block it made \
is not in the role's tab"
);
}
}
created_id(&created, "block")
.ok_or_else(|| anyhow::anyhow!("tern split returned no block id"))
}
pub(super) fn focus_block(&self, pane_id: &str) -> Result<()> {
self.json(vec!["focus".into(), pane_id.into(), "--json".into()])
.map(|_| ())
}
pub(super) fn focus_here(&self, listing: &Listing) -> Option<FocusSite> {
listing.sessions.iter().find_map(|session| {
session.tabs.iter().find_map(|tab| {
tab.blocks
.iter()
.find(|block| block.focused)
.map(|block| FocusSite {
pane_id: block.id.clone(),
tab_id: tab.id.clone(),
session_id: session.id.clone(),
})
})
})
}
pub(super) fn process_of(&self, pane_id: &str) -> Option<Value> {
self.json(vec!["process".into(), pane_id.into(), "--json".into()])
.ok()
}
pub(super) fn is_gone(&self, error: &anyhow::Error) -> bool {
block_is_gone(error) || session_is_gone(error)
}
}
pub(super) struct FocusSite {
pub(super) pane_id: String,
pub(super) tab_id: String,
pub(super) session_id: String,
}
pub(super) fn launch_argv(spec: &SpawnSpec) -> Vec<String> {
let mut argv = vec!["env".to_string()];
for (key, value) in &spec.env {
argv.push(format!("{key}={value}"));
}
argv.extend(spec.command.iter().cloned());
argv
}