aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml5
-rw-r--r--.run/src/bin/ci.rs11
-rwxr-xr-x[-rw-r--r--].run/src/bin/clippy.sh0
-rw-r--r--.run/version-files.toml4
-rw-r--r--CHANGELOG.md7
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml6
-rw-r--r--GETTING_STARTED.md2
-rw-r--r--build.rs13
-rw-r--r--docs/_zh_CN/pages/advanced/1-completion.md4
-rw-r--r--docs/pages/advanced/1-completion.md4
-rw-r--r--examples/example-completion/Cargo.toml4
-rw-r--r--examples/example-completion/src/main.rs2
-rw-r--r--examples/example-pathfinder/Cargo.toml4
-rw-r--r--mingling/Cargo.toml6
-rw-r--r--mingling/src/example_docs.rs10
-rw-r--r--mingling/src/features.rs11
-rw-r--r--mingling_cli/Cargo.toml2
-rw-r--r--mingling_cli/src/linter.rs7
-rw-r--r--mingling_cli/src/linter/cmd_mlint_install.rs454
-rw-r--r--mingling_cli/src/lints.rs2
-rw-r--r--mingling_cli/tmpls/lints.tmpl2
-rw-r--r--mingling_cli/tmpls/rust-analyzer.toml9
-rw-r--r--mingling_core/Cargo.toml2
-rw-r--r--mingling_core/src/any.rs6
-rw-r--r--mingling_core/src/asset.rs35
-rw-r--r--mingling_core/src/asset/global_resource.rs5
-rw-r--r--mingling_core/src/build.rs13
-rw-r--r--mingling_core/src/build/comp.rs (renamed from mingling_core/src/builds/comp.rs)0
-rw-r--r--mingling_core/src/build/pathf.rs (renamed from mingling_core/src/builds/pathf.rs)0
-rw-r--r--mingling_core/src/builds.rs7
-rw-r--r--mingling_core/src/lib.rs120
-rw-r--r--mingling_core/src/private.rs12
-rw-r--r--mingling_core/tests/test-all/tests/integration.rs2
-rw-r--r--mingling_core/tests/test-comp/tests/integration.rs2
-rw-r--r--src/main.rs1
36 files changed, 194 insertions, 584 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 563e8e1..71b63ca 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -94,12 +94,17 @@ jobs:
- name: Run cov-test
run: cargo run --manifest-path .run/Cargo.toml --bin cov-test
+ - name: Delete .temp directory before deployment
+ run: rm -rf .temp
+
- name: Setup Pages
uses: actions/configure-pages@v5
+
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "."
+
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
diff --git a/.run/src/bin/ci.rs b/.run/src/bin/ci.rs
index 954034c..4b6f973 100644
--- a/.run/src/bin/ci.rs
+++ b/.run/src/bin/ci.rs
@@ -142,6 +142,11 @@ fn ci(test_docs: bool, test_codes: bool, run_all: bool) -> Result<(), i32> {
exit_code = exit_code.max(code);
}
+ println_cargo_style!("Phase: Try Build API docs");
+ if let Err(code) = deploy_api_docs() {
+ exit_code = exit_code.max(code);
+ }
+
if exit_code != 0 {
return Err(exit_code);
}
@@ -225,6 +230,12 @@ fn test_all() -> Result<(), i32> {
run_parallel("Testing", tasks)
}
+fn deploy_api_docs() -> Result<(), i32> {
+ run_cmd!(
+ "cargo run --manifest-path .run/Cargo.toml --color always --bin deploy-api-docs -- --docsrs"
+ )
+}
+
fn docs_refresh() -> Result<(), i32> {
println_cargo_style!("Refresh: document at `./docs/`");
diff --git a/.run/src/bin/clippy.sh b/.run/src/bin/clippy.sh
index b393545..b393545 100644..100755
--- a/.run/src/bin/clippy.sh
+++ b/.run/src/bin/clippy.sh
diff --git a/.run/version-files.toml b/.run/version-files.toml
index ca104d2..b69a568 100644
--- a/.run/version-files.toml
+++ b/.run/version-files.toml
@@ -17,3 +17,7 @@ pattern = "version = \"{VER}\""
[[file]]
file = "./docs/res/guide.txt"
pattern = "mingling = \"{VER}\""
+
+[[file]]
+file = "./mingling_core/src/lib.rs"
+pattern = "mingling = \"{VER}\""
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed7ad66..62ec971 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -171,6 +171,13 @@ None
_No migration is required — these are purely additive derives that expand the type's capabilities without affecting existing behavior._
+**[`core`]** Added the `build` feature (renamed from `builds`) to `mingling_core` and `mingling`. The old `builds` feature has been deprecated in favor of `build`, with a backward-compatibility alias retained in `mingling/Cargo.toml`:
+
+- **`mingling_core/Cargo.toml`**: Renamed the feature from `builds` to `build`.
+- **`mingling/Cargo.toml`**: Changed the feature dependency from `mingling_core/builds` to `mingling_core/build`. A deprecated `builds` feature alias is kept as `builds = ["mingling_core/build"]` with a note indicating it will be removed in a future breaking change.
+
+ _No behavioral changes — the `build` feature provides identical functionality to the old `builds` feature. Downstream code using `builds` continues to work via the alias, but should migrate to `build`._
+
#### Features:
1. **[`core`]** Added `RenderResult::new()` method for creating a new `RenderResult` with default values (empty text and exit code 0). This provides a more explicit and discoverable constructor compared to `RenderResult::default()`, making it clearer when a fresh result is being created for use with `write!`/`writeln!`.
diff --git a/Cargo.lock b/Cargo.lock
index 5db81a8..77fcf77 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -270,6 +270,10 @@ dependencies = [
]
[[package]]
+name = "mingling-workspace"
+version = "0.3.0"
+
+[[package]]
name = "mingling_core"
version = "0.3.0"
dependencies = [
diff --git a/Cargo.toml b/Cargo.toml
index 8baadbb..558a4b8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -77,3 +77,9 @@ lto = "fat"
codegen-units = 1
panic = "abort"
strip = true
+
+[package]
+name = "mingling-workspace"
+version.workspace = true
+edition.workspace = true
+publish = false
diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md
index 621471e..516122e 100644
--- a/GETTING_STARTED.md
+++ b/GETTING_STARTED.md
@@ -239,7 +239,7 @@ In your `build.rs`, generate the shell scripts:
```rust
// BUILD TIME
-// Features: ["comp", "builds"]
+// Features: ["comp", "build"]
mingling::build::build_comp_scripts(env!("CARGO_PKG_NAME")).unwrap();
```
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..951ecf8
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,13 @@
+use std::{env::current_dir, fs};
+
+fn main() {
+ gen_fake_cargo_toml_in_temp_dir();
+}
+
+fn gen_fake_cargo_toml_in_temp_dir() {
+ fs::write(
+ current_dir().unwrap().join(".temp").join("Cargo.toml"),
+ "[workspace]",
+ )
+ .unwrap();
+}
diff --git a/docs/_zh_CN/pages/advanced/1-completion.md b/docs/_zh_CN/pages/advanced/1-completion.md
index 3941404..a6500db 100644
--- a/docs/_zh_CN/pages/advanced/1-completion.md
+++ b/docs/_zh_CN/pages/advanced/1-completion.md
@@ -15,8 +15,8 @@ features = ["comp"]
[build-dependencies.mingling]
features = [
"comp",
- # 启用 `builds` 特性以提供构建期支持
- "builds"
+ # 启用 `build` 特性以提供构建期支持
+ "build"
]
```
diff --git a/docs/pages/advanced/1-completion.md b/docs/pages/advanced/1-completion.md
index a90c3ce..52350db 100644
--- a/docs/pages/advanced/1-completion.md
+++ b/docs/pages/advanced/1-completion.md
@@ -15,8 +15,8 @@ features = ["comp"]
[build-dependencies.mingling]
features = [
"comp",
- # Enable `builds` for build-time support
- "builds"
+ # Enable `build` for build-time support
+ "build"
]
```
diff --git a/examples/example-completion/Cargo.toml b/examples/example-completion/Cargo.toml
index 1c6b327..00c7f8c 100644
--- a/examples/example-completion/Cargo.toml
+++ b/examples/example-completion/Cargo.toml
@@ -20,8 +20,8 @@ features = [
"comp",
# If you want to build completion scripts,
- # enable `builds` features
- "builds",
+ # enable `build` features
+ "build",
]
[workspace]
diff --git a/examples/example-completion/src/main.rs b/examples/example-completion/src/main.rs
index 45cc8ef..d65be49 100644
--- a/examples/example-completion/src/main.rs
+++ b/examples/example-completion/src/main.rs
@@ -7,7 +7,7 @@
//! To make your completions work, you need to generate a completion script using Mingling's tools
//!
//! 1. Enable features
-//! You need to enable the `builds` and `comp` features for `mingling` in `[build-dependencies]`
+//! You need to enable the `build` and `comp` features for `mingling` in `[build-dependencies]`
//!
//! 2. Write `build.rs`
//! Write the following in `build.rs`
diff --git a/examples/example-pathfinder/Cargo.toml b/examples/example-pathfinder/Cargo.toml
index bd362f2..bc41bd2 100644
--- a/examples/example-pathfinder/Cargo.toml
+++ b/examples/example-pathfinder/Cargo.toml
@@ -18,8 +18,8 @@ features = [
# Enable `pathf` features
"pathf",
- # Enable the `builds` feature for build-time support
- "builds",
+ # Enable the `build` feature for build-time support
+ "build",
]
[workspace]
diff --git a/mingling/Cargo.toml b/mingling/Cargo.toml
index 351384f..9bf82a7 100644
--- a/mingling/Cargo.toml
+++ b/mingling/Cargo.toml
@@ -43,7 +43,8 @@ macros = ["dep:mingling_macros", "mingling_macros/default"]
nightly = ["mingling_core/nightly", "mingling_macros/nightly"]
debug = ["mingling_core/debug"]
async = ["mingling_core/async", "mingling_macros/async"]
-builds = ["mingling_core/builds"]
+
+build = ["mingling_core/build"]
default = ["core", "macros"]
@@ -92,6 +93,9 @@ extra_macros = ["mingling_macros/extra_macros"]
# Section only shown in docs.rs
docs_rs = []
+# This is an old name, will be Breaking Change in the future
+builds = ["mingling_core/build"]
+
[dependencies]
mingling_core = { workspace = true, optional = true }
mingling_macros = { workspace = true, optional = true }
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index 89d5af1..35cf024 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -777,7 +777,7 @@ pub mod example_combine_pathf_dispatch_tree {}
/// To make your completions work, you need to generate a completion script using Mingling's tools
///
/// 1. Enable features
-/// You need to enable the `builds` and `comp` features for `mingling` in `[build-dependencies]`
+/// You need to enable the `build` and `comp` features for `mingling` in `[build-dependencies]`
///
/// 2. Write `build.rs`
/// Write the following in `build.rs`
@@ -838,8 +838,8 @@ pub mod example_combine_pathf_dispatch_tree {}
/// "comp",
///
/// # If you want to build completion scripts,
-/// # enable `builds` features
-/// "builds",
+/// # enable `build` features
+/// "build",
/// ]
///
/// [workspace]
@@ -2268,8 +2268,8 @@ pub mod example_panic_unwind {}
/// # Enable `pathf` features
/// "pathf",
///
-/// # Enable the `builds` feature for build-time support
-/// "builds",
+/// # Enable the `build` feature for build-time support
+/// "build",
/// ]
///
/// [workspace]
diff --git a/mingling/src/features.rs b/mingling/src/features.rs
index 78d6226..0dde333 100644
--- a/mingling/src/features.rs
+++ b/mingling/src/features.rs
@@ -20,6 +20,17 @@ 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 `builds` feature is enabled
/// Current: `disabled`
#[cfg(not(feature = "builds"))]
diff --git a/mingling_cli/Cargo.toml b/mingling_cli/Cargo.toml
index 906cdd0..330ef5a 100644
--- a/mingling_cli/Cargo.toml
+++ b/mingling_cli/Cargo.toml
@@ -31,7 +31,7 @@ features = [
[build-dependencies.mingling]
path = "../mingling"
features = [
- "builds",
+ "build",
"pathf",
]
diff --git a/mingling_cli/src/linter.rs b/mingling_cli/src/linter.rs
index 5d20900..859ffc5 100644
--- a/mingling_cli/src/linter.rs
+++ b/mingling_cli/src/linter.rs
@@ -4,15 +4,11 @@ use mingling::{
};
use crate::{
- linter::{
- cmd_mlint::{CMDLint, EntryLint},
- cmd_mlint_install::CMDLintInstall,
- },
+ linter::cmd_mlint::{CMDLint, EntryLint},
metadata::setup::ResUsingJson,
};
pub mod cmd_mlint;
-pub mod cmd_mlint_install;
pub mod mlint_attr;
pub mod mlint_report;
@@ -24,7 +20,6 @@ pub fn mingling_linter_setup(program: &mut Program<crate::ThisProgram>) {
#[program_setup]
pub fn mingling_linter_command_setup(program: &mut Program<crate::ThisProgram>) {
program.with_dispatcher(CMDLint);
- program.with_dispatcher(CMDLintInstall);
program.with_dispatcher(CMDLinterSupportRustAnalyzer);
program.with_dispatcher(CMDLinterSupportRustAnalyzerWithClippy);
program.with_dispatcher(CMDLinterSupportRustAnalyzerWithCheck);
diff --git a/mingling_cli/src/linter/cmd_mlint_install.rs b/mingling_cli/src/linter/cmd_mlint_install.rs
deleted file mode 100644
index d29d3e5..0000000
--- a/mingling_cli/src/linter/cmd_mlint_install.rs
+++ /dev/null
@@ -1,454 +0,0 @@
-use crate::Next;
-use crate::linter::mlint_report::{
- LintSpan, LintSpanLine, LintSuggestion, MlintLevel, MlintReport, StateLintReports,
-};
-use mingling::Routable;
-use mingling::macros::{buffer, chain, dispatcher, pack, r_eprintln, renderer, routeify};
-use mingling::res::ResCurrentDir;
-use std::ops::Range;
-use std::path::PathBuf;
-
-const OVERRIDE_KEY: &str = "check.overrideCommand";
-const EXPECTED_LINE: &str = r#"check.overrideCommand = ["mling", "ra-lint-check"]"#;
-const VALID_FIRST: &[&str] = &["mling", "mingling-cli"];
-const RA_CONFIG_TEMPLATE: &str = include_str!("../../tmpls/rust-analyzer.toml");
-
-// Key names
-const KEY_CHECK_ON_SAVE: &str = "checkOnSave";
-const VALUE_CHECK_ON_SAVE_TRUE: &str = "true";
-const DISPLAY_CHECK_ON_SAVE_TRUE: &str = "checkOnSave = true";
-
-// File names
-const CFG_FILE_NAME: &str = ".rust-analyzer.toml";
-const SOURCE_FILE_NAME: &str = "rust-analyzer.toml";
-
-const MSG_ALREADY_CORRECT: &str = "`.rust-analyzer.toml` already has the correct mling settings";
-const MSG_NON_EMPTY_ARRAY: &str = "`check.overrideCommand`: expected a non-empty array";
-const MSG_FIRST_ARG_INVALID: &str =
- "`check.overrideCommand`: first argument should be `mling` or `mingling-cli`";
-const MSG_MISSING_SECOND: &str = "`check.overrideCommand`: missing second argument";
-const MSG_SECOND_ARG_INVALID: &str =
- "`check.overrideCommand`: second argument should be a `ra-lint-*` subcommand or `lint`";
-const MSG_MESSAGE_FORMAT_REQUIRED: &str =
- "`check.overrideCommand`: `lint` subcommand needs `--message-format=json`";
-
-// Suggestions / replacements
-const SUGGEST_RA_LINT_CHECK_ARRAY: &str = r#"["mling", "ra-lint-check"]"#;
-const SUGGEST_MLING_QUOTED: &str = r#""mling""#;
-const SUGGEST_RA_LINT_CHECK_QUOTED: &str = r#""ra-lint-check""#;
-const SUGGEST_MESSAGE_FORMAT_JSON: &str = ", \"--message-format=json\"]";
-const SUGGEST_OVERRIDE_LINE: &str = "overrideCommand = [\"mling\", \"ra-lint-check\"]\n";
-const SUGGEST_OVERRIDE_FULL_LINE: &str = r#"check.overrideCommand = ["mling", "ra-lint-check"]"#;
-
-// Subcommand constants
-const SUB_CMD_LINT: &str = "lint";
-const MESSAGE_FORMAT_FLAG: &str = "--message-format=json";
-
-dispatcher!("lint-install", CMDLintInstall => EntryLintInstall);
-
-pack!(StateWriteMlingLinterConfig = PathBuf);
-pack!(StateSuggestMlingLinterSetup = ());
-pack!(ResultMlingLinterConfigInstalled = PathBuf);
-
-#[chain]
-pub fn handle_lint_install(_: EntryLintInstall, current_dir: &ResCurrentDir) -> Next {
- let cfg_file_path = current_dir.join(CFG_FILE_NAME);
-
- if !cfg_file_path.exists() {
- return StateWriteMlingLinterConfig::new(cfg_file_path).to_chain();
- }
-
- StateSuggestMlingLinterSetup::new(()).to_chain()
-}
-
-#[chain(routeify)]
-pub fn handle_state_write_mling_linter_config(prev: StateWriteMlingLinterConfig) -> Next {
- let cfg_file_path = prev.inner;
- std::fs::write(&cfg_file_path, RA_CONFIG_TEMPLATE)?;
- ResultMlingLinterConfigInstalled::new(cfg_file_path).into()
-}
-
-#[renderer(buffer)]
-pub fn render_mling_linter_config_installed(result: ResultMlingLinterConfigInstalled) {
- let cfg_file_path = result.inner;
- r_eprintln!(
- "info: created `{}` with mling lint-integrated settings",
- cfg_file_path.display()
- );
-}
-
-#[chain]
-pub fn handle_state_suggest_mling_linter_setup(
- _: StateSuggestMlingLinterSetup,
- current_dir: &ResCurrentDir,
-) -> StateLintReports {
- let cfg_file_path = current_dir.join(CFG_FILE_NAME);
- let file_name = cfg_file_path.to_string_lossy().to_string();
-
- let content = match std::fs::read_to_string(&cfg_file_path) {
- Ok(c) => c,
- Err(e) => {
- return StateLintReports::new(vec![MlintReport {
- level: MlintLevel::Error,
- message: format!("failed to read `{file_name}`: {e}"),
- ..Default::default()
- }]);
- }
- };
-
- let mut reports: Vec<MlintReport> = vec![];
- reports.extend(check_simple_key(
- &content,
- KEY_CHECK_ON_SAVE,
- VALUE_CHECK_ON_SAVE_TRUE,
- DISPLAY_CHECK_ON_SAVE_TRUE,
- SOURCE_FILE_NAME,
- ));
- reports.extend(check_override_command(&content, SOURCE_FILE_NAME));
-
- if reports.is_empty() {
- reports.push(MlintReport {
- level: MlintLevel::Note,
- message: MSG_ALREADY_CORRECT.to_string(),
- ..Default::default()
- });
- }
-
- StateLintReports::new(reports)
-}
-
-/// A `MlintReport` at `Help` level with the given message, file, and source.
-fn report_help(file_name: &str, source_code: &str, message: String) -> MlintReport {
- MlintReport {
- file_name: file_name.to_string(),
- source_code: source_code.to_string(),
- level: MlintLevel::Help,
- message,
- ..Default::default()
- }
-}
-
-/// Attach a single-line span + replace suggestion to a report.
-fn with_replace_suggestion(
- report: MlintReport,
- line: usize,
- line_text: &str,
- byte_range: Range<usize>,
- replacement: String,
- label: Option<String>,
-) -> MlintReport {
- let span = LintSpan {
- line_start: line,
- line_end: line,
- column_start: byte_range.start + 1,
- column_end: byte_range.end + 1,
- text: vec![LintSpanLine {
- text: line_text.to_string(),
- highlight_start: byte_range.start + 1,
- highlight_end: byte_range.end + 1,
- }],
- label,
- };
- let suggestion = LintSuggestion {
- source: line_text.to_string(),
- line_start: line,
- byte_range,
- replacement,
- };
- MlintReport {
- spans: vec![span],
- suggestions: vec![suggestion],
- ..report
- }
-}
-
-/// Attach an "insert new content" suggestion (byte_range 0..0) to a report.
-fn with_insert_suggestion(report: MlintReport, line: usize, new_content: String) -> MlintReport {
- let suggestion = LintSuggestion {
- source: new_content.clone(),
- line_start: line,
- byte_range: 0..0,
- replacement: new_content,
- };
- MlintReport {
- suggestions: vec![suggestion],
- ..report
- }
-}
-
-fn check_simple_key(
- content: &str,
- key: &str,
- expected_val: &str,
- display_line: &str,
- source_file: &str,
-) -> Vec<MlintReport> {
- let found = find_key_value(content, key);
-
- let matches = found
- .as_ref()
- .is_some_and(|(_, v)| collapse_whitespace(v) == collapse_whitespace(expected_val));
-
- if matches {
- return vec![];
- }
-
- let msg = format!("expected `{display_line}` in `rust-analyzer.toml`");
- let report = report_help(source_file, content, msg);
-
- match found {
- Some((ln, val)) => {
- // Key exists but value is wrong → suggest replacing the value
- let line_text = nth_line(content, ln);
- let byte_start = line_text.find(&val).unwrap_or(0);
- let byte_end = byte_start + val.len();
- vec![with_replace_suggestion(
- report,
- ln,
- &line_text,
- byte_start..byte_end,
- expected_val.to_string(),
- Some(format!("expected {expected_val}")),
- )]
- }
- None => {
- // Key missing entirely → suggest inserting line at end
- let insert_line = content.lines().count().max(1) + 1;
- let new_content = format!("{display_line}\n");
- vec![with_insert_suggestion(report, insert_line, new_content)]
- }
- }
-}
-
-fn check_override_command(content: &str, source_file: &str) -> Vec<MlintReport> {
- let mut reports = Vec::new();
-
- let Some((ln, val)) = find_key_value(content, OVERRIDE_KEY) else {
- // Setting entirely missing
- let report = report_help(
- source_file,
- content,
- format!("expected `{EXPECTED_LINE}` in `rust-analyzer.toml`"),
- );
- let (insert_line, new_content) = match find_table_header(content, "check") {
- Some(header_line) => (header_line + 1, SUGGEST_OVERRIDE_LINE.to_string()),
- None => (
- content.lines().count().max(1) + 1,
- format!("{SUGGEST_OVERRIDE_FULL_LINE}\n"),
- ),
- };
- reports.push(with_insert_suggestion(report, insert_line, new_content));
- return reports;
- };
-
- let line_text = nth_line(content, ln);
- let args = parse_array_items(&val);
-
- // First: must be `mling` or `mingling-cli`
- if !args
- .first()
- .is_some_and(|a| VALID_FIRST.contains(&a.as_str()))
- {
- let Some(first) = args.first() else {
- let report = report_help(source_file, content, MSG_NON_EMPTY_ARRAY.into());
- reports.push(with_replace_suggestion(
- report,
- ln,
- &line_text,
- 0..val.len(),
- SUGGEST_RA_LINT_CHECK_ARRAY.into(),
- None,
- ));
- return reports;
- };
- let quoted = format!("\"{first}\"");
- let byte_start = line_text.find(&quoted).unwrap_or(0);
- let byte_end = byte_start + quoted.len();
- let report = report_help(source_file, content, MSG_FIRST_ARG_INVALID.into());
- reports.push(with_replace_suggestion(
- report,
- ln,
- &line_text,
- byte_start..byte_end,
- SUGGEST_MLING_QUOTED.into(),
- None,
- ));
- return reports;
- }
-
- // Second: must be `ra-lint-*` or `lint`
- let Some(second) = args.get(1) else {
- let report = report_help(source_file, content, MSG_MISSING_SECOND.into());
- reports.push(with_replace_suggestion(
- report,
- ln,
- &line_text,
- 0..val.len(),
- SUGGEST_RA_LINT_CHECK_ARRAY.into(),
- None,
- ));
- return reports;
- };
-
- if !second.starts_with("ra-lint-") && second != SUB_CMD_LINT {
- let quoted = format!("\"{second}\"");
- let byte_start = line_text.find(&quoted).unwrap_or(0);
- let byte_end = byte_start + quoted.len();
- let report = report_help(source_file, content, MSG_SECOND_ARG_INVALID.into());
- reports.push(with_replace_suggestion(
- report,
- ln,
- &line_text,
- byte_start..byte_end,
- SUGGEST_RA_LINT_CHECK_QUOTED.into(),
- None,
- ));
- return reports;
- }
-
- // If second arg is `lint`, it must be followed by --message-format=json
- if second == SUB_CMD_LINT && !has_message_format_json(&args[2..]) {
- let byte_start = line_text
- .rfind(']')
- .unwrap_or(line_text.len().saturating_sub(1));
- let byte_end = byte_start + 1;
- let report = report_help(source_file, content, MSG_MESSAGE_FORMAT_REQUIRED.into());
- reports.push(with_replace_suggestion(
- report,
- ln,
- &line_text,
- byte_start..byte_end,
- SUGGEST_MESSAGE_FORMAT_JSON.into(),
- None,
- ));
- }
-
- reports
-}
-
-fn has_message_format_json(rest: &[String]) -> bool {
- rest.contains(&MESSAGE_FORMAT_FLAG.to_string())
- || rest
- .windows(2)
- .any(|w| w[0] == "--message-format" && w[1] == "json")
-}
-
-fn parse_array_items(s: &str) -> Vec<String> {
- let s = s.trim();
- if !s.starts_with('[') || !s.ends_with(']') {
- return vec![];
- }
- let inner = s[1..s.len() - 1].trim();
- if inner.is_empty() {
- return vec![];
- }
- let mut items = Vec::new();
- let mut current = String::new();
- let mut in_quote = false;
- for ch in inner.chars() {
- match ch {
- '"' => in_quote = !in_quote,
- ',' if !in_quote => {
- let trimmed = current.trim().trim_matches('"').to_string();
- if !trimmed.is_empty() {
- items.push(trimmed);
- }
- current.clear();
- }
- _ => current.push(ch),
- }
- }
- let trimmed = current.trim().trim_matches('"').to_string();
- if !trimmed.is_empty() {
- items.push(trimmed);
- }
- items
-}
-
-/// Result of looking up a key=value pair in TOML content.
-///
-/// - `Some((line, value))` — found on that 1-based line with that value string.
-/// - `None` — key not found.
-type FoundKey = Option<(usize, String)>;
-
-fn find_key_value(content: &str, dotted_key: &str) -> FoundKey {
- let parts: Vec<&str> = dotted_key.split('.').collect();
- let field = parts.last().copied().unwrap_or(dotted_key);
- let table_path = if parts.len() > 1 {
- &parts[..parts.len() - 1]
- } else {
- &[]
- };
- let table_path_str = if parts.len() > 1 {
- Some(parts[..parts.len() - 1].join("."))
- } else {
- None
- };
-
- let mut in_correct_table = table_path.is_empty();
-
- for (i, line) in content.lines().enumerate() {
- let trimmed = line.trim();
-
- // Track table headers like [check]
- if trimmed.starts_with('[') && trimmed.ends_with(']') {
- let header = &trimmed[1..trimmed.len() - 1];
- in_correct_table = header.split('.').collect::<Vec<_>>() == table_path;
- continue;
- }
-
- let without_comment = trimmed.split('#').next().unwrap_or("").trim();
- if without_comment.is_empty() {
- continue;
- }
-
- if let Some(eq_pos) = without_comment.find('=') {
- let k = without_comment[..eq_pos].trim();
- let v = without_comment[eq_pos + 1..].trim();
-
- // Inside explicit [table] header
- if in_correct_table && k == field {
- return Some((i + 1, v.to_string()));
- }
- // Inline dotted key at root (e.g. `check.overrideCommand = ...`)
- if table_path_str.is_some() && k == dotted_key {
- return Some((i + 1, v.to_string()));
- }
- }
- }
-
- None
-}
-
-fn find_table_header(content: &str, table_name: &str) -> Option<usize> {
- let target = format!("[{table_name}]");
- content
- .lines()
- .position(|line| line.trim() == target)
- .map(|i| i + 1)
-}
-
-fn nth_line(content: &str, n: usize) -> String {
- content
- .lines()
- .nth(n.saturating_sub(1))
- .unwrap_or("")
- .to_string()
-}
-
-fn collapse_whitespace(s: &str) -> String {
- let mut out = String::with_capacity(s.len());
- let mut in_space = false;
- for ch in s.chars() {
- if ch.is_whitespace() {
- if !in_space {
- out.push(' ');
- in_space = true;
- }
- } else {
- out.push(ch);
- in_space = false;
- }
- }
- out.trim().to_string()
-}
diff --git a/mingling_cli/src/lints.rs b/mingling_cli/src/lints.rs
index 89f5ca3..8cc1e6e 100644
--- a/mingling_cli/src/lints.rs
+++ b/mingling_cli/src/lints.rs
@@ -1,3 +1,5 @@
+// This file is auto-generated by pre/lint_registry.rs
+
#![allow(unused)]
use crate::linter::mlint_report::{MlintLevel, MlintReport};
diff --git a/mingling_cli/tmpls/lints.tmpl b/mingling_cli/tmpls/lints.tmpl
index 590828a..e177079 100644
--- a/mingling_cli/tmpls/lints.tmpl
+++ b/mingling_cli/tmpls/lints.tmpl
@@ -1,3 +1,5 @@
+// This file is auto-generated by pre/lint_registry.rs
+
#![allow(unused)]
use crate::linter::mlint_report::{MlintLevel, MlintReport};
diff --git a/mingling_cli/tmpls/rust-analyzer.toml b/mingling_cli/tmpls/rust-analyzer.toml
deleted file mode 100644
index 96a96b4..0000000
--- a/mingling_cli/tmpls/rust-analyzer.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-checkOnSave = true
-
-# Use mling with ra-lint-check for code checking
-#
-# This tool will:
-# 1. first run `cargo check` to perform basic checks on your workspace
-# 2. then run `mling lint` to perform additional checks
-# on the `Mingling` framework code in your workspace
-check.overrideCommand = ["mling", "ra-lint-check"]
diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml
index 14140c6..f525609 100644
--- a/mingling_core/Cargo.toml
+++ b/mingling_core/Cargo.toml
@@ -14,7 +14,7 @@ categories = ["command-line-interface"]
nightly = []
default = []
async = []
-builds = []
+build = []
picker = []
dispatch_tree = []
diff --git a/mingling_core/src/any.rs b/mingling_core/src/any.rs
index 3e8fdf0..e922e2e 100644
--- a/mingling_core/src/any.rs
+++ b/mingling_core/src/any.rs
@@ -1,8 +1,8 @@
+use crate::ProgramCollect;
use crate::error::ChainProcessError;
-use crate::{Grouped, ProgramCollect};
-#[doc(hidden)]
-pub mod group;
+mod group;
+pub use group::*;
/// Any type output
///
diff --git a/mingling_core/src/asset.rs b/mingling_core/src/asset.rs
index 9b9a5d4..f26952b 100644
--- a/mingling_core/src/asset.rs
+++ b/mingling_core/src/asset.rs
@@ -1,26 +1,9 @@
-#[doc(hidden)]
-pub mod chain;
-
-#[doc(hidden)]
-pub mod dispatcher;
-
-#[doc(hidden)]
-pub mod enum_tag;
-
-#[doc(hidden)]
-pub mod global_resource;
-
-#[doc(hidden)]
-pub mod help;
-
-#[doc(hidden)]
-pub mod lazy_resource;
-
-#[doc(hidden)]
-pub mod node;
-
-#[doc(hidden)]
-pub mod renderer;
-
-#[doc(hidden)]
-pub mod routable;
+pub(crate) mod chain;
+pub(crate) mod dispatcher;
+pub(crate) mod enum_tag;
+pub(crate) mod global_resource;
+pub(crate) mod help;
+pub(crate) mod lazy_resource;
+pub(crate) mod node;
+pub(crate) mod renderer;
+pub(crate) mod routable;
diff --git a/mingling_core/src/asset/global_resource.rs b/mingling_core/src/asset/global_resource.rs
index a610378..19374e7 100644
--- a/mingling_core/src/asset/global_resource.rs
+++ b/mingling_core/src/asset/global_resource.rs
@@ -184,7 +184,10 @@ pub trait ResourceMarker {
C: ProgramCollect<Enum = C> + 'static;
}
-impl<T: Default + Clone + Send + Sync + 'static> ResourceMarker for T {
+impl<T> ResourceMarker for T
+where
+ T: Default + Clone + Send + Sync + 'static,
+{
fn res_clone(&self) -> Self {
Clone::clone(self)
}
diff --git a/mingling_core/src/build.rs b/mingling_core/src/build.rs
new file mode 100644
index 0000000..7918f3a
--- /dev/null
+++ b/mingling_core/src/build.rs
@@ -0,0 +1,13 @@
+#[doc(hidden)]
+#[cfg(feature = "comp")]
+mod comp;
+
+#[cfg(feature = "comp")]
+pub use comp::*;
+
+#[doc(hidden)]
+#[cfg(feature = "pathf")]
+mod pathf;
+
+#[cfg(feature = "pathf")]
+pub use pathf::*;
diff --git a/mingling_core/src/builds/comp.rs b/mingling_core/src/build/comp.rs
index 2abb1e1..2abb1e1 100644
--- a/mingling_core/src/builds/comp.rs
+++ b/mingling_core/src/build/comp.rs
diff --git a/mingling_core/src/builds/pathf.rs b/mingling_core/src/build/pathf.rs
index d8d4698..d8d4698 100644
--- a/mingling_core/src/builds/pathf.rs
+++ b/mingling_core/src/build/pathf.rs
diff --git a/mingling_core/src/builds.rs b/mingling_core/src/builds.rs
deleted file mode 100644
index 3c52907..0000000
--- a/mingling_core/src/builds.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#[doc(hidden)]
-#[cfg(feature = "comp")]
-pub mod comp;
-
-#[doc(hidden)]
-#[cfg(feature = "pathf")]
-pub mod pathf;
diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs
index 31476c9..b9dbd06 100644
--- a/mingling_core/src/lib.rs
+++ b/mingling_core/src/lib.rs
@@ -1,3 +1,4 @@
+// #![deny(missing_docs)]
//! Mingling Core
//!
//! # Intro
@@ -8,7 +9,7 @@
//!
//! Recommended to import [mingling](https://crates.io/crates/mingling) to use its features.
-#![deny(missing_docs)]
+// Private Modules
mod any;
mod asset;
@@ -16,20 +17,65 @@ mod program;
mod renderer;
mod tester;
+/// Module for setting up a `Mingling` program.
+///
+/// This module provides the [`ProgramSetup`] type, which allows users to configure
+/// and initialize the program's execution environment.
+pub mod setup {
+ pub use crate::program::setup::ProgramSetup;
+}
+
+/// This module provides result types for Mingling components.
+///
+/// These are re-exported at the top level via `mingling::res`.
+#[doc(hidden)]
+pub mod core_res {
+ #[cfg(feature = "repl")]
+ pub use crate::program::repl_exec::res::*;
+}
+
+/// Provides the runtime logic for Mingling's dynamic completion system.
+///
+/// This module contains the core functionality for the "comp" (completion) feature,
+/// which enables dynamic tab-completion and input suggestion capabilities within
+/// Mingling applications.
+#[cfg(feature = "comp")]
+pub(crate) mod comp;
+
+/// Provides Mingling's build script module, used in `build.rs` to provide build-time behavior for certain features.
+///
+/// To use it, add the following to your `Cargo.toml` under `[build-dependencies]`, and enable the features
+/// that require build-time behavior from the crate:
+///
+/// ```toml
+/// [build-dependencies.mingling]
+/// version = "0.3.0"
+/// features = [
+/// "build", // Enable it
+/// "comp", // If you need completion-related build-time behavior, enable this as well
+/// ]
+/// ```
+#[cfg(feature = "build")]
+#[doc(hidden)]
+pub mod build;
+
+// Public Modules
+
/// Provides a toolkit for `Mingling` testing capabilities.
pub mod test {
pub use crate::tester::*;
}
-#[cfg(feature = "structural_renderer")]
-pub use crate::renderer::structural::StructuralRenderer;
+/// Provided for framework developers
+pub mod debug;
// NOT re-exported at top level: the `StructuralData` trait is sealed and only
// accessible through the derive macro. Users who need the trait can access it
// via `mingling::renderer::structural::StructuralData` (through the inner alias).
-pub use crate::any::group::*;
-pub use crate::any::*;
+#[cfg(feature = "structural_renderer")]
+pub use crate::renderer::structural::StructuralRenderer;
+pub use crate::any::*;
pub use crate::asset::chain::*;
pub use crate::asset::dispatcher::*;
pub use crate::asset::enum_tag::*;
@@ -39,74 +85,32 @@ pub use crate::asset::lazy_resource::*;
pub use crate::asset::node::*;
pub use crate::asset::renderer::*;
pub use crate::asset::routable::*;
+#[cfg(feature = "comp")]
+pub use crate::comp::*;
+pub use crate::program::*;
+pub use crate::renderer::render_result::*;
/// All error types of `Mingling`
pub mod error {
pub use crate::asset::chain::error::*;
pub use crate::exec::error::*;
pub use crate::program::error::*;
+
#[cfg(feature = "structural_renderer")]
pub use crate::renderer::structural::error::*;
- #[cfg(feature = "pathf")]
- pub use mingling_pathf::error::*;
-}
-
-pub use crate::program::*;
-
-pub use crate::renderer::render_result::*;
-
-#[cfg(feature = "builds")]
-#[doc(hidden)]
-pub mod builds;
-
-/// Provides build scripts for users
-#[cfg(feature = "builds")]
-pub mod build {
- #[cfg(feature = "comp")]
- pub use crate::builds::comp::*;
#[cfg(feature = "pathf")]
- pub use crate::builds::pathf::*;
+ pub use mingling_pathf::error::*;
}
-/// Provided for framework developers
-pub mod debug;
-
-#[cfg(feature = "comp")]
#[doc(hidden)]
-pub mod comp;
-
-#[cfg(feature = "comp")]
-pub use crate::comp::*;
+mod private;
-/// Module for setting up a `Mingling` program.
+/// Internal API provided by Mingling Core
///
-/// This module provides the [`ProgramSetup`] type, which allows users to configure
-/// and initialize the program's execution environment.
-pub mod setup {
- pub use crate::program::setup::ProgramSetup;
-}
-
-/// Private API — not intended for direct use.
+/// These are used by macros and are not exposed to users, but are still accessible externally.
#[doc(hidden)]
+#[allow(unused_imports)]
pub mod __private {
- use crate::ProgramCollect;
-
- /// Sealed trait for `StructuralData` — only implementable via derive macro.
- pub trait StructuralDataSealed<C>
- where
- C: ProgramCollect<Enum = C>,
- {
- }
-
- /// Re-export so the derive macro can reference the trait without
- /// conflicting with the derive macro name at `::mingling::StructuralData`.
- #[cfg(feature = "structural_renderer")]
- pub use crate::renderer::structural::structural_data::StructuralData;
-}
-
-#[doc(hidden)]
-pub mod core_res {
- #[cfg(feature = "repl")]
- pub use crate::program::repl_exec::res::ResREPL;
+ pub use crate::private::*;
}
diff --git a/mingling_core/src/private.rs b/mingling_core/src/private.rs
new file mode 100644
index 0000000..371ada2
--- /dev/null
+++ b/mingling_core/src/private.rs
@@ -0,0 +1,12 @@
+/// Sealed trait for `StructuralData` — only implementable via derive macro.
+#[cfg(feature = "structural_renderer")]
+pub trait StructuralDataSealed<C>
+where
+ C: crate::ProgramCollect<Enum = C>,
+{
+}
+
+/// Re-export so the derive macro can reference the trait without
+/// conflicting with the derive macro name at `::mingling::StructuralData`.
+#[cfg(feature = "structural_renderer")]
+pub use crate::renderer::structural::structural_data::StructuralData;
diff --git a/mingling_core/tests/test-all/tests/integration.rs b/mingling_core/tests/test-all/tests/integration.rs
index d36b9df..acb12db 100644
--- a/mingling_core/tests/test-all/tests/integration.rs
+++ b/mingling_core/tests/test-all/tests/integration.rs
@@ -7,9 +7,9 @@ use mingling::StringVec;
use mingling::StructuralData;
use mingling::StructuralRenderer;
use mingling::StructuralRendererSetting;
-use mingling::comp::{ShellContext, ShellFlag, Suggest};
use mingling::core_res::ResREPL;
use mingling::hook::ProgramHook;
+use mingling::{ShellContext, ShellFlag, Suggest};
use serde::Serialize;
use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/mingling_core/tests/test-comp/tests/integration.rs b/mingling_core/tests/test-comp/tests/integration.rs
index 37aa716..5c5a9e4 100644
--- a/mingling_core/tests/test-comp/tests/integration.rs
+++ b/mingling_core/tests/test-comp/tests/integration.rs
@@ -1,6 +1,6 @@
use mingling::MockProgramCollect;
use mingling::Program;
-use mingling::comp::{ShellContext, ShellFlag, Suggest, SuggestItem};
+use mingling::{ShellContext, ShellFlag, Suggest, SuggestItem};
#[test]
fn test_shell_context_parsing_full() {
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1 @@
+fn main() {}