rmux-server 0.10.0

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
use rmux_core::formats::{FormatVariable, FormatVariables};
use rmux_core::{AlertFlags, Window, WINLINK_ACTIVITY, WINLINK_BELL, WINLINK_SILENCE};
use rmux_proto::SessionName;

use super::{bool_string, RuntimeFormatContext};

impl RuntimeFormatContext<'_> {
    pub(super) fn session_group_name(&self) -> Option<SessionName> {
        let session = self.session?;
        self.session_store
            .and_then(|store| store.session_group_name(session.name()).cloned())
            .or_else(|| session.group_name().cloned())
    }

    pub(super) fn session_group_members(&self) -> Vec<SessionName> {
        let Some(session) = self.session else {
            return Vec::new();
        };
        if self.session_group_name().is_none() {
            return Vec::new();
        }
        self.session_store
            .map(|store| store.session_group_members(session.name()))
            .unwrap_or_default()
    }

    pub(super) fn session_attached_count(&self) -> usize {
        self.base
            .format_value(FormatVariable::SessionAttached)
            .and_then(|value| value.parse::<usize>().ok())
            .unwrap_or(0)
    }

    pub(super) fn window_flags(&self) -> Option<String> {
        Some(self.printable_window_flags(true))
    }

    pub(super) fn window_linked(&self) -> Option<String> {
        let session_name = self.session_name()?;
        let window_index = self.window_index?;
        Some(bool_string(
            self.state?
                .window_link_count(session_name, window_index)
                .saturating_sub(1)
                > 0,
        ))
    }

    pub(super) fn window_linked_sessions(&self) -> Option<String> {
        let session_name = self.session_name()?;
        let window_index = self.window_index?;
        Some(
            self.state?
                .window_linked_session_count(session_name, window_index)
                .to_string(),
        )
    }

    pub(super) fn window_linked_sessions_list(&self) -> Option<String> {
        let session_name = self.session_name()?;
        let window_index = self.window_index?;
        Some(
            self.state?
                .window_linked_sessions_list(session_name, window_index)
                .into_iter()
                .map(|session_name| session_name.to_string())
                .collect::<Vec<_>>()
                .join(","),
        )
    }

    fn window_alert_flags(&self) -> AlertFlags {
        self.session
            .zip(self.window_index)
            .map(|(session, window_index)| session.winlink_alert_flags(window_index))
            .unwrap_or_else(AlertFlags::empty)
    }

    pub(super) fn printable_window_flags(&self, escape_activity: bool) -> String {
        let active = self
            .base
            .format_value(FormatVariable::WindowActive)
            .is_some_and(|value| value == "1");
        let last = self
            .base
            .format_value(FormatVariable::WindowLastFlag)
            .is_some_and(|value| value == "1");
        let zoomed = self.window.is_some_and(Window::is_zoomed);
        let alerts = self.window_alert_flags();

        let mut flags = String::new();
        if alerts.contains(WINLINK_ACTIVITY) {
            if escape_activity {
                flags.push_str("##");
            } else {
                flags.push('#');
            }
        }
        if alerts.contains(WINLINK_BELL) {
            flags.push('!');
        }
        if alerts.contains(WINLINK_SILENCE) {
            flags.push('~');
        }
        if active {
            flags.push('*');
        } else if last {
            flags.push('-');
        }
        if zoomed {
            flags.push('Z');
        }
        flags
    }

    pub(super) fn session_alert(&self) -> Option<String> {
        let session = self.session?;
        let flags = session.session_alert_flags();
        let mut value = String::new();
        if flags.contains(WINLINK_ACTIVITY) {
            value.push('#');
        }
        if flags.contains(WINLINK_BELL) {
            value.push('!');
        }
        if flags.contains(WINLINK_SILENCE) {
            value.push('~');
        }
        Some(value)
    }

    pub(super) fn session_alerts(&self) -> Option<String> {
        let session = self.session?;
        let alerts = session
            .alerted_window_indexes()
            .into_iter()
            .filter_map(|window_index| {
                let flags = session.winlink_alert_flags(window_index);
                if flags.is_empty() {
                    return None;
                }

                let mut value = window_index.to_string();
                if flags.contains(WINLINK_ACTIVITY) {
                    value.push('#');
                }
                if flags.contains(WINLINK_BELL) {
                    value.push('!');
                }
                if flags.contains(WINLINK_SILENCE) {
                    value.push('~');
                }
                Some(value)
            })
            .collect::<Vec<_>>();
        Some(alerts.join(","))
    }

    pub(super) fn session_flag(&self, flag: AlertFlags) -> Option<String> {
        self.session
            .map(|session| bool_string(session.session_alert_flags().contains(flag)))
    }

    pub(super) fn window_flag(&self, flag: AlertFlags) -> Option<String> {
        self.window_index
            .map(|_| bool_string(self.window_alert_flags().contains(flag)))
    }
}