hrtor 0.3.0

A scalable line editor
Documentation
//! # Hrtor processor module

mod actions;
pub mod constants;
mod parser;

use crate::cli::FileInfo;
use crate::processor::parser::{Action, Expression};
use constants::{CommandResult, CommandStatus};
use linefeed::{ReadResult, Signal};
use std::sync::{Arc, Mutex};

pub struct HrtorProcessor {
    pub editing_file: Arc<Mutex<FileInfo>>,
}

impl HrtorProcessor {
    fn from(file: FileInfo) -> Self {
        Self {
            editing_file: Arc::new(Mutex::new(file)),
        }
    }
}

pub fn command_status_ok() -> CommandStatus {
    CommandStatus::Continue(CommandResult::Ok)
}

pub trait Processor {
    fn handle_command(&self, command: ReadResult) -> anyhow::Result<CommandStatus>;

    /// Evaluates the command
    fn eval(&self, str: String) -> anyhow::Result<CommandStatus>;
}

pub struct Hrtor {
    pub processor: Arc<HrtorProcessor>,
}

impl Hrtor {
    /// Creates Hrtor instance by HrtorProcessor
    pub fn new(processor: HrtorProcessor) -> Self {
        Self {
            processor: processor.into(),
        }
    }

    /// Creates Hrtor instance from the file user want to edit
    pub fn from(file: FileInfo) -> Self {
        Self {
            processor: Arc::new(HrtorProcessor::from(file)),
        }
    }
}

impl Processor for HrtorProcessor {
    fn handle_command(&self, command: ReadResult) -> anyhow::Result<CommandStatus> {
        match command {
            ReadResult::Input(str) => self.eval(str),
            ReadResult::Eof
            | ReadResult::Signal(Signal::Interrupt)
            | ReadResult::Signal(Signal::Quit) => Ok(CommandStatus::Quit),
            _ => Ok(CommandStatus::Continue(CommandResult::NothingToDo)),
        }
    }

    /// Eval function
    /// This function receives a String, then the internal logic converts it to a Expression.
    ///
    /// 1. Receives a String
    /// 2. Converts it to a Expression
    /// 3. Forks process by the Expression, then returns CommandStatus
    fn eval(&self, str: String) -> anyhow::Result<CommandStatus> {
        let expr: Expression = match parser::parse(str.as_str()) {
            Ok(v) => v,
            Err(e) => anyhow::bail!(e),
        };

        match expr.action {
            Action::Exit => Ok(self.exit()),
            Action::Write => Ok(self.write()),
            Action::Add => Ok(self.add()),
            Action::DeleteAll => Ok(self.delete_all()),
            Action::Print => Ok(self.print()),
        }
    }
}

#[cfg(test)]
mod test {
    use crate::cli::FileInfo;
    use crate::processor::Hrtor;
    use crate::processor::HrtorProcessor;
    use std::path::PathBuf;
    use std::sync::{Arc, Mutex};

    #[test]
    fn test_handle_command() {
        let hrtor_processor: HrtorProcessor = HrtorProcessor {
            editing_file: Arc::new(Mutex::new(FileInfo {
                path: PathBuf::from("test"),
                context: String::from("test"),
            })),
        };
        let _hrtor = Hrtor::new(hrtor_processor);
    }
}