31 个版本
0.5.0-pre1 | 2024 年 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 在 过程宏
567 每月下载量
在 3 crates 中使用
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
不解析注释(有时除外),因此所有注释都在处理开始时提取出来。通常,注释与下一个语法元素相关联,除了行尾注释//
,这些注释与当前行上的第一个语法元素相关联。
在构建拆分组时,如果当前语法元素具有与提取的注释行/列匹配的标记,则该注释将被添加到拆分组中。
宏
宏使用一些技巧进行格式化
- 如果它被解析为Rust代码(表达式或语句列表),则按正常方式格式化。
- 如果不解析为Rust代码,则通过
;
和,
进行拆分,因为那些通常是分隔符,然后对每个块尝试上述操作。 - 否则,每个宏中的标记都用空格连接(还有一些其他针对特定情况的调整)
优先格式化宏的最终用户使用,而不是格式化macro_rules
,因为宏的使用比定义更频繁。大多数宏看起来像正常的Rust语法,因此可以使用许多常规格式化规则。
Q&A
有关许多问题和答案,请参阅这篇Reddit帖子。
有关其他问题或错误报告等,请使用此处的问题和/或讨论。
依赖项
约12–23MB
约341K SLoC