rmux-server 0.5.0

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
use rmux_core::PaneId;
use rmux_proto::{PaneTarget, RmuxError, SessionName};

use super::HandlerState;
use crate::pane_terminal_lookup::pane_id_for_target;

#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct MarkedPane {
    pub(super) target: PaneTarget,
    pub(super) pane_id: PaneId,
}

impl HandlerState {
    pub(crate) fn marked_pane_target(&self) -> Option<PaneTarget> {
        let marked = self.marked_pane.as_ref()?;
        self.pane_target_for_id_in_window(
            marked.target.session_name(),
            marked.target.window_index(),
            marked.pane_id,
        )
        .or_else(|| self.pane_target_for_id(marked.pane_id))
    }

    pub(crate) fn pane_is_marked(&self, target: &PaneTarget) -> bool {
        let Some(marked) = self.marked_pane.as_ref() else {
            return false;
        };
        pane_id_for_target(
            &self.sessions,
            target.session_name(),
            target.window_index(),
            target.pane_index(),
        )
        .ok()
            == Some(marked.pane_id)
    }

    pub(crate) fn session_has_marked_pane(&self, session_name: &SessionName) -> bool {
        self.marked_pane_target()
            .is_some_and(|target| target.session_name() == session_name)
    }

    pub(crate) fn window_has_marked_pane(
        &self,
        session_name: &SessionName,
        window_index: u32,
    ) -> bool {
        self.marked_pane_target().is_some_and(|target| {
            target.session_name() == session_name && target.window_index() == window_index
        })
    }

    pub(crate) fn clear_marked_pane(&mut self) {
        self.marked_pane = None;
    }

    pub(crate) fn toggle_marked_pane(&mut self, target: &PaneTarget) -> Result<bool, RmuxError> {
        let pane_id = pane_id_for_target(
            &self.sessions,
            target.session_name(),
            target.window_index(),
            target.pane_index(),
        )?;
        if self
            .marked_pane
            .as_ref()
            .is_some_and(|marked| marked.pane_id == pane_id)
        {
            self.marked_pane = None;
            Ok(false)
        } else {
            self.marked_pane = Some(MarkedPane {
                target: target.clone(),
                pane_id,
            });
            Ok(true)
        }
    }

    pub(in crate::pane_terminals) fn clear_marked_pane_if_id(&mut self, pane_id: PaneId) {
        if self
            .marked_pane
            .as_ref()
            .is_some_and(|marked| marked.pane_id == pane_id)
        {
            self.marked_pane = None;
        }
    }

    fn pane_target_for_id_in_window(
        &self,
        session_name: &SessionName,
        window_index: u32,
        pane_id: PaneId,
    ) -> Option<PaneTarget> {
        let session = self.sessions.session(session_name)?;
        let pane_index = session
            .window_at(window_index)?
            .panes()
            .iter()
            .find(|pane| pane.id() == pane_id)
            .map(|pane| pane.index())?;
        Some(PaneTarget::with_window(
            session_name.clone(),
            window_index,
            pane_index,
        ))
    }

    fn pane_target_for_id(&self, pane_id: PaneId) -> Option<PaneTarget> {
        self.sessions.iter().find_map(|(session_name, session)| {
            let window_index = session.window_index_for_pane_id(pane_id)?;
            self.pane_target_for_id_in_window(session_name, window_index, pane_id)
        })
    }
}