aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rwxr-xr-xdev_tools/scripts/http-page-preview.sh3
-rw-r--r--dev_tools/src/bin/refresh-examples.rs96
-rw-r--r--docs/res/graph.drawio (renamed from res/graph.drawio)0
-rw-r--r--docs/res/graph.png (renamed from res/graph.png)bin69856 -> 69856 bytes
-rw-r--r--docs/res/guide.txt (renamed from res/guide.txt)0
-rw-r--r--docs/res/icon.png (renamed from res/icon.png)bin206092 -> 206092 bytes
-rw-r--r--docs/res/icon_shadow.png (renamed from res/icon_shadow.png)bin595392 -> 595392 bytes
-rw-r--r--mingling/Cargo.lock18
-rw-r--r--mingling_core/Cargo.lock18
-rw-r--r--mingling_core/Cargo.toml2
-rw-r--r--mingling_core/src/program.rs2
-rw-r--r--mingling_core/src/program/flag.rs8
-rw-r--r--run-tools.ps125
-rwxr-xr-xrun-tools.sh21
15 files changed, 117 insertions, 85 deletions
diff --git a/README.md b/README.md
index cf3430e..09f19cb 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
<p align="center">
<a href="https://github.com/CatilGrass/mingling">
- <img alt="Mingling" src="res/icon_shadow.png" width="30%">
+ <img alt="Mingling" src="docs/res/icon_shadow.png" width="30%">
</a>
</p>
<h1 align="center">Mìng Lìng - 命令</h1>
@@ -38,7 +38,10 @@
## Intro
-`Mingling` is a Rust command-line framework. Its name comes from the Chinese Pinyin for "命令", which means "Command".
+[`Mingling`](https://github.com/CatilGrass/mingling) is a **proc-macro and type system-based** Rust CLI framework, suitable for developing complex command-line programs with numerous subcommands.
+
+> BTW: Its name comes from the Chinese Pinyin "mìng lìng", meaning "Command". 😄
+
## Quick Start
@@ -102,7 +105,7 @@ Mingling abstracts command execution into the following parts:
<summary>Architecture Diagram (click to expand)</summary>
<p align="center">
<a href="https://github.com/CatilGrass/mingling">
- <img alt="Mingling" src="res/graph.png" width="75%">
+ <img alt="Mingling" src="docs/res/graph.png" width="75%">
</a>
</p>
</details>
diff --git a/dev_tools/scripts/http-page-preview.sh b/dev_tools/scripts/http-page-preview.sh
new file mode 100755
index 0000000..6c822d8
--- /dev/null
+++ b/dev_tools/scripts/http-page-preview.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+cd "docs"
+python3 -m http.server 3000
diff --git a/dev_tools/src/bin/refresh-examples.rs b/dev_tools/src/bin/refresh-examples.rs
index be5da82..08ecf90 100644
--- a/dev_tools/src/bin/refresh-examples.rs
+++ b/dev_tools/src/bin/refresh-examples.rs
@@ -6,8 +6,64 @@ use just_template::{Template, tmpl};
const EXAMPLE_ROOT: &str = "./examples/";
const OUTPUT_PATH: &str = "./mingling/src/example_docs.rs";
+const DOCS_README_FILE: &str = "./docs/README.md";
+
+const README_CONTENT: &str = include_str!("../../../README.md");
const TEMPLATE_CONTENT: &str = include_str!("../../../mingling/src/example_docs.rs.tmpl");
+fn main() {
+ gen_example_doc_module();
+ gen_docs_readme();
+}
+
+fn gen_example_doc_module() {
+ let mut template = Template::from(TEMPLATE_CONTENT);
+ let repo_root = find_git_repo().unwrap();
+ let example_root = repo_root.join(EXAMPLE_ROOT);
+ let mut examples = Vec::new();
+ if let Ok(entries) = std::fs::read_dir(&example_root) {
+ for entry in entries.flatten() {
+ if let Ok(file_type) = entry.file_type() {
+ if file_type.is_dir() {
+ let example_name = entry.file_name().to_string_lossy().to_string();
+ let example_content = ExampleContent::read(&example_name);
+ examples.push(example_content);
+ }
+ }
+ }
+ }
+
+ for example in examples {
+ tmpl!(template += {
+ examples {
+ (
+ example_header = example.header,
+ example_import = example.cargo_toml,
+ example_code = example.code,
+ example_name = snake_case!(example.name)
+ )
+ }
+ });
+ }
+
+ let template_str = template.to_string();
+ let template_str = template_str
+ .lines()
+ .map(|line| line.trim_end())
+ .collect::<Vec<_>>()
+ .join("\n")
+ + "\n";
+ std::fs::write(repo_root.join(OUTPUT_PATH), template_str).unwrap();
+}
+
+fn gen_docs_readme() {
+ let repo_root = find_git_repo().unwrap();
+
+ // Convert relative addresses in the documentation
+ let content = README_CONTENT.replace("docs/res/", "res/");
+ std::fs::write(repo_root.join(DOCS_README_FILE), content).unwrap();
+}
+
struct ExampleContent {
name: String,
header: String,
@@ -88,46 +144,6 @@ impl ExampleContent {
}
}
-fn main() {
- let mut template = Template::from(TEMPLATE_CONTENT);
- let repo_root = find_git_repo().unwrap();
- let example_root = repo_root.join(EXAMPLE_ROOT);
- let mut examples = Vec::new();
- if let Ok(entries) = std::fs::read_dir(&example_root) {
- for entry in entries.flatten() {
- if let Ok(file_type) = entry.file_type() {
- if file_type.is_dir() {
- let example_name = entry.file_name().to_string_lossy().to_string();
- let example_content = ExampleContent::read(&example_name);
- examples.push(example_content);
- }
- }
- }
- }
-
- for example in examples {
- tmpl!(template += {
- examples {
- (
- example_header = example.header,
- example_import = example.cargo_toml,
- example_code = example.code,
- example_name = snake_case!(example.name)
- )
- }
- });
- }
-
- let template_str = template.to_string();
- let template_str = template_str
- .lines()
- .map(|line| line.trim_end())
- .collect::<Vec<_>>()
- .join("\n")
- + "\n";
- std::fs::write(repo_root.join(OUTPUT_PATH), template_str).unwrap();
-}
-
fn find_git_repo() -> Option<std::path::PathBuf> {
let mut current_dir = std::env::current_dir().ok()?;
diff --git a/res/graph.drawio b/docs/res/graph.drawio
index 47ac9f4..47ac9f4 100644
--- a/res/graph.drawio
+++ b/docs/res/graph.drawio
diff --git a/res/graph.png b/docs/res/graph.png
index c942f02..c942f02 100644
--- a/res/graph.png
+++ b/docs/res/graph.png
Binary files differ
diff --git a/res/guide.txt b/docs/res/guide.txt
index 4de56b3..4de56b3 100644
--- a/res/guide.txt
+++ b/docs/res/guide.txt
diff --git a/res/icon.png b/docs/res/icon.png
index 4fa4f03..4fa4f03 100644
--- a/res/icon.png
+++ b/docs/res/icon.png
Binary files differ
diff --git a/res/icon_shadow.png b/docs/res/icon_shadow.png
index cb5eef9..cb5eef9 100644
--- a/res/icon_shadow.png
+++ b/docs/res/icon_shadow.png
Binary files differ
diff --git a/mingling/Cargo.lock b/mingling/Cargo.lock
index a6682ed..cdc62c3 100644
--- a/mingling/Cargo.lock
+++ b/mingling/Cargo.lock
@@ -569,9 +569,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.9.12+spec-1.1.0"
+version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
+checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
"indexmap",
"serde_core",
@@ -579,14 +579,14 @@ dependencies = [
"toml_datetime",
"toml_parser",
"toml_writer",
- "winnow 0.7.15",
+ "winnow",
]
[[package]]
name = "toml_datetime"
-version = "0.7.5+spec-1.1.0"
+version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
@@ -597,7 +597,7 @@ version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow 1.0.1",
+ "winnow",
]
[[package]]
@@ -653,12 +653,6 @@ dependencies = [
[[package]]
name = "winnow"
-version = "0.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
-
-[[package]]
-name = "winnow"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
diff --git a/mingling_core/Cargo.lock b/mingling_core/Cargo.lock
index 315939f..5755757 100644
--- a/mingling_core/Cargo.lock
+++ b/mingling_core/Cargo.lock
@@ -416,9 +416,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.9.12+spec-1.1.0"
+version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863"
+checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
dependencies = [
"indexmap",
"serde_core",
@@ -426,14 +426,14 @@ dependencies = [
"toml_datetime",
"toml_parser",
"toml_writer",
- "winnow 0.7.15",
+ "winnow",
]
[[package]]
name = "toml_datetime"
-version = "0.7.5+spec-1.1.0"
+version = "1.1.1+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
+checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
dependencies = [
"serde_core",
]
@@ -444,7 +444,7 @@ version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow 1.0.1",
+ "winnow",
]
[[package]]
@@ -494,12 +494,6 @@ dependencies = [
[[package]]
name = "winnow"
-version = "0.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
-
-[[package]]
-name = "winnow"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml
index f7f7c00..54f6a2c 100644
--- a/mingling_core/Cargo.toml
+++ b/mingling_core/Cargo.toml
@@ -31,7 +31,7 @@ once_cell = "1.21.4"
ron = { version = "0.12.1", optional = true }
serde_json = { version = "1", optional = true }
serde_yaml = { version = "0.9", optional = true }
-toml = { version = "0.9.8", optional = true }
+toml = { version = "1.1.2+spec-1.1.0", optional = true }
log = { version = "0.4", optional = true }
env_logger = { version = "0.11", optional = true }
diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs
index cf8b06c..bee9772 100644
--- a/mingling_core/src/program.rs
+++ b/mingling_core/src/program.rs
@@ -257,7 +257,7 @@ macro_rules! __dispatch_program_chains {
};
}
-// Get all registered dispatcher names from the program
+/// Get all registered dispatcher names from the program
pub fn get_nodes<C: ProgramCollect<Enum = G>, G: Display>(
program: &Program<C, G>,
) -> Vec<(String, &(dyn Dispatcher<G> + Send + Sync))> {
diff --git a/mingling_core/src/program/flag.rs b/mingling_core/src/program/flag.rs
index ba3376c..f44cf33 100644
--- a/mingling_core/src/program/flag.rs
+++ b/mingling_core/src/program/flag.rs
@@ -480,9 +480,9 @@ where
G: Display,
{
/// Registers a global argument (with value) and its handler.
- pub fn global_argument<F, A>(&mut self, arguments: A, do_fn: F)
+ pub fn global_argument<F, A>(&mut self, arguments: A, mut do_fn: F)
where
- F: Fn(&mut Program<C, G>, String),
+ F: FnMut(&mut Program<C, G>, String),
A: Into<Flag>,
{
let flag = arguments.into();
@@ -496,9 +496,9 @@ where
}
/// Registers a global flag (boolean) and its handler.
- pub fn global_flag<F, A>(&mut self, flag: A, do_fn: F)
+ pub fn global_flag<F, A>(&mut self, flag: A, mut do_fn: F)
where
- F: Fn(&mut Program<C, G>),
+ F: FnMut(&mut Program<C, G>),
A: Into<Flag>,
{
let flag = flag.into();
diff --git a/run-tools.ps1 b/run-tools.ps1
index fa06ecd..43e39d8 100644
--- a/run-tools.ps1
+++ b/run-tools.ps1
@@ -12,15 +12,28 @@ if ($args.Count -eq 0) {
} else {
Write-Host "Warning: dev_tools/src/bin directory does not exist"
}
+ if (Test-Path "dev_tools/scripts") {
+ $scripts = Get-ChildItem -Path "dev_tools/scripts/*.ps1"
+ foreach ($script in $scripts) {
+ if ($script -is [System.IO.FileInfo]) {
+ Write-Host $script.BaseName
+ }
+ }
+ } else {
+ Write-Host "Warning: dev_tools/scripts directory does not exist"
+ }
exit 1
}
-$target_bin = $args[0]
-$target_file = "dev_tools/src/bin/${target_bin}.rs"
+$target_name = $args[0]
+$script_file = "dev_tools/scripts/${target_name}.ps1"
+$rust_file = "dev_tools/src/bin/${target_name}.rs"
-if (-not (Test-Path $target_file)) {
- Write-Host "Error: target file '$target_file' does not exist"
+if (Test-Path $script_file) {
+ & $script_file
+} elseif (Test-Path $rust_file) {
+ cargo run --manifest-path dev_tools/Cargo.toml --bin $target_name
+} else {
+ Write-Host "Error: target '$target_name' does not exist as a script or Rust program"
exit 1
}
-
-cargo run --manifest-path dev_tools/Cargo.toml --bin $args[0]
diff --git a/run-tools.sh b/run-tools.sh
index 7bfcd29..c0c2c4a 100755
--- a/run-tools.sh
+++ b/run-tools.sh
@@ -4,24 +4,33 @@ cd "$(dirname "$0")" || exit 1
if [ $# -eq 0 ]; then
echo "Available:"
+ if [ -d "dev_tools/scripts" ]; then
+ for file in dev_tools/scripts/*.sh; do
+ if [ -f "$file" ]; then
+ basename "$file" .sh
+ fi
+ done
+ fi
if [ -d "dev_tools/src/bin" ]; then
for file in dev_tools/src/bin/*.rs; do
if [ -f "$file" ]; then
basename "$file" .rs
fi
done
- else
- echo "Warning: dev_tools/src/bin directory does not exist"
fi
exit 1
fi
target_bin="$1"
+target_script="dev_tools/scripts/${target_bin}.sh"
target_file="dev_tools/src/bin/${target_bin}.rs"
-if [ ! -f "$target_file" ]; then
- echo "Error: target file '$target_file' does not exist"
+if [ -f "$target_script" ]; then
+ chmod +x "$target_script"
+ "$target_script"
+elif [ -f "$target_file" ]; then
+ cargo run --manifest-path dev_tools/Cargo.toml --bin "$1"
+else
+ echo "Error: target '$target_bin' does not exist"
exit 1
fi
-
-cargo run --manifest-path dev_tools/Cargo.toml --bin "$1"