31 个版本

0.5.0-pre12024 年 7 月 21 日
0.3.3 2024 年 7 月 5 日
0.2.4 2024 年 5 月 10 日
0.2.3 2023 年 9 月 17 日
0.1.15 2022 年 12 月 30 日

#53过程宏

Download history 96/week @ 2024-05-03 266/week @ 2024-05-10 172/week @ 2024-05-17 137/week @ 2024-05-24 156/week @ 2024-05-31 122/week @ 2024-06-07 164/week @ 2024-06-14 140/week @ 2024-06-21 415/week @ 2024-06-28 320/week @ 2024-07-05 331/week @ 2024-07-12 310/week @ 2024-07-19 235/week @ 2024-07-26 103/week @ 2024-08-02 111/week @ 2024-08-09 92/week @ 2024-08-16

567 每月下载量
3 crates 中使用

ISC 许可证

260KB
6.5K SLoC

Gene Michaels

状态: Delta(在 gamma 之后)。我已经使用它多年而没有遇到重大问题,并且我已经在各种代码库中进行了测试,它们都没有崩溃。我认为其他人也可能使用它!目前,在格式化后重新解析并确认所有注释都被作为安全检查消耗。此外,超过 500kb 的文件可能会消耗所有内存并触发 OOM 杀手。

  • 格式化一切
  • 不格式化某些内容
  • 这是一首俳句

以 Gene Michaels 命名。

包括宏和注释在内的所有内容。在这个仓库中使用了狗粮。

与 Rustfmt 的差异

  • 这格式化所有宏,Rustfmt 只在特定条件下格式化宏
  • 这是完全确定的,Rustfmt 保留某些样式选择,如
  • Rustfmt 有 几个 限制 在它通常格式化的内容上,这总是格式化一切(如果它没有,那就是一个错误)
  • 这也会根据 Markdown 规则重新格式化注释

使用方法

运行 cargo install genemichaels

运行 genemichaels 将默认格式化当前包中的所有文件(查看当前目录中的 Cargo.toml)。您还可以传递要格式化的文件名列表。

VS Code

如果您正在使用 VS Code,请添加以下设置

  "rust-analyzer.rustfmt.overrideCommand": [
    "${userHome}/.cargo/bin/genemichaels", "--stdin"
  ]

以无拘无束地使用它。

配置

配置文件包含用于调整输出格式的参数,适合为项目建立规范。不影响输出的内容(线程数、详细程度等)是命令行参数。

配置文件是json格式,但如果你想要添加注释,它将首先去除以//开头的行。

以下是配置文件。所有显示的值都是默认值,如果默认值适合你,可以省略键。

{
  // Ideal maximum line width. If there's an unbreakable element the line won't be split.
  "max_width": 120,
  // When breaking a child element, also break all parent elements.
  "root_splits": false,
  // Break a `()` or `{}` if it has greater than this number of children.  Set to `null` to
  // disable breaking due to high child counts.
  "split_brace_threshold": 1,
  // Break a `#[]` on a separate line before the element it's associated with.
  "split_attributes": true,
  // Put the `where` clause on a new line.
  "split_where": true,
  // Maximum relative line length for comments (past the comment indentation level). Can be
  // `null` to disable relative wrapping.  If disabled, still wraps at `max_width`.
  "comment_width": 80,
  // If reformatting comments results in an error, abort formatting the document.
  "comment_errors_fatal": false,
  // Genemichaels will replace line breaks with it's own deterministic line breaks.  You can
  // use this to keep extra line breaks (1 will keep up to 1 extra line break) during comment
  // extraction. This is unused during formatting.
  "keep_max_blank_lines": 0
}

禁用特定注释的格式化

由于假设注释是markdown格式,它们将按照markdown规则进行格式化。要禁用某些注释的格式化,请从以下方式开始注释://.,例如

//. fn main() {
//.    println!("hi");
//. }

禁用特定文件的格式化

要跳过特定文件,在源代码的前5行添加一个包含nogenemichaels的注释,例如

// nogenemichaels
...

程序性使用

执行cargo add genemichaels

有三个主要功能

  • genemichaels::format_str - 格式化字符串(完整的Rust源文件,目前不支持代码片段)。
  • genemichaels::format_ast - 格式化AST元素(实现了genemichaels::Formattable,大多数syn::*结构体都)。如果有任何注释,需要单独传递。
  • genemichaels::extract_comments - 从源代码字符串中提取注释,将每个注释映射到语法元素的开头

如果你想要格式化TokenStream,可以使用syn::parse2::<syn::File>(token_stream)将其解析为AST,然后调用format_ast

格式化函数还返回丢失的注释——在处理过程中未格式化/添加到格式化源代码中的注释。在理想世界中,这不会存在,但当前注释是逐个添加的,并且不是所有源代码标记都支持注释。

工作原理

从非常高的层面来看

  • 语法树被转换为线性列表的段,其中每个段正好属于一个“分割组”。分割组有一个布尔状态开关:分割或不分割。

    例如,match {}的分割组可能包含段match { <break>}。这些段与其他组的段交织在一起,例如,其他段可能位于{}之间。

    所有分割组都从非分割状态开始。

    当切换分组的拆分状态时,<break>及其之后的该行内容都将移到该行之后的新行。

该算法基本是将节点包裹起来,直到所有行都小于最大行宽。

这是一个简化的解释;还有一些其他因素

  • 对齐
  • 根据其组是否拆分而改变的段(即上面的<break>只有在组拆分时才断行,而无条件断行)

多线程

默认情况下,Gene Michaels在所有可用核心上格式化多个文件,但这会使用更多的内存。如果您有一个特别大的文件项目,可以在配置中限制使用更少的核心。

注释

注释值得特别提及,因为它们是在带外处理的。

syn不解析注释(有时除外),因此所有注释都在处理开始时提取出来。通常,注释与下一个语法元素相关联,除了行尾注释//,这些注释与当前行上的第一个语法元素相关联。

在构建拆分组时,如果当前语法元素具有与提取的注释行/列匹配的标记,则该注释将被添加到拆分组中。

宏使用一些技巧进行格式化

  1. 如果它被解析为Rust代码(表达式或语句列表),则按正常方式格式化。
  2. 如果不解析为Rust代码,则通过;,进行拆分,因为那些通常是分隔符,然后对每个块尝试上述操作。
  3. 否则,每个宏中的标记都用空格连接(还有一些其他针对特定情况的调整)

优先格式化宏的最终用户使用,而不是格式化macro_rules,因为宏的使用比定义更频繁。大多数宏看起来像正常的Rust语法,因此可以使用许多常规格式化规则。

Q&A

有关许多问题和答案,请参阅这篇Reddit帖子

有关其他问题或错误报告等,请使用此处的问题和/或讨论。

依赖项

约12–23MB
约341K SLoC