aboutsummaryrefslogtreecommitdiff
path: root/mingling_cli
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_cli')
-rw-r--r--mingling_cli/Cargo.lock147
-rw-r--r--mingling_cli/Cargo.toml18
-rw-r--r--mingling_cli/build.rs5
-rw-r--r--mingling_cli/src/linter.rs15
-rw-r--r--mingling_cli/src/linter/cmd_mlint.rs6
-rw-r--r--mingling_cli/src/main.rs27
-rw-r--r--mingling_cli/src/metadata.rs12
-rw-r--r--mingling_cli/src/metadata/cmd_metadata.rs16
-rw-r--r--mingling_cli/src/metadata/setup.rs120
9 files changed, 360 insertions, 6 deletions
diff --git a/mingling_cli/Cargo.lock b/mingling_cli/Cargo.lock
index 378c81b..e6098d5 100644
--- a/mingling_cli/Cargo.lock
+++ b/mingling_cli/Cargo.lock
@@ -16,29 +16,78 @@ version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
+name = "camino"
+version = "1.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0"
+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.2.0"
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"
version = "0.3.0"
dependencies = [
"arg-picker",
"mingling_core",
"mingling_macros",
+ "serde",
]
[[package]]
name = "mingling-cli"
version = "0.3.0"
dependencies = [
+ "cargo_metadata",
"mingling",
+ "serde",
+ "serde_json",
]
[[package]]
@@ -47,6 +96,8 @@ version = "0.3.0"
dependencies = [
"just_fmt",
"mingling_pathf",
+ "serde",
+ "serde_json",
]
[[package]]
@@ -56,7 +107,7 @@ dependencies = [
"just_fmt",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -65,7 +116,7 @@ version = "0.3.0"
dependencies = [
"just_fmt",
"proc-macro2",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -87,6 +138,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.2",
+]
+
+[[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.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -98,7 +202,44 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.2",
+]
+
+[[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"
diff --git a/mingling_cli/Cargo.toml b/mingling_cli/Cargo.toml
index 1cc45b6..93021f0 100644
--- a/mingling_cli/Cargo.toml
+++ b/mingling_cli/Cargo.toml
@@ -11,15 +11,29 @@ description = "Mingling's scaffolding tool for generating, analyzing, and modify
keywords = ["cli", "cli-framework", "command-line", "tools"]
categories = ["command-line-interface"]
+[[bin]]
+name = "mling"
+path = "src/main.rs"
+
[dependencies.mingling]
path = "../mingling"
features = [
"picker",
"pathf",
- "dispatch_tree",
- "extra_macros"
+ "extra_macros",
+ "structural_renderer"
+]
+
+[build-dependencies.mingling]
+path = "../mingling"
+features = [
+ "builds",
+ "pathf",
]
[dependencies]
+cargo_metadata = "0.23.1"
+serde = { version = "1.0.229", features = ["derive"] }
+serde_json = "1.0.151"
[workspace]
diff --git a/mingling_cli/build.rs b/mingling_cli/build.rs
new file mode 100644
index 0000000..2a36e37
--- /dev/null
+++ b/mingling_cli/build.rs
@@ -0,0 +1,5 @@
+use mingling::build::analyze_and_build_type_mapping;
+
+fn main() {
+ analyze_and_build_type_mapping().unwrap();
+}
diff --git a/mingling_cli/src/linter.rs b/mingling_cli/src/linter.rs
new file mode 100644
index 0000000..870efeb
--- /dev/null
+++ b/mingling_cli/src/linter.rs
@@ -0,0 +1,15 @@
+use mingling::{Program, macros::program_setup};
+
+use crate::linter::cmd_mlint::CMDMinglingLinter;
+
+pub mod cmd_mlint;
+
+#[program_setup]
+pub fn mingling_linter_setup(program: &mut Program<crate::ThisProgram>) {
+ program.with_setup(MinglingLinterCommandSetup);
+}
+
+#[program_setup]
+pub fn mingling_linter_command_setup(program: &mut Program<crate::ThisProgram>) {
+ program.with_dispatcher(CMDMinglingLinter);
+}
diff --git a/mingling_cli/src/linter/cmd_mlint.rs b/mingling_cli/src/linter/cmd_mlint.rs
new file mode 100644
index 0000000..1431c43
--- /dev/null
+++ b/mingling_cli/src/linter/cmd_mlint.rs
@@ -0,0 +1,6 @@
+use mingling::macros::{chain, dispatcher};
+
+dispatcher!("mlint", CMDMinglingLinter => EntryMinglingLinter);
+
+#[chain]
+pub fn handle_mlint(_args: EntryMinglingLinter) {}
diff --git a/mingling_cli/src/main.rs b/mingling_cli/src/main.rs
index e7a11a9..59fa92d 100644
--- a/mingling_cli/src/main.rs
+++ b/mingling_cli/src/main.rs
@@ -1,3 +1,28 @@
+use crate::{linter::MinglingLinterSetup, metadata::MinglingMetadataSetup};
+use mingling::{
+ macros::gen_program,
+ setup::{
+ ExitCodeSetup,
+ picker::{HelpFlagSetup, StructuralRendererSetup},
+ },
+};
+
+pub mod linter;
+pub mod metadata;
+
fn main() {
- println!("Hello, world!");
+ let mut program = ThisProgram::new();
+
+ // Setups
+ program.with_setup(HelpFlagSetup::default());
+ program.with_setup(ExitCodeSetup::default());
+ program.with_setup(StructuralRendererSetup);
+
+ program.with_setup(MinglingMetadataSetup);
+ program.with_setup(MinglingLinterSetup);
+
+ // Exec
+ program.exec_and_exit();
}
+
+gen_program!();
diff --git a/mingling_cli/src/metadata.rs b/mingling_cli/src/metadata.rs
new file mode 100644
index 0000000..0c0b0bf
--- /dev/null
+++ b/mingling_cli/src/metadata.rs
@@ -0,0 +1,12 @@
+use mingling::{Program, macros::program_setup};
+
+use crate::metadata::{cmd_metadata::CMDMetadata, setup::CargoMetadataSetup};
+
+pub mod cmd_metadata;
+pub mod setup;
+
+#[program_setup]
+pub fn mingling_metadata_setup(program: &mut Program<crate::ThisProgram>) {
+ program.with_setup(CargoMetadataSetup);
+ program.with_dispatcher(CMDMetadata);
+}
diff --git a/mingling_cli/src/metadata/cmd_metadata.rs b/mingling_cli/src/metadata/cmd_metadata.rs
new file mode 100644
index 0000000..867e606
--- /dev/null
+++ b/mingling_cli/src/metadata/cmd_metadata.rs
@@ -0,0 +1,16 @@
+use mingling::{
+ LazyRes,
+ macros::{chain, dispatcher, pack_structural},
+};
+
+use crate::metadata::setup::ResMetadata;
+
+dispatcher!("metadata");
+
+pack_structural!(ResultMetadata = ResMetadata);
+
+#[chain]
+pub fn handle_metadata(_: EntryMetadata, metadata: &mut LazyRes<ResMetadata>) -> ResultMetadata {
+ let metadata = metadata.get_ref().clone();
+ ResultMetadata::new(metadata)
+}
diff --git a/mingling_cli/src/metadata/setup.rs b/mingling_cli/src/metadata/setup.rs
new file mode 100644
index 0000000..4a891b6
--- /dev/null
+++ b/mingling_cli/src/metadata/setup.rs
@@ -0,0 +1,120 @@
+use std::{env::current_dir, path::PathBuf};
+
+use cargo_metadata::{CargoOpt, MetadataCommand};
+use mingling::{
+ LazyInit, Program,
+ consts::REMAINS,
+ macros::program_setup,
+ picker::{IntoPicker, value::Flag},
+ prelude::*,
+ res::ResCurrentDir,
+};
+
+/// Name of Cargo manifest file
+pub const CARGO_TOML: &str = "Cargo.toml";
+
+use cargo_metadata::Metadata;
+use serde::Serialize;
+
+#[derive(Default, Clone, Serialize)]
+pub struct ResMetadata {
+ data: Option<Metadata>,
+}
+
+impl ResMetadata {
+ /// Returns a reference to the parsed `cargo metadata`.
+ ///
+ /// # Panics
+ ///
+ /// This function does **not** panic in practice, because `ResMetadata` is
+ /// always initialized via [`LazyInit`] inside the program setup, and the
+ /// initialization either succeeds (setting `data` to `Some(...)`) or fails
+ /// by propagating the error from `cmd.exec().unwrap()`. Therefore, by the
+ /// time this getter is called, `self.data` is guaranteed to be `Some`.
+ pub fn data(&self) -> &Metadata {
+ self.data.as_ref().unwrap()
+ }
+}
+
+#[program_setup]
+pub fn cargo_metadata_setup(program: &mut Program<crate::ThisProgram>) {
+ let args = program.take_args();
+ let (
+ feature_args,
+ manifest_path,
+ message_format,
+ enable_all_features,
+ no_default_features,
+ no_deps,
+ args,
+ ) = args
+ .pick(&arg![features: Vec<String>])
+ .pick(&arg![manifest_path: Option<String>])
+ .pick_or(&arg![message_format: String], || "disable".to_string())
+ .pick(&arg![all_features: Flag])
+ .pick(&arg![no_default_features: Flag])
+ .pick(&arg![no_deps: Flag])
+ .pick(&REMAINS)
+ .unwrap();
+ program.replace_args(args.into());
+
+ // Bind format setting to StructuralRenderer
+ program.structural_renderer_name = message_format.into();
+
+ // Current Dir
+ let current_dir = current_dir().unwrap();
+
+ // Leak `feature_args` into a static slice so it can be captured by the metadata closure.
+ // Since the process does not loop, this memory leak is harmless.
+ let feature_args_leaked: &[String] = Box::leak(feature_args.into_boxed_slice());
+ let manifest_path_clone = manifest_path.clone();
+ let current_dir_clone = current_dir.clone();
+
+ program.with_resource(ResMetadata::lazy_init(move || {
+ // Paths
+ let metadata_path = match manifest_path_clone {
+ Some(ref path_str) => PathBuf::from(path_str),
+ None => find_manifest().unwrap(),
+ };
+
+ // Cargo Metadata - bind to a longer-lived variable
+ let mut cmd = MetadataCommand::new();
+ cmd.manifest_path(metadata_path)
+ .current_dir(&current_dir_clone);
+
+ if *enable_all_features {
+ cmd.features(CargoOpt::AllFeatures);
+ }
+
+ if *no_default_features {
+ cmd.features(CargoOpt::NoDefaultFeatures);
+ }
+
+ if *no_deps {
+ cmd.no_deps();
+ }
+
+ cmd.features(CargoOpt::SomeFeatures(feature_args_leaked.to_vec()));
+
+ ResMetadata {
+ data: Some(cmd.exec().unwrap()),
+ }
+ }));
+
+ // Current Dir
+ program.with_resource(ResCurrentDir::from(current_dir));
+}
+
+/// Find `Cargo.toml` by searching upward from `current_dir`.
+fn find_manifest() -> Option<PathBuf> {
+ let mut dir = current_dir().ok()?;
+ loop {
+ let candidate = dir.join(CARGO_TOML);
+ if candidate.is_file() {
+ return Some(candidate);
+ }
+ if !dir.pop() {
+ return None;
+ }
+ }
+}