1use crate::completion;
2use crate::version;
3use clap::{Args, Parser, Subcommand, ValueEnum};
4use std::path::PathBuf;
5
6use super::{
7 AppCommands, EnvCommands, LocalCommands, PresetCommands, SelfCommands, ServeCommands,
8 ShellCommands, StateCommands, SysCommands, TaskCommands, TaskRunCommand, ThemeCommands,
9};
10
11#[derive(Parser, Debug)]
13#[command(name = "shine")]
14#[command(version = version::display(), about, long_about = None)]
15#[command(
16 after_help = "QUICK START:\n shine list --available\n shine info app/starship\n shine install app/starship\n shine update && shine upgrade\n\nTARGETS:\n Use app/<category>, shell/<category>, or sys/<item>. A bare app/shell category is accepted when unique.\n\nNAMESPACES:\n app, shell, and sys expose resource-specific operations; preset, state, self, serve, completions, theme, and local are advanced tools."
17)]
18pub struct Cli {
19 #[arg(long, global = true)]
20 pub config_dir: Option<String>,
21
22 #[command(subcommand)]
23 pub command: Commands,
24}
25
26#[derive(Subcommand, Debug)]
27pub enum Commands {
28 #[command(name = "__shell-render", hide = true)]
29 ShellRender {
30 #[arg(value_name = "TARGET")]
31 target: String,
32 },
33 Init(InitCommand),
35 Shell {
37 #[command(subcommand)]
38 command: ShellCommands,
39 },
40 App {
42 #[command(subcommand)]
43 command: AppCommands,
44 },
45 Install {
47 #[arg(value_name = "TARGET")]
49 target: String,
50 #[arg(long)]
52 replace_managed: bool,
53 },
54 Uninstall {
56 #[arg(value_name = "TARGET")]
58 target: String,
59 #[arg(long)]
61 force: bool,
62 #[arg(long)]
64 purge: bool,
65 #[arg(long)]
67 dry_run: bool,
68 },
69 Completions {
71 #[command(subcommand)]
72 command: CompletionCommands,
73 },
74 List {
76 #[arg(long)]
78 available: bool,
79 #[arg(value_enum, requires = "available", value_name = "KIND")]
81 kind: Option<ResourceKind>,
82 },
83 Info {
85 #[arg(value_name = "TARGET")]
87 target: String,
88 #[arg(long)]
90 diff: bool,
91 #[arg(long)]
93 verbose: bool,
94 },
95 Preset {
97 #[command(subcommand)]
98 command: PresetCommands,
99 },
100 Update(UpdateCommand),
102 Upgrade(UpgradeCommand),
104 State {
106 #[command(subcommand)]
107 command: StateCommands,
108 },
109 #[command(name = "self")]
111 Self_ {
112 #[command(subcommand)]
113 command: SelfCommands,
114 },
115 Serve {
117 #[command(subcommand)]
118 command: ServeCommands,
119 },
120 Env {
122 #[command(subcommand)]
123 command: EnvCommands,
124 },
125 Sys {
127 #[command(subcommand)]
128 command: SysCommands,
129 },
130 Theme {
132 #[command(subcommand)]
133 command: ThemeCommands,
134 },
135 Ssh {
137 #[arg(long, value_enum, default_value_t = RemoteShell::Posix)]
140 remote_shell: RemoteShell,
141 #[arg(long = "with", value_name = "KEY[=ALIAS]")]
144 with: Vec<String>,
145 #[arg(long = "with-secret", value_name = "KEY[=ALIAS]")]
148 with_secret: Vec<String>,
149 #[arg(long)]
151 secret_broker: bool,
152 #[arg(
155 long = "secret-broker-policy",
156 value_name = "FILE",
157 requires = "secret_broker"
158 )]
159 secret_broker_policy: Vec<PathBuf>,
160 #[arg(
163 long = "allow-secret",
164 value_name = "KEY[=ALIAS]",
165 requires = "secret_broker"
166 )]
167 allow_secret: Vec<String>,
168 #[arg(long, requires = "secret_broker")]
171 trust_remote_session: bool,
172 #[arg(long, conflicts_with_all = ["secret_broker", "secret_broker_enroll"])]
175 secret_broker_inspect: bool,
176 #[arg(long, conflicts_with_all = ["secret_broker", "secret_broker_inspect"])]
179 secret_broker_enroll: bool,
180 #[arg(long, requires = "secret_broker_enroll")]
182 trust_remote_metadata: bool,
183 #[arg(
186 long = "update-policy",
187 value_name = "NAME",
188 requires = "secret_broker_enroll"
189 )]
190 secret_broker_update_policy: Option<String>,
191 #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
194 args: Vec<String>,
195 },
196 Local {
198 #[command(subcommand)]
199 command: LocalCommands,
200 },
201 Task {
203 #[command(subcommand)]
204 command: TaskCommands,
205 },
206 Run(TaskRunCommand),
208}
209
210#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
212pub enum RemoteShell {
213 Posix,
215 Windows,
217}
218
219#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
220pub enum ResourceKind {
221 App,
222 Shell,
223 Sys,
224}
225
226#[derive(Args, Debug)]
227pub struct InitCommand {
228 #[arg(long)]
230 pub yes: bool,
231}
232
233#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
234pub enum CompletionShell {
235 #[value(name = "bash")]
236 Bash,
237 #[value(name = "powershell")]
238 PowerShell,
239 #[value(name = "zsh")]
240 Zsh,
241}
242
243#[derive(Copy, Clone, Debug, Eq, PartialEq, Subcommand)]
244pub enum CompletionCommands {
245 Install,
247 Bash,
249 #[command(name = "powershell")]
251 PowerShell,
252 Zsh,
254}
255
256impl CompletionCommands {
257 pub fn generate(self) {
258 match self {
259 CompletionCommands::Bash => completion::generate_registration(CompletionShell::Bash),
260 CompletionCommands::PowerShell => {
261 completion::generate_registration(CompletionShell::PowerShell)
262 }
263 CompletionCommands::Zsh => completion::generate_registration(CompletionShell::Zsh),
264 CompletionCommands::Install => unreachable!("install is handled by the async runtime"),
265 }
266 }
267}
268
269impl CompletionShell {
270 pub fn from_command(command: &CompletionCommands) -> Option<Self> {
271 match command {
272 CompletionCommands::Bash => Some(CompletionShell::Bash),
273 CompletionCommands::PowerShell => Some(CompletionShell::PowerShell),
274 CompletionCommands::Zsh => Some(CompletionShell::Zsh),
275 CompletionCommands::Install => None,
276 }
277 }
278
279 pub fn as_str(self) -> &'static str {
280 match self {
281 CompletionShell::Bash => "bash",
282 CompletionShell::PowerShell => "powershell",
283 CompletionShell::Zsh => "zsh",
284 }
285 }
286}
287
288#[derive(Parser, Debug)]
289pub struct UpdateCommand {
290 #[arg(value_name = "TARGET")]
292 pub target: Option<String>,
293 #[arg(long)]
295 pub pull: bool,
296 #[arg(long)]
298 pub diff: bool,
299 #[arg(long, conflicts_with = "target")]
301 pub verbose: bool,
302 #[arg(long, conflicts_with = "target")]
304 pub refresh_release: bool,
305}
306
307#[derive(Parser, Debug)]
308pub struct UpgradeCommand {
309 #[arg(value_name = "TARGET")]
311 pub target: Option<String>,
312 #[arg(long)]
314 pub pull: bool,
315 #[arg(long)]
317 pub verbose: bool,
318 #[arg(long)]
320 pub prune_stale: bool,
321}