3 个版本
新版本 0.1.2 | 2024 年 8 月 24 日 |
---|---|
0.1.1 | 2024 年 8 月 22 日 |
0.1.0 | 2024 年 8 月 22 日 |
66 在 构建实用工具 中
每月 244 次下载
765KB
17K SLoC
thag_rs
简介
thag_rs
(命令 thag
) 是适用于 Rust 表达式、片段和程序的通用脚本运行器和 REPL。它是一个开发者工具,允许您从命令行运行和测试 Rust 代码,以实现快速原型设计和探索。它旨在处理超出 Rust 演示场或普通脚本运行器范围的情况,同时希望使用简单方便。它还支持通过 shebangs 进行脚本编写、从您的片段构建可执行文件、循环过滤模式和纯文本或编辑标准输入。
thag_rs
包含一个超过 170 个示例脚本的演示库。如果您有一些好的内容想要分享,请随时提供,前提是遵守 MIT / Apache 2 许可证条款。
快速入门:运行 thag
命令的方法
* 带表达式参数
thag --expr '"Hello world!"' # Short form: -e
调用静默模式 (--quiet (-q)
) 会抑制大部分反馈,除了用于突出显示输出的花盒。调用两次 (-qq
简写) 会抑制所有非错误反馈,包括花盒,使输出可用于过滤。
默认情况下,thag
和 Cargo 将向您反馈
thag -e ' {
use jiff::{Zoned, Unit};
Zoned::now().round(Unit::Second)?
}' # Long form: --expr
* 使用脚本
thag demo/py_thag.rs
thag demo/iced_tour.rs
这将调用 cargo build
并运行跨平台 GUI 库 iced
的导游。脚本取自 iced
仓库中发布的示例。
要直接运行脚本,您可以在第一行添加类似 #! /usr/bin/env thag
的 shebang。您需要给予脚本执行权限才能运行它。例如 (*nix)
chmod ug+x demo/fib_basic.rs
demo/fib_basic.rs -- 10
但是,为什么要在 shebang 中构建脚本,而不是按照 Rust 的意图将其作为命令呢?请参阅下面的 As an executable
。
作为REPL(读取-评估-打印循环)
thag --repl # Short form: -l
REPL具有文件支持的搜索历史记录,并且可以通过VISUAL或EDITOR环境变量访问VS Code、Zed、Helix、Vim、Nano等图形和基于文本的编辑器,以防其reedline
编辑器在某些任务上表现不佳。后者的快捷键将取决于您的终端设置,您可能不需要太多导航快捷键。
带有标准输入
echo '(1..=10).product::<u32>()' | thag --stdin # Short form: -s
将脚本的所有参数放在--
之后,以将其与thag
参数分开
echo 'println!("Hello {}", std::env::args().nth(1).unwrap());' | thag -s -- Ferris
这相当于
thag -e 'println!("Hello {}", std::env::args().nth(1).unwrap());' -- Ferris
使用TUI(终端用户界面)编辑器
thag --edit # Short form: -d
将标准输入输入到TUI编辑器
cat my_file.rs | thag --edit # Short form: -d
这允许您在提交给thag_rs
之前编辑或追加到stdin输入。它具有文件支持的历史记录,这样您就不会丢失您的编辑。
关于TUI编辑器的说明
为了在Apple终端上使Shift-Up和Shift-Down键组合正常工作,您可能需要在Apple终端设置 | 配置文件 | 键盘设置中添加以下内容:Shift-Up: \033;[2A
和 Shift-Down
: \033;[2B。使用Esc键生成\033。这在Iterm2或WezTerm中不是必需的。
一般来说,如果您没有遇到您想要的关键绑定,那可能是因为您的终端已经拦截了它们,您可能可以通过调整终端设置来解决这个问题。同样也适用于REPL。
作为标准输入上的过滤器(循环模式)
至少,它将循环遍历stdin
,并对每一行运行--loop
表达式。行号和内容分别作为i
和line
提供给表达式。
cat demo/iter.rs | thag --loop 'format!("{i}.\t{line}")' -q # Short form: -l
注意使用上面的--quiet (-q)
选项来抑制Cargo构建的消息。
或者
thag -l 'format!("{i}.\t{line}")' < demo/hello.rs # Long form: --loop
对于可以将其管道传输到另一个进程的真正过滤器,您可以使用-qq
(或--quiet --quiet
)来抑制所有非错误输出。
循环模式也接受以下可选参数,提供类似于AWK的代码
--cargo (-C) for specifying dependencies etc. in Cargo.toml format.
--begin (-B) for specifying any imports, functions/closures, declarations etc. to be run before the loop.
--end (-E) for specifying any summary or final logic to run after the loop.
注意:一般来说,如果您计划将Rust输出管道传输,那么使用writeln!(io::stdout())
而不是println!
可能是一个好主意,因为截至编写时,如果println!
遇到错误(包括来自head命令的broken pipe错误),它将恐慌。有关容忍broken pipe的示例,请参阅demo/thag_from_rust_script.rs。
作为可执行文件
使用--executable (-x)选项以发布模式构建您的脚本并将其移动到~/.cargo/bin/,这是建议将其添加到您的路径中的。
thag -x my_script.rs # Long form: --executable
当然,如果您希望,可以使用操作系统命令重命名可执行文件。
但是,最好首先重命名您的源文件,这样如果您想更新它,就不会丢失跟踪命令来源。
我建议构建可执行文件而不是使用shebang,因为它在几个方面都更快
- 它消除了中间商(
thag
) - 您只需在最初承担一次构建开销
- 它将以发布模式构建,使其运行速度更快
- 您可以使用像
llvm-strip
这样的工具从可执行文件中删除部分
并且在一个方面更加方便:它消除了需要--
参数分隔符的需要,因为thag
不再首先被调用,因此我们不需要分开两组参数。
投入使用
** 命令行选项
希望帮助屏幕是自我解释的
您可以按任何顺序输入 thag
参数和选项,只要您用 --
分隔符将它们与任何脚本参数分开。
** 入门指南
您可以选择安装 thag_rs
(推荐),或者您可能更喜欢克隆它并自行编译,然后通过 cargo run --
运行。
- 安装将为您提供开箱即用的速度和更简单的命令行界面,无需自行调用 Cargo。您有选择
cargo install thag_rs
或者从 Github 发布页面选择适合您环境的合适安装程序 https://github.com/durbanlegend/thag_rs/releases
,从 v0.1.1
开始。
您还可以从同一页面下载演示脚本的起始套件,作为 demo.zip
下载。
- 克隆为您提供立即访问演示脚本库以及本地更改或分叉的机会。您还可以使用带有环境变量
RUST_LOG=thag_rs=debug
的标志--features=debug-logs
来获取调试日志。
概述
thag_rs
使用 Cargo、syn
、quote
和 cargo_toml
分析并包装良好的片段和表达式,将其转换为可工作的程序。良好的输入程序通过具有有效的 fn main
(或一个以上 - 见下文)并保持不变传递给 cargo build
。
thag_rs
使用 syn
包将有效代码解析为抽象语法树(AST)。其他好处包括防止它被注释或字符串字面量中的代码所欺骗,这是正则表达式和字符串解析的诅咒。然后,thag_rs
使用 syn
访问者机制遍历 AST 以识别代码中的依赖项,从而生成 Cargo.toml
。它过滤这些依赖项以删除重复项和错误信息,如内置 Rust 包、重命名的包和本地模块。
良好性是通过在 AST 中计算 main
函数的任何出现次数来确定的。没有 fn main
的缺失表示一个片段或表达式,而一个以上的 fn main
有时是有效的,但必须通过用户使用 --multimain (-m)
选项来积极标记。
如果您的代码由于编码错误而无法成功解析为 AST,thag_rs
将回退到使用源代码分析为 Rust 编译器准备您的代码,然后 Rust 编译器可以显示错误消息以帮助您找到问题。
您可以根据以下描述在 TOML 块中提供可选的元数据。thag_rs
使用 cargo_toml
包将任何元数据解析到 manifest 结构体中,合并从 AST 推理出的任何依赖项,然后使用 toml
包编写 Cargo 需要构建脚本的专用 Cargo.toml 文件。最后,在代码片段和表达式的案例中,它使用 quote
包将逻辑嵌入到格式良好的程序模板中,然后调用 Cargo 进行构建。
所有这些操作都非常快:真正的瓶颈将是熟悉的 Cargo 构建过程在首次构建时下载和编译您的依赖项。Cargo 构建输出将实时显示,以确保没有神秘的延迟。如果您重新运行编译后的脚本,它应该非常快。
以这种方式,thag_rs
尝试处理任何有效的(或无效的)Rust 脚本,无论是程序、代码片段还是表达式。它将从您的代码中的 use
语句尝试生成针对您的脚本的专用 Cargo.toml,尽管为了速度和精度,我建议您将自定义的嵌入到脚本开头的 toml 块中,就像大多数演示中所做的那样。为此,在每次成功的 Cargo 搜索之后,thag_rs
将生成并打印一个基本的 toml 块,其中包含包名和版本,在 [dependencies]
标题下,供您复制并粘贴到脚本中(如上面的第二个 --expr
示例所示)。它不会打印合并块,因此合并所有依赖项到单个 toml 块的工作由您自己完成。所有依赖项通常可以放在 toml 块下的单个 [dependencies]
标题下,但由于 cargo_toml
的存在,在 toml 块中放置有效 Cargo 代码没有特定的限制。
[toml]
[dependencies]
...
*/
thag_rs
力求在速度和透明度之间取得平衡,尽可能全面。它使用时间戳来重新运行编译后的脚本而无需不必要的重建,尽管您可以覆盖此行为。例如,一个预编译的脚本在我的 M1 MacBook Air 上将在不到半秒内计算出 10,000 的 35,661 位阶乘。
安装
支持的最低 Rust 版本
thag_rs
支持的最低 Rust 版本(MSRV)是 1.74.1。
您可以使用 cargo install
安装 thag_rs
。
从 v0.1.1
开始可以下载 demo.zip
,地址为 https://github.com/durbanlegend/thag_rs/releases
。
cargo install thag_rs
下载起始套件(演示目录)
从 v0.1.1
开始可以下载 demo.zip
,地址为 https://github.com/durbanlegend/thag_rs/releases
。
请注意,您还可以通过 demo/README.md
中的链接链接到单个演示文件,并手动通过提供的下载图标下载文件。作为参考,rs_thag
演示文件 download_demo_dir.rs 可以从 Github 下载整个演示目录。点击上面的链接,并从 Github 提供的图标中下载并运行它,或将其复制并粘贴到 thag -d
编辑器中,然后选择 Ctrl-d 运行它。它应将整个演示目录从存储库下载到您选择的目录。Thag pull self up by own sandal straps. Thag eating own dog food! Thag like dog food.
用法
安装后,您可以从命令行使用 thag
命令。 thag
使用 clap crate 处理命令行参数,包括 --help。
以下是一些示例
评估一个表达式
简洁快速的阶乘计算
thag -e '(1..=34).product::<u128>()'
由于使用 Rust 原始数据类型,超过 34! 时会引发恐慌,但请参阅 demo/factorial_dashu_product.rs
以获得任意大的数字
将脚本强行塞入一个表达式,仅仅因为这样!
thag -e "$(cat demo/fizz_buzz_gpt.rs)"
--expr
标志不仅可以评估一个表达式,还可以接受一个有效的 Rust 程序或语句集。 thag
接受代码的方式尽可能地与它处理它们的标准方式“正交”。
在静默模式下运行脚本但显示计时
thag -tq demo/fizz_buzz_gpt.rs
Completed generation in 0.276s
Completed build in 1.171s
----------------------------------------------------------------------
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
...
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
----------------------------------------------------------------------
Completed run in 0.558s
thag_rs completed processing script fizz_buzz_gpt.rs in 2.43s
使用 REPL
thag -r
这将启动一个交互式 REPL 会话,您可以输入或粘贴单行或多行 Rust 表达式,然后按 Enter 运行。您还可以从历史记录中检索和(可选)编辑一个表达式。在评估表达式后,您可以选择在您首选的编辑器(VS Code、Helix、Zed、nano...)中编辑它和/或生成的 Cargo.toml,然后重新运行它。REPL 还提供了对临时文件的基本管理功能,否则这些文件将在适当的时候由操作系统清理。
回顾一个之前的 REPL 表达式
thag -r repl_<nnnnnn>.rs
将返回并编辑和运行之前 REPL 会话中命名的生成脚本。
更不正式地说,您可以通过在 REPL 函数中使用上箭头键和下箭头键来导航历史记录,从而访问最后 25 个之前的 REPL 命令或表达式。
关于 REPL 的一般说明
所有 REPL 文件都存储在您的临时目录(例如 *nix 中的 $TMPDIR)下的 rs_repl
子目录中,以免占用您的系统空间。在它们被操作系统收集之前,您可以显示它们的位置并将文件复制出来。
由于底层行编辑器的限制,REPL 功能不适合超过约 1K 字符的脚本。您可以通过使用 REPL 的 edit
模式来克服这些限制,但在这个阶段,可能更方便使用 --stdin / -s 功能或 --edit / -d 功能,或者将源代码保存在 .rs 文件中并在命令行中运行它。
功能
Rust 主要是表达式语言... —— Rust 参考
- 可以运行严肃的 Rust 脚本(不仅仅是“Hello, world!”类型),无需创建项目。
- 旨在成为功能最强大且最可靠的 Rust 代码脚本运行器。
- 可以指定依赖项的特定功能,使您的脚本能够访问高级功能。还可以指定本地路径和 git 依赖项,允许您访问您未发布的 crate。
- 模式选择 - 考虑到 Rust 中表达式的重要性
- 表达式模式用于即时执行的小型基本表达式。
- REPL 模式提供交互性,并接受多行表达式,因为它使用括号匹配来等待闭合括号、方括号、括号和引号。
- stdin 模式接受即时输入的大型脚本或程序,无论是键入、粘贴还是管道输入。
- 编辑模式是 stdin 模式,添加了基本 TUI(终端用户界面)原地编辑功能,可带或不带管道输入。
- 经典脚本模式运行由有效 Rust 片段或程序组成的 .rs 文件。
- 您可以使用 shebang 在 Rust 中编写脚本。
- 为了获得更快的速度,您可以构建自己的命令,使用
--executable
(-x
)选项。这将编译一个有效的脚本到Cargo bin目录中的发布优化可执行命令<home>/.cargo/bin
。 thag_rs
支持一个用于重用的代码样本个人库。在demo子目录中提供的可下载的起始集包括众多来自流行crate的示例,以及包括快速大整数阶乘和斐波那契计算、以及以下描述的TUI编辑和自适应颜色调板的原始示例。- 根据终端能力,自动支持浅色或深色背景以及16或256色调色板以适应不同消息类型。或者,您可以在
config.toml
文件中指定您的终端首选项。在Windows上,查询终端不支持且可能引起干扰,因此在没有config.toml
文件的情况下,thag_rs
默认使用基本的ANSI-16颜色和深色模式支持。但是,它使用的深色模式颜色已被选择以与大多数浅色模式很好地协同工作。 - 在某些情况下,您可能可以通过为其提供自己的主方法和内嵌的Cargo依赖项来单独开发项目的模块,然后从thag_rs中运行它。如果不行,您总是可以在另一个位置上工作在一个最少修改的副本。这种方法允许您在不破坏项目的情况下开发和新模块调试。例如,colors.rs和stdin.rs的演示版本都是完全作为脚本开发的原型,然后才被合并到主要的
thag_rs
项目中。
平台支持
这个crate被设计成跨平台,支持MacOS、Linux和Windows。
目前已在MacOS(M1)Sonoma、Zorin和(WSL2)Ubuntu以及Windows 11 PowerShell 5、Windows Terminal和Windows控制台下的CMD和WSL2上进行了测试。
GitHub Actions在 ubuntu-latest
、macos-latest
和 windows-latest
上测试每个提交。
为什么叫“thag”?
纪念已故的Thag Simmons。一个石器时代的强大工具,用于让开发者屈服于Rust代码。为什么要输入长名字,当简短的名字就能解决问题呢?
相关项目
(向 rust-script
的作者致敬)
cargo-script
- Rust RFC书籍https://rust-lang.github.io/rfcs/3424-cargo-script.html
evcxr
- 可能是最知名的Rust REPL。cargo-script
- (与Rust RFC无关)。Rust脚本运行器(已维护的项目)。rust-script
- 前一个cargo-script的维护分支。cargo-eval
- 前一个cargo-script的维护分支。cargo-play
- 本地Rust沙盒。irust
- 有限的Rust REPL。runner
- 运行Rust代码片段的实验性工具,不使用Cargo,探索动态链接与静态链接的速度。我在GitHub上有这个crate的广泛修改版本,但我强烈推荐使用当前的thag_rs
crate而不是这个分支。cargo-script-mvs
- RFC演示。
在Rust RFC链接中还有更多关于先前艺术品的讨论。
许可协议
SPDX-License-Identifier: Apache-2.0 OR MIT
根据您的要求,以下任一协议
Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
或
MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
任选其一。
贡献
如果贡献符合项目的目标,将被考虑。
除非您明确声明,否则您有意提交的任何贡献将被作为上述协议双重许可,没有任何额外的条款或条件。
依赖关系
~20–32MB
~492K SLoC