From c1d9da0e7367c3053378af38b7ee43f6f03ef8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20M=2E=20Bezerra?= Date: Thu, 17 Feb 2022 02:57:52 -0300 Subject: [PATCH] chore: refactor and improve docs of build.rs --- build.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/build.rs b/build.rs index bc8e13d..c0eb9eb 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,39 @@ -use std::{env, fs::create_dir_all}; +/// This build script checks for env vars to build ouch with shell completions. +/// +/// # How to generate shell completions: +/// +/// Set `OUCH_COMPLETIONS_FOLDER` to the name of the destination folder: +/// +/// ```sh +/// OUCH_COMPLETIONS_FOLDER=my-folder cargo build +/// ``` +/// +/// All completion files will be generated inside of the folder "my-folder". +/// +/// If the folder does not exist, it will be created. +/// +/// We recommend you naming this folder "completions" for the sake of consistency. +/// +/// ```sh +/// OUCH_COMPLETIONS_FOLDER=completions cargo build +/// ``` +/// +/// # Retrocompatibility +/// +/// The old method that still works so it does not break older packages. +/// +/// Using `GEN_COMPLETIONS=1` still works for those packages who need it, +/// however. +/// +/// ```sh +/// GEN_COMPLETIONS=1 cargo build +/// ``` +/// +/// Will generate completions to a cargo target default folder, for example: +/// - `target/debug/build/ouch-195b34a8adca6ec3/out/completions` +/// +/// The _"195b34a8adca6ec3"_ part is a hash that might change between runs. +use std::{env, ffi::OsStr, fs::create_dir_all, path::Path}; use clap::{ArgEnum, IntoApp}; use clap_complete::{generate_to, Shell}; @@ -8,19 +43,33 @@ include!("src/opts.rs"); fn main() { println!("cargo:rerun-if-env-changed=GEN_COMPLETIONS"); - if env::var_os("GEN_COMPLETIONS") != Some("1".into()) { - return; - } + if let Some(completions_output_directory) = detect_completions_output_directory() { + create_dir_all(&completions_output_directory).expect("Could not create shell completions output folder."); + let app = &mut Opts::into_app(); - let out = &env::var_os("OUCH_COMPLETIONS_DIR") - .map(|path| PathBuf::from(&path)) - .or_else(|| env::var_os("OUT_DIR").map(|path| PathBuf::from(&path)).map(|path| path.join("completions"))) - .unwrap(); - - create_dir_all(out).unwrap(); - let app = &mut Opts::into_app(); - - for shell in Shell::value_variants() { - generate_to(*shell, app, "ouch", out).unwrap(); + for shell in Shell::value_variants() { + generate_to(*shell, app, "ouch", &completions_output_directory) + .unwrap_or_else(|err| panic!("Failed to generate shell completions for {}: {}.", shell, err)); + } } } + +/// Decide whether or not to generate completions, and the destination. +/// +/// Note that `OUCH_COMPLETIONS_FOLDER` is checked before `GEN_COMPLETIONS`. +fn detect_completions_output_directory() -> Option { + // Get directory from var + if let Some(dir) = env::var_os("OUCH_COMPLETIONS_FOLDER") { + return Some(dir.into()); + }; + + // If set, directory goes inside of cargo's `target/` + let gen_completions = env::var_os("GEN_COMPLETIONS").map(|var| &var == OsStr::new("1")).unwrap_or(false); + if gen_completions { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let dir = Path::new(&out_dir).join("completions"); + return Some(dir); + } + + return None; +}