aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src/builds/comp.rs
blob: 694af0cd9256c989a0189dac237fc3b399147c8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use just_template::tmpl_param;

use crate::ShellFlag;

const TMPL_COMP_BASH: &str = include_str!("../../tmpls/comps/bash.sh");
const TMPL_COMP_ZSH: &str = include_str!("../../tmpls/comps/zsh.zsh");
const TMPL_COMP_FISH: &str = include_str!("../../tmpls/comps/fish.fish");
const TMPL_COMP_PWSL: &str = include_str!("../../tmpls/comps/pwsl.ps1");

/// Generate shell completion scripts for the current binary.
/// On Windows, generates PowerShell completion.
/// On Linux, generates Zsh, Bash, and Fish completions.
/// Scripts are written to the `OUT_DIR` (or `target/` if `OUT_DIR` is not set).
///
/// # Example
/// ```
/// // Typically called from a build script (`build.rs`):
/// build_comp_scripts().unwrap();
/// // Or, to specify a custom binary name:
/// build_comp_scripts_with_bin_name("myapp").unwrap();
/// ```
pub fn build_comp_scripts() -> Result<(), std::io::Error> {
    let bin_name = env!("CARGO_PKG_NAME");
    build_comp_scripts_with_bin_name(bin_name)
}

/// Generate shell completion scripts for a given binary name.
/// On Windows, generates PowerShell completion.
/// On Linux, generates Zsh, Bash, and Fish completions.
/// Scripts are written to the `OUT_DIR` (or `target/` if `OUT_DIR` is not set).
///
/// # Example
/// ```
/// // Generate completion scripts for "myapp"
/// build_comp_scripts_with_bin_name("myapp").unwrap();
/// ```
pub fn build_comp_scripts_with_bin_name(name: &str) -> Result<(), std::io::Error> {
    #[cfg(target_os = "windows")]
    {
        build_comp_script(&ShellFlag::Powershell, name)?;
        Ok(())
    }

    #[cfg(target_os = "linux")]
    {
        build_comp_script(&ShellFlag::Zsh, name)?;
        build_comp_script(&ShellFlag::Bash, name)?;
        build_comp_script(&ShellFlag::Fish, name)?;
        Ok(())
    }

    #[cfg(target_os = "macos")]
    {
        build_comp_script(&ShellFlag::Zsh, name)?;
        build_comp_script(&ShellFlag::Bash, name)?;
        build_comp_script(&ShellFlag::Fish, name)?;
        Ok(())
    }
}

fn build_comp_script(shell_flag: &ShellFlag, bin_name: &str) -> Result<(), std::io::Error> {
    let (tmpl_str, ext) = get_tmpl(shell_flag);
    let mut tmpl = just_template::Template::from(tmpl_str);
    tmpl_param!(tmpl, bin_name = bin_name);
    let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
    let target_dir = out_dir.join("../../../").to_path_buf();
    let output_path = target_dir.join(format!("{}_comp{}", bin_name, ext));
    std::fs::create_dir_all(&target_dir)?;
    std::fs::write(&output_path, tmpl.to_string())
}

fn get_tmpl(shell_flag: &ShellFlag) -> (&'static str, &'static str) {
    match shell_flag {
        ShellFlag::Bash => (TMPL_COMP_BASH, ".sh"),
        ShellFlag::Zsh => (TMPL_COMP_ZSH, ".zsh"),
        ShellFlag::Fish => (TMPL_COMP_FISH, ".fish"),
        ShellFlag::Powershell => (TMPL_COMP_PWSL, ".ps1"),
        ShellFlag::Other(_) => (TMPL_COMP_BASH, ".sh"),
    }
}