Cargo Commander:增强 Rust 项目的命令行工具

文摘   2024-06-23 07:29   江苏  

Cargo Commander:增强 Rust 项目的命令行工具

简介

Cargo Commander 旨在填补 cargo 命令功能的空白,即不能像 npm 运行脚本那样运行命令。但在此过程中,我决定为其添加一些额外的功能。

新增功能:除了在 Commands.tomlCargo.tomlpackage.json 中指定的命令外,还在开发类似于 cargo-script 的脚本执行功能。您可以通过运行本地脚本 cargo cmd script.rs 或远程脚本 cargo cmd https://url.to.script 来尝试。目前这处于早期测试阶段,其工作原理是运行 rustc input -o output,然后执行输出结果,因此目前仅限于使用标准库,且脚本必须包含在单一文件中。更多功能即将推出!

开始使用

您可以在 Cargo.toml 中的 [commands][package.metadata.commands] 部分创建命令,或者创建一个新的 Commands.toml 文件。它们都使用相同的语法。如果发现 package.json 中的 scripts 部分,Cargo Commander 也会解析它。通常 package.json 中的脚本只允许是字符串,但 Cargo Commander 通过将 json 转换为 toml,意味着您可以在 json 中添加与 toml 中相同的选项。

# 安装 cargo-commander
cargo install cargo-commander
# 运行您的命令
cargo cmd COMMAND

# 'cargo cmd --help' 的输出
cargo-commander 2.0.15
一个强大的工具,用于管理项目命令

用法:
    cargo cmd [选项] [命令/URL/文件] [<参数>...]

参数:
    COMMAND              要运行的命令名称
    URL                  下载脚本,编译然后运行
    FILE                  编译文件然后运行
    <参数>...            传递给命令的参数

选项:
    -h, --help           打印帮助信息
    -f, --file PATH      自定义命令文件的路径
    -p, --parallel       强制所有命令并行运行

命令

命令可以是字符串或使用以下字段自定义其行为的命令对象。

cmd = 字符串或数组,数组可以包含字符串命令或其他命令对象
parallel = true/false,仅在命令对象包含数组时有意义,使所有命令并行运行
shell = 字符串,语法仅为 "程序 参数 参数 参数"
env = 数组,格式为 "VAR=SOMETHING" 的字符串数组
args = 数组,格式为 "ARG=默认值" 的字符串数组,如果没有给定默认值,则使用空字符串
working_dir = 字符串,相对于命令文件或当前目录的工作目录路径

cmd

这可以是字符串、命令对象或命令对象数组。

如果 cmd 是多行字符串,则命令的内容将保存到一个临时文件中,程序完成后该文件将被安全删除。然后使用参数替换字符串中的内容,传递给 shell 的唯一参数是临时文件的路径。我们可以将这种行为与 shell 选项结合使用,创建一个文件,其绝对路径作为参数传递给您指定的 shell 程序。请参阅示例了解这可能的外观。

command = "echo Basic usage"
command = ["echo As an array"]
command = { cmd = "echo Hello" }
command = { cmd = ["echo Hello", "echo World"] }
command = { cmd = [{ cmd = "echo And hello again" }] }
command = { cmd = { cmd = "echo Hello again" } }

parallel

布尔值,默认为 false。如果命令对象的 cmd 是数组,所有子命令将同时运行。

command = { cmd = ["echo first", "echo second", "echo third"], parallel = true }

working_dir

字符串。命令应该在其中执行的路径。

command = { cmd = "ls", working_dir = "src" }
command = { cmd = "ls", working_dir = "path/to/folder" }

args

格式为 args=["参数","参数=默认值"] 的字符串数组。如果参数是一个没有设置默认值的字符串,它将被替换为空字符串。

command = { cmd = "echo $name", args = ["name=World"] }

env

格式为 env=["变量=值"] 的字符串数组。在命令中设置环境变量。这与 args 的工作方式类似,但不同之处在于 env 更改环境变量。这个选项通常不是很有用,您可能更想使用 load_dotenv

# Unix
command = { cmd = "echo $HELLO", env = ["HELLO=World"] }
# Windows
command = { cmd = "echo %HELLO%", env = ["HELLO=World"] }

load_dotenv

布尔值,默认为 false。允许您从 .env 文件中加载环境变量。.env 文件应该位于包含正在运行命令的文件的同一文件夹中。此选项不受 working_dir 选项的影响。

# 创建一个包含 "HELLO=World" 的 .env 文件
# Unix
command = { cmd = "echo $HELLO", load_dotenv = true }
# Windows
command = { cmd = "echo %HELLO%", load_dotenv = true }

until

整数。哪个状态码被视为成功运行。通常我们不检查命令的状态码,但使用此选项我们可以告诉命令继续重复,直到达到特定的退出码。如果将其设置为 until=0,则意味着您将继续运行命令,直到达到状态 0 的退出码。使用 until=404 将继续运行,直到达到 404 码。如果您想避免无限循环,您也应该设置 max_repeat

command = { cmd = "echo Hello", until = 0 }

repeat

整数。命令至少应该运行的次数。如果您与 until 一起运行此命令,您将始终至少运行这么多次。

command = { cmd = "echo Hello", repeat = 2 }

delay

整数或浮点数。在运行命令之前的睡眠时间。如果您将此与任何基于重复的选项一起使用,此延迟将在每次命令运行之前添加。

command = { cmd = "echo Hello", delay = 2 }
command = { cmd = "echo Hello", delay = 3.7 }

max_repeat

整数。设置命令允许重试的最大次数。这在与 until 一起运行时最有用。

command = { cmd = "echo Hello", repeat = 5, max_repeat = 1 }
command = { cmd = "echo Hello", until = 0, max_repeat = 1000 }

示例

打开文档

我倾向于为我的项目创建多个 mdbook 书籍进行文档化。这非常整洁,但逐个打开它们可能会有点麻烦。因此,我将打开每个文档的命令放在 docs 部分下,然后运行该部分而不是每个单独的页面,使用 -p 标志使该部分并行运行。

# Commands.toml
[docs]
crate_one = { cmd = "mdbook serve --open --port 9001", working_dir = "crates/one/docs" }
crate_two = { cmd = "mdbook serve --open --port 9002", working_dir = "crates/two/docs" }
crate_three = { cmd = "mdbook serve --open --port 9003", working_dir = "crates/three/docs" }
crate_four = { cmd = "mdbook serve --open --port 9004", working_dir = "crates/four/docs" }

现在我们可以使用单个命令打开所有文档!

cargo cmd -p docs

传递自定义参数

假设您想在 Kubernetes pod 中启动一个运行中的 shell,但事先不知道 pod 名称,可能是因为 pod 是由部署或定时任务创建的。您知道一个 kubectl 命令可以让您在 pod 中获得运行中的 shell,但问题是命令非常长而且每次写都很麻烦,每次从其他地方复制命令也很快变得重复。

# Commands.toml
shell = { cmd = "kubectl exec --stdin --tty $pod -- /bin/bash", args = ["pod"] }

现在我们可以通过简单的语法始终获得我们 pod 的 shell。现在,您不必每次都找到您的 pod 名称并将其复制到更长的 kubectl 命令中,您现在可以轻松记住您有一个 shell 命令,它接受 pod 参数。

cargo cmd shell pod=my-pod-123-654

运行脚本

通过结合 shell 选项和我们为多行字符串设置的行为,我们可以实现直接在命令中编写脚本的运行。

# 使用 python -c
hello_py_c = { cmd = "print('Hello')", shell = "python -c" }
# 使用 python 和多行字符串以及参数
hello_py = { cmd = """import os
print("Hello")
print("$name")
""", args = ["name=World"], shell = "python" }

然后您可以按以下方式运行它:

cargo cmd hello_py_c
Hello
# 或多行
cargo cmd hello_py
Hello
World
# ... 带参数
cargo cmd hello_py name=Commander
Hello
Commander

持续重试直到命令成功

有时您运行的程序或编写的脚本可能会失败。没关系,每个人都会遇到。也许它正在尝试到达的网络资源,或者您计算机上的文件。不管出于什么原因,程序有时以成功代码 0 退出,其他时候以代码 404 退出,因为尝试到达的页面未找到。

我们可以使用 until 轻松创建一个简单的重试循环,结合 delay 以便程序不会运行得过于频繁,以及 max_repeat 以便我们不会永远尝试。

command = { cmd = "python script.py", until = 0, delay = 3, max_repeat = 1000 }

运行该命令将使其持续重试,每次重试之间有 3 秒的延迟。它将重试,直到返回 0 状态,或最多 1000 次。

注意事项

环境变量不持久

我尝试过让这按预期工作,但目前我有点放弃了,因为这看起来在实现上要么是不可能的,要么真的非常非常烦人。所以每个命令都将有一套“新鲜”的环境变量,如果一个命令更改了环境变量,另一个命令不会捕获这些更改,它们在不同的 shell 中运行。您可以使用 env 选项,或者您可以在每个命令中运行一个脚本来设置环境变量,或者您可以使用 load_dotenv.env 文件中加载变量。我认为这些选项是足够的,如果您真的希望变量在命令之间持久存在,您将不得不提交一个拉取请求,或者等待我深入研究这个问题。


编程悟道
自制软件研发、软件商店,全栈,ARTS 、架构,模型,原生系统,后端(Node、React)以及跨平台技术(Flutter、RN).vue.js react.js next.js express koa hapi uniapp Astro
 最新文章