use crate::engine::Executor;
use crate::error::Result;
use crate::theme::Theme;
use crossterm::style::Attribute;
use std::sync::mpsc;
use std::thread::{self, JoinHandle};
pub type CapriceMessage = (
mpsc::Sender<CapriceCommand>,
mpsc::Receiver<String>,
JoinHandle<Result<()>>,
);
pub enum CapriceCommand {
Println(String),
Exit,
Continue,
}
pub struct CapriceBuilder {
caprice: Caprice,
}
impl CapriceBuilder {
pub fn init(mut self) -> Caprice {
if self.caprice.executor.reset_prompt().is_ok() {
self.caprice
} else {
panic!("Caprice: Error initializing prompt");
}
}
pub fn theme(mut self, theme: Theme) -> Self {
self.caprice.executor.theme = theme;
self
}
pub fn set_keywords(mut self, keywords: Vec<String>) -> Self {
self.caprice.executor.set_keywords(keywords);
self
}
pub fn enable_alternate_screen(mut self) -> Self {
self.caprice
.executor
.terminal
.enable_alternate_screen()
.expect("Caprice: Error enabling alternate screen");
self
}
pub fn disable_ctrl_c(mut self) -> Self {
self.caprice.executor.scanner.enable_ctrl_c = false;
self
}
pub fn set_prompt(mut self, prompt: &'static str) -> Self {
self.caprice.executor.prompt = prompt;
self
}
}
#[derive(Debug)]
pub struct Caprice {
executor: Executor,
}
impl Caprice {
#![allow(clippy::new_ret_no_self)]
pub fn new() -> CapriceBuilder {
CapriceBuilder {
caprice: Caprice {
executor: Executor::new(),
},
}
}
pub fn run(mut self) -> Result<CapriceMessage> {
let (tx_keyword, rx_keyword) = mpsc::channel();
let (tx_command, rx_command) = mpsc::channel();
let handle = thread::spawn(move || -> Result<()> {
loop {
if let Some(keyword) = self.executor.get_next_key_event()? {
tx_keyword.send(keyword)?;
} else {
continue;
}
if let Ok(command) = rx_command.recv() {
match command {
CapriceCommand::Println(msg) => {
self.executor.print_msg(msg)?;
}
CapriceCommand::Exit => {
self.executor.exec_exit()?;
return Ok(());
}
CapriceCommand::Continue => continue,
}
}
}
});
Ok((tx_command, rx_keyword, handle))
}
pub fn get(&mut self) -> Result<String> {
loop {
if let Some(keyword) = self.executor.get_next_key_event()? {
return Ok(keyword);
} else {
continue;
}
}
}
pub fn send(&mut self, command: CapriceCommand) -> Result<()> {
match command {
CapriceCommand::Println(msg) => self.executor.print_msg(msg),
CapriceCommand::Exit => {
self.executor.exec_exit()?;
Ok(())
}
CapriceCommand::Continue => Ok(()),
}
}
}
impl Drop for Caprice {
fn drop(&mut self) {
println!("{}", Attribute::Reset);
self.executor.terminal.clear_from_cursor().unwrap();
self.executor.terminal.flush().unwrap();
self.executor.terminal.disable_raw_mode().unwrap();
}
}