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/Cargo.lock | 77 ++++++++++++++++++++++++++++++++++ mingling_core/Cargo.toml | 3 ++ 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 + 6 files changed, 183 insertions(+) create mode 100644 mingling_core/src/comp/installation.rs (limited to 'mingling_core') diff --git a/mingling_core/Cargo.lock b/mingling_core/Cargo.lock index 9c2f9aa..358fa67 100644 --- a/mingling_core/Cargo.lock +++ b/mingling_core/Cargo.lock @@ -70,12 +70,39 @@ dependencies = [ "serde_core", ] +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + [[package]] name = "env_filter" version = "1.0.1" @@ -105,6 +132,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hashbrown" version = "0.17.0" @@ -172,6 +210,21 @@ dependencies = [ "just_fmt", ] +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "libc", +] + [[package]] name = "log" version = "0.4.29" @@ -188,6 +241,7 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" name = "mingling_core" version = "0.1.8" dependencies = [ + "dirs", "env_logger", "just_fmt", "just_template", @@ -213,6 +267,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "portable-atomic" version = "1.13.1" @@ -246,6 +306,17 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.12.3" @@ -454,6 +525,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "windows-link" version = "0.2.1" diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml index 4a8d593..f3ba9a2 100644 --- a/mingling_core/Cargo.toml +++ b/mingling_core/Cargo.toml @@ -10,6 +10,7 @@ repository = "https://github.com/catilgrass/mingling" nightly = [] default = [] async = [] +builds = ["dep:dirs"] dispatch_tree = [] general_renderer = [ @@ -31,6 +32,8 @@ thiserror = "2" once_cell = "1.21.4" +dirs = { version = "6", optional = true } + # comp just_template = { version = "0.1.3", optional = true } 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