1use getopts::Options;
2use std::env;
3use std::io::IsTerminal;
4use std::path::PathBuf;
5use std::process;
6
7#[derive(Debug, Default)]
9pub struct Args {
10 pub config: Option<PathBuf>,
12 pub server: Option<String>,
14 pub auth: Option<String>,
16 pub url: Option<String>,
18 pub remote: Option<String>,
20 pub files: Vec<String>,
22 pub oneshot: bool,
24 pub expire: Option<String>,
26 pub prettify: bool,
28 pub print_server_version: bool,
30 pub list_files: bool,
32 pub delete: bool,
34 pub filename: Option<String>,
36}
37
38impl Args {
39 pub fn parse() -> Self {
41 let mut opts = Options::new();
42 opts.optflag("h", "help", "prints help information");
43 opts.optflag("v", "version", "prints version information");
44 opts.optflag("V", "server-version", "retrieves the server version");
45 opts.optflag("l", "list", "lists files on the server");
46 opts.optflag("d", "delete", "delete files from server");
47 opts.optflag("o", "oneshot", "generates one shot links");
48 opts.optflag("p", "pretty", "prettifies the output");
49 opts.optopt("c", "config", "sets the configuration file", "CONFIG");
50 opts.optopt(
51 "s",
52 "server",
53 "sets the address of the rustypaste server",
54 "SERVER",
55 );
56 opts.optopt(
57 "a",
58 "auth",
59 "sets the authentication or delete token",
60 "TOKEN",
61 );
62 opts.optopt("u", "url", "sets the URL to shorten", "URL");
63 opts.optopt("r", "remote", "sets the remote URL for uploading", "URL");
64 opts.optopt(
65 "e",
66 "expire",
67 "sets the expiration time for the link",
68 "TIME",
69 );
70 opts.optopt("n", "filename", "sets and overrides the filename", "NAME");
71
72 let env_args: Vec<String> = env::args().collect();
73 let matches = match opts.parse(&env_args[1..]) {
74 Ok(m) => m,
75 Err(e) => {
76 eprintln!("Argument error: `{e}`");
77 process::exit(1);
78 }
79 };
80
81 if matches.opt_present("h")
82 || (matches.free.is_empty()
83 && !matches.opt_present("u")
84 && !matches.opt_present("r")
85 && !matches.opt_present("V")
86 && !matches.opt_present("l")
87 && !matches.opt_present("d")
88 && !matches.opt_present("v")
89 && std::io::stdin().is_terminal())
90 {
91 let usage = format!(
92 "\n{} {} \u{2014} {}.\
93 \n\u{221F} written by {}\
94 \n\u{221F} licensed under MIT <{}>\
95 \n\nUsage:\n {} [options] <file(s)>",
96 env!("CARGO_PKG_NAME"),
97 env!("CARGO_PKG_VERSION"),
98 env!("CARGO_PKG_DESCRIPTION"),
99 env!("CARGO_PKG_AUTHORS"),
100 env!("CARGO_PKG_REPOSITORY"),
101 "rpaste",
102 );
103 println!("{}", opts.usage(&usage));
104 process::exit(0)
105 }
106
107 if matches.opt_present("v") {
108 println!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
109 process::exit(0)
110 }
111
112 Args {
113 config: env::var("RPASTE_CONFIG")
114 .ok()
115 .or_else(|| matches.opt_str("c"))
116 .map(PathBuf::from),
117 server: matches.opt_str("s"),
118 auth: matches.opt_str("a"),
119 url: matches.opt_str("u"),
120 remote: matches.opt_str("r"),
121 oneshot: matches.opt_present("o"),
122 expire: matches.opt_str("e"),
123 prettify: matches.opt_present("p"),
124 print_server_version: matches.opt_present("V"),
125 list_files: matches.opt_present("l"),
126 delete: matches.opt_present("d"),
127 filename: matches.opt_str("n"),
128 files: matches.free,
129 }
130 }
131}