|
| 1 | +# `rust-script` |
| 2 | + - ## What **rust-script** Is |
| 3 | + - **rust-script** is a lightweight tool that allows you to run **single-file Rust programs** as scripts—similar to how you might use Python, Ruby, or Node.js—without manually creating a full Cargo project. |
| 4 | + - You can write Rust in a single `.rs` file with special "script headers," and run it directly with: |
| 5 | + - ~~~bash |
| 6 | + rust-script my_script.rs |
| 7 | + ~~~ |
| 8 | + - It handles: |
| 9 | + - On-demand compilation |
| 10 | + - Dependency resolution via Cargo |
| 11 | + - Caching for fast re-runs |
| 12 | + - Optional shebang execution (`#!/usr/bin/env rust-script`) |
| 13 | + - ## Why People Use rust-script |
| 14 | + - **rust-script makes Rust feel like a scripting language** while preserving full Rust performance and tooling. |
| 15 | + - Use cases include: |
| 16 | + - Utility scripts |
| 17 | + - Build scripts and automation |
| 18 | + - Prototyping Rust code |
| 19 | + - Teaching and examples |
| 20 | + - Quick CLIs without scaffolding |
| 21 | + - Compared with writing a whole Cargo project, it's dramatically quicker for small tasks. |
| 22 | + - ## Key Features |
| 23 | + - ### 1. **Single-file executables** |
| 24 | + - Write a script like: |
| 25 | + - ~~~rust |
| 26 | + fn main() { |
| 27 | + println!("Hello, world!"); |
| 28 | + } |
| 29 | + ~~~ |
| 30 | + - Run with: |
| 31 | + - ~~~bash |
| 32 | + rust-script hello.rs |
| 33 | + ~~~ |
| 34 | + - ### 2. **Inline dependencies** |
| 35 | + - Add dependencies right in the file (much like Rust's `cargo-script` used to allow): |
| 36 | + - ~~~rust |
| 37 | + //! cargo-deps: reqwest = "0.11", tokio = { version = "1", features = ["full"] } |
| 38 | + |
| 39 | + #[tokio::main] |
| 40 | + async fn main() { |
| 41 | + let body = reqwest::get("https://example.com").await.unwrap().text().await.unwrap(); |
| 42 | + println!("{body}"); |
| 43 | + } |
| 44 | + ~~~ |
| 45 | + - rust-script reads these headers, generates a temporary Cargo project, compiles it, and caches it. |
| 46 | + - ### 3. **Shebang support** |
| 47 | + - You can make Rust scripts directly executable on Unix-like systems: |
| 48 | + - ~~~rust |
| 49 | + #!/usr/bin/env rust-script |
| 50 | + fn main() { |
| 51 | + println!("Hello from a shebang!"); |
| 52 | + } |
| 53 | + ~~~ |
| 54 | + - Run directly: |
| 55 | + - ~~~bash |
| 56 | + ./myscript |
| 57 | + ~~~ |
| 58 | + - ### 4. **Cargo-like experience, minimal ceremony** |
| 59 | + - It automatically: |
| 60 | + - Creates an implicit Cargo manifest |
| 61 | + - Pulls dependencies |
| 62 | + - Compiles and caches binaries |
| 63 | + - You stay focused on the code. |
| 64 | + - ### 5. **Fast re-runs via caching** |
| 65 | + - The first run compiles; subsequent runs are nearly instant unless the script changes. |
| 66 | + - ## How rust-script Compares to Alternatives |
| 67 | + - **rust-script**: Easiest for single-file scripts with inline deps; very ergonomic. |
| 68 | + - **cargo-script**: Similar predecessor; rust-script is generally more up-to-date and idiomatic. |
| 69 | + - **cargo + `fn main`**: Standard approach, but requires project scaffolding. |
| 70 | + - **EvCxR** (Jupyter/REPL): Great for interactive experimentation; slower for scripting. |
| 71 | + - **shebang with `cargo run`**: Possible but much heavier. |
| 72 | + - rust-script strikes the balance between **real Rust** and **script-like workflows**. |
| 73 | + - ## Installation |
| 74 | + - [[cargo/install]] is used to install binary crates (executables) globally, not libraries. Libraries are added as dependencies in `Cargo.toml`. |
| 75 | + - ~~~bash |
| 76 | + cargo install rust-script |
| 77 | + ~~~ |
| 78 | + - ## Execution model |
| 79 | + - When invoked: |
| 80 | + - It parses script headers (dependencies, features, edition). |
| 81 | + - Generates a temporary Cargo project under the hood. |
| 82 | + - Compiles and caches the executable. |
| 83 | + - Runs the compiled binary. |
| 84 | + - The cache invalidates when: |
| 85 | + - The script contents change |
| 86 | + - The inline dependency list changes |
| 87 | + - Toolchain changes |
| 88 | + - ## Limitations |
| 89 | + - Not ideal for multi-file projects |
| 90 | + - Compilation is still Rust-fast (but not Python-fast) |
| 91 | + - Inline dependency parsing has some constraints (header comment formats) |
| 92 | + - Requires Cargo and the Rust toolchain |
| 93 | + - ## Quick Example |
| 94 | + - `echo.rs`: |
| 95 | + - ~~~rust |
| 96 | + //! cargo-deps: clap = "4" |
| 97 | + |
| 98 | + use clap::Parser; |
| 99 | + |
| 100 | + #[derive(Parser)] |
| 101 | + struct Args { |
| 102 | + message: String, |
| 103 | + } |
| 104 | + |
| 105 | + fn main() { |
| 106 | + let args = Args::parse(); |
| 107 | + println!("You said: {}", args.message); |
| 108 | + } |
| 109 | + ~~~ |
| 110 | + - Run: |
| 111 | + - ~~~bash |
| 112 | + rust-script echo.rs "hello" |
| 113 | + ~~~ |
| 114 | + - If you'd like, I can also prepare: |
| 115 | + - A cheat sheet |
| 116 | + - A comparison to Python / Node scripting workflows |
| 117 | + - A template for a reusable internal tool script |
| 118 | + - Examples for specific tasks (file I/O, HTTP, concurrency) |
0 commit comments