alma 0.1.1

A Bevy-native modal text editor with Vim-style navigation.
Documentation
//! Vim adapter effects.

use crate::ecs::events::{
    command::CommandRequested,
    cursor::CursorMoveRequested,
    edit::{BufferEditRequested, EditHistoryRequested},
    intent::ViewportIntent,
    status::StatusMessageRequested,
};
use bevy::prelude::MessageWriter;

/// ECS requests collected during Vim interpretation.
#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) enum VimEffect {
    /// Buffer edit request.
    BufferEdit(BufferEditRequested),
    /// Undo or redo request.
    EditHistory(EditHistoryRequested),
    /// Cursor move.
    CursorMove(CursorMoveRequested),
    /// Viewport placement.
    Viewport(ViewportIntent),
    /// Status update.
    Status(StatusMessageRequested),
    /// Command request.
    Command(CommandRequested),
}

/// Ordered adapter-local effects produced by one input dispatch.
///
/// The batch is the commit point before typed ECS messages. Vim interpretation
/// may populate it, but authoritative mutation still belongs to owner systems.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub(super) struct VimEffectBatch {
    /// Ordered effects waiting to cross into ECS messages.
    effects: Vec<VimEffect>,
}

impl VimEffectBatch {
    /// Appends one effect to the batch.
    pub(super) fn push(&mut self, effect: VimEffect) {
        self.effects.push(effect);
    }

    /// Appends multiple effects preserving iterator order.
    pub(super) fn extend(&mut self, effects: impl IntoIterator<Item = VimEffect>) {
        self.effects.extend(effects);
    }

    /// Reads the ordered effects.
    pub(super) fn as_slice(&self) -> &[VimEffect] {
        &self.effects
    }
}

/// Vim effect sinks.
#[derive(bevy::ecs::system::SystemParam)]
pub struct VimEffectWriters<'w> {
    /// Buffer edits.
    buffer_edits: MessageWriter<'w, BufferEditRequested>,
    /// Edit-history replay requests.
    edit_history: MessageWriter<'w, EditHistoryRequested>,
    /// Cursor moves.
    cursor_moves: MessageWriter<'w, CursorMoveRequested>,
    /// Viewport intents.
    viewport_intents: MessageWriter<'w, ViewportIntent>,
    /// Status requests.
    status_requests: MessageWriter<'w, StatusMessageRequested>,
    /// Command requests.
    command_requests: MessageWriter<'w, CommandRequested>,
}

impl VimEffectWriters<'_> {
    /// Emits collected effects.
    pub(super) fn emit(&mut self, effects: &VimEffectBatch) {
        for effect in effects.as_slice() {
            match effect {
                VimEffect::BufferEdit(request) => {
                    let _sent = self.buffer_edits.write(request.clone());
                }
                VimEffect::EditHistory(request) => {
                    let _sent = self.edit_history.write(*request);
                }
                VimEffect::CursorMove(request) => {
                    let _sent = self.cursor_moves.write(*request);
                }
                VimEffect::Viewport(intent) => {
                    let _sent = self.viewport_intents.write(*intent);
                }
                VimEffect::Status(request) => {
                    let _sent = self.status_requests.write(request.clone());
                }
                VimEffect::Command(request) => {
                    let _sent = self.command_requests.write(*request);
                }
            }
        }
    }
}