1use crate::cli::{Cli, Commands};
4use crate::ui::UI;
5use vx_plugin::PluginRegistry;
6
7pub mod cleanup;
8pub mod config;
9pub mod execute;
10#[cfg(test)]
11mod execute_tests;
12pub mod fetch;
13pub mod global;
14pub mod init;
15pub mod install;
16pub mod list;
17pub mod plugin;
18pub mod remove;
19pub mod search;
20pub mod self_update;
21pub mod shell;
22pub mod stats;
23pub mod switch;
24pub mod sync;
25
26pub mod update;
27pub mod venv_cmd;
28pub mod version;
29pub mod where_cmd;
30
31pub struct CommandHandler;
34
35impl CommandHandler {
36 pub async fn handle(cli: Cli, registry: &PluginRegistry) -> anyhow::Result<()> {
37 UI::set_verbose(cli.verbose);
39
40 match cli.command {
41 Some(Commands::Version) => version::handle().await,
42
43 Some(Commands::List {
44 tool,
45 status,
46 installed: _,
47 available: _,
48 }) => list::handle(registry, tool.as_deref(), status).await,
49
50 Some(Commands::Install {
51 tool,
52 version,
53 force,
54 }) => install::handle(registry, &tool, version.as_deref(), force).await,
55
56 Some(Commands::Update { tool, apply: _ }) => {
57 update::handle(registry, tool.as_deref(), false).await
58 }
59
60 Some(Commands::SelfUpdate {
61 check,
62 version: _,
63 token,
64 prerelease,
65 force,
66 }) => self_update::handle(token.as_deref(), prerelease, force, check).await,
67
68 Some(Commands::Uninstall {
69 tool,
70 version,
71 force,
72 }) => remove::handle(registry, &tool, version.as_deref(), force).await,
73
74 Some(Commands::Which { tool, all }) => where_cmd::handle(registry, &tool, all).await,
75
76 Some(Commands::Versions {
77 tool,
78 latest,
79 prerelease,
80 detailed,
81 interactive,
82 }) => fetch::handle(registry, &tool, latest, detailed, interactive, prerelease).await,
83
84 Some(Commands::Switch {
85 tool_version,
86 global,
87 }) => switch::handle(registry, &tool_version, global).await,
88
89 Some(Commands::Config { command }) => match command {
90 Some(crate::cli::ConfigCommand::Show) | None => config::handle().await,
91 Some(crate::cli::ConfigCommand::Set { key, value }) => {
92 config::handle_set(&key, &value).await
93 }
94 Some(crate::cli::ConfigCommand::Get { key }) => config::handle_get(&key).await,
95 Some(crate::cli::ConfigCommand::Reset { key }) => {
96 config::handle_reset(key.clone()).await
97 }
98 Some(crate::cli::ConfigCommand::Edit) => config::handle_edit().await,
99 },
100
101 Some(Commands::Search {
102 query,
103 category,
104 installed_only,
105 available_only,
106 format,
107 verbose,
108 }) => {
109 let registry = PluginRegistry::new();
112 search::handle(
113 ®istry,
114 query.clone(),
115 category.clone(),
116 installed_only,
117 available_only,
118 format.clone(),
119 verbose,
120 )
121 .await
122 }
123
124 Some(Commands::Sync {
125 check,
126 force,
127 dry_run,
128 verbose,
129 no_parallel,
130 no_auto_install,
131 }) => {
132 let registry = PluginRegistry::new();
134 sync::handle(
135 ®istry,
136 check,
137 force,
138 dry_run,
139 verbose,
140 no_parallel,
141 no_auto_install,
142 )
143 .await
144 }
145
146 Some(Commands::Init {
147 interactive,
148 template,
149 tools,
150 force,
151 dry_run,
152 list_templates,
153 }) => {
154 init::handle(
155 interactive,
156 template.clone(),
157 tools.clone(),
158 force,
159 dry_run,
160 list_templates,
161 )
162 .await
163 }
164
165 Some(Commands::Clean {
166 dry_run,
167 cache,
168 orphaned,
169 all,
170 force,
171 older_than,
172 verbose,
173 }) => {
174 let cache_only = cache && !all;
176 let orphaned_only = orphaned && !all;
177 cleanup::handle(
178 dry_run,
179 cache_only,
180 orphaned_only,
181 force,
182 older_than,
183 verbose,
184 )
185 .await
186 }
187
188 Some(Commands::Stats) => stats::handle(registry).await,
189
190 Some(Commands::Plugin { command }) => plugin::handle(registry, command).await,
191
192 Some(Commands::Venv { command }) => venv_cmd::handle(command).await,
193
194 Some(Commands::Global { command }) => global::handle(command).await,
195
196 None => {
197 if cli.args.is_empty() {
199 UI::error("No tool specified");
200 UI::hint("Usage: vx <tool> [args...]");
201 UI::hint("Example: vx uv pip install requests");
202 UI::hint("Run 'vx list --all' to see supported tools");
203 std::process::exit(1);
204 }
205
206 let tool_name = &cli.args[0];
207 let tool_args = &cli.args[1..];
208
209 let exit_code =
211 execute::execute_tool(registry, tool_name, tool_args, cli.use_system_path)
212 .await?;
213 if exit_code != 0 {
214 std::process::exit(exit_code);
215 }
216 Ok(())
217 }
218
219 Some(Commands::Shell { command }) => {
220 use crate::cli::ShellCommand;
221 match command {
222 ShellCommand::Init { shell } => shell::handle_shell_init(shell.clone()).await,
223 ShellCommand::Completions { shell } => {
224 shell::handle_completion(shell.clone()).await
225 }
226 }
227 }
228 }
229 }
230}