1use std::sync::Arc;
2
3use aurora_core::{
4 AuroraError, AuroraResult, Command, CommandCategory, Engine, Pipeline, Value,
5};
6use aurora_locale::Localizer;
7
8use crate::session::SessionStore;
9use crate::todo::find_todos;
10
11pub struct ContextEngine {
12 localizer: Arc<Localizer>,
13}
14
15impl ContextEngine {
16 pub fn new(localizer: Arc<Localizer>) -> Self {
17 Self { localizer }
18 }
19}
20
21impl Engine for ContextEngine {
22 fn name(&self) -> &'static str {
23 "context"
24 }
25
26 fn can_handle(&self, cmd: &Command) -> bool {
27 matches!(cmd.category, CommandCategory::Context)
28 }
29
30 fn execute(&self, cmd: &Command, _input: &Pipeline) -> AuroraResult<Pipeline> {
31 match cmd.action.as_str() {
32 "show" => execute_show(cmd, &self.localizer),
33 "todos" => execute_todos(cmd, &self.localizer),
34 "review" => execute_review(cmd, &self.localizer),
35 _ => Err(AuroraError::CommandNotFound(format!(
36 "context.{}",
37 cmd.action
38 ))),
39 }
40 }
41}
42
43fn execute_show(cmd: &Command, _localizer: &Localizer) -> AuroraResult<Pipeline> {
44 let ago = cmd
45 .args
46 .first()
47 .map(|s| s.as_str())
48 .unwrap_or("1 hour");
49
50 let store = SessionStore::new()?;
51 store.recent(ago)
52}
53
54fn execute_todos(_cmd: &Command, _localizer: &Localizer) -> AuroraResult<Pipeline> {
55 let path = _cmd.args.first().map(|s| s.as_str()).unwrap_or(".");
56 find_todos(path)
57}
58
59fn execute_review(_cmd: &Command, _localizer: &Localizer) -> AuroraResult<Pipeline> {
60 let mut pipeline = Pipeline::new();
61
62 let log_output = std::process::Command::new("git")
63 .args(["log", "--oneline", "-10"])
64 .output()
65 .map_err(|e| AuroraError::ContextError(format!("git log: {e}")))?;
66
67 let log_text = String::from_utf8_lossy(&log_output.stdout).to_string();
68 pipeline.push(Value::Record(
69 vec![("log".to_string(), Value::String(log_text))]
70 .into_iter()
71 .collect(),
72 ));
73
74 let status_output = std::process::Command::new("git")
75 .args(["status", "--short"])
76 .output()
77 .map_err(|e| AuroraError::ContextError(format!("git status: {e}")))?;
78
79 let status_text = String::from_utf8_lossy(&status_output.stdout).to_string();
80 pipeline.push(Value::Record(
81 vec![("status".to_string(), Value::String(status_text))]
82 .into_iter()
83 .collect(),
84 ));
85
86 Ok(pipeline)
87}