From e42567b25093907cfd939edc92ace94a5d59b398 Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Mon, 11 May 2026 19:56:10 +0800 Subject: Add `builds` feature and install completion scripts --- mingling_core/src/builds/comp.rs | 23 +++++++++++ mingling_core/src/comp.rs | 6 +++ mingling_core/src/comp/installation.rs | 72 ++++++++++++++++++++++++++++++++++ mingling_core/src/lib.rs | 2 + 4 files changed, 103 insertions(+) create mode 100644 mingling_core/src/comp/installation.rs (limited to 'mingling_core/src') diff --git a/mingling_core/src/builds/comp.rs b/mingling_core/src/builds/comp.rs index 228ef81..ad70cd2 100644 --- a/mingling_core/src/builds/comp.rs +++ b/mingling_core/src/builds/comp.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use just_template::tmpl_param; use crate::ShellFlag; @@ -84,6 +86,27 @@ pub fn build_comp_script_to( std::fs::write(&output_path, tmpl.to_string()) } +/// Generate a shell completion script and write it to a specified file path. +/// +/// This function takes a shell flag, a binary name, and an output file path, +/// selects the appropriate template, substitutes the binary name into the template, +/// and writes the resulting completion script directly to the specified file path. +/// +/// # Example +/// ``` +/// build_comp_script_to_file(&ShellFlag::Bash, "myapp", "target/completions/myapp_comp.sh").unwrap(); +/// ``` +pub fn build_comp_script_to_file( + shell_flag: &ShellFlag, + bin_name: &str, + output_path: impl Into, +) -> 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); + std::fs::write(output_path.into(), tmpl.to_string()) +} + fn get_tmpl(shell_flag: &ShellFlag) -> (&'static str, &'static str) { match shell_flag { ShellFlag::Bash => (TMPL_COMP_BASH, ".sh"), diff --git a/mingling_core/src/comp.rs b/mingling_core/src/comp.rs index 4fb17c7..fd26e1b 100644 --- a/mingling_core/src/comp.rs +++ b/mingling_core/src/comp.rs @@ -2,11 +2,17 @@ mod flags; mod shell_ctx; mod suggest; +#[cfg(feature = "builds")] +mod installation; + use std::collections::BTreeSet; use std::fmt::Display; #[doc(hidden)] pub use flags::*; +#[cfg(feature = "builds")] +#[doc(hidden)] +pub use installation::*; #[doc(hidden)] pub use shell_ctx::*; #[doc(hidden)] diff --git a/mingling_core/src/comp/installation.rs b/mingling_core/src/comp/installation.rs new file mode 100644 index 0000000..d3d31d6 --- /dev/null +++ b/mingling_core/src/comp/installation.rs @@ -0,0 +1,72 @@ +use crate::{build::build_comp_script_to_file, ShellFlag}; + +pub fn install_comp_script( + flag: ShellFlag, + bin_name: impl AsRef, +) -> Result<(), std::io::Error> { + match flag { + // ~/.local/share/bash-completion/completions/ + ShellFlag::Bash => { + let Some(data_dir) = dirs::data_dir() else { + return Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "Data directory not found!", + )); + }; + + let bin_name = bin_name.as_ref(); + + let comp_script_path = data_dir + .join("bash-completion") + .join("completions") + .join(format!("{}.sh", bin_name)); + + build_comp_script_to_file(&ShellFlag::Bash, bin_name, comp_script_path)?; + Ok(()) + } + + // ~/.zsh/completions/ + ShellFlag::Zsh => { + let Some(home_dir) = dirs::home_dir() else { + return Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "Home directory not found!", + )); + }; + + let bin_name = bin_name.as_ref(); + + let comp_script_path = home_dir + .join(".zsh") + .join("completions") + .join(format!("{}.zsh", bin_name)); + + build_comp_script_to_file(&ShellFlag::Zsh, bin_name, comp_script_path)?; + Ok(()) + } + + // ~/.config/fish/completions/ + ShellFlag::Fish => { + let Some(config_dir) = dirs::config_dir() else { + return Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "Config directory not found!", + )); + }; + + let bin_name = bin_name.as_ref(); + + let comp_script_path = config_dir + .join("fish") + .join("completions") + .join(format!("{}.fish", bin_name)); + + build_comp_script_to_file(&ShellFlag::Fish, bin_name, comp_script_path)?; + Ok(()) + } + _ => Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "unsupported shell flag", + )), + } +} diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs index 83edda8..e1c188f 100644 --- a/mingling_core/src/lib.rs +++ b/mingling_core/src/lib.rs @@ -51,10 +51,12 @@ pub mod setup { pub use crate::program::setup::*; } +#[cfg(feature = "builds")] #[doc(hidden)] pub mod builds; /// Provides build scripts for users +#[cfg(feature = "builds")] pub mod build { #[cfg(feature = "comp")] pub use crate::builds::comp::*; -- cgit