knave 0.14.6

A Lisp programming language for humans and agents that infers types and ownership and compiles to readable Rust
Documentation
use std::io;
use std::rc::Rc;

use anstream::ColorChoice;
use rustyline::config::Config;
use rustyline::error::ReadlineError;
use rustyline::history::FileHistory;
use rustyline::{ColorMode, Editor, EventHandler, KeyCode, KeyEvent, Modifiers};

use super::diagnostic_output::DiagnosticOutput;
use super::enter_key::EnterKey;
use super::input_helper::InputHelper;
use super::prompt_history::PromptHistory;
use super::prompt_lines::EnteredText;

pub type LineEditor = Editor<InputHelper, FileHistory>;

pub struct EditedLines {
    editor: LineEditor,
    history: PromptHistory,
}

impl EditedLines {
    const PROMPT: &str = "> ";
    const HISTORY_SIZE: usize = 1000;
    const ENTER: KeyEvent = KeyEvent(KeyCode::Enter, Modifiers::NONE);

    pub fn new(standard_output: ColorChoice, notes: Rc<dyn DiagnosticOutput>) -> io::Result<Self> {
        let mut editor = Self::config(standard_output)
            .and_then(LineEditor::with_config)
            .map_err(io::Error::other)?;
        editor.set_helper(Some(InputHelper));
        editor.bind_sequence(Self::ENTER, EventHandler::Conditional(Box::new(EnterKey)));
        let history = PromptHistory::open_or_create(&mut editor, notes);
        Ok(Self { editor, history })
    }

    fn config(standard_output: ColorChoice) -> rustyline::Result<Config> {
        let color_mode = match standard_output {
            ColorChoice::Never => ColorMode::Disabled,
            _ => ColorMode::Forced,
        };
        Ok(Config::builder()
            .max_history_size(Self::HISTORY_SIZE)?
            .auto_add_history(true)
            .color_mode(color_mode)
            .build())
    }

    pub fn next_text(&mut self) -> io::Result<Option<EnteredText>> {
        loop {
            match self.editor.readline(Self::PROMPT) {
                Ok(line) => return Ok(Some(self.entered(line))),
                Err(ReadlineError::Interrupted) => {}
                Err(ReadlineError::Eof) => return Ok(None),
                Err(error) => return Err(io::Error::other(error)),
            }
        }
    }

    fn entered(&mut self, line: String) -> EnteredText {
        self.history.save(&mut self.editor);
        EnteredText::Complete(line + "\n")
    }
}