diff options
Diffstat (limited to 'mingling_cli')
| -rw-r--r-- | mingling_cli/Cargo.lock | 147 | ||||
| -rw-r--r-- | mingling_cli/Cargo.toml | 18 | ||||
| -rw-r--r-- | mingling_cli/build.rs | 5 | ||||
| -rw-r--r-- | mingling_cli/src/linter.rs | 15 | ||||
| -rw-r--r-- | mingling_cli/src/linter/cmd_mlint.rs | 6 | ||||
| -rw-r--r-- | mingling_cli/src/main.rs | 27 | ||||
| -rw-r--r-- | mingling_cli/src/metadata.rs | 12 | ||||
| -rw-r--r-- | mingling_cli/src/metadata/cmd_metadata.rs | 16 | ||||
| -rw-r--r-- | mingling_cli/src/metadata/setup.rs | 120 |
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(¤t_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; + } + } +} |
