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 { check, version }) => {
61 self_update::handle(check, version.as_deref()).await
62 }
63
64 Some(Commands::Uninstall {
65 tool,
66 version,
67 force,
68 }) => remove::handle(registry, &tool, version.as_deref(), force).await,
69
70 Some(Commands::Which { tool, all }) => where_cmd::handle(registry, &tool, all).await,
71
72 Some(Commands::Versions {
73 tool,
74 latest,
75 prerelease,
76 detailed,
77 interactive,
78 }) => fetch::handle(registry, &tool, latest, detailed, interactive, prerelease).await,
79
80 Some(Commands::Switch {
81 tool_version,
82 global,
83 }) => switch::handle(registry, &tool_version, global).await,
84
85 Some(Commands::Config { command }) => match command {
86 Some(crate::cli::ConfigCommand::Show) | None => config::handle().await,
87 Some(crate::cli::ConfigCommand::Set { key, value }) => {
88 config::handle_set(&key, &value).await
89 }
90 Some(crate::cli::ConfigCommand::Get { key }) => config::handle_get(&key).await,
91 Some(crate::cli::ConfigCommand::Reset { key }) => {
92 config::handle_reset(key.clone()).await
93 }
94 Some(crate::cli::ConfigCommand::Edit) => config::handle_edit().await,
95 },
96
97 Some(Commands::Search {
98 query,
99 category,
100 installed_only,
101 available_only,
102 format,
103 verbose,
104 }) => {
105 let registry = PluginRegistry::new();
108 search::handle(
109 ®istry,
110 query.clone(),
111 category.clone(),
112 installed_only,
113 available_only,
114 format.clone(),
115 verbose,
116 )
117 .await
118 }
119
120 Some(Commands::Sync {
121 check,
122 force,
123 dry_run,
124 verbose,
125 no_parallel,
126 no_auto_install,
127 }) => {
128 let registry = PluginRegistry::new();
130 sync::handle(
131 ®istry,
132 check,
133 force,
134 dry_run,
135 verbose,
136 no_parallel,
137 no_auto_install,
138 )
139 .await
140 }
141
142 Some(Commands::Init {
143 interactive,
144 template,
145 tools,
146 force,
147 dry_run,
148 list_templates,
149 }) => {
150 init::handle(
151 interactive,
152 template.clone(),
153 tools.clone(),
154 force,
155 dry_run,
156 list_templates,
157 )
158 .await
159 }
160
161 Some(Commands::Clean {
162 dry_run,
163 cache,
164 orphaned,
165 all,
166 force,
167 older_than,
168 verbose,
169 }) => {
170 let cache_only = cache && !all;
172 let orphaned_only = orphaned && !all;
173 cleanup::handle(
174 dry_run,
175 cache_only,
176 orphaned_only,
177 force,
178 older_than,
179 verbose,
180 )
181 .await
182 }
183
184 Some(Commands::Stats) => stats::handle(registry).await,
185
186 Some(Commands::Plugin { command }) => plugin::handle(registry, command).await,
187
188 Some(Commands::Venv { command }) => venv_cmd::handle(command).await,
189
190 Some(Commands::Global { command }) => global::handle(command).await,
191
192 None => {
193 if cli.args.is_empty() {
195 UI::error("No tool specified");
196 UI::hint("Usage: vx <tool> [args...]");
197 UI::hint("Example: vx uv pip install requests");
198 UI::hint("Run 'vx list --all' to see supported tools");
199 std::process::exit(1);
200 }
201
202 let tool_name = &cli.args[0];
203 let tool_args = &cli.args[1..];
204
205 let exit_code =
207 execute::execute_tool(registry, tool_name, tool_args, cli.use_system_path)
208 .await?;
209 if exit_code != 0 {
210 std::process::exit(exit_code);
211 }
212 Ok(())
213 }
214
215 Some(Commands::Shell { command }) => {
216 use crate::cli::ShellCommand;
217 match command {
218 ShellCommand::Init { shell } => shell::handle_shell_init(shell.clone()).await,
219 ShellCommand::Completions { shell } => {
220 shell::handle_completion(shell.clone()).await
221 }
222 }
223 }
224 }
225 }
226}