aurora-context 0.1.0

Session history, TODO finder, and code review
Documentation
use std::sync::Arc;

use aurora_core::{
    AuroraError, AuroraResult, Command, CommandCategory, Engine, Pipeline, Value,
};
use aurora_locale::Localizer;

use crate::session::SessionStore;
use crate::todo::find_todos;

pub struct ContextEngine {
    localizer: Arc<Localizer>,
}

impl ContextEngine {
    pub fn new(localizer: Arc<Localizer>) -> Self {
        Self { localizer }
    }
}

impl Engine for ContextEngine {
    fn name(&self) -> &'static str {
        "context"
    }

    fn can_handle(&self, cmd: &Command) -> bool {
        matches!(cmd.category, CommandCategory::Context)
    }

    fn execute(&self, cmd: &Command, _input: &Pipeline) -> AuroraResult<Pipeline> {
        match cmd.action.as_str() {
            "show" => execute_show(cmd, &self.localizer),
            "todos" => execute_todos(cmd, &self.localizer),
            "review" => execute_review(cmd, &self.localizer),
            _ => Err(AuroraError::CommandNotFound(format!(
                "context.{}",
                cmd.action
            ))),
        }
    }
}

fn execute_show(cmd: &Command, _localizer: &Localizer) -> AuroraResult<Pipeline> {
    let ago = cmd
        .args
        .first()
        .map(|s| s.as_str())
        .unwrap_or("1 hour");

    let store = SessionStore::new()?;
    store.recent(ago)
}

fn execute_todos(_cmd: &Command, _localizer: &Localizer) -> AuroraResult<Pipeline> {
    let path = _cmd.args.first().map(|s| s.as_str()).unwrap_or(".");
    find_todos(path)
}

fn execute_review(_cmd: &Command, _localizer: &Localizer) -> AuroraResult<Pipeline> {
    let mut pipeline = Pipeline::new();

    let log_output = std::process::Command::new("git")
        .args(["log", "--oneline", "-10"])
        .output()
        .map_err(|e| AuroraError::ContextError(format!("git log: {e}")))?;

    let log_text = String::from_utf8_lossy(&log_output.stdout).to_string();
    pipeline.push(Value::Record(
        vec![("log".to_string(), Value::String(log_text))]
            .into_iter()
            .collect(),
    ));

    let status_output = std::process::Command::new("git")
        .args(["status", "--short"])
        .output()
        .map_err(|e| AuroraError::ContextError(format!("git status: {e}")))?;

    let status_text = String::from_utf8_lossy(&status_output.stdout).to_string();
    pipeline.push(Value::Record(
        vec![("status".to_string(), Value::String(status_text))]
            .into_iter()
            .collect(),
    ));

    Ok(pipeline)
}