use rmux_proto::{PaneTarget, RmuxError, WindowId, WindowTarget};
use super::super::{session_not_found, HandlerState};
pub(super) struct PaneTransferWindowMetadata {
source: WindowTarget,
source_aliases: Vec<WindowTarget>,
window_id: WindowId,
single_pane: bool,
}
impl PaneTransferWindowMetadata {
pub(super) fn capture(state: &HandlerState, source: &PaneTarget) -> Result<Self, RmuxError> {
let session = state
.sessions
.session(source.session_name())
.ok_or_else(|| session_not_found(source.session_name()))?;
let window = session.window_at(source.window_index()).ok_or_else(|| {
RmuxError::invalid_target(
format!("{}:{}", source.session_name(), source.window_index()),
"window index does not exist in session",
)
})?;
let source =
WindowTarget::with_window(source.session_name().clone(), source.window_index());
let mut source_aliases =
state.window_linked_window_targets(source.session_name(), source.window_index());
if !source_aliases.contains(&source) {
source_aliases.push(source.clone());
}
Ok(Self {
source,
source_aliases,
window_id: window.id(),
single_pane: window.pane_count() == 1,
})
}
pub(super) fn move_to_surviving_window(
&self,
state: &mut HandlerState,
destination: &WindowTarget,
) -> Result<(), RmuxError> {
if !self.single_pane || self.source == *destination {
return Ok(());
}
let destination_window_id = state
.sessions
.session(destination.session_name())
.and_then(|session| session.window_at(destination.window_index()))
.map(rmux_core::Window::id)
.ok_or_else(|| {
RmuxError::invalid_target(
destination.to_string(),
"break-pane destination window does not exist",
)
})?;
if destination_window_id != self.window_id {
return Err(RmuxError::Server(format!(
"break-pane destination {} does not contain moved window @{}",
destination,
self.window_id.as_u32()
)));
}
state
.options
.move_window_overrides(&self.source, destination);
state.move_auto_named_window_slot(
self.source.session_name(),
self.source.window_index(),
destination.session_name(),
destination.window_index(),
);
Ok(())
}
pub(super) fn prune_removed_aliases(&self, state: &mut HandlerState) {
for target in &self.source_aliases {
let occupant = state
.sessions
.session(target.session_name())
.and_then(|session| session.window_at(target.window_index()))
.map(rmux_core::Window::id);
match occupant {
Some(id) if id == self.window_id => continue,
Some(_) => continue,
None => {}
}
let _ = state.options.remove_window(target);
state.clear_auto_named_window(target.session_name(), target.window_index());
}
}
}