cc_switch_lib/cli/commands/
env.rs1use crate::app_config::AppType;
2use crate::cli::ui::{create_table, error, highlight, info, success};
3use crate::error::AppError;
4use crate::services::env_checker;
5use crate::services::local_env_check::{check_local_environment, ToolCheckStatus};
6use clap::Subcommand;
7
8#[derive(Subcommand)]
9pub enum EnvCommand {
10 Check,
12 List,
14 Tools,
16}
17
18pub fn execute(cmd: EnvCommand, app: Option<AppType>) -> Result<(), AppError> {
19 let app_type = app.unwrap_or(AppType::Claude);
20
21 match cmd {
22 EnvCommand::Check => check_conflicts(app_type),
23 EnvCommand::List => list_env_vars(app_type),
24 EnvCommand::Tools => check_local_tools(),
25 }
26}
27
28fn check_conflicts(app_type: AppType) -> Result<(), AppError> {
29 let app_str = app_type.as_str();
30
31 println!(
32 "\n{}",
33 highlight(&format!("Checking Environment Variables for {}", app_str))
34 );
35 println!("{}", "═".repeat(60));
36
37 let conflicts = env_checker::check_env_conflicts(app_str)
39 .map_err(|e| AppError::Message(format!("Failed to check environment variables: {}", e)))?;
40
41 if conflicts.is_empty() {
42 println!(
43 "\n{}",
44 success("✓ No environment variable conflicts detected")
45 );
46 println!(
47 "{}",
48 info(&format!(
49 "Your {} configuration should work correctly.",
50 app_str
51 ))
52 );
53 return Ok(());
54 }
55
56 println!(
58 "\n{}",
59 error(&format!(
60 "⚠ Found {} environment variable(s) that may conflict:",
61 conflicts.len()
62 ))
63 );
64 println!();
65
66 let mut table = create_table();
67 table.set_header(vec!["Variable", "Value", "Source Type", "Source Location"]);
68
69 for conflict in &conflicts {
70 let value_display = if conflict.var_value.len() > 30 {
72 format!("{}...", &conflict.var_value[..27])
73 } else {
74 conflict.var_value.clone()
75 };
76
77 table.add_row(vec![
78 conflict.var_name.as_str(),
79 &value_display,
80 conflict.source_type.as_str(),
81 conflict.source_path.as_str(),
82 ]);
83 }
84
85 println!("{}", table);
86 println!();
87 println!(
88 "{}",
89 info("These environment variables may override CC-Switch's configuration.")
90 );
91 println!(
92 "{}",
93 info("Please manually remove them from your shell config files or system settings.")
94 );
95
96 Ok(())
97}
98
99fn list_env_vars(app_type: AppType) -> Result<(), AppError> {
100 let app_str = app_type.as_str();
101
102 println!(
103 "\n{}",
104 highlight(&format!("Environment Variables for {}", app_str))
105 );
106 println!("{}", "═".repeat(60));
107
108 let conflicts = env_checker::check_env_conflicts(app_str)
110 .map_err(|e| AppError::Message(format!("Failed to list environment variables: {}", e)))?;
111
112 if conflicts.is_empty() {
113 println!("\n{}", info("No related environment variables found."));
114 return Ok(());
115 }
116
117 println!("\n{} environment variable(s) found:\n", conflicts.len());
118
119 let mut table = create_table();
120 table.set_header(vec!["Variable", "Value", "Source Type", "Source Location"]);
121
122 for conflict in &conflicts {
123 table.add_row(vec![
124 conflict.var_name.as_str(),
125 conflict.var_value.as_str(),
126 conflict.source_type.as_str(),
127 conflict.source_path.as_str(),
128 ]);
129 }
130
131 println!("{}", table);
132
133 Ok(())
134}
135
136fn check_local_tools() -> Result<(), AppError> {
137 let results = check_local_environment();
138
139 println!("\n{}", highlight("Local CLI Tools"));
140 println!("{}", "═".repeat(60));
141
142 let mut table = create_table();
143 table.set_header(vec!["Tool", "Status"]);
144 for result in results {
145 table.add_row(vec![
146 result.display_name.to_string(),
147 tool_status_summary(&result.status),
148 ]);
149 }
150
151 println!("{}", table);
152
153 Ok(())
154}
155
156fn tool_status_summary(status: &ToolCheckStatus) -> String {
157 match status {
158 ToolCheckStatus::Ok { version } => format!("ok ({version})"),
159 ToolCheckStatus::NotInstalledOrNotExecutable => "not installed".to_string(),
160 ToolCheckStatus::Error { message } => format!("error ({message})"),
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::tool_status_summary;
167 use crate::services::local_env_check::ToolCheckStatus;
168
169 #[test]
170 fn tool_status_summary_formats_ok_version() {
171 let summary = tool_status_summary(&ToolCheckStatus::Ok {
172 version: "1.2.3".to_string(),
173 });
174
175 assert_eq!(summary, "ok (1.2.3)");
176 }
177
178 #[test]
179 fn tool_status_summary_formats_missing_tool() {
180 let summary = tool_status_summary(&ToolCheckStatus::NotInstalledOrNotExecutable);
181
182 assert_eq!(summary, "not installed");
183 }
184}