alma 0.1.1

A Bevy-native modal text editor with Vim-style navigation.
Documentation
//! Vim command-line and search prompt handling.

use super::{
    effects::{VimEffect, VimEffectBatch},
    status::push_status_effect_from_line,
};
use crate::{
    ecs::{
        components::buffer::{BufferEntity, ViewEntity},
        events::{
            command::CommandRequested,
            input::EditorInputEvent,
            status::{StatusMessage, StatusMessageRequested},
        },
    },
    vim::{
        KeyToken, VimCommandState, VimConfig, VimCursor, VimSearchState, VimStatusLine,
        apply_search_outcome,
    },
};

/// Handles `:` prompt input.
pub(super) fn handle_command_input(
    target: ViewEntity,
    buffer_target: BufferEntity,
    input_events: &[EditorInputEvent],
    command_state: &mut VimCommandState,
    effects: &mut VimEffectBatch,
) {
    for event in input_events {
        match event {
            EditorInputEvent::Key(key) if key.token == KeyToken::Escape => {
                command_state.cancel();
                effects.push(VimEffect::Status(StatusMessageRequested {
                    target,
                    message: StatusMessage::Clear,
                }));
                return;
            }
            EditorInputEvent::Key(key) if key.token == KeyToken::Backspace => {
                command_state.backspace();
            }
            EditorInputEvent::Key(key) if key.token == KeyToken::Enter => {
                match command_state.submit() {
                    Ok(command) => {
                        effects.push(VimEffect::Command(CommandRequested {
                            target: buffer_target,
                            source: target,
                            command,
                        }));
                    }
                    Err(error) => {
                        effects.push(VimEffect::Status(StatusMessageRequested {
                            target,
                            message: StatusMessage::Error(error),
                        }));
                    }
                }
                return;
            }
            EditorInputEvent::Text(text) => command_state.push_text(&text.text),
            EditorInputEvent::Key(_) => {}
        }
    }
}

/// Handles `/` prompt input.
pub(super) fn handle_search_input(
    text: &str,
    input_events: &[EditorInputEvent],
    cursor: &mut VimCursor,
    search_state: &mut VimSearchState,
    vim_config: &VimConfig,
    target: ViewEntity,
    effects: &mut VimEffectBatch,
) {
    let mut status_line = VimStatusLine::default();
    for event in input_events {
        match event {
            EditorInputEvent::Key(key) if key.token == KeyToken::Escape => {
                search_state.cancel();
                effects.push(VimEffect::Status(StatusMessageRequested {
                    target,
                    message: StatusMessage::Clear,
                }));
                return;
            }
            EditorInputEvent::Key(key) if key.token == KeyToken::Backspace => {
                search_state.backspace();
            }
            EditorInputEvent::Key(key) if key.token == KeyToken::Enter => {
                let outcome = search_state.submit(text, cursor.byte_index(), &vim_config.options);
                apply_search_outcome(text, cursor, &mut status_line, outcome);
                push_status_effect_from_line(target, &status_line, effects);
                return;
            }
            EditorInputEvent::Text(text) => search_state.push_text(&text.text),
            EditorInputEvent::Key(_) => {}
        }
    }
}