1pub mod install;
7
8use crate::config::ShellType;
9use clap::{Parser, Subcommand};
10use std::path::PathBuf;
11
12#[derive(Debug, Clone, Copy, clap::ValueEnum)]
14pub enum ShellTypeArg {
15 Bash,
16 Zsh,
17 Fish,
18}
19
20impl From<ShellTypeArg> for ShellType {
21 fn from(arg: ShellTypeArg) -> Self {
22 match arg {
23 ShellTypeArg::Bash => ShellType::Bash,
24 ShellTypeArg::Zsh => ShellType::Zsh,
25 ShellTypeArg::Fish => ShellType::Fish,
26 }
27 }
28}
29
30#[derive(Parser)]
32#[command(name = "par-term")]
33#[command(author, version, about, long_about = None)]
34pub struct Cli {
35 #[command(subcommand)]
36 pub command: Option<Commands>,
37
38 #[arg(long, value_name = "SHADER")]
40 pub shader: Option<String>,
41
42 #[arg(long, value_name = "SECONDS")]
44 pub exit_after: Option<f64>,
45
46 #[arg(long, value_name = "PATH", num_args = 0..=1, default_missing_value = "")]
48 pub screenshot: Option<PathBuf>,
49
50 #[arg(long, value_name = "COMMAND")]
52 pub command_to_send: Option<String>,
53
54 #[arg(long)]
56 pub log_session: bool,
57
58 #[arg(long, value_enum, value_name = "LEVEL")]
60 pub log_level: Option<LogLevelArg>,
61}
62
63#[derive(Debug, Clone, Copy, clap::ValueEnum)]
65pub enum LogLevelArg {
66 Off,
67 Error,
68 Warn,
69 Info,
70 Debug,
71 Trace,
72}
73
74impl LogLevelArg {
75 pub fn to_level_filter(self) -> log::LevelFilter {
77 match self {
78 LogLevelArg::Off => log::LevelFilter::Off,
79 LogLevelArg::Error => log::LevelFilter::Error,
80 LogLevelArg::Warn => log::LevelFilter::Warn,
81 LogLevelArg::Info => log::LevelFilter::Info,
82 LogLevelArg::Debug => log::LevelFilter::Debug,
83 LogLevelArg::Trace => log::LevelFilter::Trace,
84 }
85 }
86}
87
88#[derive(Subcommand)]
89pub enum Commands {
90 InstallShaders {
92 #[arg(short = 'y', long)]
94 yes: bool,
95
96 #[arg(short, long)]
98 force: bool,
99 },
100
101 InstallShellIntegration {
103 #[arg(long, value_enum)]
105 shell: Option<ShellTypeArg>,
106 },
107
108 UninstallShellIntegration,
110
111 UninstallShaders {
113 #[arg(short, long)]
115 force: bool,
116 },
117
118 ShaderLint {
120 path: PathBuf,
122
123 #[arg(long)]
125 readability: bool,
126
127 #[arg(long)]
129 apply: bool,
130
131 #[arg(long)]
133 no_prompt: bool,
134 },
135
136 InstallIntegrations {
138 #[arg(short = 'y', long)]
140 yes: bool,
141 },
142
143 SelfUpdate {
145 #[arg(short = 'y', long)]
147 yes: bool,
148 },
149
150 McpServer,
152}
153
154#[derive(Clone, Debug, Default)]
156pub struct RuntimeOptions {
157 pub shader: Option<String>,
159 pub exit_after: Option<f64>,
161 pub screenshot: Option<PathBuf>,
163 pub command_to_send: Option<String>,
165 pub log_session: bool,
167 pub log_level: Option<log::LevelFilter>,
169}
170
171pub enum CliResult {
173 Continue(RuntimeOptions),
175 Exit(i32),
177}
178
179pub fn process_cli() -> CliResult {
181 use install::{
182 install_integrations_cli, install_shaders_cli, install_shell_integration_cli,
183 self_update_cli, uninstall_shaders_cli, uninstall_shell_integration_cli,
184 };
185
186 let cli = Cli::parse();
187
188 match cli.command {
189 Some(Commands::InstallShaders { yes, force }) => {
190 let result = install_shaders_cli(yes || force);
191 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
192 }
193 Some(Commands::InstallShellIntegration { shell }) => {
194 let result = install_shell_integration_cli(shell.map(Into::into));
195 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
196 }
197 Some(Commands::UninstallShellIntegration) => {
198 let result = uninstall_shell_integration_cli();
199 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
200 }
201 Some(Commands::UninstallShaders { force }) => {
202 let result = uninstall_shaders_cli(force);
203 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
204 }
205 Some(Commands::ShaderLint {
206 path,
207 readability,
208 apply,
209 no_prompt,
210 }) => {
211 let result = crate::shader_lint::shader_lint_cli(&path, readability, apply, !no_prompt);
212 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
213 }
214 Some(Commands::InstallIntegrations { yes }) => {
215 let result = install_integrations_cli(yes);
216 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
217 }
218 Some(Commands::SelfUpdate { yes }) => {
219 let result = self_update_cli(yes);
220 CliResult::Exit(if result.is_ok() { 0 } else { 1 })
221 }
222 Some(Commands::McpServer) => {
223 crate::mcp_server::set_app_version(crate::VERSION);
224 crate::mcp_server::run_mcp_server();
225 CliResult::Exit(0)
226 }
227 None => {
228 let options = RuntimeOptions {
230 shader: cli.shader,
231 exit_after: cli.exit_after,
232 screenshot: cli.screenshot,
233 command_to_send: cli.command_to_send,
234 log_session: cli.log_session,
235 log_level: cli.log_level.map(|l| l.to_level_filter()),
236 };
237 CliResult::Continue(options)
238 }
239 }
240}