Skip to main content

pretty_please/
cli.rs

1use clap::{Args, Parser, Subcommand, ValueEnum};
2
3use crate::shell::Shell;
4
5#[derive(Debug, Parser)]
6#[command(
7    name = "pls",
8    bin_name = "pls",
9    version,
10    about = "The polite sudo.",
11    long_about = None,
12    override_usage = "pls [ARGS...]\n       pls init <SHELL>\n       pls completions <SHELL>",
13    after_help = "Examples:\n  pls chmod 600 secrets.txt\n  pls init zsh\n  pls completions fish",
14    disable_help_subcommand = true,
15    propagate_version = true
16)]
17pub struct Cli {
18    /// Raw command captured by a shell hook. Hidden because it is only meant for shell integrations.
19    #[arg(long, hide = true, env = "PLS_HISTORY_COMMAND")]
20    pub history_command: Option<String>,
21
22    #[command(subcommand)]
23    pub command: Option<Command>,
24}
25
26#[derive(Debug, Subcommand)]
27pub enum Command {
28    /// Print the shell hook for your shell.
29    Init(InitArgs),
30    /// Generate completion scripts for your shell.
31    Completions(CompletionArgs),
32    #[command(external_subcommand)]
33    Exec(Vec<String>),
34}
35
36#[derive(Debug, Args)]
37pub struct InitArgs {
38    pub shell: Shell,
39}
40
41#[derive(Debug, Args)]
42pub struct CompletionArgs {
43    pub shell: Shell,
44}
45
46#[derive(Clone, Debug, Eq, PartialEq)]
47pub enum CommandInput {
48    History(String),
49    Explicit(Vec<String>),
50}
51
52impl Cli {
53    pub fn into_command_input(self) -> CliAction {
54        match self.command {
55            Some(Command::Init(args)) => CliAction::Init(args.shell),
56            Some(Command::Completions(args)) => CliAction::Completions(args.shell),
57            Some(Command::Exec(args)) => CliAction::Exec(CommandInput::Explicit(args)),
58            None => match self.history_command {
59                Some(command) => CliAction::Exec(CommandInput::History(command)),
60                None => CliAction::Exec(CommandInput::Explicit(Vec::new())),
61            },
62        }
63    }
64}
65
66#[derive(Clone, Debug, Eq, PartialEq)]
67pub enum CliAction {
68    Init(Shell),
69    Completions(Shell),
70    Exec(CommandInput),
71}
72
73impl ValueEnum for Shell {
74    fn value_variants<'a>() -> &'a [Self] {
75        &[Shell::Bash, Shell::Zsh, Shell::Fish, Shell::Pwsh, Shell::Nu]
76    }
77
78    fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
79        Some(match self {
80            Shell::Bash => clap::builder::PossibleValue::new("bash"),
81            Shell::Zsh => clap::builder::PossibleValue::new("zsh"),
82            Shell::Fish => clap::builder::PossibleValue::new("fish"),
83            Shell::Pwsh => clap::builder::PossibleValue::new("pwsh").alias("powershell"),
84            Shell::Nu => clap::builder::PossibleValue::new("nu").alias("nushell"),
85        })
86    }
87}