most_recently/
cli.rs

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        // A little ugly, but proves to be superior to argument groups
55        .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}