1use std::path::PathBuf;
2
3use clap::{Args, Subcommand, ValueEnum};
4
5#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
6pub enum PresetTemplateKind {
7 App,
8 Shell,
9}
10
11#[derive(Args, Debug)]
12pub struct ExportCommand {
13 #[arg(value_name = "DIR")]
15 pub dir: Option<PathBuf>,
16 #[arg(long, short = 'f')]
18 pub force: bool,
19}
20
21#[derive(Args, Debug)]
22pub struct CopyCommand {
23 #[arg(value_name = "KIND/NAME", value_parser = parse_copy_target)]
25 pub target: String,
26 #[arg(long, short = 'f')]
28 pub force: bool,
29}
30
31pub(crate) fn parse_copy_target(value: &str) -> Result<String, String> {
32 if value.contains('\\') {
33 return Err(format!(
34 "invalid preset target '{value}': expected app/name, shell/name, or sys/name"
35 ));
36 }
37
38 let mut parts = value.split('/');
39 let kind = parts.next().unwrap_or_default();
40 let name = parts.next().unwrap_or_default();
41 if parts.next().is_some()
42 || !matches!(kind, "app" | "shell" | "sys")
43 || name.is_empty()
44 || matches!(name, "." | "..")
45 {
46 return Err(format!(
47 "invalid preset target '{value}': expected app/name, shell/name, or sys/name"
48 ));
49 }
50 Ok(value.to_string())
51}
52
53#[derive(Args, Debug)]
54pub struct LinkCommand {
55 #[arg(value_name = "PATH")]
57 pub path: PathBuf,
58 #[arg(long)]
60 pub create: bool,
61 #[arg(long)]
63 pub live: bool,
64}
65
66#[derive(Args, Debug)]
67pub struct OverlayLinkCommand {
68 #[arg(value_name = "PATH", conflicts_with = "git")]
70 pub path: Option<PathBuf>,
71 #[arg(long, value_name = "URL")]
74 pub git: Option<String>,
75 #[arg(long, value_name = "BRANCH", requires = "git")]
77 pub branch: Option<String>,
78 #[arg(long)]
80 pub create: bool,
81}
82
83#[derive(Subcommand, Debug)]
84pub enum OverlayCommands {
85 Link(OverlayLinkCommand),
87 Unlink,
89 Info,
91}
92
93#[derive(Subcommand, Debug)]
94pub enum PresetCommands {
95 New {
97 #[arg(value_enum)]
98 kind: PresetTemplateKind,
99 #[arg(long, short = 'f')]
101 force: bool,
102 },
103 Export(ExportCommand),
105 Copy(CopyCommand),
107 Link(LinkCommand),
109 Unlink,
111 Overlay {
113 #[command(subcommand)]
114 command: OverlayCommands,
115 },
116 Pull,
118}