#cargo-script #script #cargo #script-file #eval #cargo-subcommand #cargo-manifest

app cargo-eval

A cargo 子命令,设计用于让人们快速轻松地运行 Rust “脚本”,这些脚本可以利用 cargo 的包生态系统。

1 个不稳定版本

0.1.0 2019年8月21日

#326Cargo 插件

27 每月下载量

MIT/Apache

115KB
2.5K SLoC

cargo-eval

cargo-eval 是一个 Cargo 子命令,设计用于让人们快速轻松地运行 Rust "脚本",这些脚本可以利用 Cargo 的包生态系统。它还可以评估表达式和运行过滤器。

cargo-eval 的一些功能包括

  • 读取嵌入在 Rust 脚本中的 Cargo 清单。
  • 缓存编译的工件(包括依赖项)以减少构建时间。
  • 通过 UNIX hashbangs 和 Windows 文件关联支持可执行 Rust 脚本。
  • 在命令行上评估表达式。
  • 将表达式用作流过滤器(例如,用于命令管道)。
  • 从脚本中运行单元测试和基准测试。
  • 为命令行表达式和过滤器自定义模板。

注意: 当 Cargo 被指示使用与默认主机架构不同的目标架构时,cargo-eval 不能 工作。

目录

安装

安装 cargo-eval 的推荐方法是使用 Cargo 的 install 子命令

cargo install cargo-eval

如果您已经安装了 cargo-eval,您可以通过以下方式更新到最新版本:

cargo install --force cargo-eval

Cargo 功能

以下功能被定义:

  • suppress-cargo-output (默认):如果构建脚本少于 2 秒并成功,cargo-eval 将抑制 Cargo 的输出。请注意,这将在 Windows 上禁用彩色 Cargo 输出。

手动编译和安装

cargo-eval 需要 Rust 1.11 或更高版本来构建。版本 0.2 之前支持 Rust 1.4+。

构建完成后,您应将生成的可执行文件放在您的 PATH 路径上的某个位置。到那时,您应该可以使用 cargo eval 来调用它。

自执行脚本

在 UNIX 系统上,您可以使用 #!/usr/bin/env cargo eval -- 作为 Rust 脚本的 shebang 行。如果脚本文件是可执行的,这将允许您直接执行脚本文件。

如果您使用的是 Windows,可以将 .crs 扩展名(这只是一个重命名的 .rs 文件)与 cargo-eval 关联。这允许您像任何其他可执行文件或脚本一样简单地通过命名来执行 Rust 脚本。

可以使用 cargo eval file-association 命令来完成此操作。此命令还可以删除文件关联。如果将 --amend-pathext 传递给 file-assocation install 命令,它还将允许您在不指定文件扩展名的情况下执行 .crs 脚本,就像 .exe.bat 文件一样。

如果您想跨平台使用脚本,建议您同时使用 shebang 行和给文件添加 .crs 文件扩展名。

用法

通常,您将使用 cargo-eval 通过调用它作为 cargo script 来使用它(注意没有连字符)。这样做等同于调用它作为 cargo-eval scriptcargo-eval 支持其他几个子命令,可以通过直接运行 cargo-eval 来访问。您还可以使用 --help 标志来获取可用选项的概述。

脚本

cargo-eval 的主要用途是作为脚本运行 Rust 源文件。例如

$ 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!

Cargo 的输出将不会显示,除非编译失败或耗时超过几秒钟。

cargo-eval 还会在脚本中查找嵌入的依赖和清单信息。例如,以下都是等效的

  • now.crs(带有 UNIX shebang 和 .crs 扩展名的代码块清单)

    #!/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(仅依赖项,简写清单)

    // 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());
    }
    

    注意:您可以通过逗号分隔来编写多个依赖项。例如 time="0.1.25", libc="0.2.5"

运行其中的任何一个,cargo-eval 将生成一个 Cargo 包,构建它并运行结果。输出可能看起来像

$ 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

如果脚本没有更改,后续运行可能会直接运行缓存的可执行文件

$ cargo eval now
Sun, 17 Sep 2017 20:39:40 +1000

有用的命令行参数

  • --bench:编译和运行基准测试。需要夜间工具链。
  • --debug:构建调试可执行文件,而不是优化后的一个。
  • --features <features>:在构建和运行时传递的 Cargo 功能。
  • --force:强制脚本重新构建。如果您想使用不同的工具链强制重新编译,则非常有用。
  • --gen-pkg-only:生成 Cargo 软件包,但不会编译或运行它。相当于“解包”脚本为 Cargo 软件包。
  • --test:编译并运行测试。

表达式

cargo-eval 还可以直接从命令行运行 Rust 代码片段。这是通过提供 --expr 选项来完成的;这将导致 cargo-eval<script> 参数解释为源代码 而不是 文件路径。例如,代码可以通过以下几种方式从命令行执行

  • cargoeval --deptime --expr "extern crate time; time::now().rfc822z().to_string()"
  • cargo eval --dep time=0.1.38 --expr "extern crate time; ..." - 使用特定的 time 版本
  • cargo eval -d time -e "extern crate time; ..." - 上述命令的简写形式
  • cargo eval -D time -e "..." - 假设并注入 extern crate time;仅当依赖项的包名和crate名称相匹配时才有效。
  • cargo eval -d time -x time -e "..." - 注入 extern crate time;当名称不匹配时也有效。

给定的代码被嵌入到表达式块中,使用 Debug 格式化器(即 {:?})进行评估和打印。

有用的命令行参数

  • -d/--dep:将依赖项添加到生成的 Cargo.toml 清单中。
  • -t/--template:为该表达式指定一个自定义模板(请参阅模板部分)。

流过滤器

您可以使用 cargo-eval 来编写快速流过滤器,通过指定一个闭包来调用从 stdin 读取的每一行,如下所示

$ cat now.crs | cargo eval --loop \
    "let mut n=0; move |l| {n+=1; println!(\"{:>6}: {}\",n,l.trim_right())}"
   Compiling loop v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/loop-58079283761aab8433b1)
     1: // cargo-deps: time="0.1.25"
     2: extern crate time;
     3: fn main() {
     4:     println!("{}", time::now().rfc822z());
     5: }

您可以通过使用 --count 标志来实现类似的效果,该标志会将行号作为第二个参数传递给您的闭包

$ cat now.crs | cargo eval --count --loop \
    "|l,n| println!(\"{:>6}: {}\", n, l.trim_right())"
   Compiling loop v0.1.0 (file:///C:/Users/drk/AppData/Local/Cargo/script-cache/loop-58079283761aab8433b1)
     1: // cargo-deps: time="0.1.25"
     2: extern crate time;
     3: fn main() {
     4:     println!("{}", time::now().rfc822z());
     5: }

请注意,与表达式类似,您可以为流过滤器指定自定义模板。

环境变量

以下环境变量由 cargo-eval 提供给脚本。

  • CARGO_EVAL_BASE_PATH:由 cargo-eval 用于解析相对依赖路径的基础路径。请注意,这不一定与工作目录或脚本编译所在的目录相同。

  • CARGO_EVAL_PKG_NAME:脚本的生成包名。

  • CARGO_EVAL_SAFE_NAME:正在运行的脚本文件名(不含文件扩展名)。对于脚本,此值来自脚本的文件名。对于这些调用,也可能是 "expr""loop"

  • CARGO_EVAL_SCRIPT_PATH:正在运行的脚本的绝对路径,如果存在的话。对于表达式,设置为空字符串。

模板

您可以使用模板来避免重复指定常见的代码和依赖项。您可以通过运行 cargo eval templates list 来查看模板列表,或者通过运行 cargo eval templates show 来显示它们应该存储的文件夹。您可以使用 cargo-eval templates dump NAME 来转储模板的内容。

模板是 Rust 源文件,包含两个占位符:用于自动生成的预览的 #{prelude}(应放置在模板顶部),以及用于脚本内容的 #{script}

例如,一个添加依赖项并导入一些额外符号的最小表达式模板可能如下所示:

// cargo-deps: itertools="0.6.2"
#![allow(unused_imports)]
#{prelude}
use std::io::prelude::*;
use std::mem;
use itertools::Itertools;

fn main() {
    let result = {
        #{script}
    };
    println!("{:?}", result);
}

如果将其存储在模板文件夹中为 grabbag.rs,则可以通过通过 --template 选项传递名称 grabbag 来使用它。

$ cargo eval -t grabbag -e "mem::size_of::<Box<Read>>()"
16

此外,还有三个内置模板:exprlooploop-count。这些用于 --expr--loop--loop --count 调用形式。可以在模板文件夹中放置同名模板来覆盖它们。如果您尚未覆盖它们,可以使用上述 templates dump 命令来转储这些内置模板的内容。

许可

根据您的选择,许可协议为以下之一:

任选其一。

贡献

除非您明确表示,否则您提交给作品的所有有意贡献均应按照上述方式双重许可,不附加任何额外条款或条件。

依赖项

~5–15MB
~166K SLoC