synd-term 0.3.2

terminal feed viewer
Documentation
use std::{cell::RefCell, ops::ControlFlow, rc::Rc};

use crossterm::event::KeyEvent;

use crate::{application::event::KeyEventResult, keymap::Keymaps, ui::widgets::prompt::Prompt};

pub enum KeyHandler {
    Prompt(Rc<RefCell<Prompt>>),
    Keymaps(Keymaps),
}

impl KeyHandler {
    fn handle(&mut self, event: &KeyEvent) -> KeyEventResult {
        match self {
            KeyHandler::Prompt(prompt) => prompt.borrow_mut().handle_key_event(event),
            KeyHandler::Keymaps(keymaps) => keymaps.search(event),
        }
    }
}

pub struct KeyHandlers {
    handlers: Vec<KeyHandler>,
}

impl KeyHandlers {
    pub fn new() -> Self {
        Self {
            handlers: Vec::new(),
        }
    }

    pub fn push(&mut self, handler: KeyHandler) {
        self.handlers.push(handler);
    }

    pub fn remove_prompt(&mut self) {
        self.handlers
            .retain(|h| !matches!(h, KeyHandler::Prompt(_)));
    }

    pub fn keymaps_mut(&mut self) -> Option<&mut Keymaps> {
        for handler in &mut self.handlers {
            match handler {
                KeyHandler::Keymaps(keymaps) => return Some(keymaps),
                KeyHandler::Prompt(_) => continue,
            }
        }
        None
    }

    pub fn handle(&mut self, event: KeyEvent) -> KeyEventResult {
        match self.handlers.iter_mut().rev().try_for_each(|h| {
            let result = h.handle(&event);
            if result.is_consumed() {
                ControlFlow::Break(result)
            } else {
                ControlFlow::Continue(())
            }
        }) {
            ControlFlow::Break(consumed) => consumed,
            ControlFlow::Continue(()) => KeyEventResult::Ignored,
        }
    }
}