rust-lang/rustfmt
GitHub: rust-lang/rustfmt
Rust 官方代码格式化工具,自动将 Rust 代码调整为符合官方风格指南的统一样式。
Stars: 6845 | Forks: 1017
# rustfmt [](https://github.com/rust-lang/rustfmt/actions/workflows/linux.yml) [](https://github.com/rust-lang/rustfmt/actions/workflows/mac.yml) [](https://github.com/rust-lang/rustfmt/actions/workflows/windows.yml) [](https://crates.io/crates/rustfmt-nightly)
一个根据风格指南格式化 Rust 代码的工具。
如果你想帮忙(你应该参与,这是一个有趣的项目!),请参阅
[贡献指南](Contributing.md) 和我们的 [行为准则](CODE_OF_CONDUCT.md)。
你可以在 Travis CI 构建中使用 rustfmt。我们提供了一个最小化的 Travis CI 配置(参见 [此处](#checking-style-on-a-ci-server))。
## 快速开始
你可以使用 Rust 1.24 及以上版本运行 `rustfmt`。
### 在 Stable 工具链上
安装:
```
rustup component add rustfmt
```
在当前工作目录的 cargo 项目上运行:
```
cargo fmt
```
### 在 Nightly 工具链上
要使用最新最好的 `rustfmt`,需要 nightly 版本。
安装:
```
rustup component add rustfmt --toolchain nightly
```
在当前工作目录的 cargo 项目上运行:
```
cargo +nightly fmt
```
## 局限性
Rustfmt 尽可能地在更多 Rust 代码上工作。有时,代码甚至不需要编译!一般来说,我们希望限制不稳定的领域;特别是在 1.0 版本之后,大多数代码的格式不应随着 Rustfmt 的改进而改变。然而,有一些事情 Rustfmt 无法做到或做得不好(因此格式可能会发生显著变化,即使在 1.0 版本之后)。我们希望随着时间推移减少这些局限性的列表。
以下列表列举了 Rustfmt 无法工作或不适用稳定性保证的地区(我们不区分这两者,因为未来 Rustfmt 可能会在当前无法处理的代码上工作):
* 程序中任何部分无法解析的程序(解析是编译的早期阶段,在 Rust 中包括宏展开)。
* 宏声明和使用(当前状态:部分宏声明和使用会被格式化)。
* 注释,包括任何"内部"有注释的 AST 节点(Rustfmt 目前不尝试格式化注释,它确实会格式化内部有代码的注释,但未来的格式化可能会改变)。
* 注释中代码块里的 Rust 代码。
* 程序的任何片段(即,稳定性保证仅适用于整个程序,即使今天可以对程序片段进行格式化)。
* 包含非 ASCII Unicode 字符的代码(我们相信 Rustfmt 在这里基本可以工作,但没有足够的测试覆盖或经验来 100% 确定)。
* Rustfmt 中的 bug(像任何软件一样,Rustfmt 也有 bug,我们不认为修复 bug 会破坏我们的稳定性保证)。
## 运行
如果你使用 `cargo install` 安装了 rustfmt,只需输入 `rustfmt filename` 即可运行。这会对给定文件运行 rustfmt,如果文件包含离行模块,我们也会重新格式化这些模块。所以要运行整个模块或 crate,只需在根文件(通常是 mod.rs 或 lib.rs)上运行即可。rustfmt 也可以从 stdin 读取数据。或者,你可以使用 `cargo fmt` 来格式化 crate 的所有二进制和库目标。
你可以运行 `rustfmt --help` 来获取可用参数的信息。
对项目运行 rustfmt 最简单的方式是使用 `cargo fmt`。`cargo fmt` 适用于单 crate 项目和 [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html)。
有关使用信息,请参阅 `cargo fmt --help`。
你可以通过设置 `RUSTFMT` 环境变量来指定 cargo 使用的 `rustfmt` 二进制文件的路径。这是在 v1.4.22 中添加的,因此你必须使用此版本或更新版本才能使用此功能(`cargo fmt --version`)。
### 直接运行 `rustfmt`
要格式化单个文件或从 stdin 读取任意代码,应使用 `rustfmt` 二进制文件。以下是一些示例:
- `rustfmt lib.rs main.rs` 将就地格式化 "lib.rs" 和 "main.rs"
- `rustfmt` 将从 stdin 读取代码并将格式化结果写入 stdout
- `echo "fn main() {}" | rustfmt` 将输出 "fn main() {}"。
有关更多信息,包括参数和输出选项,请参阅 `rustfmt --help`。
### 验证代码是否已格式化
使用 `--check` 运行时,如果 Rustfmt 不会对输入进行任何格式更改,则退出码为 `0`;如果 Rustfmt 会进行更改,则退出码为 `1`。在其他模式下,如果格式化过程中出现某些错误(例如解析或内部错误),Rustfmt 将以 `1` 退出;如果格式化完成且没有错误(无论是否进行了更改),则以 `0` 退出。
## 从编辑器运行 Rustfmt
* [Vim](https://github.com/rust-lang/rust.vim#formatting-with-rustfmt)
* [Emacs](https://github.com/rust-lang/rust-mode)
* [Sublime Text 3](https://packagecontrol.io/packages/RustFmt)
* [Atom](atom.md)
* [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
* [IntelliJ 或 CLion](intellij.md)
## 在 CI 服务器上检查风格
为了保持代码库格式一致,当 pull request 包含未格式化的代码时让 CI 构建失败会很有帮助。使用 `--check` 指示 rustfmt 在输入格式不正确时以错误码退出。它还会打印发现的任何差异。(旧版本的 Rustfmt 不支持 `--check`,请使用 `--write-mode diff`)。
一个最小化的 Travis 配置可能如下所示(需要 Rust 1.31.0 或更高版本):
```
language: rust
before_script:
- rustup component add rustfmt
script:
- cargo build
- cargo test
- cargo fmt --all -- --check
```
更多信息请参阅 [这篇博客文章](https://medium.com/@ag_dubs/enforcing-style-in-ci-for-rust-projects-18f6b09ec69d)。
## 如何构建和测试
`cargo build` 来构建。
`cargo test` 来运行所有测试。
之后要运行 rustfmt,使用 `cargo run --bin rustfmt -- filename`。请参阅上面关于运行 rustfmt 的说明。
## 配置 Rustfmt
Rustfmt 被设计为高度可配置的。你可以创建一个名为 `rustfmt.toml` 或 `.rustfmt.toml` 的 TOML 文件,将其放在项目或任何其他父目录中,它将应用该文件中的选项。使用 `rustfmt --help=config` 查看可用选项,或者如果你更喜欢查看可视化风格预览,请参阅 [GitHub 页面](https://rust-lang.github.io/rustfmt/)。
默认情况下,Rustfmt 使用符合 [Rust 风格指南][style guide] 的风格,该风格已通过 [风格 RFC 过程][fmt rfcs] 正式化。
配置选项分为稳定和不稳定两种。稳定选项始终可以使用,而不稳定选项仅在 nightly 工具链上可用,且需要选择启用。详细信息请参阅 [GitHub 页面](https://rust-lang.github.io/rustfmt/)。
### Rust 版本
`edition` 选项确定用于解析代码的 Rust 语言版本。这对于语法兼容性很重要,但不直接控制格式化行为(请参阅 [风格版本](#style-editions))。
运行 `cargo fmt` 时,`edition` 会自动从 `Cargo.toml` 文件中读取。但是,直接运行 `rustfmt` 时,`edition` 默认为 2015。为了在 rustfmt 和 `cargo fmt` 之间保持一致的解析,你应该在 `rustfmt.toml` 文件中配置 `edition`:
```
edition = "2018"
```
### 风格版本
如果未指定,此选项从 [`edition`](#rusts-editions) 推断。有关不同风格版本之间格式化差异的详细信息,请参阅 [Rust 风格版本]。
rustfmt 的默认风格版本为 `2015`,而 `cargo fmt` 从 `Cargo.toml` 中设置的 `edition` 推断风格版本。如果未明确配置风格版本,这可能导致 `rustfmt` 和 `cargo fmt` 之间的不一致。
为确保一致的格式化,建议在 `rustfmt.toml` 配置文件中指定 `style_edition`。例如:
```
style_edition = "2024"
```
## 提示
* 为确保 `cargo fmt` 和 `rustfmt` 之间的解析一致,你应该在 `rustfmt.toml` 文件中配置 [`edition`](#rusts-editions)。
* 为确保 `cargo fmt` 和 `rustfmt` 之间的格式化一致,你应该在 `rustfmt.toml` 文件中配置 [`style_edition`](#style-editions)。
* 对于你不想让 rustfmt 修改的内容,使用 `#[rustfmt::skip]`
* 要防止 rustfmt 格式化宏或属性,使用 `#[rustfmt::skip::macros(target_macro_name)]` 或 `#[rustfmt::skip::attributes(target_attribute_name)]`
示例:
#![rustfmt::skip::attributes(custom_attribute)]
#[custom_attribute(formatting , here , should , be , Skipped)]
#[rustfmt::skip::macros(html)]
fn main() {
let macro_result1 = html! {
Hello
}.to_string();
* 运行 rustfmt 时,在目标文件目录或其父目录中放置一个名为 `rustfmt.toml` 或 `.rustfmt.toml` 的文件,以覆盖 rustfmt 的默认设置。你可以使用 `rustfmt --print-config default rustfmt.toml` 生成包含默认配置的文件,并根据需要进行自定义。
* 成功编译后,可以在 target 目录中找到 `rustfmt` 可执行文件。
* 如果你在编译 Rustfmt 时遇到问题(或尝试安装时出现编译错误),请确保你安装了最新版本的 Rust。
* 你可以使用 --emit 标志更改 rustfmt 输出更改的方式:
示例:
cargo fmt -- --emit files
选项:
| 标志 | 描述 | 仅 Nightly |
|:---:|:---:|:---:|
| files | 覆盖输出到文件 | 否 |
| stdout | 输出到 stdout | 否 |
| coverage | 显示输入文件被处理了多少 | 是 |
| checkstyle | 以 checkstyle 格式输出 | 是 |
| json | 以 json 格式输出差异 | 是 |
## 许可证
Rustfmt 在 MIT 许可证和 Apache 许可证(版本 2.0)的条款下分发。
详细信息请参阅 [LICENSE-APACHE](LICENSE-APACHE) 和 [LICENSE-MIT](LICENSE-MIT)。
标签:cargo, CI, code-style, development, formatter, formatting, linting, nightly, Python安全, Rust, rustfmt, rust-lang, rustup, stable, Travis CI, 代码格式化, 可视化界面, 工具, 开源, 开源框架, 持续集成, 网络流量审计, 通知系统