alma 0.1.1

A Bevy-native modal text editor with Vim-style navigation.
Documentation
use super::display::EditShape;
use crate::{
    buffer::BufferEditShape,
    ecs::events::{
        edit::{PluginBufferProposalCapability, RevisionGuardedBufferEditRequested},
        status::{StatusMessage, StatusMessageRequested},
    },
    text_stream::TextRevision,
};
use std::fmt::{Display, Formatter};

/// Redacted drained effect shape.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PluginRuntimeTraceEffect {
    /// Buffer edit proposal routed to the buffer/proposal owners.
    BufferEdit {
        /// Capability used to submit the proposal.
        capability: PluginBufferProposalCapability,
        /// Observed buffer revision.
        base_revision: TextRevision,
        /// Redacted edit shape.
        edit: BufferEditShape,
    },
    /// Status owner request.
    Status {
        /// Redacted status shape.
        status: PluginRuntimeTraceStatus,
    },
}

impl From<&RevisionGuardedBufferEditRequested> for PluginRuntimeTraceEffect {
    fn from(request: &RevisionGuardedBufferEditRequested) -> Self {
        Self::BufferEdit {
            capability: request.provenance.capability(),
            base_revision: request.provenance.base_revision(),
            edit: BufferEditShape::from_edit(&request.edit),
        }
    }
}

impl From<&StatusMessageRequested> for PluginRuntimeTraceEffect {
    fn from(request: &StatusMessageRequested) -> Self {
        Self::Status {
            status: PluginRuntimeTraceStatus::from(&request.message),
        }
    }
}

impl Display for PluginRuntimeTraceEffect {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::BufferEdit {
                capability,
                base_revision,
                edit,
            } => write!(
                formatter,
                "buffer-edit capability={} base_revision={} edit={}",
                capability.as_str(),
                base_revision,
                EditShape(edit)
            ),
            Self::Status { status } => write!(formatter, "status {status}"),
        }
    }
}

/// Redacted status request shape.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PluginRuntimeTraceStatus {
    /// Clear status.
    Clear,
    /// Informational status text length.
    Info {
        /// Escaped status text byte length.
        byte_len: usize,
    },
    /// Error status without error payload.
    Error,
}

impl PluginRuntimeTraceStatus {
    /// Stable status class text.
    #[must_use]
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Clear => "clear",
            Self::Info { .. } => "info",
            Self::Error => "error",
        }
    }
}

impl From<&StatusMessage> for PluginRuntimeTraceStatus {
    fn from(message: &StatusMessage) -> Self {
        match message {
            StatusMessage::Clear => Self::Clear,
            StatusMessage::Info(text) => Self::Info {
                byte_len: text.as_str().len(),
            },
            StatusMessage::Error(_error) => Self::Error,
        }
    }
}

impl Display for PluginRuntimeTraceStatus {
    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Clear | Self::Error => formatter.write_str(self.as_str()),
            Self::Info { byte_len } => write!(formatter, "info byte_len={byte_len}"),
        }
    }
}