vx_cli/
lib.rs

1//! VX CLI - Command Line Interface for VX Tool Manager
2
3use anyhow::Result;
4use clap::Parser;
5use vx_core::{PluginRegistry, VxError};
6
7pub mod cli;
8pub mod commands;
9pub mod tracing_setup;
10pub mod ui;
11
12// Re-export for convenience
13pub use cli::Cli;
14pub use tracing_setup::setup_tracing;
15
16/// Main CLI application structure
17pub struct VxCli {
18    registry: PluginRegistry,
19}
20
21impl VxCli {
22    /// Create a new VxCli instance with the given plugin registry
23    pub fn new(registry: PluginRegistry) -> Self {
24        Self { registry }
25    }
26
27    /// Run the CLI application
28    pub async fn run(self) -> Result<()> {
29        let cli = Cli::parse();
30
31        // Handle global flags
32        if cli.verbose {
33            // Verbose logging is already set up in tracing_setup
34        }
35
36        // Route to appropriate command handler
37        match &cli.command {
38            Some(command) => self.handle_command(command.clone(), &cli).await,
39            None => {
40                // No subcommand provided, try to execute as tool
41                if cli.args.is_empty() {
42                    // Show help if no arguments
43                    Cli::parse_from(["vx", "--help"]);
44                    Ok(())
45                } else {
46                    // Execute tool
47                    self.execute_tool(&cli.args, cli.use_system_path).await
48                }
49            }
50        }
51    }
52
53    /// Handle a specific command
54    async fn handle_command(&self, command: cli::Commands, _cli: &Cli) -> Result<()> {
55        use cli::Commands;
56
57        match command {
58            Commands::Version => commands::version::handle().await.map_err(Into::into),
59            Commands::List { tool, status } => {
60                commands::list::handle(&self.registry, tool.as_deref(), status)
61                    .await
62                    .map_err(Into::into)
63            }
64            Commands::Install {
65                tool,
66                version,
67                force,
68            } => commands::install::handle(&self.registry, &tool, version.as_deref(), force)
69                .await
70                .map_err(Into::into),
71            Commands::Update { tool, apply } => {
72                commands::update::handle(&self.registry, tool.as_deref(), apply)
73                    .await
74                    .map_err(Into::into)
75            }
76            Commands::Remove {
77                tool,
78                version,
79                force,
80            } => commands::remove::handle(&self.registry, &tool, version.as_deref(), force)
81                .await
82                .map_err(Into::into),
83            Commands::Where { tool, all } => {
84                commands::where_cmd::handle(&self.registry, &tool, all)
85                    .await
86                    .map_err(Into::into)
87            }
88            Commands::Fetch {
89                tool,
90                latest,
91                prerelease,
92                detailed,
93                interactive,
94            } => commands::fetch::handle(
95                &self.registry,
96                &tool,
97                latest,
98                detailed,
99                interactive,
100                prerelease,
101            )
102            .await
103            .map_err(Into::into),
104            Commands::Use { tool_version } => {
105                commands::use_cmd::handle(&self.registry, &tool_version)
106                    .await
107                    .map_err(Into::into)
108            }
109            Commands::Switch {
110                tool_version,
111                global,
112            } => commands::switch::handle(&self.registry, &tool_version, global)
113                .await
114                .map_err(Into::into),
115            Commands::Config => commands::config::handle().await.map_err(Into::into),
116            Commands::Init => {
117                // TODO: Implement init command
118                println!("Init command not yet implemented");
119                Ok(())
120            }
121            Commands::Cleanup => {
122                // TODO: Implement cleanup command
123                println!("Cleanup command not yet implemented");
124                Ok(())
125            }
126            Commands::Stats => commands::stats::handle(&self.registry)
127                .await
128                .map_err(Into::into),
129            Commands::Plugin { command } => commands::plugin::handle(&self.registry, command)
130                .await
131                .map_err(Into::into),
132            Commands::Venv { command } => commands::venv_cmd::handle(command)
133                .await
134                .map_err(Into::into),
135        }
136    }
137
138    /// Execute a tool with the given arguments
139    async fn execute_tool(&self, args: &[String], use_system_path: bool) -> Result<()> {
140        if args.is_empty() {
141            return Err(VxError::Other {
142                message: "No tool specified".to_string(),
143            }
144            .into());
145        }
146
147        let tool_name = &args[0];
148        let tool_args = &args[1..];
149
150        commands::execute::handle(&self.registry, tool_name, tool_args, use_system_path)
151            .await
152            .map_err(Into::into)
153    }
154}