1use crate::Method;
2use clap::{
3 crate_description, crate_name, crate_version, App, AppSettings, Arg, Shell, SubCommand,
4};
5use itertools::Itertools;
6use strum::{IntoEnumIterator, VariantNames};
7use tracing::instrument;
8
9pub mod args {
10 pub const COMPLETIONS: &str = "completions";
11 pub const SHELL: &str = "shell";
12 pub const PATHS: &str = "paths";
13}
14
15impl Method {
16 fn helptext(&self) -> &'static str {
17 match self {
18 Method::Accessed => "Sort by access on this file or directory",
19 Method::Created => "Sort by creation on this volume",
20 Method::Modified => "Sort by modification of the file or directory",
21 }
22 }
23}
24
25#[instrument]
26pub fn app<'a, 'b>() -> App<'a, 'b> {
27 use args::*;
28 App::new(crate_name!())
29 .version(crate_version!())
30 .about(crate_description!())
31 .setting(AppSettings::ColorAuto)
32 .setting(AppSettings::SubcommandRequiredElseHelp)
33 .usage(
34 format!(
35 "{} <{}> [PATH...]>\n OR:\n {} completions <{}>",
36 crate_name!(),
37 Method::VARIANTS.iter().format(" | "),
38 crate_name!(),
39 Shell::variants().iter().format(" | ")
40 )
41 .into_static_str(),
42 )
43 .subcommand(
44 SubCommand::with_name(COMPLETIONS)
45 .about("Print out a shell completion script for a given shell")
46 .arg(
47 Arg::with_name(SHELL)
48 .takes_value(true)
49 .value_name("shell")
50 .possible_values(Shell::variants().as_ref())
51 .required(true),
52 ),
53 )
54 .subcommands(Method::iter().map(|method| {
56 SubCommand::with_name(method.as_ref())
57 .about(method.helptext())
58 .display_order(0)
59 .arg(
60 Arg::with_name(PATHS)
61 .help("Candidate paths. May be files or folders. If none supplied, will be read from stdin (one path per line)")
62 .multiple(true)
63 )
64 }))
65}
66
67trait IntoStaticStr {
68 fn into_static_str(self) -> &'static str;
69}
70
71impl IntoStaticStr for String {
72 fn into_static_str(self) -> &'static str {
73 Box::leak(self.into_boxed_str())
74 }
75}