1//! How to use value hints and generate shell completions.
2//!
3//! Usage with zsh:
4//! ```sh
5//! cargo run --example value_hints_derive -- --generate=zsh > /usr/local/share/zsh/site-functions/_value_hints_derive
6//! compinit
7//! ./target/debug/examples/value_hints_derive --<TAB>
8//! ```
9//! fish:
10//! ```sh
11//! cargo run --example value_hints_derive -- --generate=fish > value_hints_derive.fish
12//! . ./value_hints_derive.fish
13//! ./target/debug/examples/value_hints_derive --<TAB>
14//! ```
15use clap::{Args, Command, CommandFactory, Parser, Subcommand, ValueHint};
16use clap_complete::{generate, Generator, Shell};
17use std::ffi::OsString;
18use std::io;
19use std::path::PathBuf;
20
21#[derive(Parser, Debug, PartialEq)]
22#[command(name = "completion-derive")]
23struct Opt {
24    // If provided, outputs the completion file for given shell
25    #[arg(long = "generate", value_enum)]
26    generator: Option<Shell>,
27    #[command(subcommand)]
28    command: Option<Commands>,
29}
30
31#[derive(Subcommand, Debug, PartialEq)]
32enum Commands {
33    #[command(visible_alias = "hint")]
34    ValueHint(ValueHintOpt),
35}
36
37#[derive(Args, Debug, PartialEq)]
38struct ValueHintOpt {
39    // Showcasing all possible ValueHints:
40    #[arg(long, value_hint = ValueHint::Unknown)]
41    unknown: Option<String>,
42    #[arg(long, value_hint = ValueHint::Other)]
43    other: Option<String>,
44    #[arg(short, long, value_hint = ValueHint::AnyPath)]
45    path: Option<PathBuf>,
46    #[arg(short, long, value_hint = ValueHint::FilePath)]
47    file: Option<PathBuf>,
48    #[arg(short, long, value_hint = ValueHint::DirPath)]
49    dir: Option<PathBuf>,
50    #[arg(short, long, value_hint = ValueHint::ExecutablePath)]
51    exe: Option<PathBuf>,
52    #[arg(long, value_hint = ValueHint::CommandName)]
53    cmd_name: Option<OsString>,
54    #[arg(short, long, value_hint = ValueHint::CommandString)]
55    cmd: Option<String>,
56    // Command::trailing_var_ar is required to use ValueHint::CommandWithArguments
57    #[arg(trailing_var_arg = true, value_hint = ValueHint::CommandWithArguments)]
58    command_with_args: Vec<String>,
59    #[arg(short, long, value_hint = ValueHint::Username)]
60    user: Option<String>,
61    #[arg(long, value_hint = ValueHint::Hostname)]
62    host: Option<String>,
63    #[arg(long, value_hint = ValueHint::Url)]
64    url: Option<String>,
65    #[arg(long, value_hint = ValueHint::EmailAddress)]
66    email: Option<String>,
67}
68
69fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
70    generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
71}
72
73fn main() {
74    let opt = Opt::parse();
75
76    if let Some(generator) = opt.generator {
77        let mut cmd = Opt::command();
78        eprintln!("Generating completion file for {generator:?}...");
79        print_completions(generator, &mut cmd);
80    } else {
81        println!("{opt:#?}");
82    }
83}
84