Skip to content

Commit 4e234d3

Browse files
committed
Overhauled README.md.
1 parent a03053a commit 4e234d3

File tree

2 files changed

+149
-85
lines changed

2 files changed

+149
-85
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
* Several environment variables are now given to scripts by `cargo-script`.
77

8+
**Changed:**
9+
10+
* Overhauled `README.md`.
11+
812
# v0.2.6
913

1014
**Fixed:**

README.md

Lines changed: 145 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,195 @@
11
# `cargo-script`
22

3-
`cargo-script` is a Cargo subcommand designed to let people quickly and easily run Rust "scripts" which can make use of Cargo's package ecosystem.
3+
`cargo-script` is a Cargo subcommand designed to let people quickly and easily run Rust "scripts" which can make use of Cargo's package ecosystem. It can also evaluate expressions and run filters.
44

5-
Or, to put it in other words, it lets you write useful, but small, Rust programs without having to create a new directory and faff about with `Cargo.toml`.
5+
Some of `cargo-script`'s features include:
66

7-
As such, `cargo-script` does two major things:
8-
9-
1. Given a script, it extracts the embedded Cargo manifest and merges it with some sensible defaults. This manifest, along with the source code, is written to a fresh Cargo package on-disk.
10-
11-
2. It caches the generated and compiled packages, regenerating them only if the script or its metadata have changed.
7+
- Reading Cargo manifests embedded in Rust scripts.
8+
- Caching compiled artefacts (including dependencies) to amortise build times.
9+
- Supporting executable Rust scripts via UNIX hashbangs and Windows file associations.
10+
- Evaluating expressions on the command-line.
11+
- Using expressions as stream filters (*i.e.* for use in command pipelines).
12+
- Running unit tests and benchmarks from scripts.
13+
- Custom templates for command-line expressions and filters.
1214

1315
**Note**: `cargo-script` *does not* work when Cargo is instructed to use a target architecture different to the default host architecture.
1416

17+
Table of contents:
18+
19+
- [Installation](#installation)
20+
- [Migrating From Previous Versions](#migrating)
21+
- [Features](#features)
22+
- [Manually Compiling and Installing](#compiling)
23+
- [Self-Executing Scripts](#hashbang)
24+
- [Usage](#usage)
25+
- [Scripts](#scripts)
26+
- [Expressions](#expressions)
27+
- [Stream Filters](#filters)
28+
- [Environment Variables](#env-vars)
29+
- [Templates](#templates)
30+
- [License](#license)
31+
- [Contribution](#contribution)
32+
33+
<a name="installation"></a>
1534
## Installation
1635

17-
You can install `cargo-script` using Cargo's `install` subcommand:
36+
The recommended method for installing `cargo-script` is by using Cargo's `install` subcommand:
1837

1938
```sh
2039
cargo install cargo-script
2140
```
2241

23-
### Features
42+
If you have already installed `cargo-script`, you can update to the latest version by using:
43+
44+
```sh
45+
cargo install --force cargo-script
46+
```
47+
48+
<a name="migrating"></a>
49+
### Migrating From Previous Versions
50+
51+
`cargo-script` supports migrating data from previous versions. This is not mandatory, but may be preferred. Using `cargo script --migrate-data dry-run` will perform a "dry run", informing you of any applicable migrations. Using the `for-real` option will actually perform the migration. The following migrations may be applicable:
52+
53+
- 0.1 → 0.2: On non-Windows platforms, and when `CARGO_HOME` is defined, moves the location for cached data from `$CARGO_HOME/.cargo` to `$CARGO_HOME`.
54+
55+
<a name="features"></a>
56+
### Cargo Features
2457

2558
The following features are defined:
2659

27-
- `suppress-cargo-output` (default): if building the script takes less than 2 seconds and succeeds, `cargo-script` will suppress Cargo's output.
60+
- `suppress-cargo-output` (default): if building the script takes less than 2 seconds and succeeds, `cargo-script` will suppress Cargo's output. Note that this disabled coloured Cargo output on Windows.
2861

62+
<a name="compiling"></a>
2963
### Manually Compiling and Installing
3064

3165
`cargo-script` requires Rust 1.11 or higher to build. Rust 1.4+ was supported prior to version 0.2.
3266

33-
Once built, you should place the resulting executable somewhere on your `PATH`. At that point, you should be able to invoke it by using `cargo script`.
67+
Once built, you should place the resulting executable somewhere on your `PATH`. At that point, you should be able to invoke it by using `cargo script`. Note that you *can* run the executable directly, but the first argument will *need* to be `script`.
3468

35-
Note that you *can* run the executable directly, but the first argument will *need* to be `script`.
69+
If you want to run `cargo script` from a hashbang on UNIX, or via file associations on Windows, you should also install the `run-cargo-script` program somewhere on `PATH`.
3670

37-
If you want to run `cargo script` from a hashbang, you should also install the `run-cargo-script` program. We *strongly* recommend installing this program to the `PATH` and using `#!/usr/bin/env run-cargo-script` as the hashbang line.
71+
<a name="hashbang"></a>
72+
### Self-Executing Scripts
3873

39-
### File Associations
74+
On UNIX systems, you can use `#!/usr/bin/env run-cargo-script` as a hashbang line in a Rust script. If the script file is executable, this will allow you to execute a script file directly.
4075

4176
If you are using Windows, you can associate the `.crs` extension (which is simply a renamed `.rs` file) with `run-cargo-script`. This allows you to execute Rust scripts simply by naming them like any other executable or script.
4277

4378
This can be done using the `cargo-script file-association` command (note the hyphen in `cargo-script`). This command can also remove the file association. If you pass `--amend-pathext` to the `file-assocation install` command, it will also allow you to execute `.crs` scripts *without* having to specify the file extension, in the same way that `.exe` and `.bat` files can be used.
4479

80+
If you want to make a script usable across platforms, it is recommended that you use *both* a hashbang line *and* give the file a `.crs` file extension.
81+
82+
<a name="usage"></a>
4583
## Usage
4684

47-
The simplest way to use `cargo-script` is to simply pass it the name of the Rust script you want to execute:
85+
Generally, you will want to use `cargo-script` by invoking it as `cargo script` (note the lack of a hypen). Doing so is equivalent to invoking it as `cargo-script script`. `cargo-script` supports several other subcommands, which can be accessed by running `cargo-script` directly. You can also get an overview of the available options using the `--help` flag.
86+
87+
<a name="scripts"></a>
88+
### Scripts
89+
90+
The primary use for `cargo-script` is for running Rust source files as scripts. For example:
4891

4992
```shell
5093
$ echo 'fn main() { println!("Hello, World!"); }' > hello.rs
5194
$ cargo script hello.rs
52-
Compiling hello v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/file-hello-25c8c198030c5d089740-3ace88497b98af47db6e)
5395
Hello, World!
54-
$ cargo script hello # you can omit the file extension
96+
$ cargo script hello # you can leave off the file extension
5597
Hello, World!
5698
```
5799

58-
Note that `cargo-script` does not *currently* do anything to suppress the regular output of Cargo. This is *definitely* on purpose and *not* simply out of abject laziness.
59-
60-
You may also embed a partial Cargo manifest at the start of your script, as shown below. `cargo-script` specifically supports the `.crs` extension to distinguish such "Cargoified" files from regular Rust source, but it will process regular `.rs` files in *exactly* the same manner.
61-
62-
Note that all of the following are equivalent:
63-
64-
`now.rs` (code block manifest *and* UNIX hashbang):
65-
66-
```rust
67-
#!/usr/bin/env run-cargo-script
68-
//! This is a regular crate doc comment, but it also contains a partial
69-
//! Cargo manifest. Note the use of a *fenced* code block, and the
70-
//! `cargo` "language".
71-
//!
72-
//! ```cargo
73-
//! [dependencies]
74-
//! time = "0.1.25"
75-
//! ```
76-
extern crate time;
77-
fn main() {
78-
println!("{}", time::now().rfc822z());
79-
}
80-
```
81-
82-
`now.rs` (dependency-only, short-hand manifest):
100+
The output of Cargo will be hidden unless compilation fails, or takes longer than a few seconds.
101+
102+
`cargo-script` will also look for embedded dependency and manifest information in the script. For example, all of the following are equivalent:
103+
104+
- `now.crs` (code block manifest with UNIX hashbang and `.crs` extension):
105+
106+
```rust
107+
#!/usr/bin/env run-cargo-script
108+
//! This is a regular crate doc comment, but it also contains a partial
109+
//! Cargo manifest. Note the use of a *fenced* code block, and the
110+
//! `cargo` "language".
111+
//!
112+
//! ```cargo
113+
//! [dependencies]
114+
//! time = "0.1.25"
115+
//! ```
116+
extern crate time;
117+
fn main() {
118+
println!("{}", time::now().rfc822z());
119+
}
120+
```
121+
122+
- `now.rs` (dependency-only, short-hand manifest):
123+
124+
```rust
125+
// cargo-deps: time="0.1.25"
126+
// You can also leave off the version number, in which case, it's assumed
127+
// to be "*". Also, the `cargo-deps` comment *must* be a single-line
128+
// comment, and it *must* be the first thing in the file, after the
129+
// hashbang.
130+
extern crate time;
131+
fn main() {
132+
println!("{}", time::now().rfc822z());
133+
}
134+
```
135+
136+
> **Note**: you can write multiple dependencies by separating them with commas. *E.g.* `time="0.1.25", libc="0.2.5"`.
137+
138+
On running either of these, `cargo-script` will generate a Cargo package, build it, and run the result. The output may look something like:
83139

84-
```rust
85-
// cargo-deps: time="0.1.25"
86-
// You can also leave off the version number, in which case, it's assumed
87-
// to be "*". Also, the `cargo-deps` comment *must* be a single-line
88-
// comment, and it *must* be the first thing in the file, after the
89-
// hashbang.
90-
extern crate time;
91-
fn main() {
92-
println!("{}", time::now().rfc822z());
93-
}
140+
```shell
141+
$ cargo script now
142+
Updating registry `https://github.com/rust-lang/crates.io-index`
143+
Compiling winapi-build v0.1.1
144+
Compiling winapi v0.2.8
145+
Compiling libc v0.2.30
146+
Compiling kernel32-sys v0.2.2
147+
Compiling time v0.1.38
148+
Compiling now v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/file-now-37cb982cd51cc8b1)
149+
Finished release [optimized] target(s) in 49.7 secs
150+
Sun, 17 Sep 2017 20:38:58 +1000
94151
```
95152

96-
> **Note**: you can write multiple dependencies by separating them with commas. *E.g.* `time="0.1.25", libc="0.2.5"`.
153+
Subsequent runs, provided the script has not changed, will likely just run the cached executable directly:
97154

98155
```shell
99156
$ cargo script now
100-
Updating registry `https://github.com/rust-lang/crates.io-index`
101-
Compiling libc v0.1.8
102-
Compiling gcc v0.3.5
103-
Compiling time v0.1.25
104-
Compiling now v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/file-now-1410beff463a5c50726f-8dbf2bcf69d2d8208c4c)
105-
Sat, 30 May 2015 19:26:57 +1000
157+
Sun, 17 Sep 2017 20:39:40 +1000
106158
```
107159

108-
If you are in a hurry, the above can also be accomplished by telling `cargo-script` that you wish to evaluate an *expression*, rather than an actual file:
160+
Useful command-line arguments:
109161

110-
```text
111-
$ cargo script --dep time --expr \
112-
"extern crate time; time::now().rfc822z().to_string()"
113-
Updating registry `https://github.com/rust-lang/crates.io-index`
114-
Compiling gcc v0.3.5
115-
Compiling libc v0.1.8
116-
Compiling time v0.1.25
117-
Compiling expr v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/expr-a7ffe37fbe6dccff132f)
118-
"Sat, 30 May 2015 19:32:18 +1000"
119-
```
162+
- `--bench`: Compile and run benchmarks. Requires a nightly toolchain.
163+
- `--debug`: Build a debug executable, not an optimised one.
164+
- `--features <features>`: Cargo features to pass when building and running.
165+
- `--force`: Force the script to be rebuilt. Useful if you want to force a recompile with a different toolchain.
166+
- `--gen-pkg-only`: Generate the Cargo package, but don't compile or run it. Effectively "unpacks" the script into a Cargo package.
167+
- `--test`: Compile and run tests.
168+
169+
<a name="expressions"></a>
170+
### Expressions
171+
172+
`cargo-script` can also run pieces of Rust code directly from the command line. This is done by providing the `--expr` option; this causes `cargo-script` to interpret the `<script>` argument as source code *instead* of as a file path. For example, code can be executed from the command line in a number of ways:
173+
174+
- `cargo script --dep time --expr "extern crate time; time::now().rfc822z().to_string()"`
175+
- `cargo script --dep time=0.1.38 --expr "extern crate time; ..."` - uses a specific version of `time`
176+
- `cargo script -d time -e "extern crate time; ..."` - short form of above
177+
- `cargo script -D time -e "..."` - guess and inject `extern crate time`; this only works when the package and crate names of a dependency match.
178+
- `cargo script -d time -x time -e "..."` - injects `extern crate time`; works when the names do *not* match.
120179

121-
Dependencies can also be specified with specific versions (*e.g.* `--dep time=0.1.25`); when omitted, `cargo-script` will simply use `"*"` for the manifest. The above can *also* be written variously as:
180+
The code given is embedded into a block expression, evaluated, and printed out using the `Debug` formatter (*i.e.* `{:?}`).
122181

123-
* `cargo script -d time -e "extern crate time; ..."`
124-
* `cargo script -d time -x time -e "..."`
125-
* `cargo script --dep-extern time --expr "..."`
126-
* `cargo script -D time -e "..."`
182+
Useful command-line arguments:
127183

128-
The `--dep-extern`/`-D` option can be used to insert an automatic `extern crate` item into an expression (or loop, as shown below) script. This *only* works when the package name and compiled crate name match.
184+
- `-d`/`--dep`: add a dependency to the generated `Cargo.toml` manifest.
185+
- `-x`/`--extern`: inject `extern crate` into generated script.
186+
- `-D`/`--dep-extern`: do both of the above.
187+
- `-t`/`--template`: Specify a custom template for this expression (see section on templates).
129188

130-
If you wish to use a dependency where the package and crate names *do not* match, you can specify the dependency with `--dep`/`-d`, and the extern crate name with `--extern`/`-x`.
189+
<a name="filters"></a>
190+
### Stream Filters
131191

132-
Finally, you can also use `cargo-script` to write a quick stream filter, by specifying a closure to be called for each line read from stdin, like so:
192+
You can use `cargo-script` to write a quick stream filter, by specifying a closure to be called for each line read from stdin, like so:
133193

134194
```text
135195
$ cat now.crs | cargo script --loop \
@@ -142,7 +202,7 @@ $ cat now.crs | cargo script --loop \
142202
5: }
143203
```
144204

145-
Note that you can achieve a similar effect to the above by using the `--count` flag, which causes the line number to be passed as a second argument to your closure:
205+
You can achieve a similar effect to the above by using the `--count` flag, which causes the line number to be passed as a second argument to your closure:
146206

147207
```text
148208
$ cat now.crs | cargo script --count --loop \
@@ -155,6 +215,9 @@ $ cat now.crs | cargo script --count --loop \
155215
5: }
156216
```
157217

218+
Note that, like with expressions, you can specify a custom template for stream filters.
219+
220+
<a name="env-vars"></a>
158221
### Environment Variables
159222

160223
The following environment variables are provided to scripts by `cargo-script`:
@@ -167,6 +230,7 @@ The following environment variables are provided to scripts by `cargo-script`:
167230

168231
- `CARGO_SCRIPT_SCRIPT_PATH`: absolute path to the script being run, assuming one exists. Set to the empty string for expressions.
169232

233+
<a name="templates"></a>
170234
### Templates
171235

172236
You can use templates to avoid having to re-specify common code and dependencies. You can view a list of your templates by running `cargo-script templates list` (note the hyphen), or show the folder in which they should be stored by running `cargo-script templates show`. You can dump the contents of a template using `cargo-script templates dump NAME`.
@@ -201,12 +265,7 @@ $ cargo script -t grabbag -e "mem::size_of::<Box<Read>>()"
201265

202266
In addition, there are three built-in templates: `expr`, `loop`, and `loop-count`. These are used for the `--expr`, `--loop`, and `--loop --count` invocation forms. They can be overridden by placing templates with the same name in the template folder. If you have *not* overridden them, you can dump the contents of these built-in templates using the `templates dump` command noted above.
203267

204-
## Things That Should Probably Be Done
205-
206-
* Somehow convince the Cargo devs to add aggressive caching of dependencies so that compiling anything that has dependencies doesn't take an age.
207-
208-
* Gist support? I mean, if it's good enough for playpen...
209-
268+
<a name="license"></a>
210269
## License
211270

212271
Licensed under either of
@@ -216,6 +275,7 @@ Licensed under either of
216275

217276
at your option.
218277

278+
<a name="contribution"></a>
219279
### Contribution
220280

221281
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

0 commit comments

Comments
 (0)