aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-17 19:21:52 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-17 19:21:52 +0800
commit89bf57f33a9f0f5a96fc50e272c83d926fa35c4a (patch)
treecc5a72e850bdd9215b60dc1655f162e22ee97d12
parent40bb7ffd6954184fac718c8f99c9cdc3e054e4eb (diff)
refactor!: replace build.rs with compile-time macro build steps
BREAKING CHANGE: Replace the `build`/`builds` feature system with compile-time macro-driven generation. `gen_program!()` now automatically invokes `build_comp!()` and `build_pathf!()` when the `comp`/`pathf` features are enabled, eliminating the need for `build.rs` and `[build-dependencies]` blocks. This removes the `build` feature, the `mingling::build` module, and all related build-time API functions. Completion scripts are now written to `{target_directory}/mingling/` instead of `target/release/`. The `mingling_cli` uses `build_comp!("mling")` for its custom binary name.
-rw-r--r--.run/src/bin/install-mling.ps12
-rwxr-xr-x.run/src/bin/install-mling.sh2
-rw-r--r--.run/src/verify.rs23
-rw-r--r--CHANGELOG.md61
-rw-r--r--Cargo.lock95
-rw-r--r--Cargo.toml1
-rw-r--r--GETTING-STARTED.md10
-rw-r--r--docs/_zh_CN/pages/advanced/1-completion.md19
-rw-r--r--docs/_zh_CN/pages/other/features.md64
-rw-r--r--docs/dev/pages/abouts/code-verify-system.md7
-rw-r--r--docs/example-pages/examples.json11
-rw-r--r--docs/pages/advanced/1-completion.md19
-rw-r--r--docs/pages/other/features.md64
-rw-r--r--examples/example-combine-pathf-dispatch-tree/Cargo.lock92
-rw-r--r--examples/example-combine-pathf-dispatch-tree/Cargo.toml13
-rw-r--r--examples/example-combine-pathf-dispatch-tree/build.rs3
-rw-r--r--examples/example-combine-pathf-dispatch-tree/page.toml4
-rw-r--r--examples/example-combine-pathf-dispatch-tree/src/main.rs8
-rw-r--r--examples/example-combine-pathf-metadata/Cargo.lock92
-rw-r--r--examples/example-combine-pathf-metadata/Cargo.toml9
-rw-r--r--examples/example-combine-pathf-metadata/build.rs3
-rw-r--r--examples/example-combine-pathf-metadata/page.toml4
-rw-r--r--examples/example-completion/Cargo.lock102
-rw-r--r--examples/example-completion/Cargo.toml12
-rw-r--r--examples/example-completion/build.rs14
-rw-r--r--examples/example-completion/page.toml2
-rw-r--r--examples/example-completion/src/main.rs27
-rw-r--r--examples/example-enum-tag/Cargo.lock102
-rw-r--r--examples/example-pathfinder/Cargo.lock92
-rw-r--r--examples/example-pathfinder/Cargo.toml11
-rw-r--r--examples/example-pathfinder/build.rs10
-rw-r--r--examples/example-pathfinder/page.toml4
-rw-r--r--mingling/Cargo.toml7
-rw-r--r--mingling/src/example_docs.rs82
-rw-r--r--mingling/src/features.rs44
-rw-r--r--mingling/src/lib.rs4
-rw-r--r--mingling_cli/Cargo.lock31
-rw-r--r--mingling_cli/Cargo.toml9
-rw-r--r--mingling_cli/build.rs8
-rw-r--r--mingling_cli/src/lib.rs4
-rw-r--r--mingling_cli/src/pkg_mgr/cmd_install.rs21
-rw-r--r--mingling_core/Cargo.toml9
-rw-r--r--mingling_core/src/build.rs28
-rw-r--r--mingling_core/src/build/pathf.rs98
-rw-r--r--mingling_core/src/docs/build.md57
-rw-r--r--mingling_core/src/lib.rs7
-rw-r--r--mingling_core/tests/test-all/Cargo.lock99
-rw-r--r--mingling_core/tests/test-all/Cargo.toml1
-rw-r--r--mingling_core/tests/test-comp/Cargo.lock102
-rw-r--r--mingling_core/tests/test-comp/Cargo.toml2
-rw-r--r--mingling_macros/Cargo.toml10
-rw-r--r--mingling_macros/src/build.rs56
-rw-r--r--mingling_macros/src/build/comp.rs (renamed from mingling_core/src/build/comp.rs)113
-rw-r--r--mingling_macros/src/build/pathf.rs19
-rw-r--r--mingling_macros/src/func/gen_program.rs65
-rw-r--r--mingling_macros/src/lib.rs47
-rw-r--r--mingling_macros/tmpls/comps/bash.sh (renamed from mingling_core/tmpls/comps/bash.sh)0
-rw-r--r--mingling_macros/tmpls/comps/fish.fish (renamed from mingling_core/tmpls/comps/fish.fish)0
-rw-r--r--mingling_macros/tmpls/comps/pwsh.ps1 (renamed from mingling_core/tmpls/comps/pwsh.ps1)0
-rw-r--r--mingling_macros/tmpls/comps/zsh.zsh (renamed from mingling_core/tmpls/comps/zsh.zsh)0
-rw-r--r--mingling_pathf/Cargo.toml1
-rw-r--r--mingling_pathf/src/error.rs6
-rw-r--r--mingling_pathf/src/lib.rs2
-rw-r--r--mingling_pathf/src/type_mapping_builder.rs76
-rw-r--r--mingling_pathf/test/Cargo.lock138
65 files changed, 1357 insertions, 771 deletions
diff --git a/.run/src/bin/install-mling.ps1 b/.run/src/bin/install-mling.ps1
index 2bc28ee..2b55a09 100644
--- a/.run/src/bin/install-mling.ps1
+++ b/.run/src/bin/install-mling.ps1
@@ -6,5 +6,5 @@ New-Item -ItemType Directory -Force -Path .temp/mling/bin, .temp/mling/scripts |
Copy-Item .temp/target/release/mling.exe .temp/mling/bin/
Copy-Item .temp/target/release/mingling-cli.exe .temp/mling/bin/
-Copy-Item .temp/target/release/mling_comp.ps1 .temp/mling/scripts/mling_comp.ps1
+Copy-Item .temp/target/mingling/mling_comp.ps1 .temp/mling/scripts/mling_comp.ps1
Copy-Item mingling_cli/scripts/load_mling.ps1 .temp/mling/
diff --git a/.run/src/bin/install-mling.sh b/.run/src/bin/install-mling.sh
index 139e221..e8cfa18 100755
--- a/.run/src/bin/install-mling.sh
+++ b/.run/src/bin/install-mling.sh
@@ -10,7 +10,7 @@ cp .temp/target/release/mling .temp/mling/bin/
cp .temp/target/release/mingling-cli .temp/mling/bin/
for comp in zsh sh fish; do
- cp ".temp/target/release/mling_comp.$comp" ".temp/mling/scripts/mling_comp.$comp"
+ cp ".temp/target/mingling/mling_comp.$comp" ".temp/mling/scripts/mling_comp.$comp"
done
cp mingling_cli/scripts/load_mling.zsh .temp/mling/
cp mingling_cli/scripts/load_mling.sh .temp/mling/
diff --git a/.run/src/verify.rs b/.run/src/verify.rs
index 0a4b354..b79bb73 100644
--- a/.run/src/verify.rs
+++ b/.run/src/verify.rs
@@ -215,16 +215,15 @@ pub fn generate_cargo_toml(block: &CodeBlock, package_name: &str, manifest_path:
)
};
- // Build-time blocks: add `builds` by default, merge with explicit features
+ // Build-time blocks: mirror the declared features into [build-dependencies]
+ // so that build.rs can use the same feature set as the crate itself.
let build_deps_section = if block.is_build_time {
- let mut all_feats = vec!["builds".to_string()];
- for f in &block.features {
- if f != "builds" {
- all_feats.push(f.clone());
- }
- }
- let feats_str: Vec<String> = all_feats.iter().map(|f| format!("\"{f}\"")).collect();
- let build_feats = format!("features = [{}]", feats_str.join(", "));
+ let feats_str: Vec<String> = block.features.iter().map(|f| format!("\"{f}\"")).collect();
+ let build_feats = if feats_str.is_empty() {
+ String::new()
+ } else {
+ format!("features = [{}]", feats_str.join(", "))
+ };
format!(
"\n[build-dependencies]\nmingling = {{ path = \"{mingling_path}\", {build_feats} }}\n"
)
@@ -292,14 +291,10 @@ pub fn generate_main_rs(block: &CodeBlock) -> String {
/// Generate build.rs for a build-time block
///
-/// Default: `use mingling::builds::*;`, code wrapped in `fn main() { }`.
+/// Default: code wrapped in `fn main() { }`.
pub fn generate_build_rs(block: &CodeBlock) -> String {
let mut output = String::from("#![allow(dead_code)]\n#![allow(unused)]\n");
- if !block.code.contains("use mingling::build::*;") {
- output.push_str("#[allow(unused_imports)]\nuse mingling::build::*;\n\n");
- }
-
if block.has_main {
output.push_str(&block.code);
} else {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 969a3e2..7566451 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -395,6 +395,67 @@ None
_All internal call sites, examples, docs, and tests updated_ (e.g., `mingling_cli` completion handlers, `example-completion`, `example-enum-tag`, `GETTING-STARTED.md`, `docs/pages/advanced/1-completion.md`, `docs/_zh_CN/pages/advanced/1-completion.md`, and `mingling/src/example_docs.rs`).
+7. **[`build`]** **[BREAKING]** Replaced the `build` / `builds` build-time feature system with compile-time macro-driven build steps. The `build` feature, `builds` feature, `build_advanced` preset, `build_full` preset, `mingling::build` module, and the entire `build.rs`-based workflow have been removed. Build steps (completion script generation and pathf type-mapping analysis) now run automatically as a side effect of `gen_program!()` expansion via new `build_comp!()` / `build_pathf!()` macros.
+
+ ### What changed
+
+ Previously, build-time functionality was enabled through the `build` feature (and preset groups `build_advanced` / `build_full`, plus the deprecated `builds` alias). Users needed a `[build-dependencies.mingling]` entry in `Cargo.toml` and a hand-written `build.rs` that called `mingling::build::build_comp_scripts(...)` (for completion scripts) and `mingling::build::analyze_and_build_type_mapping()` (for pathf). These functions were gated behind the `build` + `comp` / `build` + `pathf` feature combinations and read `OUT_DIR` to locate the output directory.
+
+ Now, the build steps are integrated directly into macro expansion:
+
+ - **`gen_program!()` automatically invokes `build_comp!()`** (when the `comp` feature is enabled) and **`build_pathf!()`** (when the `pathf` feature is enabled) at the very start of its expansion. These macros run the build logic as a compile-time side effect and expand to nothing.
+ - **`build_comp!()`** is a proc macro (re-exported as `mingling::macros::build_comp`) that generates completion scripts into `{target_directory}/mingling/`. It accepts an optional string literal for the binary name; without an argument it defaults to `CARGO_PKG_NAME`. On failure it emits a `compile_error!`.
+ - **`build_pathf!()`** is a proc macro (re-exported as `mingling::macros::build_pathf`) that runs the pathf type-mapping analysis, writing mapping files into `{target_directory}/mingling/{CARGO_PKG_NAME}/`. On failure it emits a `compile_error!`.
+ - **No `build.rs` is required anymore.** Build logic runs from proc-macro expansion, so no `[build-dependencies.mingling]` entry, no `build` feature, and no `build.rs` file are needed.
+
+ **Removed API:**
+
+ - **`build` feature** — Removed from `mingling/Cargo.toml` and `mingling_core/Cargo.toml`. The `build = ["mingling_core/build"]` feature mapping and the `mingling_core/build` feature have been deleted.
+ - **`builds` feature** — Removed (deprecated alias, mapped to `mingling_core/build`).
+ - **`build_advanced` / `build_full` preset features** — Removed from `mingling/Cargo.toml` feature groups.
+ - **`mingling::build` module** — Removed entirely from `mingling_core`:
+ - `mingling_core/src/build.rs` and the `mingling_core/src/build/` directory deleted.
+ - `mingling_core/src/docs/build.md` deleted.
+ - `mingling_core/src/lib.rs` no longer gates `pub mod build` behind the `build` feature.
+ - **Build functions** — Removed: `build_comp_scripts`, `build_comp_script`, `build_comp_script_to`, `build_comp_script_to_file`, `analyze_and_build_type_mapping`, `analyze_and_build_type_mapping_for`, `analyze`.
+ - **`MINGLING_BUILD` / `MINGLING_BUILDS` / `MINGLING_BUILD_ADVANCED` / `MINGLING_BUILD_FULL` feature constants** — Removed from `mingling/src/features.rs`.
+ - **`mingling_core` dependencies** — Removed `just_template` (comp) and `mingling_pathf` (pathf) from `mingling_core/Cargo.toml`; these moved to `mingling_macros` as optional dependencies gated behind the `comp` / `pathf` features.
+ - **`mingling_macros` feature wiring** — Changed `comp = []` to `comp = ["dep:just_template", "dep:mingling_pathf"]` and `pathf = []` to `pathf = ["dep:mingling_pathf"]`; `mingling` crate's `pathf` feature no longer forwards to `mingling_core/pathf`.
+ - **`mingling::build::pathf` error re-exports** — `mingling_core::error` no longer re-exports `mingling_pathf::error::*`.
+
+ **New internal infrastructure:**
+
+ - **`mingling_macros/src/build.rs`** — New module hosting `comp_build_impl` (behind `comp`) and `pathf_build_impl` (behind `pathf`), which parse the macro input and delegate to the build logic, converting errors into `compile_error!` token streams.
+ - **`mingling_macros/src/build/comp.rs`** — Moved from `mingling_core/src/build/comp.rs` (with the shell templates, which moved from `mingling_core/tmpls/comps/` to `mingling_macros/tmpls/comps/`). Contains a private copy of `ShellFlag` (since the macros crate cannot depend on `mingling_core`); the template files are identical. Scripts are written to `{target_directory}/mingling/` resolved via the new `mingling_pathf::build_output_dir()`.
+ - **`mingling_macros/src/build/pathf.rs`** — New module providing `output_dir()` (`{target_directory}/mingling/{CARGO_PKG_NAME}`) and `analyze_and_build_type_mapping()` delegating to `mingling_pathf`.
+ - **`mingling_pathf::build_output_dir()`** — New public function resolving `{target_directory}/mingling/` via `cargo metadata` (from `CARGO_MANIFEST_DIR`).
+ - **`mingling_pathf::target_directory()`** — New public function running `cargo metadata` (`no_deps`) from a crate directory and returning the target directory.
+ - **`MinglingPathfinderError::CargoMetadata(String)`** — New error variant added to `mingling_pathf`'s error enum.
+ - **`cargo_metadata` dependency** — Added to `mingling_pathf` (workspace, version `0.23.1`) and to the root workspace `Cargo.toml`.
+
+ **`gen_program!()` changes** (`mingling_macros/src/func/gen_program.rs`):
+ - Emits `::mingling::macros::build_comp!();` at the start of the expansion when `comp` is enabled (and `::mingling::macros::build_pathf!();` when `pathf` is enabled).
+ - The pathf `use`-statement loading now runs the analysis inline via `crate::build::pathf::analyze_and_build_type_mapping()` (so the mapping exists when the `use` statements are read) and loads `type_using.rs` from `crate::build::pathf::output_dir()`.
+ - The `load_pathf_uses` function now reads from `{target_directory}/mingling/{CARGO_PKG_NAME}/type_using.rs` instead of `{OUT_DIR}/{CARGO_PKG_NAME}/type_using.rs`.
+ - The empty-uses `compile_error!` hint was reworded: it no longer mentions `build.rs` or the `build` feature; it now says the analyzer found no types and suggests ensuring the `pathf` feature is enabled and `gen_program!()` is called in a crate with a `src/` directory.
+ - `mingling_pathf::analyze_and_build_type_mapping` no longer emits `cargo:rerun-if-changed=src/` / `cargo:rerun-if-env-changed=...` directives (there is no build script for Cargo to track).
+
+ **Migration guide:**
+
+ - **Delete `build.rs`** (and the `[build-dependencies]` block in `Cargo.toml`). Completion scripts are generated automatically when the `comp` feature is enabled; pathf analysis and any `[build-dependencies.mingling]`). If a feature list references only these, delete the whole section.
+ - **If your binary name differs from the crate name**, call `build_comp!()` manually with the binary name:
+ ```rust
+ // Features: ["comp"]
+ mingling::macros::build_comp!("mybin");
+ ```
+ This can be placed at module scope (e.g., in `src/lib.rs` or `src/main.rs`) alongside `gen_program!()`.
+ - **Remove any `mingling::build::...` imports.**
+ - **Example/build artifacts**: The completion scripts are now written to `{target_directory}/mingling/` rather than `{target_directory}/release/` or the `OUT_DIR`-derived path. Any scripts that copied them from the release directory must be updated (e.g., `.run/src/bin/install-mling.sh` now copies from `.temp/target/mingling/mling_comp.$comp`, and `.run/src/bin/install-mling.ps1` from `.temp/target/mingling/mling_comp.ps1`).
+ - **`mingling_cli`**: `build.rs` no longer calls `analyze_and_build_type_mapping` / `build_comp_scripts`; `mingling_cli/src/lib.rs` now invokes `mingling::macros::build_comp!("mling")` to generate scripts for the `mling` binary. `StateInstallBuild` / `StateInstallCopy` gained a `mingling_dir` field (`{target}/mingling/`) and the install copy step reads completion scripts from `{target}/mingling/` instead of `{target}/release/`.
+ - **Tests/examples**: Removed the `builds` feature from `mingling_core/tests/test-all`, `mingling_core/tests/test-comp`, and all pathf/completion examples, and deleted the corresponding `build.rs` files and `[build-dependencies]` blocks.
+
+ _Behavioral note:_ the runtime behavior of programs is unchanged — completion scripts and pathf type mappings are still produced, just from compile-time macro expansion instead of a separate `build.rs` step. The output directory changed from an `OUT_DIR`-derived path (effectively `{target}/<profile>` style) to a dedicated `{target_directory}/mingling/` directory resolved via `cargo metadata`, which is deterministic regardless of build profile.
+
---
## Contents
diff --git a/Cargo.lock b/Cargo.lock
index b5116a3..fbcfb31 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -75,7 +75,7 @@ version = "0.2.0"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -94,6 +94,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -193,7 +226,7 @@ checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -226,7 +259,7 @@ checksum = "1471eb68722ecefeb71debdde2859e8725341f171d3f42b3a98a0862ad19416e"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -264,7 +297,7 @@ checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
"toml 0.8.23",
]
@@ -290,10 +323,8 @@ version = "0.5.0"
dependencies = [
"env_logger",
"just_fmt 0.2.0",
- "just_template",
"log",
"might_be_async",
- "mingling_pathf",
"ron",
"serde",
"serde_json",
@@ -307,18 +338,21 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
+ "just_template",
+ "mingling_pathf",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
name = "mingling_pathf"
version = "0.5.0"
dependencies = [
+ "cargo_metadata",
"just_fmt 0.2.0",
"proc-macro2",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -471,6 +505,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -497,7 +541,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -582,6 +626,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "temp-env"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -591,6 +646,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "tokio"
version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -615,7 +690,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 6b0e6b3..595053b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,7 @@ arg-picker-macros = { path = "arg_picker_macros", default-features = false }
just_fmt = "0.2.0"
just_template = "0.2.0"
+cargo_metadata = "0.23.1"
might_be_async = "0.1.0"
diff --git a/GETTING-STARTED.md b/GETTING-STARTED.md
index 020e098..e4a706a 100644
--- a/GETTING-STARTED.md
+++ b/GETTING-STARTED.md
@@ -234,13 +234,9 @@ fn main() {
}
```
-In your `build.rs`, generate the shell scripts:
-
-```rust
-// BUILD TIME
-// Features: ["comp", "build"]
-mingling::build::build_comp_scripts(env!("CARGO_PKG_NAME")).unwrap();
-```
+The completion scripts are generated automatically: with the `comp` feature enabled,
+`gen_program!()` invokes `build_comp!()` at compile time and writes the shell scripts
+(named after `CARGO_PKG_NAME`) into `target/mingling/`.
For enum-based completions, use `suggest_enum!`:
diff --git a/docs/_zh_CN/pages/advanced/1-completion.md b/docs/_zh_CN/pages/advanced/1-completion.md
index d70786e..290fab0 100644
--- a/docs/_zh_CN/pages/advanced/1-completion.md
+++ b/docs/_zh_CN/pages/advanced/1-completion.md
@@ -11,13 +11,6 @@ Mingling 的补全是**完全动态**的——没有静态的补全文件,而
# Cargo.toml
[dependencies.mingling]
features = ["comp"]
-
-[build-dependencies.mingling]
-features = [
- "comp",
- # 启用 `build` 特性以提供构建期支持
- "build"
-]
```
## 工作原理
@@ -72,8 +65,18 @@ suggest! {
## 生成补全脚本
-在 `build.rs` 中调用 `build_comp_scripts` 生成补全脚本(需要 `builds` + `comp` 特性)。
+开启 `comp` 特性后,`gen_program!()` 会在编译期自动调用 `build_comp!()`,生成以 `CARGO_PKG_NAME` 命名的补全脚本到 `target/mingling/`。
+
+如果你的二进制名与 crate 名不同,可以手动调用 `build_comp!()` 并指定二进制名:
+```rust
+// Features: ["comp"]
+@@@use mingling::macros::build_comp;
+@@@fn example() {
+build_comp!("mybin");
+@@@}
+```
+
详见 [example-completion](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-completion)。
<p align="center" style="font-size: 0.85em; color: gray;">
diff --git a/docs/_zh_CN/pages/other/features.md b/docs/_zh_CN/pages/other/features.md
index 5fa7c86..f8753e5 100644
--- a/docs/_zh_CN/pages/other/features.md
+++ b/docs/_zh_CN/pages/other/features.md
@@ -25,42 +25,6 @@ Mingling 提供了一系列**预设特性组**,方便用户按需组合启用
**定位:** 完整模式,启用 Mingling 的全部核心功能。在 `advanced` 的基础上额外包含 clap 集成、完整的结构化渲染器(含所有序列化格式)以及实验性的路径分析器,适合大型、功能全面的命令行应用。
-## `build_advanced`
-
-**启用特性:** `build`、`comp`
-
-**定位:** 构建期增强配置,用于在项目构建时生成补全脚本等构建辅助材料(`comp` 特性提供补全脚本生成能力)。
-
-> [!NOTE]
->
-> 此特性组为**构建依赖**专用,需配合 `advanced` 特性使用。请在 `Cargo.toml` 的 `[build-dependencies]` 中启用:
-
-```toml
-[dependencies.mingling]
-features = ["advanced"]
-
-[build-dependencies.mingling]
-features = ["build_advanced"]
-```
-
-## `build_full`
-
-**启用特性:** `build`、`comp`、`pathf`、`dispatch_tree`
-
-**定位:** 完整的构建期配置,在 `build_advanced` 的基础上额外包含路径分析器(`pathf`)以自动解析类型模块路径,适合结构复杂、需要自动化构建期分析的项目。
-
-> [!NOTE]
->
-> 此特性组为**构建依赖**专用,需配合 `full` 特性使用。请在 `Cargo.toml` 的 `[build-dependencies]` 中启用:
-
-```toml
-[dependencies.mingling]
-features = ["full"]
-
-[build-dependencies.mingling]
-features = ["build_full"]
-```
-
# 特性详解
## 特性 `all_serde_fmt`
@@ -91,23 +55,6 @@ async fn handle_state_foo(foo: StateFoo) -> Next {
详见 [示例](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-async-support)
-## 特性 `builds`
-
-**介绍:**
-
-启用部分需要在 `build.rs` 使用的脚本,目前包含:
-
-1. `comp` 特性下的补全脚本生成:
-
-```rust
-// BUILD TIME
-// Features: ["builds", "comp"]
-use mingling::build::build_comp_scripts;
-
-// 为 `myprogram` 生成补全脚本
-build_comp_scripts("myprogram").unwrap();
-```
-
## 特性 `clap`
**介绍:**
@@ -318,17 +265,10 @@ pub struct ErrorNotDir(PathBuf);
# Cargo.toml
[dependencies.mingling]
features = ["pathf"]
-
-[build-dependencies.mingling]
-features = ["builds", "pathf"]
-```
-
-```rust
-// BUILD TIME
-// Features: ["pathf"]
-analyze_and_build_type_mapping().unwrap();
```
+开启 `pathf` 特性后,`gen_program!()` 会在编译期自动调用 `build_pathf!()` 执行类型映射分析。
+
详见 [示例](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-pathfinder)
## 特性 `picker`
diff --git a/docs/dev/pages/abouts/code-verify-system.md b/docs/dev/pages/abouts/code-verify-system.md
index 929b337..20da045 100644
--- a/docs/dev/pages/abouts/code-verify-system.md
+++ b/docs/dev/pages/abouts/code-verify-system.md
@@ -125,8 +125,11 @@ Marks the block as a `build.rs` script instead of `src/main.rs`. The block code
```rust
// BUILD TIME
-// Features: ["builds", "pathf"]
-analyze_and_build_type_mapping().unwrap();
+// Dependencies:
+// serde = "1"
+fn main() {
+ // build-time work, e.g. writing generated sources into OUT_DIR
+}
```
### `// Features: [...]`
diff --git a/docs/example-pages/examples.json b/docs/example-pages/examples.json
index 38f73cd..dd5b65b 100644
--- a/docs/example-pages/examples.json
+++ b/docs/example-pages/examples.json
@@ -69,13 +69,11 @@
"tags": [
"pathf",
"dispatch_tree",
- "extras",
- "build.rs"
+ "extras"
],
"files": [
"src/main.rs",
"src/sub/mod.rs",
- "build.rs",
"Cargo.toml"
]
},
@@ -87,13 +85,11 @@
"desc": "Combines the `pathf` feature with entry metadata. The metadata `DataType` and the entry `BindType` are defined inside a submodule, and `pathf` resolves them for `gen_program!()` at build time.\n",
"tags": [
"pathf",
- "metadata",
- "build.rs"
+ "metadata"
],
"files": [
"src/main.rs",
"src/sub/mod.rs",
- "build.rs",
"Cargo.toml"
]
},
@@ -124,7 +120,6 @@
],
"files": [
"src/main.rs",
- "build.rs",
"Cargo.toml"
]
},
@@ -294,12 +289,10 @@
"desc": "Demonstrates the `pathf` feature, which automatically resolves type module paths at build time. Types can be defined in submodules without explicit `use` in the main module.\n",
"tags": [
"pathf",
- "build.rs",
"architecture"
],
"files": [
"Cargo.toml",
- "build.rs",
"src/main.rs",
"src/sub/mod.rs"
]
diff --git a/docs/pages/advanced/1-completion.md b/docs/pages/advanced/1-completion.md
index 20bd59e..ca1f621 100644
--- a/docs/pages/advanced/1-completion.md
+++ b/docs/pages/advanced/1-completion.md
@@ -11,13 +11,6 @@ Mingling's completion is **fully dynamic** — no static completion files, sugge
# Cargo.toml
[dependencies.mingling]
features = ["comp"]
-
-[build-dependencies.mingling]
-features = [
- "comp",
- # Enable `build` for build-time support
- "build"
-]
```
## How it works
@@ -72,8 +65,18 @@ suggest! {
## Generate completion scripts
-Call `build_comp_scripts` in `build.rs` to generate completion scripts (requires `builds` + `comp` features).
+When the `comp` feature is enabled, `gen_program!()` automatically invokes `build_comp!()` at compile time, which generates the completion scripts (named after `CARGO_PKG_NAME`) into `target/mingling/`.
+
+If your binary name differs from the crate name, call `build_comp!()` manually with the binary name:
+```rust
+// Features: ["comp"]
+@@@use mingling::macros::build_comp;
+@@@fn example() {
+build_comp!("mybin");
+@@@}
+```
+
See [example-completion](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-completion).
<p align="center" style="font-size: 0.85em; color: gray;">
diff --git a/docs/pages/other/features.md b/docs/pages/other/features.md
index b2c0ea5..858e556 100644
--- a/docs/pages/other/features.md
+++ b/docs/pages/other/features.md
@@ -25,42 +25,6 @@ Mingling provides a set of **preset feature groups** that make it easy to enable
**Positioning:** Full mode, enables all of Mingling's core functionality. In addition to `advanced`, it includes clap integration, the full structural renderer (with all serialization formats), and the experimental path analyzer. Suitable for large, feature-complete command-line applications.
-## `build_advanced`
-
-**Enables features:** `build`, `comp`
-
-**Positioning:** Build-time enhanced configuration, used to generate build helpers such as completion scripts at build time (the `comp` feature provides completion script generation).
-
-> [!NOTE]
->
-> This feature group is intended for **build dependencies** only and must be used alongside the `advanced` feature. Enable it in the `[build-dependencies]` section of `Cargo.toml`:
-
-```toml
-[dependencies.mingling]
-features = ["advanced"]
-
-[build-dependencies.mingling]
-features = ["build_advanced"]
-```
-
-## `build_full`
-
-**Enables features:** `build`, `comp`, `pathf`, `dispatch_tree`
-
-**Positioning:** Full build-time configuration, extends `build_advanced` with the path analyzer (`pathf`) to automatically resolve type module paths, suitable for projects with complex structures that require automated build-time analysis.
-
-> [!NOTE]
->
-> This feature group is intended for **build dependencies** only and must be used alongside the `full` feature. Enable it in the `[build-dependencies]` section of `Cargo.toml`:
-
-```toml
-[dependencies.mingling]
-features = ["full"]
-
-[build-dependencies.mingling]
-features = ["build_full"]
-```
-
# Feature Details
## Feature `all_serde_fmt`
@@ -91,23 +55,6 @@ async fn handle_state_foo(foo: StateFoo) -> Next {
See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-async-support)
-## Feature `builds`
-
-**Description:**
-
-Enables scripts needed for use in `build.rs`, currently including:
-
-1. Completion script generation under the `comp` feature:
-
-```rust
-// BUILD TIME
-// Features: ["builds", "comp"]
-use mingling::build::build_comp_scripts;
-
-// Generate completion scripts for `myprogram`
-build_comp_scripts("myprogram").unwrap();
-```
-
## Feature `clap`
**Description:**
@@ -318,17 +265,10 @@ When enabled, types can be defined in any submodule, and `gen_program!()` can au
# Cargo.toml
[dependencies.mingling]
features = ["pathf"]
-
-[build-dependencies.mingling]
-features = ["builds", "pathf"]
-```
-
-```rust
-// BUILD TIME
-// Features: ["pathf"]
-analyze_and_build_type_mapping().unwrap();
```
+With the `pathf` feature enabled, `gen_program!()` automatically invokes `build_pathf!()` at compile time to run the type mapping analysis.
+
See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-pathfinder)
## Feature `picker`
diff --git a/examples/example-combine-pathf-dispatch-tree/Cargo.lock b/examples/example-combine-pathf-dispatch-tree/Cargo.lock
index 9fdbf4f..3603db8 100644
--- a/examples/example-combine-pathf-dispatch-tree/Cargo.lock
+++ b/examples/example-combine-pathf-dispatch-tree/Cargo.lock
@@ -3,6 +3,39 @@
version = 4
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -32,6 +65,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -69,7 +108,6 @@ version = "0.5.0"
dependencies = [
"just_fmt",
"might_be_async",
- "mingling_pathf",
]
[[package]]
@@ -77,6 +115,7 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.118",
@@ -86,6 +125,7 @@ dependencies = [
name = "mingling_pathf"
version = "0.5.0"
dependencies = [
+ "cargo_metadata",
"just_fmt",
"proc-macro2",
"syn 2.0.118",
@@ -110,12 +150,23 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -139,6 +190,19 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -170,6 +234,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -224,3 +308,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/examples/example-combine-pathf-dispatch-tree/Cargo.toml b/examples/example-combine-pathf-dispatch-tree/Cargo.toml
index 2c866f7..6fcfc48 100644
--- a/examples/example-combine-pathf-dispatch-tree/Cargo.toml
+++ b/examples/example-combine-pathf-dispatch-tree/Cargo.toml
@@ -10,17 +10,4 @@ mingling = { path = "../../mingling", features = [
"pathf",
] }
-[build-dependencies]
-mingling = { path = "../../mingling", features = [
- "builds",
-
- # --------- IMPORTANT ---------
- # To use pathf under dispatch_tree
- # **must** enable the `dispatch_tree`
- # feature in build dependencies
- "dispatch_tree",
- "pathf",
- # --------- IMPORTANT ---------
-] }
-
[workspace]
diff --git a/examples/example-combine-pathf-dispatch-tree/build.rs b/examples/example-combine-pathf-dispatch-tree/build.rs
deleted file mode 100644
index d909431..0000000
--- a/examples/example-combine-pathf-dispatch-tree/build.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
- mingling::build::analyze_and_build_type_mapping().unwrap();
-}
diff --git a/examples/example-combine-pathf-dispatch-tree/page.toml b/examples/example-combine-pathf-dispatch-tree/page.toml
index 88557af..b4e64e9 100644
--- a/examples/example-combine-pathf-dispatch-tree/page.toml
+++ b/examples/example-combine-pathf-dispatch-tree/page.toml
@@ -6,5 +6,5 @@ category = "advanced"
desc = """
Demonstrates combining the `pathf` and `dispatch_tree` features. Types are defined in submodules and automatically resolved. Requires `dispatch_tree` in both `[dependencies]` and `[build-dependencies]`.
"""
-tags = ["pathf", "dispatch_tree", "extras", "build.rs"]
-files = ["src/main.rs", "src/sub/mod.rs", "build.rs", "Cargo.toml"]
+tags = ["pathf", "dispatch_tree", "extras"]
+files = ["src/main.rs", "src/sub/mod.rs", "Cargo.toml"]
diff --git a/examples/example-combine-pathf-dispatch-tree/src/main.rs b/examples/example-combine-pathf-dispatch-tree/src/main.rs
index 75888ee..a93e7ae 100644
--- a/examples/example-combine-pathf-dispatch-tree/src/main.rs
+++ b/examples/example-combine-pathf-dispatch-tree/src/main.rs
@@ -4,11 +4,13 @@
//! > Types are defined in a submodule (`sub`), and `gen_program!()` resolves
//! > them automatically via pathf without explicit `use` imports.
//! >
-//! > **Important**: `dispatch_tree` must be enabled in BOTH `[dependencies]`
-//! > AND `[build-dependencies]` so that pathf's builder can detect
-//! > `__internal_dispatcher_*` types needed by the dispatch tree.
+//! > **Important**: `dispatch_tree` must be enabled so that pathf's builder can
+//! > detect `__internal_dispatcher_*` types needed by the dispatch tree.
//! >
//! > Also requires `extras` for the implicit `dispatcher!("hello")` form.
+//! >
+//! > With the `pathf` feature, `gen_program!()` automatically invokes
+//! > `build_pathf!()` at compile time — no `build.rs` needed.
//!
//! Run:
//! ```bash
diff --git a/examples/example-combine-pathf-metadata/Cargo.lock b/examples/example-combine-pathf-metadata/Cargo.lock
index 0e1782e..304810b 100644
--- a/examples/example-combine-pathf-metadata/Cargo.lock
+++ b/examples/example-combine-pathf-metadata/Cargo.lock
@@ -3,6 +3,39 @@
version = 4
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -32,6 +65,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -69,7 +108,6 @@ version = "0.5.0"
dependencies = [
"just_fmt",
"might_be_async",
- "mingling_pathf",
]
[[package]]
@@ -77,6 +115,7 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.119",
@@ -86,6 +125,7 @@ dependencies = [
name = "mingling_pathf"
version = "0.5.0"
dependencies = [
+ "cargo_metadata",
"just_fmt",
"proc-macro2",
"syn 2.0.119",
@@ -110,12 +150,23 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -139,6 +190,19 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -170,6 +234,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -224,3 +308,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/examples/example-combine-pathf-metadata/Cargo.toml b/examples/example-combine-pathf-metadata/Cargo.toml
index fd14c74..26ed74a 100644
--- a/examples/example-combine-pathf-metadata/Cargo.toml
+++ b/examples/example-combine-pathf-metadata/Cargo.toml
@@ -12,13 +12,4 @@ features = [
"pathf",
]
-[build-dependencies.mingling]
-path = "../../mingling"
-features = [
- # Enable the `build` feature for build-time support
- "build",
- # `pathf` must also be enabled in build-dependencies
- "pathf",
-]
-
[workspace]
diff --git a/examples/example-combine-pathf-metadata/build.rs b/examples/example-combine-pathf-metadata/build.rs
deleted file mode 100644
index d909431..0000000
--- a/examples/example-combine-pathf-metadata/build.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
- mingling::build::analyze_and_build_type_mapping().unwrap();
-}
diff --git a/examples/example-combine-pathf-metadata/page.toml b/examples/example-combine-pathf-metadata/page.toml
index 76c1700..7e9b48c 100644
--- a/examples/example-combine-pathf-metadata/page.toml
+++ b/examples/example-combine-pathf-metadata/page.toml
@@ -6,5 +6,5 @@ category = "advanced"
desc = """
Combines the `pathf` feature with entry metadata. The metadata `DataType` and the entry `BindType` are defined inside a submodule, and `pathf` resolves them for `gen_program!()` at build time.
"""
-tags = ["pathf", "metadata", "build.rs"]
-files = ["src/main.rs", "src/sub/mod.rs", "build.rs", "Cargo.toml"]
+tags = ["pathf", "metadata"]
+files = ["src/main.rs", "src/sub/mod.rs", "Cargo.toml"]
diff --git a/examples/example-completion/Cargo.lock b/examples/example-completion/Cargo.lock
index d4b2f33..d98661c 100644
--- a/examples/example-completion/Cargo.lock
+++ b/examples/example-completion/Cargo.lock
@@ -20,6 +20,39 @@ dependencies = [
]
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -49,6 +82,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -113,7 +152,6 @@ name = "mingling_core"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
- "just_template",
"might_be_async",
]
@@ -122,12 +160,24 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
+ "just_template",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.118",
]
[[package]]
+name = "mingling_pathf"
+version = "0.5.0"
+dependencies = [
+ "cargo_metadata",
+ "just_fmt 0.2.0",
+ "proc-macro2",
+ "syn 2.0.118",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -146,12 +196,23 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -175,6 +236,19 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -206,6 +280,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -260,3 +354,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/examples/example-completion/Cargo.toml b/examples/example-completion/Cargo.toml
index 9884f4e..59b6902 100644
--- a/examples/example-completion/Cargo.toml
+++ b/examples/example-completion/Cargo.toml
@@ -12,16 +12,4 @@ features = [
"picker",
]
-[build-dependencies.mingling]
-path = "../../mingling"
-
-features = [
- # Enable `comp` features
- "comp",
-
- # If you want to build completion scripts,
- # enable `build` features
- "build",
-]
-
[workspace]
diff --git a/examples/example-completion/build.rs b/examples/example-completion/build.rs
deleted file mode 100644
index e1ffba1..0000000
--- a/examples/example-completion/build.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-fn main() {
- build_scripts();
-}
-
-/// Generate completion scripts
-fn build_scripts() {
- // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name.
- // If your binary name differs from the crate name, specify it explicitly.
- mingling::build::build_comp_scripts(
- // Your binary name:
- env!("CARGO_PKG_NAME"),
- )
- .unwrap();
-}
diff --git a/examples/example-completion/page.toml b/examples/example-completion/page.toml
index adccd86..4336513 100644
--- a/examples/example-completion/page.toml
+++ b/examples/example-completion/page.toml
@@ -7,4 +7,4 @@ desc = """
Demonstrates how to implement dynamic shell completion with `#[completion]` and generate scripts for bash, zsh, fish, and pwsh.
"""
tags = ["comp"]
-files = ["src/main.rs", "build.rs", "Cargo.toml"]
+files = ["src/main.rs", "Cargo.toml"]
diff --git a/examples/example-completion/src/main.rs b/examples/example-completion/src/main.rs
index 389cf74..385387b 100644
--- a/examples/example-completion/src/main.rs
+++ b/examples/example-completion/src/main.rs
@@ -7,30 +7,15 @@
//! To make your completions work, you need to generate a completion script using Mingling's tools
//!
//! 1. Enable features
-//! You need to enable the `build` and `comp` features for `mingling` in `[build-dependencies]`
+//! Enable the `comp` feature for `mingling` in `[dependencies]`
//!
-//! 2. Write `build.rs`
-//! Write the following in `build.rs`
-//!
-//! ```rust,ignore
-//! fn main() {
-//! build_scripts();
-//! }
-//!
-//! /// Generate completion scripts
-//! fn build_scripts() {
-//! // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name.
-//! // If your binary name differs from the crate name, specify it explicitly.
-//! mingling::build::build_comp_scripts(
-//! // Your binary name:
-//! env!("CARGO_PKG_NAME"),
-//! )
-//! .unwrap();
-//! }
-//! ```
+//! 2. Generate completion scripts
+//! When the `comp` feature is enabled, `gen_program!()` automatically invokes
+//! `build_comp!()` at compile time, which generates the completion scripts
+//! (named after `CARGO_PKG_NAME`) into `target/mingling/`.
//!
//! 3. Verify
-//! Build your project with `cargo build --release`. The completion scripts will be generated in `target/release/`
+//! Build your project with `cargo build`. The completion scripts will be generated in `target/mingling/`
//!
//! Execute the script or have it be automatically sourced by your Shell
//!
diff --git a/examples/example-enum-tag/Cargo.lock b/examples/example-enum-tag/Cargo.lock
index 492d708..9b97008 100644
--- a/examples/example-enum-tag/Cargo.lock
+++ b/examples/example-enum-tag/Cargo.lock
@@ -20,6 +20,39 @@ dependencies = [
]
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -49,6 +82,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -113,7 +152,6 @@ name = "mingling_core"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
- "just_template",
"might_be_async",
]
@@ -122,12 +160,24 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
+ "just_template",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.118",
]
[[package]]
+name = "mingling_pathf"
+version = "0.5.0"
+dependencies = [
+ "cargo_metadata",
+ "just_fmt 0.2.0",
+ "proc-macro2",
+ "syn 2.0.118",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -146,12 +196,23 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -175,6 +236,19 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -206,6 +280,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -260,3 +354,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/examples/example-pathfinder/Cargo.lock b/examples/example-pathfinder/Cargo.lock
index b93e443..155e762 100644
--- a/examples/example-pathfinder/Cargo.lock
+++ b/examples/example-pathfinder/Cargo.lock
@@ -3,6 +3,39 @@
version = 4
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -32,6 +65,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -69,7 +108,6 @@ version = "0.5.0"
dependencies = [
"just_fmt",
"might_be_async",
- "mingling_pathf",
]
[[package]]
@@ -77,6 +115,7 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.118",
@@ -86,6 +125,7 @@ dependencies = [
name = "mingling_pathf"
version = "0.5.0"
dependencies = [
+ "cargo_metadata",
"just_fmt",
"proc-macro2",
"syn 2.0.118",
@@ -110,12 +150,23 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -139,6 +190,19 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -170,6 +234,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -224,3 +308,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/examples/example-pathfinder/Cargo.toml b/examples/example-pathfinder/Cargo.toml
index bc41bd2..00fc2a1 100644
--- a/examples/example-pathfinder/Cargo.toml
+++ b/examples/example-pathfinder/Cargo.toml
@@ -11,15 +11,4 @@ features = [
"pathf",
]
-[build-dependencies.mingling]
-path = "../../mingling"
-
-features = [
- # Enable `pathf` features
- "pathf",
-
- # Enable the `build` feature for build-time support
- "build",
-]
-
[workspace]
diff --git a/examples/example-pathfinder/build.rs b/examples/example-pathfinder/build.rs
deleted file mode 100644
index e96f978..0000000
--- a/examples/example-pathfinder/build.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use mingling::build::analyze_and_build_type_mapping;
-
-fn main() {
- // --------- IMPORTANT ---------
- // Use this method in build.rs,
- // to analyze the project structure at build time,
- // and automatically introduce members from other modules into gen_program!()
- analyze_and_build_type_mapping().unwrap();
- // --------- IMPORTANT ---------
-}
diff --git a/examples/example-pathfinder/page.toml b/examples/example-pathfinder/page.toml
index 54f4118..6cf42e3 100644
--- a/examples/example-pathfinder/page.toml
+++ b/examples/example-pathfinder/page.toml
@@ -6,5 +6,5 @@ category = "advanced"
desc = """
Demonstrates the `pathf` feature, which automatically resolves type module paths at build time. Types can be defined in submodules without explicit `use` in the main module.
"""
-tags = ["pathf", "build.rs", "architecture"]
-files = [ "Cargo.toml", "build.rs", "src/main.rs", "src/sub/mod.rs"]
+tags = ["pathf", "architecture"]
+files = [ "Cargo.toml", "src/main.rs", "src/sub/mod.rs"]
diff --git a/mingling/Cargo.toml b/mingling/Cargo.toml
index 6130b1b..f1439af 100644
--- a/mingling/Cargo.toml
+++ b/mingling/Cargo.toml
@@ -25,7 +25,6 @@ features = [
"docs_rs",
"core",
"macros",
- "builds",
"structural_renderer",
"repl",
"comp",
@@ -40,8 +39,6 @@ features = [
mini = ["extras", "picker"]
advanced = ["extras", "picker", "repl", "comp", "dispatch_tree", "structural_renderer"]
full = ["extras", "picker", "repl", "clap", "comp", "dispatch_tree", "structural_renderer_full", "pathf"]
-build_advanced = ["build", "comp"]
-build_full = ["build", "comp", "pathf", "dispatch_tree"]
# Core
core = ["dep:mingling_core", "mingling_core/default"]
@@ -52,7 +49,6 @@ nightly = ["mingling_core/nightly", "mingling_macros/nightly"]
debug = ["mingling_core/debug"]
async = ["mingling_core/async", "mingling_macros/async"]
default = ["core", "macros"]
-build = ["mingling_core/build"]
# - Section only shown in docs.rs
docs_rs = []
@@ -62,7 +58,7 @@ dispatch_tree = ["mingling_macros/dispatch_tree"]
repl = ["mingling_core/repl", "mingling_macros/repl"]
comp = ["mingling_core/comp", "mingling_macros/comp"]
picker = ["mingling_core/picker", "dep:arg-picker", "arg-picker/mingling_support"]
-pathf = ["mingling_core/pathf", "mingling_macros/pathf"]
+pathf = ["mingling_macros/pathf"]
structural_renderer = [
"mingling_core/structural_renderer",
@@ -101,7 +97,6 @@ extras = ["mingling_macros/extras"]
# - LEGACY -
# These are old names, will be Breaking Change in the future
-builds = ["mingling_core/build"]
extra_macros = ["mingling_macros/extras"]
[dependencies]
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index 2b1d21e..c9955b5 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -595,11 +595,13 @@ pub mod example_clap_binding {}
/// > Types are defined in a submodule (`sub`), and `gen_program!()` resolves
/// > them automatically via pathf without explicit `use` imports.
/// >
-/// > **Important**: `dispatch_tree` must be enabled in BOTH `[dependencies]`
-/// > AND `[build-dependencies]` so that pathf's builder can detect
-/// > `__internal_dispatcher_*` types needed by the dispatch tree.
+/// > **Important**: `dispatch_tree` must be enabled so that pathf's builder can
+/// > detect `__internal_dispatcher_*` types needed by the dispatch tree.
/// >
/// > Also requires `extras` for the implicit `dispatcher!("hello")` form.
+/// >
+/// > With the `pathf` feature, `gen_program!()` automatically invokes
+/// > `build_pathf!()` at compile time — no `build.rs` needed.
///
/// Run:
/// ```bash
@@ -625,19 +627,6 @@ pub mod example_clap_binding {}
/// "pathf",
/// ] }
///
-/// [build-dependencies]
-/// mingling = { path = "../../mingling", features = [
-/// "builds",
-///
-/// # --------- IMPORTANT ---------
-/// # To use pathf under dispatch_tree
-/// # **must** enable the `dispatch_tree`
-/// # feature in build dependencies
-/// "dispatch_tree",
-/// "pathf",
-/// # --------- IMPORTANT ---------
-/// ] }
-///
/// [workspace]
/// ```
///
@@ -691,15 +680,6 @@ pub mod example_combine_pathf_dispatch_tree {}
/// "pathf",
/// ]
///
-/// [build-dependencies.mingling]
-/// path = "../../mingling"
-/// features = [
-/// # Enable the `build` feature for build-time support
-/// "build",
-/// # `pathf` must also be enabled in build-dependencies
-/// "pathf",
-/// ]
-///
/// [workspace]
/// ```
///
@@ -811,30 +791,15 @@ pub mod example_command_macro {}
/// To make your completions work, you need to generate a completion script using Mingling's tools
///
/// 1. Enable features
-/// You need to enable the `build` and `comp` features for `mingling` in `[build-dependencies]`
-///
-/// 2. Write `build.rs`
-/// Write the following in `build.rs`
-///
-/// ```rust,ignore
-/// fn main() {
-/// build_scripts();
-/// }
-///
-/// /// Generate completion scripts
-/// fn build_scripts() {
-/// // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name.
-/// // If your binary name differs from the crate name, specify it explicitly.
-/// mingling::build::build_comp_scripts(
-/// // Your binary name:
-/// env!("CARGO_PKG_NAME"),
-/// )
-/// .unwrap();
-/// }
-/// ```
+/// Enable the `comp` feature for `mingling` in `[dependencies]`
+///
+/// 2. Generate completion scripts
+/// When the `comp` feature is enabled, `gen_program!()` automatically invokes
+/// `build_comp!()` at compile time, which generates the completion scripts
+/// (named after `CARGO_PKG_NAME`) into `target/mingling/`.
///
/// 3. Verify
-/// Build your project with `cargo build --release`. The completion scripts will be generated in `target/release/`
+/// Build your project with `cargo build`. The completion scripts will be generated in `target/mingling/`
///
/// Execute the script or have it be automatically sourced by your Shell
///
@@ -864,18 +829,6 @@ pub mod example_command_macro {}
/// "picker",
/// ]
///
-/// [build-dependencies.mingling]
-/// path = "../../mingling"
-///
-/// features = [
-/// # Enable `comp` features
-/// "comp",
-///
-/// # If you want to build completion scripts,
-/// # enable `build` features
-/// "build",
-/// ]
-///
/// [workspace]
/// ```
///
@@ -2104,17 +2057,6 @@ pub mod example_panic_unwind {}
/// "pathf",
/// ]
///
-/// [build-dependencies.mingling]
-/// path = "../../mingling"
-///
-/// features = [
-/// # Enable `pathf` features
-/// "pathf",
-///
-/// # Enable the `build` feature for build-time support
-/// "build",
-/// ]
-///
/// [workspace]
/// ```
///
diff --git a/mingling/src/features.rs b/mingling/src/features.rs
index 9445328..777c3fb 100644
--- a/mingling/src/features.rs
+++ b/mingling/src/features.rs
@@ -31,50 +31,6 @@ pub const MINGLING_ASYNC: bool = false;
#[cfg(feature = "async")]
#[allow(unused)]
pub const MINGLING_ASYNC: bool = true;
-/// Whether the `build` feature is enabled
-/// Current: `disabled`
-#[cfg(not(feature = "build"))]
-#[allow(unused)]
-pub const MINGLING_BUILD: bool = false;
-
-/// Whether the `build` feature is enabled
-/// Current: `enabled`
-#[cfg(feature = "build")]
-#[allow(unused)]
-pub const MINGLING_BUILD: bool = true;
-/// Whether the `build_advanced` feature is enabled
-/// Current: `disabled`
-#[cfg(not(feature = "build_advanced"))]
-#[allow(unused)]
-pub const MINGLING_BUILD_ADVANCED: bool = false;
-
-/// Whether the `build_advanced` feature is enabled
-/// Current: `enabled`
-#[cfg(feature = "build_advanced")]
-#[allow(unused)]
-pub const MINGLING_BUILD_ADVANCED: bool = true;
-/// Whether the `build_full` feature is enabled
-/// Current: `disabled`
-#[cfg(not(feature = "build_full"))]
-#[allow(unused)]
-pub const MINGLING_BUILD_FULL: bool = false;
-
-/// Whether the `build_full` feature is enabled
-/// Current: `enabled`
-#[cfg(feature = "build_full")]
-#[allow(unused)]
-pub const MINGLING_BUILD_FULL: bool = true;
-/// Whether the `builds` feature is enabled
-/// Current: `disabled`
-#[cfg(not(feature = "builds"))]
-#[allow(unused)]
-pub const MINGLING_BUILDS: bool = false;
-
-/// Whether the `builds` feature is enabled
-/// Current: `enabled`
-#[cfg(feature = "builds")]
-#[allow(unused)]
-pub const MINGLING_BUILDS: bool = true;
/// Whether the `clap` feature is enabled
/// Current: `disabled`
#[cfg(not(feature = "clap"))]
diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs
index 55240e5..45c8ec3 100644
--- a/mingling/src/lib.rs
+++ b/mingling/src/lib.rs
@@ -64,6 +64,10 @@ pub mod macros {
#[cfg(feature = "picker")]
pub use arg_picker::macros::*;
pub use mingling_macros::buffer;
+ #[cfg(feature = "comp")]
+ pub use mingling_macros::build_comp;
+ #[cfg(feature = "pathf")]
+ pub use mingling_macros::build_pathf;
pub use mingling_macros::chain;
#[cfg(feature = "extras")]
pub use mingling_macros::command;
diff --git a/mingling_cli/Cargo.lock b/mingling_cli/Cargo.lock
index c738a0e..aab6b82 100644
--- a/mingling_cli/Cargo.lock
+++ b/mingling_cli/Cargo.lock
@@ -95,9 +95,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
[[package]]
name = "camino"
-version = "1.2.4"
+version = "1.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
dependencies = [
"serde_core",
]
@@ -746,15 +746,15 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.187"
+version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7743783ea728ef5c31194c6590797eed286449b4a4e87d626d8a51f0a94e732"
+checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "libredox"
-version = "0.1.19"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2026a5056764a10b2bf5d56488cba40da507f5493a6a429340e2004d9ed085fa"
+checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a"
dependencies = [
"libc",
]
@@ -849,9 +849,7 @@ name = "mingling_core"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
- "just_template",
"might_be_async",
- "mingling_pathf",
]
[[package]]
@@ -859,6 +857,8 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
+ "just_template",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.119",
@@ -868,6 +868,7 @@ dependencies = [
name = "mingling_pathf"
version = "0.5.0"
dependencies = [
+ "cargo_metadata",
"just_fmt 0.2.0",
"proc-macro2",
"syn 2.0.119",
@@ -1402,18 +1403,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.19"
+version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.19"
+version = "2.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
dependencies = [
"proc-macro2",
"quote",
@@ -1464,13 +1465,13 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "2.7.1"
+version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba"
+checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.119",
+ "syn 3.0.2",
]
[[package]]
diff --git a/mingling_cli/Cargo.toml b/mingling_cli/Cargo.toml
index dfc686d..19b4c1b 100644
--- a/mingling_cli/Cargo.toml
+++ b/mingling_cli/Cargo.toml
@@ -30,15 +30,6 @@ features = [
"comp",
]
-[build-dependencies.mingling]
-path = "../mingling"
-features = [
- "build",
- "pathf",
- "dispatch_tree",
- "comp"
-]
-
[dependencies]
# Project analyze
diff --git a/mingling_cli/build.rs b/mingling_cli/build.rs
index 0dc0b28..4df33d0 100644
--- a/mingling_cli/build.rs
+++ b/mingling_cli/build.rs
@@ -1,14 +1,6 @@
-use mingling::build::{analyze_and_build_type_mapping, build_comp_scripts};
-
pub mod pre;
fn main() {
- // Perform path analysis and build type mapping table
- analyze_and_build_type_mapping().ok();
-
- // Generate Mingling CLI Completion Scripts
- build_comp_scripts("mling").unwrap();
-
// Generate lint registry
pre::gen_mod_file().unwrap();
pre::gen_lint_registry().unwrap();
diff --git a/mingling_cli/src/lib.rs b/mingling_cli/src/lib.rs
index d5a5b22..0b93f08 100644
--- a/mingling_cli/src/lib.rs
+++ b/mingling_cli/src/lib.rs
@@ -24,6 +24,10 @@ pub mod proj_mgr;
pub mod updater;
pub mod utils;
+// The `comp` feature makes `gen_program!()` generate completion scripts named after
+// the crate (`mingling-cli_comp.*`). Generate an additional set for the `mling` binary.
+mingling::macros::build_comp!("mling");
+
#[help]
pub fn help_global(_: EntryFallback) -> String {
format!("{}\n", include_str!("../help/help.txt").parse_color_code())
diff --git a/mingling_cli/src/pkg_mgr/cmd_install.rs b/mingling_cli/src/pkg_mgr/cmd_install.rs
index c7dcaef..0b552a6 100644
--- a/mingling_cli/src/pkg_mgr/cmd_install.rs
+++ b/mingling_cli/src/pkg_mgr/cmd_install.rs
@@ -34,6 +34,9 @@ pub struct StateInstallBuild {
pub workspace_root: PathBuf,
pub install_dir: PathBuf,
pub release_dir: PathBuf,
+ /// Directory holding Mingling's compile-time build outputs
+ /// (`{target_directory}/mingling/`), e.g. the completion scripts.
+ pub mingling_dir: PathBuf,
pub exe_suffix: &'static str,
pub enable: bool,
}
@@ -43,6 +46,9 @@ pub struct StateInstallBuild {
pub struct StateInstallCopy {
pub install_dir: PathBuf,
pub release_dir: PathBuf,
+ /// Directory holding Mingling's compile-time build outputs
+ /// (`{target_directory}/mingling/`), e.g. the completion scripts.
+ pub mingling_dir: PathBuf,
pub exe_suffix: &'static str,
pub installed: Vec<PathBuf>,
pub enable: bool,
@@ -95,6 +101,10 @@ pub fn install(
.target_directory
.join("release")
.into_std_path_buf(),
+ mingling_dir: metadata
+ .target_directory
+ .join("mingling")
+ .into_std_path_buf(),
exe_suffix: env::consts::EXE_SUFFIX,
enable: enable.bool(),
}
@@ -117,6 +127,7 @@ pub fn handle_state_install_build(state: StateInstallBuild) -> Next {
StateInstallCopy {
install_dir: state.install_dir,
release_dir: state.release_dir,
+ mingling_dir: state.mingling_dir,
exe_suffix: state.exe_suffix,
installed: vec![],
enable: state.enable,
@@ -159,13 +170,13 @@ pub fn handle_state_install_copy(
}
}
- // Completion scripts are generated into the build profile directory
- // (OUT_DIR/../../../), copy every one whose name contains `_comp`,
- // regardless of its suffix
- for entry in fs::read_dir(&state.release_dir).map_err(|e| {
+ // Completion scripts are generated into `{target_directory}/mingling/` at
+ // compile time (via `build_comp!()`); copy every one whose name contains
+ // `_comp`, regardless of its suffix.
+ for entry in fs::read_dir(&state.mingling_dir).map_err(|e| {
io::Error::new(
e.kind(),
- format!("failed to read {}: {e}", state.release_dir.display()),
+ format!("failed to read {}: {e}", state.mingling_dir.display()),
)
})? {
let entry = entry.map_err(|e| {
diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml
index aecf476..989abe4 100644
--- a/mingling_core/Cargo.toml
+++ b/mingling_core/Cargo.toml
@@ -14,7 +14,6 @@ categories = ["command-line-interface"]
nightly = []
default = []
async = []
-build = []
picker = []
structural_renderer = ["dep:serde"]
@@ -26,18 +25,12 @@ toml_serde_fmt = ["dep:toml"]
repl = []
clap = []
-comp = ["dep:just_template"]
+comp = []
debug = ["dep:log", "dep:env_logger"]
-pathf = ["dep:mingling_pathf"]
[dependencies]
-mingling_pathf = { workspace = true, optional = true }
-
just_fmt.workspace = true
-# comp
-just_template = { workspace = true, optional = true }
-
# structural_renderer
serde = { workspace = true, optional = true }
ron = { workspace = true, optional = true }
diff --git a/mingling_core/src/build.rs b/mingling_core/src/build.rs
deleted file mode 100644
index 213d529..0000000
--- a/mingling_core/src/build.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#[doc(hidden)]
-#[cfg(feature = "comp")]
-mod comp;
-
-#[cfg(feature = "comp")]
-mod comp_re_export {
- pub use super::comp::build_comp_script;
- pub use super::comp::build_comp_script_to;
- pub use super::comp::build_comp_script_to_file;
- pub use super::comp::build_comp_scripts;
-}
-
-#[cfg(feature = "comp")]
-pub use comp_re_export::*;
-
-#[doc(hidden)]
-#[cfg(feature = "pathf")]
-mod pathf;
-
-#[cfg(feature = "pathf")]
-mod pathf_re_export {
- pub use super::pathf::analyze;
- pub use super::pathf::analyze_and_build_type_mapping;
- pub use super::pathf::analyze_and_build_type_mapping_for;
-}
-
-#[cfg(feature = "pathf")]
-pub use pathf_re_export::*;
diff --git a/mingling_core/src/build/pathf.rs b/mingling_core/src/build/pathf.rs
deleted file mode 100644
index 4b8af1b..0000000
--- a/mingling_core/src/build/pathf.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-#![allow(unused_imports)]
-
-pub use mingling_pathf::module_pathf::*;
-pub use mingling_pathf::pattern_analyzer::*;
-pub use mingling_pathf::patterns::*;
-
-use std::path::Path;
-
-/// Analyzes and builds a type mapping for a specific crate.
-///
-/// Accepts `crate_dir` and `output_dir`, and invokes `pathf` to build the type mapping.
-///
-/// # Arguments
-///
-/// - `crate_dir`: Root directory of the crate's source code to analyze (usually `CARGO_MANIFEST_DIR`).
-/// - `output_dir`: Output directory for generated artifacts (type mapping data).
-///
-/// # Returns
-///
-/// - On success: returns `Ok(())`;
-/// - On failure: returns the corresponding `MinglingPathfinderError`.
-///
-/// # Example
-///
-/// ```
-/// # #[cfg(all(feature = "build", feature = "pathf"))] {
-/// use mingling_core::build::analyze_and_build_type_mapping_for;
-/// use std::path::Path;
-///
-/// let crate_dir = Path::new(".");
-/// let output_dir = Path::new(".temp/target/out");
-/// analyze_and_build_type_mapping_for(crate_dir, output_dir).expect("analysis failed");
-/// # }
-/// ```
-pub fn analyze_and_build_type_mapping_for(
- crate_dir: &Path,
- output_dir: &Path,
-) -> Result<(), crate::error::MinglingPathfinderError> {
- mingling_pathf::analyze_and_build_type_mapping_for(crate_dir, output_dir)
-}
-
-/// # Analyzes and builds a type mapping
-///
-/// This function reads the current crate directory (`CARGO_PKG_NAME`) and output directory (`OUT_DIR`)
-/// from environment variables, automatically combines them into the target output path, and invokes
-/// the underlying analysis logic. Suitable for use in `build.rs`.
-///
-/// It also sends the `cargo:rerun-if-changed=src/` directive to Cargo so that a rebuild is
-/// automatically triggered when source code changes.
-///
-/// # Prerequisites
-///
-/// This function depends on the following environment variables, which are typically set
-/// automatically during a Cargo build:
-///
-/// - `CARGO_PKG_NAME`: Name of the current crate.
-/// - `OUT_DIR`: Build output directory provided by Cargo.
-///
-/// If these variables are missing, a corresponding [`MinglingPathfinderError`](crate::error::MinglingPathfinderError)
-/// is returned.
-///
-/// # Returns
-///
-/// Returns `Ok(())` on success; returns a corresponding
-/// [`MinglingPathfinderError`](crate::error::MinglingPathfinderError) on failure.
-///
-/// # Example
-///
-/// ```
-/// # #[cfg(all(feature = "build", feature = "pathf"))] {
-/// use mingling_core::build::analyze_and_build_type_mapping;
-///
-/// fn main() {
-/// analyze_and_build_type_mapping().expect("failed to build type mapping");
-/// }
-/// # }
-/// ```
-
-pub fn analyze_and_build_type_mapping() -> Result<(), crate::error::MinglingPathfinderError> {
- let crate_dir =
- std::env::current_dir().map_err(crate::error::MinglingPathfinderError::IoError)?;
- let crate_name = std::env::var("CARGO_PKG_NAME").map_err(|_| {
- crate::error::MinglingPathfinderError::IoError(std::io::Error::new(
- std::io::ErrorKind::NotFound,
- "CARGO_PKG_NAME not set",
- ))
- })?;
- let out_dir = std::env::var("OUT_DIR").map_err(|_| {
- crate::error::MinglingPathfinderError::IoError(std::io::Error::new(
- std::io::ErrorKind::NotFound,
- "OUT_DIR not set",
- ))
- })?;
- let output_dir = Path::new(&out_dir).join(&crate_name);
- mingling_pathf::analyze_and_build_type_mapping_for(&crate_dir, &output_dir)?;
- println!("cargo:rerun-if-changed=src/");
- Ok(())
-}
diff --git a/mingling_core/src/docs/build.md b/mingling_core/src/docs/build.md
deleted file mode 100644
index 6f9285a..0000000
--- a/mingling_core/src/docs/build.md
+++ /dev/null
@@ -1,57 +0,0 @@
-Provide Mingling's build script module for build-time behavior of specific features in `build.rs`.
-
-To use it, add a dependency on mingling under `[build-dependencies]` in `Cargo.toml`, and enable the relevant features:
-
-## Build-Time Related Features
-
-| Name | Purpose |
-| ---------------- | ------------------------------------------------------------------------------------------------- |
-| `build` | Master switch for build-time features |
-| `build_advanced` | Master switch for build-time features, paired with the `advanced` feature |
-| `build_full` | Master switch for build-time features, paired with the `full` feature |
-| `comp` | Completion script builder; both sides must enable it, generates cross-platform completion scripts |
-| `pathf` | Type path analyzer; both sides must enable it, generates type mapping tables |
-| `dispatch_tree` | Compile-time dispatch tree; when `pathf` is a build-time dependency, |
-| | and `dispatch_tree` (included in `advanced` or `full`) is enabled, both sides should enable it |
-
-```toml
-# Cargo.toml
-[dependencies.mingling]
-features = [
- "advanced", # Enable `advanced` if using it
-]
-
-[build-dependencies.mingling]
-features = [
- "build_advanced" # This side should enable `build_advanced`
-]
-```
-
-## `build.rs` Templates
-
-You can use the following template to write `build.rs` to quickly gain the build-time capabilities of `comp` and `pathf`:
-
-```rust,ignore
-// build.rs
-fn main() {
- build_scripts();
- build_pathf_mapping();
-}
-
-/// Generate completion scripts
-fn build_scripts() {
- // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name.
- // If your binary name differs from the crate name, specify it explicitly.
- mingling::build::build_comp_scripts(
- // Your binary name:
- env!("CARGO_PKG_NAME"),
- )
- .unwrap();
-}
-
-fn build_pathf_mapping() {
- // Build pathf type mapping to ensure that the enabled `pathf` feature
- // can correctly scan macros in the project
- mingling::build::analyze_and_build_type_mapping().unwrap();
-}
-```
diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs
index 2aa2ce1..1d26ebb 100644
--- a/mingling_core/src/lib.rs
+++ b/mingling_core/src/lib.rs
@@ -46,10 +46,6 @@ pub mod core_res {
#[cfg(feature = "comp")]
pub(crate) mod comp;
-#[cfg(feature = "build")]
-#[doc = include_str!("docs/build.md")]
-pub mod build;
-
// Public Modules
/// Provides a toolkit for `Mingling` testing capabilities.
@@ -90,9 +86,6 @@ pub mod error {
#[cfg(feature = "structural_renderer")]
pub use crate::renderer::structural::error::*;
-
- #[cfg(feature = "pathf")]
- pub use mingling_pathf::error::*;
}
#[doc(hidden)]
diff --git a/mingling_core/tests/test-all/Cargo.lock b/mingling_core/tests/test-all/Cargo.lock
index d239541..79202f9 100644
--- a/mingling_core/tests/test-all/Cargo.lock
+++ b/mingling_core/tests/test-all/Cargo.lock
@@ -16,7 +16,7 @@ version = "0.2.0"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -35,6 +35,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -108,7 +141,7 @@ checksum = "1471eb68722ecefeb71debdde2859e8725341f171d3f42b3a98a0862ad19416e"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -140,7 +173,7 @@ checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
"toml 0.8.23",
]
@@ -159,7 +192,6 @@ name = "mingling_core"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
- "just_template",
"might_be_async",
"ron",
"serde",
@@ -173,9 +205,21 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
+ "just_template",
+ "mingling_pathf",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
+]
+
+[[package]]
+name = "mingling_pathf"
+version = "0.5.0"
+dependencies = [
+ "cargo_metadata",
+ "just_fmt 0.2.0",
+ "proc-macro2",
+ "syn 2.0.118",
]
[[package]]
@@ -278,6 +322,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -304,7 +358,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -389,6 +443,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "test-all"
version = "0.1.0"
dependencies = [
@@ -398,6 +463,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "tokio"
version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -422,7 +507,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.118",
]
[[package]]
diff --git a/mingling_core/tests/test-all/Cargo.toml b/mingling_core/tests/test-all/Cargo.toml
index df2efdb..7f50f2f 100644
--- a/mingling_core/tests/test-all/Cargo.toml
+++ b/mingling_core/tests/test-all/Cargo.toml
@@ -10,7 +10,6 @@ publish = false
mingling = { path = "../../../mingling", features = [
"structural_renderer_full",
"comp",
- "builds",
"repl",
"dispatch_tree",
"picker",
diff --git a/mingling_core/tests/test-comp/Cargo.lock b/mingling_core/tests/test-comp/Cargo.lock
index 1a37590..199c76e 100644
--- a/mingling_core/tests/test-comp/Cargo.lock
+++ b/mingling_core/tests/test-comp/Cargo.lock
@@ -3,6 +3,39 @@
version = 4
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -25,6 +58,12 @@ dependencies = [
]
[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -88,7 +127,6 @@ name = "mingling_core"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
- "just_template",
"might_be_async",
]
@@ -97,12 +135,24 @@ name = "mingling_macros"
version = "0.5.0"
dependencies = [
"just_fmt 0.2.0",
+ "just_template",
+ "mingling_pathf",
"proc-macro2",
"quote",
"syn 2.0.118",
]
[[package]]
+name = "mingling_pathf"
+version = "0.5.0"
+dependencies = [
+ "cargo_metadata",
+ "just_fmt 0.2.0",
+ "proc-macro2",
+ "syn 2.0.118",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -121,12 +171,23 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
name = "serde"
version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
@@ -150,6 +211,19 @@ dependencies = [
]
[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -188,6 +262,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -242,3 +336,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
diff --git a/mingling_core/tests/test-comp/Cargo.toml b/mingling_core/tests/test-comp/Cargo.toml
index 9ceca3e..789e172 100644
--- a/mingling_core/tests/test-comp/Cargo.toml
+++ b/mingling_core/tests/test-comp/Cargo.toml
@@ -7,4 +7,4 @@ publish = false
[workspace]
[dependencies]
-mingling = { path = "../../../mingling", features = ["comp", "builds"] }
+mingling = { path = "../../../mingling", features = ["comp"] }
diff --git a/mingling_macros/Cargo.toml b/mingling_macros/Cargo.toml
index 137213a..6ae7aeb 100644
--- a/mingling_macros/Cargo.toml
+++ b/mingling_macros/Cargo.toml
@@ -19,11 +19,11 @@ default = []
async = []
clap = []
-comp = []
+comp = ["dep:just_template", "dep:mingling_pathf"]
dispatch_tree = []
structural_renderer = []
repl = []
-pathf = []
+pathf = ["dep:mingling_pathf"]
extras = []
@@ -33,3 +33,9 @@ quote.workspace = true
proc-macro2.workspace = true
just_fmt.workspace = true
+
+# comp — compile-time completion script generation (build_comp!())
+just_template = { workspace = true, optional = true }
+
+# pathf — compile-time type path analysis (build_pathf!())
+mingling_pathf = { workspace = true, optional = true }
diff --git a/mingling_macros/src/build.rs b/mingling_macros/src/build.rs
new file mode 100644
index 0000000..8f2949d
--- /dev/null
+++ b/mingling_macros/src/build.rs
@@ -0,0 +1,56 @@
+//! Compile-time build logic for `build_comp!()` and `build_pathf!()`.
+//!
+//! The build steps run as a side effect of macro expansion (during `gen_program!`),
+//! writing artifacts under `{target_directory}/mingling/`.
+
+#[doc(hidden)]
+#[cfg(feature = "comp")]
+pub(crate) mod comp;
+
+#[doc(hidden)]
+#[cfg(feature = "pathf")]
+pub(crate) mod pathf;
+
+/// Shared implementation behind `build_comp!()`.
+///
+/// Accepts an optional string literal (the binary name); defaults to
+/// `CARGO_PKG_NAME`. Returns an empty token stream on success, or a
+/// `compile_error!` token stream on failure.
+#[cfg(feature = "comp")]
+pub(crate) fn comp_build_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let bin_name: String = if input.is_empty() {
+ std::env::var("CARGO_PKG_NAME").unwrap_or_default()
+ } else {
+ match syn::parse::<syn::LitStr>(input) {
+ Ok(lit) => lit.value(),
+ Err(e) => return e.to_compile_error().into(),
+ }
+ };
+
+ match comp::build_comp_scripts(&bin_name) {
+ Ok(()) => proc_macro::TokenStream::new(),
+ Err(e) => {
+ let msg = format!("build_comp: failed to generate completion scripts: {e}");
+ syn::Error::new(proc_macro2::Span::call_site(), msg)
+ .to_compile_error()
+ .into()
+ }
+ }
+}
+
+/// Shared implementation behind `build_pathf!()`.
+///
+/// Runs the pathf type-mapping analysis. Returns an empty token stream on
+/// success, or a `compile_error!` token stream on failure.
+#[cfg(feature = "pathf")]
+pub(crate) fn pathf_build_impl(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ match pathf::analyze_and_build_type_mapping() {
+ Ok(()) => proc_macro::TokenStream::new(),
+ Err(e) => {
+ let msg = format!("build_pathf: type mapping analysis failed: {e}");
+ syn::Error::new(proc_macro2::Span::call_site(), msg)
+ .to_compile_error()
+ .into()
+ }
+ }
+}
diff --git a/mingling_core/src/build/comp.rs b/mingling_macros/src/build/comp.rs
index d6bb34f..81a26e8 100644
--- a/mingling_core/src/build/comp.rs
+++ b/mingling_macros/src/build/comp.rs
@@ -2,7 +2,27 @@ use std::path::PathBuf;
use just_template::tmpl;
-use crate::ShellFlag;
+/// Represents the shell environment for which the output format is intended.
+///
+/// This is an internal copy of `mingling_core::ShellFlag`, kept private to the
+/// build module because the macros crate must not depend on `mingling_core`.
+/// Which variants are constructed depends on the target OS (`#[cfg]`), so
+/// platform-gated variants may be unused on any given host.
+#[allow(dead_code)]
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub(crate) enum ShellFlag {
+ /// Represents the Bash shell.
+ #[default]
+ Bash,
+ /// Represents the Zsh shell.
+ Zsh,
+ /// Represents the Fish shell.
+ Fish,
+ /// Represents `PowerShell`.
+ Powershell,
+ /// A custom or unsupported shell type, identified by the provided string.
+ Other(String),
+}
const TMPL_COMP_BASH: &str = include_str!("../../tmpls/comps/bash.sh");
const TMPL_COMP_ZSH: &str = include_str!("../../tmpls/comps/zsh.zsh");
@@ -15,21 +35,10 @@ const TMPL_COMP_PWSH: &str = include_str!("../../tmpls/comps/pwsh.ps1");
/// On Linux, generates Zsh, Bash, and Fish completions.
/// Scripts are written to the `OUT_DIR` (or `target/` if `OUT_DIR` is not set).
///
-/// # Example
-/// ```
-/// # #[cfg(all(feature = "build", feature = "comp"))] {
-/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || {
-/// # use mingling_core::ShellFlag;
-/// # use mingling_core::build::build_comp_scripts;
-/// // Generate completion scripts for "myapp"
-/// build_comp_scripts("myapp").unwrap();
+/// # Errors
///
-/// // Generate completion scripts for current package
-/// build_comp_scripts(env!("CARGO_PKG_NAME")).unwrap();
-/// # });
-/// # }
-/// ```
-pub fn build_comp_scripts(name: &str) -> Result<(), std::io::Error> {
+/// Returns an [`std::io::Error`] if a script cannot be written.
+pub(crate) fn build_comp_scripts(name: &str) -> Result<(), std::io::Error> {
#[cfg(target_os = "windows")]
{
build_comp_script(&ShellFlag::Powershell, name)?;
@@ -57,22 +66,23 @@ pub fn build_comp_scripts(name: &str) -> Result<(), std::io::Error> {
///
/// This function takes a shell flag and a binary name, selects the appropriate
/// template, substitutes the binary name into the template, and writes the
-/// resulting completion script to the target directory (typically `target/`).
+/// resulting completion script to the Mingling build directory
+/// (`{target_directory}/mingling/`, resolved via `cargo metadata`).
+///
+/// # Errors
///
-/// # Example
-/// ```
-/// # #[cfg(all(feature = "build", feature = "comp"))] {
-/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || {
-/// # use mingling_core::ShellFlag;
-/// # use mingling_core::build::build_comp_script;
-/// build_comp_script(&ShellFlag::Bash, "myapp").unwrap();
-/// # });
-/// # }
-/// ```
-pub fn build_comp_script(shell_flag: &ShellFlag, bin_name: &str) -> Result<(), std::io::Error> {
- let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
- let target_dir = out_dir.join("../../../");
- build_comp_script_to(shell_flag, bin_name, &target_dir.to_string_lossy())
+/// Returns an [`std::io::Error`] if the script cannot be written.
+pub(crate) fn build_comp_script(
+ shell_flag: &ShellFlag,
+ bin_name: &str,
+) -> Result<(), std::io::Error> {
+ let output_dir = comp_output_dir()?;
+ build_comp_script_to(shell_flag, bin_name, &output_dir.to_string_lossy())
+}
+
+/// The directory where completion scripts are written: `{target_directory}/mingling/`.
+fn comp_output_dir() -> Result<PathBuf, std::io::Error> {
+ mingling_pathf::build_output_dir().map_err(|e| std::io::Error::other(e.to_string()))
}
/// Generate a shell completion script to a specified directory.
@@ -81,17 +91,10 @@ pub fn build_comp_script(shell_flag: &ShellFlag, bin_name: &str) -> Result<(), s
/// selects the appropriate template, substitutes the binary name into the template,
/// and writes the resulting completion script to the specified directory.
///
-/// # Example
-/// ```
-/// # #[cfg(all(feature = "build", feature = "comp"))] {
-/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || {
-/// # use mingling_core::ShellFlag;
-/// # use mingling_core::build::build_comp_script_to;
-/// build_comp_script_to(&ShellFlag::Bash, "myapp", ".temp/target/test/out/").unwrap();
-/// # });
-/// # }
-/// ```
-pub fn build_comp_script_to(
+/// # Errors
+///
+/// Returns an [`std::io::Error`] if the script cannot be written.
+pub(crate) fn build_comp_script_to(
shell_flag: &ShellFlag,
bin_name: &str,
target_dir: &str,
@@ -105,33 +108,6 @@ 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
-/// ```
-/// # #[cfg(all(feature = "build", feature = "comp"))] {
-/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || {
-/// # use mingling_core::ShellFlag;
-/// # use mingling_core::build::build_comp_script_to_file;
-/// build_comp_script_to_file(&ShellFlag::Bash, "myapp", ".temp/target/test/out/myapp.comp.sh").unwrap();
-/// # });
-/// # }
-/// ```
-pub fn build_comp_script_to_file(
- shell_flag: &ShellFlag,
- bin_name: &str,
- output_path: impl Into<PathBuf>,
-) -> Result<(), std::io::Error> {
- let (tmpl_str, _ext) = get_tmpl(shell_flag);
- let mut tmpl = just_template::Template::from(tmpl_str);
- tmpl!(bin_name = bin_name);
- std::fs::write(output_path.into(), tmpl.to_string())
-}
-
const fn get_tmpl(shell_flag: &ShellFlag) -> (&'static str, &'static str) {
match shell_flag {
ShellFlag::Bash | ShellFlag::Other(_) => (TMPL_COMP_BASH, ".sh"),
@@ -144,7 +120,6 @@ const fn get_tmpl(shell_flag: &ShellFlag) -> (&'static str, &'static str) {
#[cfg(test)]
mod tests {
use super::*;
- use crate::ShellFlag;
#[test]
fn get_tmpl_bash() {
diff --git a/mingling_macros/src/build/pathf.rs b/mingling_macros/src/build/pathf.rs
new file mode 100644
index 0000000..788f527
--- /dev/null
+++ b/mingling_macros/src/build/pathf.rs
@@ -0,0 +1,19 @@
+use std::path::PathBuf;
+
+use mingling_pathf::error::MinglingPathfinderError;
+
+/// The directory where pathf's build artifacts are stored for the current
+/// crate: `{target_directory}/mingling/{CARGO_PKG_NAME}`.
+pub fn output_dir() -> Result<PathBuf, MinglingPathfinderError> {
+ Ok(mingling_pathf::build_output_dir()?.join(crate_name()))
+}
+
+/// Runs the pathf type-mapping analysis for the current crate at compile time
+/// (replacing the previous `build.rs` call).
+pub fn analyze_and_build_type_mapping() -> Result<(), MinglingPathfinderError> {
+ mingling_pathf::analyze_and_build_type_mapping()
+}
+
+fn crate_name() -> String {
+ std::env::var("CARGO_PKG_NAME").unwrap_or_default()
+}
diff --git a/mingling_macros/src/func/gen_program.rs b/mingling_macros/src/func/gen_program.rs
index c0a7ea8..35e8352 100644
--- a/mingling_macros/src/func/gen_program.rs
+++ b/mingling_macros/src/func/gen_program.rs
@@ -7,6 +7,11 @@ use quote::quote;
/// Generates the `Next` type alias, `Routable` impl for `ChainProcess`,
/// and delegates to `program_comp_gen!()`, `program_fallback_gen!()`,
/// and `program_final_gen!()`.
+///
+/// When the `comp` / `pathf` features are enabled, the expansion begins by
+/// invoking `build_comp!()` / `build_pathf!()`, which run the build steps
+/// (previously done in `build.rs`) as a compile-time side effect and expand
+/// to nothing.
pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream {
#[cfg(feature = "comp")]
let comp_gen = quote! {
@@ -16,18 +21,46 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream {
#[cfg(not(feature = "comp"))]
let comp_gen = quote! {};
- // When pathf is enabled, load the type_using.rs generated by the build script
+ // `build_pathf!()` / `build_comp!()` are invoked at the very beginning of the
+ // expansion: they run the build logic at compile time and expand to nothing.
+ #[cfg(feature = "comp")]
+ let comp_build = quote! {
+ ::mingling::macros::build_comp!();
+ };
+
+ #[cfg(not(feature = "comp"))]
+ let comp_build = quote! {};
+
+ #[cfg(feature = "pathf")]
+ let pathf_build = quote! {
+ ::mingling::macros::build_pathf!();
+ };
+
+ #[cfg(not(feature = "pathf"))]
+ let pathf_build = quote! {};
+
+ // When pathf is enabled, load the type_using.rs generated by the build logic
// and emit its use statements so types from submodules are in scope.
#[cfg(feature = "pathf")]
let pathf_uses: Vec<proc_macro2::TokenStream> = {
+ // The `build_pathf!()` macro emitted above will (re-)run the analysis
+ // during expansion, but the `use` statements are needed right now, so
+ // make sure the mapping exists before reading it.
+ if let Err(e) = crate::build::pathf::analyze_and_build_type_mapping() {
+ let msg = format!("pathf: type mapping analysis failed: {e}");
+ return syn::Error::new(proc_macro2::Span::call_site(), msg)
+ .to_compile_error()
+ .into();
+ }
let uses = load_pathf_uses();
if uses.is_empty() {
- // The file might not exist yet — emit a clear hint
+ // The analyzer found nothing — emit a clear hint
let hint: proc_macro2::TokenStream = syn::parse_quote! {
compile_error!(
- "pathf: `{}` not found or empty.\n\
- Make sure `build.rs` calls `mingling::build::analyze_and_build_type_mapping().unwrap();`\n\
- with features [\"build\", \"pathf\"] enabled."
+ "pathf: no types were found by the analyzer.\n\
+ Make sure the `pathf` feature is enabled (which also enables\n\
+ the `build_pathf!()` macro) and that `gen_program!()` is called\n\
+ in a crate with a `src/` directory."
);
};
vec![hint]
@@ -47,6 +80,8 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream {
};
TokenStream::from(quote! {
+ #comp_build
+ #pathf_build
pub use __this_program_impl::*;
#[doc(hidden)]
@@ -88,24 +123,16 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream {
})
}
-/// Loads `type_using.rs` generated by the pathf build script and returns each
+/// Loads `type_using.rs` generated by the pathf build logic and returns each
/// `use ...;` line as a token stream, ready to be emitted in the generated output.
#[cfg(feature = "pathf")]
fn load_pathf_uses() -> Vec<proc_macro2::TokenStream> {
- let out_dir = match std::env::var("OUT_DIR") {
- Ok(d) => d,
- Err(_) => return Vec::new(),
- };
- let crate_name = match std::env::var("CARGO_PKG_NAME") {
- Ok(n) => n,
- Err(_) => return Vec::new(),
+ let Ok(output_dir) = crate::build::pathf::output_dir() else {
+ return Vec::new();
};
- let path = std::path::Path::new(&out_dir)
- .join(&crate_name)
- .join("type_using.rs");
- let content = match std::fs::read_to_string(&path) {
- Ok(c) => c,
- Err(_) => return Vec::new(),
+ let path = output_dir.join("type_using.rs");
+ let Ok(content) = std::fs::read_to_string(&path) else {
+ return Vec::new();
};
content
.lines()
diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs
index d00773c..1aaedb1 100644
--- a/mingling_macros/src/lib.rs
+++ b/mingling_macros/src/lib.rs
@@ -20,6 +20,9 @@ mod derive;
mod func;
mod systems;
+#[cfg(any(feature = "comp", feature = "pathf"))]
+mod build;
+
mod extensions;
mod utils;
@@ -1653,6 +1656,50 @@ pub fn gen_program(input: TokenStream) -> TokenStream {
func::gen_program::gen_program_impl(input)
}
+/// Executes the completion-script build at compile time and expands to nothing.
+///
+/// **This macro is only available with the `comp` feature.**
+///
+/// The completion scripts are written to `{target_directory}/mingling/` (the
+/// target directory is resolved via `cargo metadata`).
+///
+/// `gen_program!()` calls this macro automatically when the `comp` feature is
+/// enabled. It can also be invoked manually to customize the binary name:
+///
+/// - `build_comp!()` — uses the current package name (`CARGO_PKG_NAME`).
+/// - `build_comp!("mybin")` — uses the given binary name.
+///
+/// ```rust,ignore
+/// mingling::macros::build_comp!();
+/// // or:
+/// mingling::macros::build_comp!("mybin");
+/// ```
+#[cfg(feature = "comp")]
+#[proc_macro]
+pub fn build_comp(input: TokenStream) -> TokenStream {
+ build::comp_build_impl(input)
+}
+
+/// Executes the pathf type-mapping build at compile time and expands to nothing.
+///
+/// **This macro is only available with the `pathf` feature.**
+///
+/// The mapping files are written to `{target_directory}/mingling/{CARGO_PKG_NAME}/`
+/// (the target directory is resolved via `cargo metadata`), and are consumed by
+/// `gen_program!()` so that types defined in submodules are resolved automatically.
+///
+/// `gen_program!()` calls this macro automatically when the `pathf` feature is
+/// enabled.
+///
+/// ```rust,ignore
+/// mingling::macros::build_pathf!();
+/// ```
+#[cfg(feature = "pathf")]
+#[proc_macro]
+pub fn build_pathf(input: TokenStream) -> TokenStream {
+ build::pathf_build_impl(input)
+}
+
/// Internal macro used by `gen_program!` to generate the completion infrastructure for
/// shell completion support.
///
diff --git a/mingling_core/tmpls/comps/bash.sh b/mingling_macros/tmpls/comps/bash.sh
index edec28d..edec28d 100644
--- a/mingling_core/tmpls/comps/bash.sh
+++ b/mingling_macros/tmpls/comps/bash.sh
diff --git a/mingling_core/tmpls/comps/fish.fish b/mingling_macros/tmpls/comps/fish.fish
index 64b4ed3..64b4ed3 100644
--- a/mingling_core/tmpls/comps/fish.fish
+++ b/mingling_macros/tmpls/comps/fish.fish
diff --git a/mingling_core/tmpls/comps/pwsh.ps1 b/mingling_macros/tmpls/comps/pwsh.ps1
index d72a027..d72a027 100644
--- a/mingling_core/tmpls/comps/pwsh.ps1
+++ b/mingling_macros/tmpls/comps/pwsh.ps1
diff --git a/mingling_core/tmpls/comps/zsh.zsh b/mingling_macros/tmpls/comps/zsh.zsh
index 7cf5f7b..7cf5f7b 100644
--- a/mingling_core/tmpls/comps/zsh.zsh
+++ b/mingling_macros/tmpls/comps/zsh.zsh
diff --git a/mingling_pathf/Cargo.toml b/mingling_pathf/Cargo.toml
index 0d4e37a..a649cb4 100644
--- a/mingling_pathf/Cargo.toml
+++ b/mingling_pathf/Cargo.toml
@@ -12,3 +12,4 @@ description = "A library for automatically finding internal types generated by M
syn.workspace = true
proc-macro2.workspace = true
just_fmt.workspace = true
+cargo_metadata.workspace = true
diff --git a/mingling_pathf/src/error.rs b/mingling_pathf/src/error.rs
index 5a748c4..bd850a8 100644
--- a/mingling_pathf/src/error.rs
+++ b/mingling_pathf/src/error.rs
@@ -53,6 +53,11 @@ pub enum MinglingPathfinderError {
/// Details from the parser about the parse failure.
message: String,
},
+
+ /// `cargo metadata` could not be executed or parsed.
+ ///
+ /// `message` contains the underlying error from the cargo invocation.
+ CargoMetadata(String),
}
impl fmt::Display for MinglingPathfinderError {
@@ -82,6 +87,7 @@ impl fmt::Display for MinglingPathfinderError {
Self::SynError { path, message } => {
write!(f, "Failed to parse {}: {message}", path.display())
}
+ Self::CargoMetadata(message) => write!(f, "cargo metadata failed: {message}"),
}
}
}
diff --git a/mingling_pathf/src/lib.rs b/mingling_pathf/src/lib.rs
index 492bfc7..f0637e8 100644
--- a/mingling_pathf/src/lib.rs
+++ b/mingling_pathf/src/lib.rs
@@ -13,3 +13,5 @@ pub mod patterns;
mod type_mapping_builder;
pub use type_mapping_builder::analyze_and_build_type_mapping;
pub use type_mapping_builder::analyze_and_build_type_mapping_for;
+pub use type_mapping_builder::build_output_dir;
+pub use type_mapping_builder::target_directory;
diff --git a/mingling_pathf/src/type_mapping_builder.rs b/mingling_pathf/src/type_mapping_builder.rs
index 1ccd267..4d0799f 100644
--- a/mingling_pathf/src/type_mapping_builder.rs
+++ b/mingling_pathf/src/type_mapping_builder.rs
@@ -5,7 +5,9 @@
use std::collections::HashSet;
use std::fmt::Write as FmtWrite;
-use std::path::Path;
+use std::path::{Path, PathBuf};
+
+use cargo_metadata::MetadataCommand;
use crate::error::MinglingPathfinderError;
use crate::module_pathf;
@@ -87,40 +89,74 @@ pub fn analyze_and_build_type_mapping_for(
Ok(())
}
-/// Convenience version to be called from `build.rs`, automatically reading configuration
-/// from environment variables.
+/// Runs `cargo metadata` from the given crate directory and returns the
+/// workspace's target directory.
+///
+/// The subprocess resolves the target directory exactly as Cargo does,
+/// honoring `.cargo/config.toml`, `CARGO_TARGET_DIR`, and `--target-dir`.
+///
+/// `crate_dir` — crate root directory (i.e., the directory containing Cargo.toml).
+///
+/// # Errors
+///
+/// Returns a [`MinglingPathfinderError::CargoMetadata`] if `cargo metadata`
+/// cannot be executed or its output cannot be parsed.
+pub fn target_directory(crate_dir: &Path) -> Result<PathBuf, MinglingPathfinderError> {
+ let metadata = MetadataCommand::new()
+ .current_dir(crate_dir)
+ .no_deps()
+ .exec()
+ .map_err(|e| MinglingPathfinderError::CargoMetadata(e.to_string()))?;
+ Ok(metadata.target_directory.into_std_path_buf())
+}
+
+/// The directory where all of Mingling's compile-time build artifacts are
+/// written for the current crate: `{target_directory}/mingling/`.
+///
+/// Reads `CARGO_MANIFEST_DIR` from the environment to locate the crate, then
+/// resolves the target directory via [`target_directory`]. Works both from a
+/// `build.rs` and from proc-macro expansion (no `OUT_DIR` required).
+///
+/// # Errors
+///
+/// Returns a [`MinglingPathfinderError`] if the environment variables are
+/// missing or the target directory cannot be resolved.
+pub fn build_output_dir() -> Result<PathBuf, MinglingPathfinderError> {
+ let crate_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| {
+ MinglingPathfinderError::IoError(std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ "CARGO_MANIFEST_DIR not set",
+ ))
+ })?;
+ Ok(target_directory(Path::new(&crate_dir))?.join("mingling"))
+}
+
+/// Convenience version to be called from `build.rs` or macro expansion,
+/// automatically reading configuration from environment variables.
///
-/// Reads `CARGO_PKG_NAME` and `OUT_DIR`, and outputs to `{OUT_DIR}/{CARGO_PKG_NAME}/`.
+/// Reads `CARGO_PKG_NAME` and `CARGO_MANIFEST_DIR`, and outputs to
+/// `{target_directory}/mingling/{CARGO_PKG_NAME}/` (see [`build_output_dir`]).
///
/// # Errors
///
/// Returns a [`MinglingPathfinderError`] if the required environment variables
-/// (`CARGO_PKG_NAME`, `OUT_DIR`) are not set, the current directory cannot be
-/// determined, or the type mapping generation fails.
+/// (`CARGO_PKG_NAME`, `CARGO_MANIFEST_DIR`) are not set or the type mapping
+/// generation fails.
pub fn analyze_and_build_type_mapping() -> Result<(), MinglingPathfinderError> {
let crate_name = std::env::var("CARGO_PKG_NAME").map_err(|_| {
MinglingPathfinderError::IoError(std::io::Error::new(
std::io::ErrorKind::NotFound,
- "CARGO_PKG_NAME not set (not running in build.rs?)",
+ "CARGO_PKG_NAME not set",
))
})?;
-
- let out_dir = std::env::var("OUT_DIR").map_err(|_| {
+ let crate_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| {
MinglingPathfinderError::IoError(std::io::Error::new(
std::io::ErrorKind::NotFound,
- "OUT_DIR not set (not running in build.rs?)",
+ "CARGO_MANIFEST_DIR not set",
))
})?;
- let crate_dir = std::env::current_dir()?;
- let output_dir = Path::new(&out_dir).join(&crate_name);
-
- analyze_and_build_type_mapping_for(&crate_dir, &output_dir)?;
+ let output_dir = build_output_dir()?.join(&crate_name);
- // Notify Cargo to re-run build.rs when source files change
- println!("cargo:rerun-if-changed=src/");
- println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS");
- println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH");
-
- Ok(())
+ analyze_and_build_type_mapping_for(Path::new(&crate_dir), &output_dir)
}
diff --git a/mingling_pathf/test/Cargo.lock b/mingling_pathf/test/Cargo.lock
index 58c7c9a..7dc772a 100644
--- a/mingling_pathf/test/Cargo.lock
+++ b/mingling_pathf/test/Cargo.lock
@@ -3,6 +3,45 @@
version = 4
[[package]]
+name = "camino"
+version = "1.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d"
+dependencies = [
+ "serde_core",
+]
+
+[[package]]
+name = "cargo-platform"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "cargo_metadata"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9"
+dependencies = [
+ "camino",
+ "cargo-platform",
+ "semver",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+
+[[package]]
name = "just_fmt"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -15,12 +54,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96"
[[package]]
+name = "memchr"
+version = "2.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
+
+[[package]]
name = "mingling_pathf"
version = "0.5.0"
dependencies = [
+ "cargo_metadata",
"just_fmt 0.2.0",
"proc-macro2",
- "syn",
+ "syn 2.0.118",
]
[[package]]
@@ -42,6 +88,59 @@ dependencies = [
]
[[package]]
+name = "semver"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
+dependencies = [
+ "serde",
+ "serde_core",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
+dependencies = [
+ "serde_core",
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_core"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.229"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
name = "syn"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -53,6 +152,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "test-mingling-pathf"
version = "0.1.0"
dependencies = [
@@ -61,7 +171,33 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
+[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "zmij"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"