1use std::str::FromStr;
2
3/// Provide shell with hint on how to complete an argument.
4///
5/// See [Arg::value_hint][crate::Arg::value_hint] to set this on an argument.
6///
7/// See the `clap_complete` crate for completion script generation.
8///
9/// Overview of which hints are supported by which shell:
10///
11/// | Hint                   | zsh | fish[^1]|
12/// | ---------------------- | --- | ------- |
13/// | `AnyPath`              | Yes | Yes     |
14/// | `FilePath`             | Yes | Yes     |
15/// | `DirPath`              | Yes | Yes     |
16/// | `ExecutablePath`       | Yes | Partial |
17/// | `CommandName`          | Yes | Yes     |
18/// | `CommandString`        | Yes | Partial |
19/// | `CommandWithArguments` | Yes |         |
20/// | `Username`             | Yes | Yes     |
21/// | `Hostname`             | Yes | Yes     |
22/// | `Url`                  | Yes |         |
23/// | `EmailAddress`         | Yes |         |
24///
25/// [^1]: fish completions currently only support named arguments (e.g. -o or --opt), not
26///       positional arguments.
27#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
28#[non_exhaustive]
29pub enum ValueHint {
30    /// Default value if hint is not specified. Follows shell default behavior, which is usually
31    /// auto-completing filenames.
32    Unknown,
33    /// None of the hints below apply. Disables shell completion for this argument.
34    Other,
35    /// Any existing path.
36    AnyPath,
37    /// Path to a file.
38    FilePath,
39    /// Path to a directory.
40    DirPath,
41    /// Path to an executable file.
42    ExecutablePath,
43    /// Name of a command, without arguments. May be relative to PATH, or full path to executable.
44    CommandName,
45    /// A single string containing a command and its arguments.
46    CommandString,
47    /// Capture the remaining arguments as a command name and arguments for that command. This is
48    /// common when writing shell wrappers that execute anther command, for example `sudo` or `env`.
49    ///
50    /// This hint is special, the argument must be a positional argument and have
51    /// [`.num_args(1..)`] and Command must use [`Command::trailing_var_arg(true)`]. The result is that the
52    /// command line `my_app ls -la /` will be parsed as `["ls", "-la", "/"]` and clap won't try to
53    /// parse the `-la` argument itself.
54    ///
55    /// [`Command::trailing_var_arg(true)`]: crate::Command::trailing_var_arg
56    /// [`.num_args(1..)`]: crate::Arg::num_args()
57    CommandWithArguments,
58    /// Name of a local operating system user.
59    Username,
60    /// Host name of a computer.
61    /// Shells usually parse `/etc/hosts` and `.ssh/known_hosts` to complete hostnames.
62    Hostname,
63    /// Complete web address.
64    Url,
65    /// Email address.
66    EmailAddress,
67}
68
69impl Default for ValueHint {
70    fn default() -> Self {
71        ValueHint::Unknown
72    }
73}
74
75impl FromStr for ValueHint {
76    type Err = String;
77    fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
78        Ok(match &*s.to_ascii_lowercase() {
79            "unknown" => ValueHint::Unknown,
80            "other" => ValueHint::Other,
81            "anypath" => ValueHint::AnyPath,
82            "filepath" => ValueHint::FilePath,
83            "dirpath" => ValueHint::DirPath,
84            "executablepath" => ValueHint::ExecutablePath,
85            "commandname" => ValueHint::CommandName,
86            "commandstring" => ValueHint::CommandString,
87            "commandwitharguments" => ValueHint::CommandWithArguments,
88            "username" => ValueHint::Username,
89            "hostname" => ValueHint::Hostname,
90            "url" => ValueHint::Url,
91            "emailaddress" => ValueHint::EmailAddress,
92            _ => return Err(format!("unknown ValueHint: `{s}`")),
93        })
94    }
95}
96