xtask/completions/
mod.rs
1use clap::Parser;
5use std::io::IsTerminal;
6use std::io::Write;
7
8#[derive(Clone, clap::ValueEnum)]
9enum Shell {
10 Zsh,
11}
12
13#[derive(Parser)]
15pub struct Completions {
16 shell: Shell,
18}
19
20impl Completions {
21 pub fn run(self) -> anyhow::Result<()> {
22 match self.shell {
23 Shell::Zsh => {
24 std::io::stdout().write_all(include_bytes!("./complete.zsh"))?;
25 if std::io::stdout().is_terminal() {
26 eprintln!(
27 "{}",
28 ZSH_HELP.replace(
29 "<<CMD_PATH>>",
30 &std::env::current_exe()?.display().to_string()
31 )
32 );
33 }
34 }
35 }
36
37 Ok(())
38 }
39}
40
41const ZSH_HELP: &str = r#"
42# To enable `cargo xtask` completions, there are two steps:
43#
44# 1. Use `rustup completions cargo` to set up `cargo` completions.
45# 2. Copy this script into your `.zshrc`
46#
47# NOTE: This is _not_ your typical `zsh` completion!
48#
49# No need to `compdef` anything. Just make sure that the `_cargo-xtask` function
50# is in-scope, and that `rustup completions cargo` infrastructure redirect
51# `cargo xtask` completions to that function.
52"#;
53
54pub(crate) struct XtaskCompleteFactory {
55 pub ctx: crate::XtaskCtx,
56}
57
58impl clap_dyn_complete::CustomCompleterFactory for XtaskCompleteFactory {
59 type CustomCompleter = XtaskComplete;
60 async fn build(&self, _ctx: &clap_dyn_complete::RootCtx<'_>) -> Self::CustomCompleter {
61 XtaskComplete {
62 ctx: self.ctx.clone(),
63 }
64 }
65}
66
67pub(crate) struct XtaskComplete {
68 ctx: crate::XtaskCtx,
69}
70
71impl clap_dyn_complete::CustomCompleter for XtaskComplete {
72 async fn complete(
73 &self,
74 _ctx: &clap_dyn_complete::RootCtx<'_>,
75 command_path: &[&str],
76 arg_id: &str,
77 ) -> Vec<String> {
78 match (command_path, arg_id) {
79 (["xtask", "fuzz", cmd], "target")
80 if matches!(
81 *cmd,
82 "run"
83 | "build"
84 | "clean"
85 | "fmt"
86 | "cmin"
87 | "tmin"
88 | "coverage"
89 | "onefuzz-allowlist"
90 ) =>
91 {
92 crate::tasks::cli_completions::fuzz::complete_fuzzer_targets(&self.ctx)
93 }
94 _ => Vec::new(),
95 }
96 }
97}