gmsg 0.1.3

AI-powered commit message generator with a TUI editor
Documentation
use ratatui::{
    Frame,
    crossterm::event::{Event, KeyCode, KeyModifiers, read},
};
use ratatui_textarea::TextArea;

use crate::tui::TerminalGuard;
#[derive(Default)]
pub struct Editor<'a> {
    state: State,
    textarea: TextArea<'a>,
}
#[derive(Debug, Default)]
enum State {
    #[default]
    Editing,
    Saved,
    Discarded,
}

impl<'a> Editor<'a> {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn run(&mut self, guard: &mut TerminalGuard) -> anyhow::Result<String> {
        let terminal = &mut guard.0;
        loop {
            terminal.draw(|frame| self.render(frame))?;

            if let Event::Key(key) = read()? {
                match (key.modifiers, key.code) {
                    (KeyModifiers::CONTROL, KeyCode::Char('s')) => {
                        self.state = State::Saved;
                        break;
                    }
                    (KeyModifiers::CONTROL, KeyCode::Char('q')) => {
                        self.state = State::Discarded;
                        return Ok(String::new());
                    }
                    _ => {
                        self.textarea.input(key);
                    }
                }
            }
        }
        let mut out = String::new();
        for line in self.textarea.lines() {
            out.push_str(&format!("{}\n", line));
        }
        Ok(out)
    }

    fn render(&self, frame: &mut Frame) {
        let area = frame.area();
        let _width = area.width.max(3) - 3;

        frame.render_widget(&self.textarea, area);
    }
}

impl<'a> From<String> for Editor<'a> {
    fn from(input: String) -> Self {
        Self {
            state: State::Editing,
            textarea: TextArea::from(input.split("\n")),
        }
    }
}