use thiserror::Error;
use crate::{
direction::Direction,
id::{PaneId, SessionId, WindowId},
layout::LayoutKind,
pane::TearPane,
pane_snapshot::PaneSnapshot,
session::TearSession,
window::TearWindow,
};
pub type ControlResult<T> = Result<T, ControlError>;
#[derive(Debug, Error)]
pub enum ControlError {
#[error("no such session: {0}")]
NoSuchSession(SessionId),
#[error("no such window: {0}")]
NoSuchWindow(WindowId),
#[error("no such pane: {0}")]
NoSuchPane(PaneId),
#[error("backend transport error: {0}")]
Transport(String),
#[error("backend rejected operation: {0}")]
Rejected(String),
#[error("backend internal: {0}")]
Internal(#[from] anyhow::Error),
}
pub trait MultiplexerControl: Send + Sync {
fn list_sessions(&self) -> ControlResult<Vec<TearSession>>;
fn get_session(&self, id: SessionId) -> ControlResult<TearSession>;
fn get_window(&self, id: WindowId) -> ControlResult<(SessionId, TearWindow)>;
fn get_pane(&self, id: PaneId) -> ControlResult<TearPane>;
fn new_session(&self, name: &str, shell: &str) -> ControlResult<SessionId> {
self.new_session_with_source(name, shell, crate::session::SessionSource::Human)
}
fn new_session_with_source(
&self,
name: &str,
shell: &str,
source: crate::session::SessionSource,
) -> ControlResult<SessionId> {
self.new_session_with_source_and_size(name, shell, source, (80, 24))
}
fn new_session_with_source_and_size(
&self,
name: &str,
shell: &str,
source: crate::session::SessionSource,
size_cells: (u16, u16),
) -> ControlResult<SessionId>;
fn rename_session(&self, id: SessionId, new_name: &str) -> ControlResult<()>;
fn kill_session(&self, id: SessionId) -> ControlResult<()>;
fn new_window(&self, session: SessionId, name: &str, shell: &str) -> ControlResult<WindowId>;
fn kill_window(&self, id: WindowId) -> ControlResult<()>;
fn select_window(&self, id: WindowId) -> ControlResult<()>;
fn split_pane(
&self,
origin: PaneId,
direction: Direction,
shell: &str,
) -> ControlResult<PaneId>;
fn kill_pane(&self, id: PaneId) -> ControlResult<()>;
fn select_pane(&self, id: PaneId) -> ControlResult<()>;
fn resize_pane(&self, id: PaneId, direction: Direction, delta_cells: i16) -> ControlResult<()>;
fn apply_layout(&self, window: WindowId, kind: LayoutKind) -> ControlResult<()>;
fn pane_resize_absolute(&self, id: PaneId, cols: u16, rows: u16) -> ControlResult<()> {
let _ = (id, cols, rows);
Err(ControlError::Rejected(
"this backend does not support absolute pane resize".into(),
))
}
fn send_keys(&self, id: PaneId, bytes: &[u8]) -> ControlResult<()>;
fn pane_subscriber_count(&self, id: PaneId) -> ControlResult<u32>;
fn set_input_policy(
&self,
id: PaneId,
policy: crate::pane::InputPolicy,
) -> ControlResult<()>;
fn pane_snapshot(&self, id: PaneId) -> ControlResult<PaneSnapshot> {
let _ = id;
Err(ControlError::Rejected(
"this backend does not expose per-pane snapshots".into(),
))
}
fn pane_cursor_keys_mode(&self, id: PaneId) -> ControlResult<bool> {
Ok(self.pane_snapshot(id)?.cursor_keys_mode)
}
}