use anyhow::Result;
use rustyline::{error::ReadlineError, DefaultEditor};
use std::path::PathBuf;
pub enum ReplInput {
Line(String),
Interrupted,
Eof,
}
pub struct ReplSession {
editor: DefaultEditor,
history_file: Option<PathBuf>,
}
impl ReplSession {
pub fn new() -> Result<Self> {
Ok(Self {
editor: DefaultEditor::new()?,
history_file: None,
})
}
pub fn with_history(history_file: PathBuf) -> Result<Self> {
let mut editor = DefaultEditor::new()?;
let _ = editor.load_history(&history_file);
Ok(Self {
editor,
history_file: Some(history_file),
})
}
pub fn readline(&mut self, prompt: &str) -> Result<ReplInput> {
match self.editor.readline(prompt) {
Ok(line) => Ok(ReplInput::Line(line)),
Err(ReadlineError::Interrupted) => Ok(ReplInput::Interrupted),
Err(ReadlineError::Eof) => Ok(ReplInput::Eof),
Err(err) => Err(err.into()),
}
}
pub fn add_history_entry(&mut self, line: &str) -> Result<()> {
self.editor.add_history_entry(line)?;
Ok(())
}
}
impl Drop for ReplSession {
fn drop(&mut self) {
if let Some(ref file) = self.history_file {
let _ = self.editor.save_history(file);
}
}
}