# `cargo-eval` `cargo-eval` 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. Some of `cargo-eval`'s features include: - Reading Cargo manifests embedded in Rust scripts. - Caching compiled artefacts (including dependencies) to amortise build times. - Supporting executable Rust scripts via UNIX hashbangs and Windows file associations. - Evaluating expressions on the command-line. - Using expressions as stream filters (*i.e.* for use in command pipelines). - Running unit tests and benchmarks from scripts. - Custom templates for command-line expressions and filters. **Note**: `cargo-eval` *does not* work when Cargo is instructed to use a target architecture different to the default host architecture. Table of contents: - [Installation](#installation) - [Features](#features) - [Manually Compiling and Installing](#compiling) - [Self-Executing Scripts](#hashbang) - [Usage](#usage) - [Scripts](#scripts) - [Expressions](#expressions) - [Stream Filters](#filters) - [Environment Variables](#env-vars) - [Templates](#templates) - [Known Issues](#issues) - [License](#license) - [Contribution](#contribution) ## Installation The recommended method for installing `cargo-eval` is by using Cargo's `install` subcommand: ```sh cargo install cargo-eval ``` If you have already installed `cargo-eval`, you can update to the latest version by using: ```sh cargo install --force cargo-eval ``` ### Cargo Features The following features are defined: - `suppress-cargo-output` (default): if building the script takes less than 2 seconds and succeeds, `cargo-eval` will suppress Cargo's output. Note that this disabled coloured Cargo output on Windows. ### Manually Compiling and Installing `cargo-eval` requires Rust 1.11 or higher to build. Rust 1.4+ was supported prior to version 0.2. 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 eval`. ### Self-Executing Scripts On UNIX systems, you can use `#!/usr/bin/env cargo eval --` as a hashbang line in a Rust script. If the script file is executable, this will allow you to execute a script file directly. If you are using Windows, you can associate the `.crs` extension (which is simply a renamed `.rs` file) with `cargo-eval`. This allows you to execute Rust scripts simply by naming them like any other executable or script. This can be done using the `cargo eval file-association` command. 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. 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. ## Usage Generally, you will want to use `cargo-eval` by invoking it as `cargo script` (note the lack of a hypen). Doing so is equivalent to invoking it as `cargo-eval script`. `cargo-eval` supports several other subcommands, which can be accessed by running `cargo-eval` directly. You can also get an overview of the available options using the `--help` flag. ### Scripts The primary use for `cargo-eval` is for running Rust source files as scripts. For example: ```shell $ echo 'fn main() { println!("Hello, World!"); }' > hello.rs $ cargo eval hello.rs Hello, World! $ cargo eval hello # you can leave off the file extension Hello, World! ``` The output of Cargo will be hidden unless compilation fails, or takes longer than a few seconds. `cargo-eval` will also look for embedded dependency and manifest information in the script. For example, all of the following are equivalent: - `now.crs` (code block manifest with UNIX hashbang and `.crs` extension): ```rust #!/usr/bin/env cargo eval -- //! This is a regular crate doc comment, but it also contains a partial //! Cargo manifest. Note the use of a *fenced* code block, and the //! `cargo` "language". //! //! ```cargo //! [dependencies] //! time = "0.1.25" //! ``` extern crate time; fn main() { println!("{}", time::now().rfc822z()); } ``` - `now.rs` (dependency-only, short-hand manifest): ```rust // cargo-deps: time="0.1.25" // You can also leave off the version number, in which case, it's assumed // to be "*". Also, the `cargo-deps` comment *must* be a single-line // comment, and it *must* be the first thing in the file, after the // hashbang. extern crate time; fn main() { println!("{}", time::now().rfc822z()); } ``` > **Note**: you can write multiple dependencies by separating them with commas. *E.g.* `time="0.1.25", libc="0.2.5"`. On running either of these, `cargo-eval` will generate a Cargo package, build it, and run the result. The output may look something like: ```shell $ cargo eval now Updating registry `https://github.com/rust-lang/crates.io-index` Compiling winapi-build v0.1.1 Compiling winapi v0.2.8 Compiling libc v0.2.30 Compiling kernel32-sys v0.2.2 Compiling time v0.1.38 Compiling now v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/file-now-37cb982cd51cc8b1) Finished release [optimized] target(s) in 49.7 secs Sun, 17 Sep 2017 20:38:58 +1000 ``` Subsequent runs, provided the script has not changed, will likely just run the cached executable directly: ```shell $ cargo eval now Sun, 17 Sep 2017 20:39:40 +1000 ``` Useful command-line arguments: - `--bench`: Compile and run benchmarks. Requires a nightly toolchain. - `--debug`: Build a debug executable, not an optimised one. - `--features `: Cargo features to pass when building and running. - `--force`: Force the script to be rebuilt. Useful if you want to force a recompile with a different toolchain. - `--gen-pkg-only`: Generate the Cargo package, but don't compile or run it. Effectively "unpacks" the script into a Cargo package. - `--test`: Compile and run tests. ### Expressions `cargo-eval` can also run pieces of Rust code directly from the command line. This is done by providing the `--expr` option; this causes `cargo-eval` to interpret the `