summaryrefslogtreecommitdiffstats
path: root/vendor/clap_complete/src/generator/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/clap_complete/src/generator/mod.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/clap_complete/src/generator/mod.rs')
-rw-r--r--vendor/clap_complete/src/generator/mod.rs242
1 files changed, 242 insertions, 0 deletions
diff --git a/vendor/clap_complete/src/generator/mod.rs b/vendor/clap_complete/src/generator/mod.rs
new file mode 100644
index 000000000..2d00c281d
--- /dev/null
+++ b/vendor/clap_complete/src/generator/mod.rs
@@ -0,0 +1,242 @@
+//! Shell completion machinery
+
+pub mod utils;
+
+use std::ffi::OsString;
+use std::fs::File;
+use std::io::Error;
+use std::io::Write;
+use std::path::PathBuf;
+
+use clap::Command;
+
+/// Generator trait which can be used to write generators
+pub trait Generator {
+ /// Returns the file name that is created when this generator is called during compile time.
+ ///
+ /// # Panics
+ ///
+ /// May panic when called outside of the context of [`generate`] or [`generate_to`]
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::io::Write;
+ /// # use clap::Command;
+ /// use clap_complete::Generator;
+ ///
+ /// pub struct Fish;
+ ///
+ /// impl Generator for Fish {
+ /// # fn generate(&self, cmd: &Command, buf: &mut dyn Write) {}
+ /// fn file_name(&self, name: &str) -> String {
+ /// format!("{}.fish", name)
+ /// }
+ /// }
+ /// ```
+ fn file_name(&self, name: &str) -> String;
+
+ /// Generates output out of [`clap::Command`](Command).
+ ///
+ /// # Panics
+ ///
+ /// May panic when called outside of the context of [`generate`] or [`generate_to`]
+ ///
+ /// # Examples
+ ///
+ /// The following example generator displays the [`clap::Command`](Command)
+ /// as if it is printed using [`std::println`].
+ ///
+ /// ```
+ /// use std::{io::Write, fmt::write};
+ /// use clap::Command;
+ /// use clap_complete::Generator;
+ ///
+ /// pub struct ClapDebug;
+ ///
+ /// impl Generator for ClapDebug {
+ /// fn generate(&self, cmd: &Command, buf: &mut dyn Write) {
+ /// write!(buf, "{}", cmd).unwrap();
+ /// }
+ /// # fn file_name(&self, name: &str) -> String {
+ /// # name.into()
+ /// # }
+ /// }
+ /// ```
+ fn generate(&self, cmd: &Command, buf: &mut dyn Write);
+}
+
+/// Generate a completions file for a specified shell at compile-time.
+///
+/// **NOTE:** to generate the file at compile time you must use a `build.rs` "Build Script" or a
+/// [`cargo-xtask`](https://github.com/matklad/cargo-xtask)
+///
+/// # Examples
+///
+/// The following example generates a bash completion script via a `build.rs` script. In this
+/// simple example, we'll demo a very small application with only a single subcommand and two
+/// args. Real applications could be many multiple levels deep in subcommands, and have tens or
+/// potentially hundreds of arguments.
+///
+/// First, it helps if we separate out our `Command` definition into a separate file. Whether you
+/// do this as a function, or bare Command definition is a matter of personal preference.
+///
+/// ```
+/// // src/cli.rs
+///
+/// use clap::{Command, Arg};
+///
+/// pub fn build_cli() -> Command<'static> {
+/// Command::new("compl")
+/// .about("Tests completions")
+/// .arg(Arg::new("file")
+/// .help("some input file"))
+/// .subcommand(Command::new("test")
+/// .about("tests things")
+/// .arg(Arg::new("case")
+/// .long("case")
+/// .takes_value(true)
+/// .help("the case to test")))
+/// }
+/// ```
+///
+/// In our regular code, we can simply call this `build_cli()` function, then call
+/// `get_matches()`, or any of the other normal methods directly after. For example:
+///
+/// ```ignore
+/// // src/main.rs
+///
+/// mod cli;
+///
+/// fn main() {
+/// let _m = cli::build_cli().get_matches();
+///
+/// // normal logic continues...
+/// }
+/// ```
+///
+/// Next, we set up our `Cargo.toml` to use a `build.rs` build script.
+///
+/// ```toml
+/// # Cargo.toml
+/// build = "build.rs"
+///
+/// [dependencies]
+/// clap = "*"
+///
+/// [build-dependencies]
+/// clap = "*"
+/// clap_complete = "*"
+/// ```
+///
+/// Next, we place a `build.rs` in our project root.
+///
+/// ```ignore
+/// use clap_complete::{generate_to, shells::Bash};
+/// use std::env;
+/// use std::io::Error;
+///
+/// include!("src/cli.rs");
+///
+/// fn main() -> Result<(), Error> {
+/// let outdir = match env::var_os("OUT_DIR") {
+/// None => return Ok(()),
+/// Some(outdir) => outdir,
+/// };
+///
+/// let mut cmd = build_cli();
+/// let path = generate_to(
+/// Bash,
+/// &mut cmd, // We need to specify what generator to use
+/// "myapp", // We need to specify the bin name manually
+/// outdir, // We need to specify where to write to
+/// )?;
+///
+/// println!("cargo:warning=completion file is generated: {:?}", path);
+///
+/// Ok(())
+/// }
+/// ```
+///
+/// Now, once we compile there will be a `{bin_name}.bash` file in the directory.
+/// Assuming we compiled with debug mode, it would be somewhere similar to
+/// `<project>/target/debug/build/myapp-<hash>/out/myapp.bash`.
+///
+/// **NOTE:** Please look at the individual [shells][crate::shells]
+/// to see the name of the files generated.
+pub fn generate_to<G, S, T>(
+ gen: G,
+ cmd: &mut clap::Command,
+ bin_name: S,
+ out_dir: T,
+) -> Result<PathBuf, Error>
+where
+ G: Generator,
+ S: Into<String>,
+ T: Into<OsString>,
+{
+ cmd.set_bin_name(bin_name);
+
+ let out_dir = PathBuf::from(out_dir.into());
+ let file_name = gen.file_name(cmd.get_bin_name().unwrap());
+
+ let path = out_dir.join(file_name);
+ let mut file = File::create(&path)?;
+
+ _generate::<G, S>(gen, cmd, &mut file);
+ Ok(path)
+}
+
+/// Generate a completions file for a specified shell at runtime.
+///
+/// Until `cargo install` can install extra files like a completion script, this may be
+/// used e.g. in a command that outputs the contents of the completion script, to be
+/// redirected into a file by the user.
+///
+/// # Examples
+///
+/// Assuming a separate `cli.rs` like the [example above](generate_to()),
+/// we can let users generate a completion script using a command:
+///
+/// ```ignore
+/// // src/main.rs
+///
+/// mod cli;
+/// use std::io;
+/// use clap_complete::{generate, shells::Bash};
+///
+/// fn main() {
+/// let matches = cli::build_cli().get_matches();
+///
+/// if matches.is_present("generate-bash-completions") {
+/// generate(Bash, &mut cli::build_cli(), "myapp", &mut io::stdout());
+/// }
+///
+/// // normal logic continues...
+/// }
+///
+/// ```
+///
+/// Usage:
+///
+/// ```shell
+/// $ myapp generate-bash-completions > /usr/share/bash-completion/completions/myapp.bash
+/// ```
+pub fn generate<G, S>(gen: G, cmd: &mut clap::Command, bin_name: S, buf: &mut dyn Write)
+where
+ G: Generator,
+ S: Into<String>,
+{
+ cmd.set_bin_name(bin_name);
+ _generate::<G, S>(gen, cmd, buf)
+}
+
+fn _generate<G, S>(gen: G, cmd: &mut clap::Command, buf: &mut dyn Write)
+where
+ G: Generator,
+ S: Into<String>,
+{
+ cmd._build_all();
+
+ gen.generate(cmd, buf)
+}