Skip to main content

track/cli/
handler.rs

1//! Command handler dispatch for the track CLI.
2
3use crate::cli::handlers::CommandCtx;
4use crate::cli::Commands;
5use crate::db::Database;
6use crate::utils::Result;
7use clap_complete::Shell;
8
9pub struct CommandHandler {
10    db: Database,
11}
12
13impl CommandHandler {
14    pub fn new() -> Result<Self> {
15        let db = Database::new()?;
16        Ok(Self { db })
17    }
18
19    #[allow(dead_code)]
20    pub fn from_db(db: Database) -> Self {
21        Self { db }
22    }
23
24    /// Returns a reference to the database instance.
25    /// This is primarily used for testing.
26    #[allow(dead_code)]
27    pub fn get_db(&self) -> &Database {
28        &self.db
29    }
30
31    pub fn handle(&self, command: Commands) -> Result<()> {
32        let ctx = CommandCtx::new(&self.db);
33        match command {
34            Commands::New {
35                name,
36                description,
37                ticket,
38                ticket_url,
39                template,
40            } => super::handlers::handle_new(
41                &ctx,
42                &name,
43                description.as_deref(),
44                ticket.as_deref(),
45                ticket_url.as_deref(),
46                template.as_deref(),
47            ),
48            Commands::List { all } => super::handlers::handle_list(&ctx, all),
49            Commands::Switch { task_ref } => super::handlers::handle_switch(&ctx, &task_ref),
50            Commands::Status { id, json, all } => super::handlers::handle_info(&ctx, id, json, all),
51            Commands::Desc { description, task } => {
52                super::handlers::handle_desc(&ctx, description.as_deref(), task)
53            }
54            Commands::Ticket {
55                ticket_id,
56                url,
57                task,
58            } => super::handlers::handle_ticket(&ctx, &ticket_id, &url, task),
59            Commands::Archive { task_ref, force } => {
60                super::handlers::handle_archive(&ctx, task_ref.as_deref(), force)
61            }
62            Commands::Todo(cmd) => super::handlers::handle_todo(&ctx, cmd),
63            Commands::Link(cmd) => super::handlers::handle_link(&ctx, cmd),
64            Commands::Scrap(cmd) => super::handlers::handle_scrap(&ctx, cmd),
65            Commands::Sync { legacy } => super::handlers::handle_sync(&ctx, legacy),
66            Commands::Migrate(cmd) => super::handlers::handle_migrate(&ctx, cmd),
67            Commands::Repo(cmd) => super::handlers::handle_repo(&ctx, cmd),
68            Commands::Alias(cmd) => super::handlers::handle_alias(&ctx, cmd),
69            Commands::LlmHelp => super::handlers::handle_llm_help(&ctx),
70            Commands::Completion { shell, dynamic } => {
71                super::handlers::handle_completion(&ctx, shell, dynamic)
72            }
73            Commands::Complete { completion_type } => {
74                super::handlers::handle_complete(&ctx, completion_type)
75            }
76            Commands::Config(cmd) => super::handlers::handle_config(&ctx, cmd),
77            Commands::Webui { .. } => unreachable!("Webui command is handled in main.rs"),
78        }
79    }
80
81    #[allow(dead_code)]
82    pub(crate) fn handle_llm_help(&self) -> Result<()> {
83        super::handlers::handle_llm_help(&CommandCtx::new(&self.db))
84    }
85
86    #[allow(dead_code)]
87    pub(crate) fn handle_completion(&self, shell: Shell, dynamic: bool) -> Result<()> {
88        super::handlers::handle_completion(&CommandCtx::new(&self.db), shell, dynamic)
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use crate::db::Database;
96
97    #[test]
98    fn test_llm_help() {
99        let db = Database::new_in_memory().unwrap();
100        let handler = CommandHandler::from_db(db);
101
102        let result = handler.handle_llm_help();
103        assert!(result.is_ok());
104    }
105
106    #[test]
107    fn test_completion() {
108        let db = Database::new_in_memory().unwrap();
109        let handler = CommandHandler::from_db(db);
110
111        for shell in [
112            clap_complete::Shell::Bash,
113            clap_complete::Shell::Zsh,
114            clap_complete::Shell::Fish,
115            clap_complete::Shell::PowerShell,
116        ] {
117            let result = handler.handle_completion(shell, false);
118            assert!(
119                result.is_ok(),
120                "Static completion generation failed for {:?}",
121                shell
122            );
123        }
124
125        for shell in [clap_complete::Shell::Bash, clap_complete::Shell::Zsh] {
126            let result = handler.handle_completion(shell, true);
127            assert!(
128                result.is_ok(),
129                "Dynamic completion generation failed for {:?}",
130                shell
131            );
132        }
133    }
134}