aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cargo/config.toml4
-rw-r--r--.run/.gitignore7
-rw-r--r--.run/Cargo.lock (renamed from dev_tools/Cargo.lock)0
-rw-r--r--.run/Cargo.toml (renamed from dev_tools/Cargo.toml)2
-rw-r--r--.run/src/bin/build-all.ps1 (renamed from dev_tools/scripts/build-all.ps1)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/build-all.sh (renamed from dev_tools/scripts/build-all.sh)0
-rw-r--r--.run/src/bin/ci.rs (renamed from dev_tools/src/bin/ci.rs)0
-rw-r--r--.run/src/bin/clippy-fix.ps1 (renamed from dev_tools/scripts/clippy-fix.ps1)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/clippy-fix.sh (renamed from dev_tools/scripts/clippy-fix.sh)0
-rw-r--r--.run/src/bin/clippy.ps1 (renamed from dev_tools/scripts/clippy.ps1)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/clippy.sh (renamed from dev_tools/scripts/clippy.sh)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/doc.ps1 (renamed from dev_tools/scripts/doc.ps1)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/doc.sh (renamed from dev_tools/scripts/doc.sh)0
-rw-r--r--.run/src/bin/docs-code-box-fix.rs (renamed from dev_tools/src/bin/docs-code-box-fix.rs)0
-rw-r--r--.run/src/bin/docsify-sidebar-gen.rs (renamed from dev_tools/src/bin/docsify-sidebar-gen.rs)15
-rw-r--r--.run/src/bin/http-page-preview.ps1 (renamed from dev_tools/scripts/http-page-preview.ps1)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/http-page-preview.sh (renamed from dev_tools/scripts/http-page-preview.sh)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/install-mling.ps1 (renamed from dev_tools/scripts/install-mling.ps1)0
-rw-r--r--[-rwxr-xr-x].run/src/bin/install-mling.sh (renamed from dev_tools/scripts/install-mling.sh)0
-rw-r--r--.run/src/bin/refresh-docs.rs (renamed from dev_tools/src/bin/refresh-docs.rs)0
-rw-r--r--.run/src/bin/refresh-feature-mod.rs (renamed from dev_tools/src/bin/refresh-feature-mod.rs)0
-rw-r--r--.run/src/bin/sync-examples.rs (renamed from dev_tools/src/bin/sync-examples.rs)0
-rw-r--r--.run/src/bin/test-all-markdown-code.rs (renamed from dev_tools/src/bin/test-all-markdown-code.rs)0
-rw-r--r--.run/src/bin/test-all.ps1 (renamed from dev_tools/scripts/test-all.ps1)0
-rw-r--r--.run/src/bin/test-all.sh (renamed from dev_tools/scripts/test-all.sh)0
-rw-r--r--.run/src/bin/test-examples.rs (renamed from dev_tools/src/bin/test-examples.rs)0
-rw-r--r--.run/src/bin/update-version.rs (renamed from dev_tools/src/bin/update-version.rs)0
-rw-r--r--.run/src/bin/windows-folder-hide.ps1 (renamed from dev_tools/scripts/windows-folder-hide.ps1)0
-rw-r--r--.run/src/lib.rs (renamed from dev_tools/src/lib.rs)0
-rw-r--r--.run/src/verify.rs (renamed from dev_tools/src/verify.rs)4
-rw-r--r--.run/version-files.toml (renamed from dev_tools/version-files.toml)0
-rw-r--r--ABOUT-CI.md22
-rw-r--r--CONTRIBUTING.md54
-rw-r--r--Cargo.toml2
-rw-r--r--run-tools.ps160
-rwxr-xr-xrun-tools.sh64
-rw-r--r--run.ps1232
-rw-r--r--run.sh257
38 files changed, 547 insertions, 176 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml
index 0b45ca9..f375b03 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -4,5 +4,5 @@ target-dir = "./.temp/target"
[env]
[alias]
-ci = "run --manifest-path dev_tools/Cargo.toml --bin ci --quiet --"
-dev_tool = "run --manifest-path dev_tools/Cargo.toml --quiet --bin "
+ci = "run --manifest-path .run/Cargo.toml --bin ci --quiet --"
+dev_tool = "run --manifest-path .run/Cargo.toml --quiet --bin "
diff --git a/.run/.gitignore b/.run/.gitignore
new file mode 100644
index 0000000..0dc39b0
--- /dev/null
+++ b/.run/.gitignore
@@ -0,0 +1,7 @@
+# All temp build artifacts will be stored in this dir
+/target
+
+# If you want to add some Rust crates? Remove this line
+# /Cargo.*
+
+last_check
diff --git a/dev_tools/Cargo.lock b/.run/Cargo.lock
index bb510bd..bb510bd 100644
--- a/dev_tools/Cargo.lock
+++ b/.run/Cargo.lock
diff --git a/dev_tools/Cargo.toml b/.run/Cargo.toml
index 9855580..283aa47 100644
--- a/dev_tools/Cargo.toml
+++ b/.run/Cargo.toml
@@ -19,3 +19,5 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
indicatif = "0.18.4"
+
+[workspace]
diff --git a/dev_tools/scripts/build-all.ps1 b/.run/src/bin/build-all.ps1
index 4f35ed8..4f35ed8 100644
--- a/dev_tools/scripts/build-all.ps1
+++ b/.run/src/bin/build-all.ps1
diff --git a/dev_tools/scripts/build-all.sh b/.run/src/bin/build-all.sh
index 2036b41..2036b41 100755..100644
--- a/dev_tools/scripts/build-all.sh
+++ b/.run/src/bin/build-all.sh
diff --git a/dev_tools/src/bin/ci.rs b/.run/src/bin/ci.rs
index f8aed79..f8aed79 100644
--- a/dev_tools/src/bin/ci.rs
+++ b/.run/src/bin/ci.rs
diff --git a/dev_tools/scripts/clippy-fix.ps1 b/.run/src/bin/clippy-fix.ps1
index 1d24f92..1d24f92 100644
--- a/dev_tools/scripts/clippy-fix.ps1
+++ b/.run/src/bin/clippy-fix.ps1
diff --git a/dev_tools/scripts/clippy-fix.sh b/.run/src/bin/clippy-fix.sh
index 9771ad4..9771ad4 100755..100644
--- a/dev_tools/scripts/clippy-fix.sh
+++ b/.run/src/bin/clippy-fix.sh
diff --git a/dev_tools/scripts/clippy.ps1 b/.run/src/bin/clippy.ps1
index 1858873..1858873 100644
--- a/dev_tools/scripts/clippy.ps1
+++ b/.run/src/bin/clippy.ps1
diff --git a/dev_tools/scripts/clippy.sh b/.run/src/bin/clippy.sh
index b393545..b393545 100755..100644
--- a/dev_tools/scripts/clippy.sh
+++ b/.run/src/bin/clippy.sh
diff --git a/dev_tools/scripts/doc.ps1 b/.run/src/bin/doc.ps1
index 987f0de..987f0de 100755..100644
--- a/dev_tools/scripts/doc.ps1
+++ b/.run/src/bin/doc.ps1
diff --git a/dev_tools/scripts/doc.sh b/.run/src/bin/doc.sh
index 5e8a311..5e8a311 100755..100644
--- a/dev_tools/scripts/doc.sh
+++ b/.run/src/bin/doc.sh
diff --git a/dev_tools/src/bin/docs-code-box-fix.rs b/.run/src/bin/docs-code-box-fix.rs
index 21d2cce..21d2cce 100644
--- a/dev_tools/src/bin/docs-code-box-fix.rs
+++ b/.run/src/bin/docs-code-box-fix.rs
diff --git a/dev_tools/src/bin/docsify-sidebar-gen.rs b/.run/src/bin/docsify-sidebar-gen.rs
index b926112..5beda7f 100644
--- a/dev_tools/src/bin/docsify-sidebar-gen.rs
+++ b/.run/src/bin/docsify-sidebar-gen.rs
@@ -43,7 +43,7 @@ fn find_all_readmes(dir: &Path) -> Vec<PathBuf> {
let path = entry.path();
if path.is_dir() {
results.extend(find_all_readmes(&path));
- } else if path.file_name().map_or(false, |n| n == "README.md") {
+ } else if path.file_name().is_some_and(|n| n == "README.md") {
results.push(path);
}
}
@@ -67,11 +67,10 @@ fn find_content_dir(site_root: &Path) -> Option<PathBuf> {
entries.sort_by_key(|e| e.path());
for entry in entries {
let path = entry.path();
- if path.is_dir() {
- if has_markdown_files(&path) {
+ if path.is_dir()
+ && has_markdown_files(&path) {
return Some(path);
}
- }
}
}
@@ -254,12 +253,10 @@ fn natural_cmp(a: &str, b: &str) -> std::cmp::Ordering {
/// Looks at the filename stem (after the last `/`) for a number before the first `-`.
/// Returns `usize::MAX` for entries without a numeric prefix.
fn extract_leading_number(link: &str) -> usize {
- if let Some(file_stem) = link.rsplit('/').next() {
- if let Some(num_end) = file_stem.find('-') {
- if let Ok(num) = file_stem[..num_end].parse::<usize>() {
+ if let Some(file_stem) = link.rsplit('/').next()
+ && let Some(num_end) = file_stem.find('-')
+ && let Ok(num) = file_stem[..num_end].parse::<usize>() {
return num;
}
- }
- }
usize::MAX
}
diff --git a/dev_tools/scripts/http-page-preview.ps1 b/.run/src/bin/http-page-preview.ps1
index 8cc3579..8cc3579 100644
--- a/dev_tools/scripts/http-page-preview.ps1
+++ b/.run/src/bin/http-page-preview.ps1
diff --git a/dev_tools/scripts/http-page-preview.sh b/.run/src/bin/http-page-preview.sh
index bed4b1c..bed4b1c 100755..100644
--- a/dev_tools/scripts/http-page-preview.sh
+++ b/.run/src/bin/http-page-preview.sh
diff --git a/dev_tools/scripts/install-mling.ps1 b/.run/src/bin/install-mling.ps1
index bebe9ff..bebe9ff 100755..100644
--- a/dev_tools/scripts/install-mling.ps1
+++ b/.run/src/bin/install-mling.ps1
diff --git a/dev_tools/scripts/install-mling.sh b/.run/src/bin/install-mling.sh
index 5f2ee7a..5f2ee7a 100755..100644
--- a/dev_tools/scripts/install-mling.sh
+++ b/.run/src/bin/install-mling.sh
diff --git a/dev_tools/src/bin/refresh-docs.rs b/.run/src/bin/refresh-docs.rs
index 82ef906..82ef906 100644
--- a/dev_tools/src/bin/refresh-docs.rs
+++ b/.run/src/bin/refresh-docs.rs
diff --git a/dev_tools/src/bin/refresh-feature-mod.rs b/.run/src/bin/refresh-feature-mod.rs
index 2255dbc..2255dbc 100644
--- a/dev_tools/src/bin/refresh-feature-mod.rs
+++ b/.run/src/bin/refresh-feature-mod.rs
diff --git a/dev_tools/src/bin/sync-examples.rs b/.run/src/bin/sync-examples.rs
index 0923b33..0923b33 100644
--- a/dev_tools/src/bin/sync-examples.rs
+++ b/.run/src/bin/sync-examples.rs
diff --git a/dev_tools/src/bin/test-all-markdown-code.rs b/.run/src/bin/test-all-markdown-code.rs
index 280fca7..280fca7 100644
--- a/dev_tools/src/bin/test-all-markdown-code.rs
+++ b/.run/src/bin/test-all-markdown-code.rs
diff --git a/dev_tools/scripts/test-all.ps1 b/.run/src/bin/test-all.ps1
index 231698a..231698a 100644
--- a/dev_tools/scripts/test-all.ps1
+++ b/.run/src/bin/test-all.ps1
diff --git a/dev_tools/scripts/test-all.sh b/.run/src/bin/test-all.sh
index b387463..b387463 100644
--- a/dev_tools/scripts/test-all.sh
+++ b/.run/src/bin/test-all.sh
diff --git a/dev_tools/src/bin/test-examples.rs b/.run/src/bin/test-examples.rs
index 539459e..539459e 100644
--- a/dev_tools/src/bin/test-examples.rs
+++ b/.run/src/bin/test-examples.rs
diff --git a/dev_tools/src/bin/update-version.rs b/.run/src/bin/update-version.rs
index 475e54b..475e54b 100644
--- a/dev_tools/src/bin/update-version.rs
+++ b/.run/src/bin/update-version.rs
diff --git a/dev_tools/scripts/windows-folder-hide.ps1 b/.run/src/bin/windows-folder-hide.ps1
index 0ab2632..0ab2632 100644
--- a/dev_tools/scripts/windows-folder-hide.ps1
+++ b/.run/src/bin/windows-folder-hide.ps1
diff --git a/dev_tools/src/lib.rs b/.run/src/lib.rs
index d38a156..d38a156 100644
--- a/dev_tools/src/lib.rs
+++ b/.run/src/lib.rs
diff --git a/dev_tools/src/verify.rs b/.run/src/verify.rs
index 2ddff0c..0a4b354 100644
--- a/dev_tools/src/verify.rs
+++ b/.run/src/verify.rs
@@ -76,10 +76,10 @@ fn parse_single_block(lines: &[&str], start: usize, source_file: &str) -> Option
// @@@ lines: strip the prefix and treat as regular Rust code
// These lines are hidden in the rendered docs (filtered by a docsify plugin)
// but must still compile.
- if trimmed.starts_with("@@@") {
+ if let Some(stripped) = trimmed.strip_prefix("@@@") {
in_header = false;
// Strip @@@ and optionally one following space
- let code = trimmed[3..].trim_start();
+ let code = stripped.trim_start();
if code.contains("fn main") {
has_main = true;
}
diff --git a/dev_tools/version-files.toml b/.run/version-files.toml
index ca104d2..ca104d2 100644
--- a/dev_tools/version-files.toml
+++ b/.run/version-files.toml
diff --git a/ABOUT-CI.md b/ABOUT-CI.md
index 762fab8..4cbcd6f 100644
--- a/ABOUT-CI.md
+++ b/ABOUT-CI.md
@@ -1,6 +1,6 @@
# About Mingling CI Process
-Mingling's CI process is built into the project, with its execution logic located in `dev_tools/src/bin/ci.rs`. You can run it locally via the `cargo ci` command, which produces the same results as the `CI` workflow in GitHub Actions.
+Mingling's CI process is built into the project, with its execution logic located in `.run/src/bin/ci.rs`. You can run it locally via the `cargo ci` command, which produces the same results as the `CI` workflow in GitHub Actions.
During development, you can run `cargo ci` at any time to verify that your code hasn't introduced regressions.
@@ -10,7 +10,7 @@ An alias is defined in `.cargo/config.toml` at the project root:
```toml
[alias]
-ci = "run --manifest-path dev_tools/Cargo.toml --bin ci --quiet --"
+ci = "run --manifest-path .run/Cargo.toml --bin ci --quiet --"
```
Simply execute:
@@ -34,11 +34,11 @@ cargo ci
- **Test all examples**: Runs the `test-examples` tool.
- **Verify Markdown code blocks compile**: Runs the `test-all-markdown-code` tool to check code blocks in all `*.md` files. See [ABOUT_CODE_VERIFY](docs/_ABOUT_CODE_VERIFY.md) for details.
- **Check if documentation is up to date**: Runs the following documentation refresh tools in sequence:
- - `docs-code-box-fix`
- - `docsify-sidebar-gen`
- - `refresh-docs`
- - `refresh-feature-mod`
- - `sync-examples`
+ - `docs-code-box-fix`
+ - `docsify-sidebar-gen`
+ - `refresh-docs`
+ - `refresh-feature-mod`
+ - `sync-examples`
- Finally, runs `cargo fmt` to unify code formatting.
### 3. File Normalization
@@ -50,11 +50,11 @@ Runs `git add --renormalize .` to ensure file attributes such as line endings co
To ensure reproducible CI results, `ci.rs` imposes strict requirements on the workspace state:
- If the current workspace is not clean and `--dirty` has not been specified, the script will prompt whether to create a temporary commit:
- - The commit message is `[DO NOT PUSH] CI TEMP [DO NOT PUSH]`.
- - Use `-y` to auto-confirm without interaction.
+ - The commit message is `[DO NOT PUSH] CI TEMP [DO NOT PUSH]`.
+ - Use `-y` to auto-confirm without interaction.
- After CI finishes, the script automatically restores the workspace:
- - First, `git reset --hard` discards all changes.
- - If a temporary commit was created, it then runs `git reset --soft HEAD~1` and unstages everything, restoring the state to before CI started.
+ - First, `git reset --hard` discards all changes.
+ - If a temporary commit was created, it then runs `git reset --soft HEAD~1` and unstages everything, restoring the state to before CI started.
- If `--dirty` is specified, the temporary commit and the final cleanliness check are skipped.
> **Warning**: `git reset --hard` is executed at the end of CI. If you use `--dirty`, ensure you have no unsaved important changes.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d90db4a..e8e4bed 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,46 +6,46 @@ Before contributing, we recommend reading [README](README.md) to get an overview
## 1. Project Structure
-| Category | Path/Name | Description |
-| ---------------------------- | ------------------------- | ------------------------------------------------------------------------------------- |
-| **Entry crate** | `mingling/` | Project entry point |
-| **Core library** | `mingling_core/` | Imported as an external dependency |
-| **Macro library** | `mingling_macros/` | Imported as an external dependency |
-| **Examples** | `examples/` | To add expected output tests, modify `examples/test-examples.toml` |
-| **Documentation, resources** | `docs/` | All documentation and resource files |
-| **Development tools** | `dev_tools/` | Contains scripts and Rust tools |
-| Scripts | `dev_tools/scripts/` | Helper `.sh`/`.ps1`/`.py` scripts, executed via `./run-tools.sh` or `.\run-tools.ps1` |
-| Rust tools | `dev_tools/src/bin/` | Same as above |
-| CI check entry | `dev_tools/src/bin/ci.rs` | Can be invoked directly via `cargo ci` |
-| **Scaffolding tool** | `mling/` | Scaffolding tool `mingling-cli` |
-| **Temporary files** | `.temp/` | Ignored by `.gitignore` |
+| Category | Path/Name | Description |
+| ---------------------------- | ------------------------- | ------------------------------------------------------------------------- |
+| **Entry crate** | `mingling/` | Project entry point |
+| **Core library** | `mingling_core/` | Imported as an external dependency |
+| **Macro library** | `mingling_macros/` | Imported as an external dependency |
+| **Examples** | `examples/` | To add expected output tests, modify `examples/test-examples.toml` |
+| **Documentation, resources** | `docs/` | All documentation and resource files |
+| **Development tools** | `.run/src/bin` | Contains scripts and Rust tools |
+| Scripts | `.run/src/bin` | Helper `.sh`/`.ps1`/`.py` scripts, executed via `./run.sh` or `.\run.ps1` |
+| Rust tools | `dev_tools/src/bin/` | Same as above |
+| CI check entry | `dev_tools/src/bin/ci.rs` | Can be invoked directly via `cargo ci` |
+| **Scaffolding tool** | `mling/` | Scaffolding tool `mingling-cli` |
+| **Temporary files** | `.temp/` | Ignored by `.gitignore` |
## 2. Submission Guide
1. **Pull Request**
- - Submit a GitHub Pull Request and @Reviewer **[Weicao-CatilGrass](https://github.com/Weicao-CatilGrass)** for review
- - Or send patches to **catil_grass@qq.com**
+ - Submit a GitHub Pull Request and @Reviewer **[Weicao-CatilGrass](https://github.com/Weicao-CatilGrass)** for review
+ - Or send patches to **catil_grass@qq.com**
2. **Commit Messages**
- - Clearly and concisely describe the changes, no stringent requirements
- - Provide more detail for complex changes, keep it brief for simple changes
- - But: if you use [Conventional Commits](https://www.conventionalcommits.org/), it would make me even happier :)
+ - Clearly and concisely describe the changes, no stringent requirements
+ - Provide more detail for complex changes, keep it brief for simple changes
+ - But: if you use [Conventional Commits](https://www.conventionalcommits.org/), it would make me even happier :)
3. **CHANGELOG**
- - If the submission includes functional changes or fixes, **the PR must include modifications to CHANGELOG.md** to describe the changes
- - For minor changes like typo fixes, **CHANGELOG.md modification is not required**, and we will merge faster
+ - If the submission includes functional changes or fixes, **the PR must include modifications to CHANGELOG.md** to describe the changes
+ - For minor changes like typo fixes, **CHANGELOG.md modification is not required**, and we will merge faster
4. **Multi-commit PR**
- - A PR can contain multiple commits
- - However, at least one commit must modify CHANGELOG.md
+ - A PR can contain multiple commits
+ - However, at least one commit must modify CHANGELOG.md
5. **Review**
- - After submission, please notify [Weicao-CatilGrass](https://github.com/Weicao-CatilGrass) for review — this is the most efficient way to get feedback
+ - After submission, please notify [Weicao-CatilGrass](https://github.com/Weicao-CatilGrass) for review — this is the most efficient way to get feedback
6. **Binary Resources**
- - For binary resource files (images, etc.), please be cautious about adding them to avoid repository bloat
+ - For binary resource files (images, etc.), please be cautious about adding them to avoid repository bloat
## 3. Documentation Contribution
@@ -60,11 +60,11 @@ After editing documentation, refresh relevant files:
```bash
# Refresh sidebar and README sync
-./run-tools.sh docsify-sidebar-gen
-./run-tools.sh refresh-docs
+./run.sh docsify-sidebar-gen
+./run.sh refresh-docs
# Fix code block blank line issues
-./run-tools.sh docs-code-box-fix
+./run.sh docs-code-box-fix
```
These steps are included in `cargo ci`; running `cargo ci` will execute them automatically.
diff --git a/Cargo.toml b/Cargo.toml
index dba7264..201f88e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ exclude = [
"examples/*",
# Dev Tools
- "dev_tools",
+ ".run",
# Tests
"mingling_core/tests/*",
diff --git a/run-tools.ps1 b/run-tools.ps1
deleted file mode 100644
index 7aa2c9c..0000000
--- a/run-tools.ps1
+++ /dev/null
@@ -1,60 +0,0 @@
-Set-Location -Path (Split-Path -Parent $MyInvocation.MyCommand.Path) -ErrorAction Stop
-
-# Collect all available tool names
-$tools = @()
-
-if (Test-Path "dev_tools/scripts") {
- $scripts = Get-ChildItem -Path "dev_tools/scripts/*.ps1", "dev_tools/scripts/*.py"
- foreach ($script in $scripts) {
- if ($script -is [System.IO.FileInfo]) {
- $tools += $script.BaseName
- }
- }
-}
-if (Test-Path "dev_tools/src/bin") {
- $files = Get-ChildItem -Path "dev_tools/src/bin/*.rs"
- foreach ($file in $files) {
- if ($file -is [System.IO.FileInfo]) {
- $tools += $file.BaseName
- }
- }
-}
-
-if ($args.Count -eq 0) {
- Write-Host "Available:"
- for ($i = 0; $i -lt $tools.Count; $i++) {
- Write-Host (" [{0,2}] {1}" -f ($i + 1), $tools[$i])
- }
- exit 1
-}
-
-$target_name = $args[0]
-
-# Check if input is a number
-if ($target_name -match '^\d+$') {
- $idx = [int]$target_name - 1
- if ($idx -ge 0 -and $idx -lt $tools.Count) {
- $target_name = $tools[$idx]
- } else {
- Write-Host "Error: invalid number '$target_name', valid range is 1-$($tools.Count)"
- exit 1
- }
-}
-
-# Collect remaining arguments to pass to the script
-$script_args = $args[1..$args.Count]
-
-$script_file_ps1 = "dev_tools/scripts/${target_name}.ps1"
-$script_file_py = "dev_tools/scripts/${target_name}.py"
-$rust_file = "dev_tools/src/bin/${target_name}.rs"
-
-if (Test-Path $script_file_ps1) {
- & $script_file_ps1 $script_args
-} elseif (Test-Path $script_file_py) {
- python $script_file_py $script_args
-} elseif (Test-Path $rust_file) {
- cargo run --manifest-path dev_tools/Cargo.toml --bin $target_name --quiet -- $script_args
-} else {
- Write-Host "Error: target '$target_name' does not exist as a script or Rust program"
- exit 1
-}
diff --git a/run-tools.sh b/run-tools.sh
deleted file mode 100755
index 9a68f0e..0000000
--- a/run-tools.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/bash
-
-cd "$(dirname "$0")" || exit 1
-
-# Collect all available tool names
-tools=()
-
-if [ -d "dev_tools/scripts" ]; then
- for file in dev_tools/scripts/*.sh; do
- if [ -f "$file" ]; then
- tools+=("$(basename "$file" .sh)")
- fi
- done
- for file in dev_tools/scripts/*.py; do
- if [ -f "$file" ]; then
- tools+=("$(basename "$file" .py)")
- fi
- done
-fi
-if [ -d "dev_tools/src/bin" ]; then
- for file in dev_tools/src/bin/*.rs; do
- if [ -f "$file" ]; then
- tools+=("$(basename "$file" .rs)")
- fi
- done
-fi
-
-if [ $# -eq 0 ]; then
- echo "Available:"
- for i in "${!tools[@]}"; do
- printf " [%2d] %s\n" $((i + 1)) "${tools[$i]}"
- done
- exit 1
-fi
-
-target_bin="$1"
-shift # Remove the first argument (tool name), keep the rest as tool arguments
-
-# Check if input is a number
-if [[ "$target_bin" =~ ^[0-9]+$ ]]; then
- idx=$((target_bin - 1))
- if [ "$idx" -ge 0 ] && [ "$idx" -lt "${#tools[@]}" ]; then
- target_bin="${tools[$idx]}"
- else
- echo "Error: invalid number '$target_bin', valid range is 1-${#tools[@]}"
- exit 1
- fi
-fi
-
-target_script="dev_tools/scripts/${target_bin}.sh"
-target_python="dev_tools/scripts/${target_bin}.py"
-target_file="dev_tools/src/bin/${target_bin}.rs"
-
-if [ -f "$target_script" ]; then
- chmod +x "$target_script"
- "$target_script" "$@"
-elif [ -f "$target_python" ]; then
- python "$target_python" "$@"
-elif [ -f "$target_file" ]; then
- cargo run --manifest-path dev_tools/Cargo.toml --bin "$target_bin" --quiet -- "$@"
-else
- echo "Error: target '$target_bin' does not exist"
- exit 1
-fi
diff --git a/run.ps1 b/run.ps1
new file mode 100644
index 0000000..af8effe
--- /dev/null
+++ b/run.ps1
@@ -0,0 +1,232 @@
+#
+# ██ ██████ ██ ██ ███ ██ ██████ ███████ ██
+# ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ███
+# ██ ██████ ██ ██ ██ ██ ██ ██████ ███████ ██
+# ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+# ██ ██ ██ ██ ██████ ██ ████ ██ ██ ███████ ██
+#
+# You can go to [https://catilgrass.github.io/run] to install it
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Set-Location -Path (Split-Path -Parent $MyInvocation.MyCommand.Path) -ErrorAction Stop
+
+$tools = @{}
+
+if (Test-Path ".run/src/bin/*.ps1") {
+ Get-ChildItem -Path ".run/src/bin/*.ps1" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "ps1"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.cs") {
+ Get-ChildItem -Path ".run/src/bin/*.cs" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "cs"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.exe") {
+ Get-ChildItem -Path ".run/src/bin/*.exe" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "exe"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.go") {
+ Get-ChildItem -Path ".run/src/bin/*.go" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "go"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.nim") {
+ Get-ChildItem -Path ".run/src/bin/*.nim" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "nim"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.pl") {
+ Get-ChildItem -Path ".run/src/bin/*.pl" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "pl"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.py") {
+ Get-ChildItem -Path ".run/src/bin/*.py" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "py"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.rb") {
+ Get-ChildItem -Path ".run/src/bin/*.rb" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "rb"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.rs") {
+ Get-ChildItem -Path ".run/src/bin/*.rs" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "rs"; Path = $_.FullName }
+ }
+}
+
+if (Test-Path ".run/src/bin/*.zig") {
+ Get-ChildItem -Path ".run/src/bin/*.zig" | ForEach-Object {
+ $tools[$_.BaseName] = @{ Type = "zig"; Path = $_.FullName }
+ }
+}
+
+if ($args.Count -eq 0) {
+ $sorted = @($tools.Keys | Sort-Object @{Expression={if ($tools[$_].Type -eq 'ps1') {0} else {1}}}, {$_})
+ $total = $sorted.Count
+ $num_w = $total.ToString().Length
+
+ $max_name = ($sorted | ForEach-Object { $_.Length } | Measure-Object -Maximum).Maximum
+
+ $inner_w = 2 + $num_w + 1 + 1 + $max_name + 2 + 10 + 1 + 2
+ if ($inner_w -lt 38) { $inner_w = 38 }
+
+ $title = '.\run.ps1 <NUMBER/NAME> [ARGS...]'
+ $title_len = $title.Length
+ $dash_total = $inner_w - 2 - $title_len
+ $dash_left = [Math]::Floor($dash_total / 2)
+ $dash_right = $dash_total - $dash_left
+
+ Write-Host ("┌" + ("─" * $dash_left) + " " + $title + " " + ("─" * $dash_right) + "┐")
+ Write-Host ("│" + (" " * $inner_w) + "│")
+
+ $i = 1
+ foreach ($name in $sorted) {
+ $type = $tools[$name].Type
+ $lang = switch ($type) {
+ "ps1" { "PowerShell" }
+ "cs" { "C#" }
+ "exe" { "Binary" }
+ "go" { "Go" }
+ "nim" { "Nim" }
+ "pl" { "Perl" }
+ "py" { "Python" }
+ "rb" { "Ruby" }
+ "rs" { "Rust" }
+ "zig" { "Zig" }
+ }
+ $displayName = $name -replace '[_\-]', ' '
+ $entry = " " + $i.ToString().PadRight($num_w) + ") " + $displayName.PadRight($max_name) + " [$lang]"
+ Write-Host ("│" + $entry.PadRight($inner_w) + "│")
+ $i++
+ }
+
+ Write-Host ("│" + (" " * $inner_w) + "│")
+ Write-Host ("└" + ("─" * $inner_w) + "┘")
+ exit 1
+}
+
+$target_name = $args[0]
+
+if ($target_name -match '^\d+$') {
+ $sorted = @($tools.Keys | Sort-Object @{Expression={if ($tools[$_].Type -eq 'ps1') {0} else {1}}}, {$_})
+ $idx = [int]$target_name - 1
+ if ($idx -ge 0 -and $idx -lt $sorted.Count) {
+ $target_name = $sorted[$idx]
+ } else {
+ Write-Host "Error: invalid number '$target_name', valid range is 1-$($sorted.Count)"
+ exit 1
+ }
+}
+
+if (-not $tools.ContainsKey($target_name)) {
+ $normalized = $target_name.ToLower() -replace '[ _\-\.]', ''
+ $found = $null
+ foreach ($key in $tools.Keys) {
+ $keyNormalized = $key.ToLower() -replace '[ _\-\.]', ''
+ if ($normalized -eq $keyNormalized) {
+ $found = $key
+ break
+ }
+ }
+ if ($found) {
+ $target_name = $found
+ } else {
+ Write-Host "Error: target '$target_name' does not exist"
+ exit 1
+ }
+}
+
+$script_args = $args[1..$args.Count]
+$info = $tools[$target_name]
+
+switch ($info.Type) {
+ "ps1" {
+ & $info.Path @script_args
+ }
+ "cs" {
+ $temp_dir = ".run/target/csproj/$target_name"
+ $null = New-Item -ItemType Directory -Path $temp_dir -Force
+
+ $props_content = @'
+<Project>
+ <PropertyGroup>
+ <BaseOutputPath>$(MSBuildThisFileDirectory)../../csharp/bin</BaseOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)../../csharp/obj</BaseIntermediateOutputPath>
+ </PropertyGroup>
+</Project>
+'@
+ Set-Content -Path "$temp_dir/Directory.Build.props" -Value $props_content
+
+ $csproj_content = @"
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net8.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ </PropertyGroup>
+
+</Project>
+"@
+ Set-Content -Path "$temp_dir/$target_name.csproj" -Value $csproj_content
+ Copy-Item -Path $info.Path -Destination "$temp_dir/Program.cs" -Force
+
+ dotnet run --project "$temp_dir/$target_name.csproj" -- $script_args
+ }
+ "exe" {
+ & $info.Path $script_args
+ }
+ "go" {
+ go run $info.Path $script_args
+ }
+ "nim" {
+ nim r --hints:off $info.Path $script_args
+ }
+ "pl" {
+ perl $info.Path $script_args
+ }
+ "py" {
+ python $info.Path $script_args
+ }
+ "rb" {
+ ruby $info.Path $script_args
+ }
+ "rs" {
+ if (-not (Test-Path ".run/Cargo.toml")) {
+@"
+[package]
+name = "run_rust"
+version = "0.1.0"
+edition = "2024"
+
+[workspace]
+
+[dependencies]
+"@ | Set-Content -Path ".run/Cargo.toml"
+ }
+ cargo build --manifest-path ".run/Cargo.toml" --target-dir ".run/target" --bin $target_name --quiet
+ $binary = ".run/target/debug/$target_name.exe"
+ if (-not (Test-Path $binary)) {
+ $binary = ".run/target/debug/$target_name"
+ }
+ & $binary $script_args
+ }
+ "zig" {
+ zig run $info.Path $script_args
+ }
+}
+
+exit $LASTEXITCODE
diff --git a/run.sh b/run.sh
new file mode 100644
index 0000000..cc03790
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,257 @@
+#!/bin/bash
+
+#
+# ██ ██████ ██ ██ ███ ██ ███████ ██ ██
+# ██ ██ ██ ██ ██ ████ ██ ██ ██ ██
+# ██ ██████ ██ ██ ██ ██ ██ ███████ ███████
+# ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+# ██ ██ ██ ██ ██████ ██ ████ ██ ███████ ██ ██
+#
+# You can go to [https://catilgrass.github.io/run] to install it
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+cd "$(dirname "$0")" || exit 1
+
+declare -A tools
+
+for file in .run/src/bin/*.sh; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .sh)
+ tools["$name"]="sh"
+ fi
+done
+
+for file in .run/src/bin/*; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file")
+ if [[ ! "$name" == *.* ]]; then
+ tools["$name"]="binary"
+ fi
+ fi
+done
+
+for file in .run/src/bin/*.cs; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .cs)
+ tools["$name"]="cs"
+ fi
+done
+
+for file in .run/src/bin/*.go; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .go)
+ tools["$name"]="go"
+ fi
+done
+
+for file in .run/src/bin/*.nim; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .nim)
+ tools["$name"]="nim"
+ fi
+done
+
+for file in .run/src/bin/*.pl; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .pl)
+ tools["$name"]="pl"
+ fi
+done
+
+for file in .run/src/bin/*.py; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .py)
+ tools["$name"]="py"
+ fi
+done
+
+for file in .run/src/bin/*.rb; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .rb)
+ tools["$name"]="rb"
+ fi
+done
+
+for file in .run/src/bin/*.rs; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .rs)
+ tools["$name"]="rs"
+ fi
+done
+
+for file in .run/src/bin/*.zig; do
+ if [ -f "$file" ]; then
+ name=$(basename "$file" .zig)
+ tools["$name"]="zig"
+ fi
+done
+
+if [ $# -eq 0 ]; then
+ sorted_names=($(
+ for name in "${!tools[@]}"; do
+ if [ "${tools[$name]}" = "sh" ]; then
+ echo "0 $name"
+ else
+ echo "1 $name"
+ fi
+ done | sort | while read -r _ n; do echo "$n"; done
+ ))
+ total=${#sorted_names[@]}
+ num_w=${#total}
+
+ max_name=0
+ for name in "${sorted_names[@]}"; do
+ len=${#name}
+ ((len > max_name)) && max_name=$len
+ done
+
+ inner_w=$((2 + num_w + 1 + 1 + max_name + 2 + 6 + 1 + 2))
+ ((inner_w < 38)) && inner_w=38
+
+ title="./run.sh <NUMBER/NAME> [ARGS...]"
+ title_len=${#title}
+ dash_total=$((inner_w - 2 - title_len))
+ dash_left=$((dash_total / 2))
+ dash_right=$((dash_total - dash_left))
+
+ echo "┌$(printf '─%.0s' $(seq 1 $dash_left)) $title $(printf '─%.0s' $(seq 1 $dash_right))┐"
+ printf "│%*s│\n" $inner_w ""
+
+ i=1
+ for name in "${sorted_names[@]}"; do
+ type="${tools[$name]}"
+ case "$type" in
+ sh) lang="Shell";;
+ binary) lang="Binary";;
+ cs) lang="C#";;
+ go) lang="Go";;
+ nim) lang="Nim";;
+ pl) lang="Perl";;
+ py) lang="Python";;
+ rb) lang="Ruby";;
+ rs) lang="Rust";;
+ zig) lang="Zig";;
+ esac
+ display_name=$(echo "$name" | tr '_-' ' ')
+ entry=$(printf " %-*d) %-*s [%s]" $num_w $i $max_name "$display_name" $lang)
+ printf "│%-*s│\n" $inner_w "$entry"
+ i=$((i + 1))
+ done
+
+ printf "│%*s│\n" $inner_w ""
+ echo "└$(printf '─%.0s' $(seq 1 $inner_w))┘"
+ exit 1
+fi
+
+target_name="$1"
+shift
+
+if [[ "$target_name" =~ ^[0-9]+$ ]]; then
+ sorted=($(
+ for name in "${!tools[@]}"; do
+ if [ "${tools[$name]}" = "sh" ]; then
+ echo "0 $name"
+ else
+ echo "1 $name"
+ fi
+ done | sort | while read -r _ n; do echo "$n"; done
+ ))
+ idx=$((target_name - 1))
+ if [ "$idx" -ge 0 ] && [ "$idx" -lt "${#sorted[@]}" ]; then
+ target_name="${sorted[$idx]}"
+ else
+ echo "Error: invalid number '$target_name', valid range is 1-${#sorted[@]}"
+ exit 1
+ fi
+fi
+
+if [ -z "${tools[$target_name]}" ]; then
+ normalized_user=$(echo "$target_name" | tr '[:upper:]' '[:lower:]' | sed 's/[_. -]//g')
+ found=""
+ for existing_name in "${!tools[@]}"; do
+ normalized_existing=$(echo "$existing_name" | tr '[:upper:]' '[:lower:]' | sed 's/[_. -]//g')
+ if [ "$normalized_user" = "$normalized_existing" ]; then
+ found="$existing_name"
+ break
+ fi
+ done
+ if [ -n "$found" ]; then
+ target_name="$found"
+ else
+ echo "Error: target '$target_name' does not exist"
+ exit 1
+ fi
+fi
+
+type="${tools[$target_name]}"
+
+case "$type" in
+ sh)
+ chmod +x ".run/src/bin/$target_name.sh"
+ ".run/src/bin/$target_name.sh" "$@"
+ ;;
+ binary)
+ chmod +x ".run/src/bin/$target_name"
+ ".run/src/bin/$target_name" "$@"
+ ;;
+ cs)
+ temp_dir=".run/target/csproj/$target_name"
+ mkdir -p "$temp_dir"
+ cat > "$temp_dir/Directory.Build.props" <<'PROPS'
+<Project>
+ <PropertyGroup>
+ <BaseOutputPath>$(MSBuildThisFileDirectory)../../csharp/bin</BaseOutputPath>
+ <BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)../../csharp/obj</BaseIntermediateOutputPath>
+ </PropertyGroup>
+</Project>
+PROPS
+ cat > "$temp_dir/$target_name.csproj" <<'CSPROJ'
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net8.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ </PropertyGroup>
+
+</Project>
+CSPROJ
+ cp ".run/src/bin/$target_name.cs" "$temp_dir/Program.cs"
+ dotnet run --project "$temp_dir/$target_name.csproj" -- "$@"
+ ;;
+ go)
+ go run ".run/src/bin/$target_name.go" "$@"
+ ;;
+ nim)
+ nim r --hints:off ".run/src/bin/$target_name.nim" "$@"
+ ;;
+ pl)
+ perl ".run/src/bin/$target_name.pl" "$@"
+ ;;
+ py)
+ python ".run/src/bin/$target_name.py" "$@"
+ ;;
+ rb)
+ ruby ".run/src/bin/$target_name.rb" "$@"
+ ;;
+ rs)
+ if [ ! -f ".run/Cargo.toml" ]; then
+ cat > ".run/Cargo.toml" <<'EOF'
+[package]
+name = "run_rust"
+version = "0.1.0"
+edition = "2024"
+
+[workspace]
+
+[dependencies]
+EOF
+ fi
+ cargo build --manifest-path ".run/Cargo.toml" --target-dir ".run/target" --bin "$target_name" --quiet
+ ".run/target/debug/$target_name" "$@"
+ ;;
+ zig)
+ zig run ".run/src/bin/$target_name.zig" "$@"
+ ;;
+esac