一款用于 Lua 5.1、5.2、5.3、5.4、LuaJIT、Luau 和 CfxLua/FiveM Lua 的确定性代码格式化工具,基于 full-moon 构建。 StyLua 受到 prettier 等工具的启发,它会解析你的 Lua 代码库,并从头重新输出, 以强制统一的代码风格。
StyLua 主要遵循 Roblox Lua Style Guide,但存在少量偏差。
安装
安装 StyLua 有多种方式:
通过 GitHub Releases
预构建的二进制文件可在 GitHub Releases Page 上获取。
默认情况下,这些二进制文件启用了所有语法变体(Lua 5.2、5.3、5.4、LuaJIT 和 Luau),以覆盖所有可能的代码库。 如果你需要选择特定的 Lua 语法进行格式化,请参阅 configuring runtime syntax selection。 或者,请参阅 installing from crates.io 了解如何安装特定版本的 StyLua。
从 Crates.io
如果你已安装 Rust,可以使用 cargo 安装 StyLua。
默认情况下,这仅针对 Lua 5.1 进行构建。
你可以传入 --features <flag> 参数以添加额外的语法变体:
cargo install stylua
cargo install stylua --features lua52
cargo install stylua --features lua53
cargo install stylua --features lua54
cargo install stylua --features luajit
cargo install stylua --features luau
您可以同时指定多个特性,然后使用 .stylua.toml 文件中的配置](#configuring-runtime-syntax-selection) 将语法选择推迟到运行时。
GitHub Actions
stylua-action GitHub Action 可以安装并运行 StyLua。 该操作使用预构建的 GitHub 发布二进制文件,而不是运行 cargo install,以加快 CI 启动时间。
pre-commit
您可以使用 StyLua 配合 pre-commit。 有 3 种可用的 pre-commit 钩子:
stylua: 通过 cargo 安装 - 需要 Rust 工具链stylua-system: 运行 PATH 上可用的stylua二进制文件。该二进制文件必须预先安装stylua-github: 自动从 GitHub Releases 安装相关的预构建二进制文件
将以下内容添加到您的 .pre-commit-config.yaml 文件中:
- repo: https://github.com/JohnnyMorganz/StyLua
rev: v2.5.2
hooks:
- id: stylua # or stylua-system / stylua-github
npm
StyLua 以二进制文件的形式发布到 npm](https://www.npmjs.com/package/@johnnymorganz/stylua-bin),名称为 @johnnymorganz/stylua-bin。
这是一个轻量级封装,用于安装该二进制文件并通过 npm / npx 使其可用。
npx @johnnymorganz/stylua-bin --help
StyLua 也可作为 WASM 库在 @johnnymorganz/stylua 获取。 它可用于 Node.js,或浏览器中(使用打包器)。
Docker
StyLua 可在 Docker Hub 上获取。
如果你正在使用 Docker,安装 StyLua 最简单的方法是:
COPY --from=JohnnyMorganz/StyLua:2.5.2 /stylua /usr/bin/stylua
Homebrew
StyLua 可通过 macOS 上的 Homebrew 包管理器获取。
brew install stylua
pip / uv
你可以通过将 git 仓库作为归档 URL 传入,使用 pip / uv 安装 StyLua
pip install git+https://github.com/johnnymorganz/stylua
uv tool install git+https://github.com/johnnymorganz/stylua
其他安装方法
aftman add johnnymorganz/stylua@2.5.2
- 一个由社区维护的软件包仓库。请注意,这些软件包由第三方维护,我们无法控制其打包清单。
其他编辑器集成
请注意,这些集成要求 StyLua 二进制文件已安装在您的系统上并可用。
- Sublime: Sublime Text Package
- Neovim: stylua-nvim / stylua.nvim
- Zed: Zed Lua StyLua formatter settings
用法
安装完成后,将需要格式化的文件传递给 CLI:
stylua src/ foo.lua bar.lua
此命令将格式化 foo.lua 和 bar.lua 文件,并向下搜索 src 目录以格式化其中的任何文件。
StyLua 还可以通过使用 - 作为文件名从 stdin 读取。
Glob 过滤
默认情况下,在搜索目录时,StyLua 会查找所有匹配 glob **/*.lua(或在启用 luau 时匹配 **/*.luau)的文件进行格式化。
您还可以在搜索时指定要匹配的显式 glob 模式:
stylua --glob '**/*.luau' -- src # format all files in src matching **/*.luau
stylua -g '*.lua' -g '!*.spec.lua' -- . # format all Lua files except test files ending with `.spec.lua`
请注意,-g/--glob 参数可以一次接受多个字符串,因此需要 -- 来分隔 glob 模式和要格式化的文件。
默认情况下,glob 过滤(以及 .styluaignore 文件)仅在目录遍历和搜索期间应用。
直接传递的文件(例如 stylua foo.txt)将覆盖 glob / ignore 并始终被格式化。
要禁用此行为,请传递 --respect-ignores 标志(stylua --respect-ignores foo.txt)。
使用 .styluaignore 进行过滤
您可以创建一个 .styluaignore 文件,其格式类似于 .gitignore。
匹配 ignore 文件中 glob 的任何文件都会被 StyLua 忽略。
例如,对于一个包含以下内容的 .styluaignore 文件:
vendor/
运行 stylua . 将忽略 vendor/ 目录。
使用 stdin 时的过滤
如果你通过指定 - 作为文件名来格式化 stdin(通常作为编辑器集成的一部分),
你可以选择通过 --stdin-filepath 提供文件名。为了尊重 glob 或 .styluaignore 过滤,请传递 --respect-ignores。
stylua --respect-ignores --stdin-filepath src/foo.lua -
--check: 检查文件格式
要检查文件是否需要格式化(但不直接写入文件),请使用 --check 标志。
它将接收文件作为输入,并将差异输出到 stdout,而不是重写文件内容。
如果有任何文件需要格式化,StyLua 将以状态码 1 退出。
有多种可用的输出样式:
--output-format=standard: 输出自定义差异(默认)--output-format=unified: 输出统一差异,可被patch或delta等工具消费--output-format=json: 输出表示更改的 JSON,适用于机器可读输出--output-format=summary: 输出格式错误的文件路径摘要列表
--verify: 验证格式化输出
作为一种安全措施,您可以使用 --verify 标志在保存文件之前验证所有格式化的输出。
如果启用,该工具将重新解析格式化后的输出,以验证 AST 是否仍然有效(无语法错误)且与输入相似(可能存在语义变化)。
这在大型代码库中采用 StyLua 时非常有用,因为手动检查所有格式是否正确很困难。 请注意,这可能会产生误报和漏报 - 我们建议同时进行手动验证并运行测试以确认。
忽略文件的部分
要跳过文件的特定部分的格式化,您可以在其前面添加 -- stylua: ignore。
如果您希望保留特定的样式以提高可读性,这很有用,例如:
-- stylua: ignore
local matrix = {
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
}
要跳过一段代码,请使用 -- stylua: ignore start 和 -- stylua: ignore end:
local foo = true
-- stylua: ignore start
local bar = false
local baz = 0
-- stylua: ignore end
local foobar = false
请注意,忽略不能跨越作用域边界——一旦退出代码块,格式化将重新启用。
格式化范围
要格式化文件中的特定范围,请使用 --range-start <num> 和/或 --range-end <num>。
两个参数均为包含边界且可选——如果未提供某个参数,则分别使用文件的起始/结束位置。
仅格式化完全位于范围内的完整语句。 如果语句的一部分位于范围之外,则该语句将被忽略。
在编辑器中,支持 Format Selection。
需要排序
StyLua 内置了对 require 语句排序的支持。我们将连续的 require 语句分组为一个“块”, 然后仅在该块内对 require 进行排序。require 块不会在文件中移动。
StyLua 仅考虑形式为 local NAME = require(EXPR) 的 require,并基于 NAME 进行字典序排序。
(StyLua 还可以对形式为 local NAME = game:GetService(EXPR) 的 Roblox 服务进行排序)
require 排序默认关闭。要启用它,请将以下内容添加到你的 stylua.toml 中:
[sort_requires]
enabled = true
语言服务器模式
StyLua 可以作为语言服务器运行,与遵循 Language Server Protocol 的语言客户端进行连接。
随后,它将响应 textDocument/formatting 和 textDocument/rangeFormatting 请求。
仅对具有 lua 或 luau 语言 ID 的文件执行格式化。
如果初始化选项 respect_editor_formatting_options 设置为 true,格式化处理器将使用 FormattingOptions 中的值覆盖配置 indent-width 和 indent-type。
您可以通过运行以下命令启动语言服务器:
stylua --lsp
StyLua 将监听 stdin 上的 LSP 消息,并在 stdout 上响应。
配置
StyLua 具有预设的默认值,但也提供了一些可按项目设置的选项。
查找配置
CLI 会从正在格式化的文件所在目录开始,查找 stylua.toml 或 .stylua.toml。
它会持续向上搜索,直到到达执行该工具时所在的当前目录。
如果未找到,则搜索 .editorconfig 文件,否则回退到默认配置。
可以使用 --no-editorconfig 禁用此功能。
有关更多详细信息,请参阅 EditorConfig。
使用 --config-path <path> 提供自定义的配置路径。
如果提供的文件未找到/格式错误,StyLua 将退出并显示错误。
默认情况下,StyLua 不会搜索当前目录以外的范围。
使用 --search-parent-directories 递归搜索父目录。
这将持续搜索祖先目录,如果未找到,则会在 $XDG_CONFIG_HOME / $XDG_CONFIG_HOME/stylua / $HOME/.config 和 $HOME/.config/stylua 中查找。
注意:由于可能导致格式冲突,不建议启用当前目录以外的搜索:
建议在项目根目录中保留一个 .stylua.toml 文件,以便其他开发人员可以使用相同的配置。
如果项目使用 StyLua 的默认配置且不存在配置文件,启用外部搜索可能会导致格式冲突。
配置运行时语法选择
默认情况下,StyLua 发布版本将所有 Lua 变体打包到一个二进制文件中,并包含所有语法风格的并集。 我们这样做是为了让 StyLua 更容易在任何使用 Lua 的代码库或项目中快速上手。
然而,有时语法并集会发生冲突,导致问题。例如,Lua 5.2 的 goto 标签语法
(::label::) 与 Luau 的类型断言语法 (x :: number) 冲突,且后者最终会获得优先权。
为了消除代码库中特定语法风格的歧义,请在 .stylua.toml 文件中设置 syntax = "Style",例如:
syntax = "Lua52"
或者,你可以在命令行中指定它,使用 stylua --syntax lua52 ...
选项
StyLua 仅提供以下选项:
| 选项 | 默认值 | 描述 |
|---|---|---|
syntax | All | 指定用于格式化 Lua 语法的风格消歧义。可选选项:All(默认)、Lua51、Lua52、Lua53、Lua54、LuaJIT、Luau、CfxLua |
column_width | 120 | 用于打印的近似行长度。作为换行的参考 - 这不是硬性要求:行可以低于或超过该限制。 |
line_endings | Unix | 行尾类型。可选值:Unix (LF) 或 Windows (CRLF) |
indent_type | Tabs | 缩进类型。可选值:Tabs 或 Spaces |
indent_width | 4 | 单个缩进的字符大小。如果 indent_type 设置为 Tabs,此选项仅用作确定列宽的启发式方法。 |
quote_style | AutoPreferDouble | 字符串字面量的引号样式。可选选项:AutoPreferDouble、AutoPreferSingle、ForceDouble、ForceSingle。AutoPrefer 样式会优先使用指定的引号样式,但如果替代样式具有更少的字符串转义,则回退到替代样式。Force 样式无论转义情况如何,始终使用指定的样式。 |
call_parentheses | Always | 是否应对带有单个字符串/表参数的函数调用应用括号。可选选项:Always, NoSingleString, NoSingleTable, None, Input。Always 在所有情况下都应用括号。NoSingleString 在带有单个字符串参数的调用中省略括号。类似地,NoSingleTable 在带有单个表参数的调用中省略括号。None 在两种情况下都省略括号。注意:在移除括号可能导致歧义的情况下(例如 foo "bar".setup -> foo("bar").setup,因为索引位于调用结果上,而非字符串上),仍会保留括号。Input 移除所有自动化处理,仅当输入代码中存在括号时才保留括号:不强制一致性。 |
space_after_function_names | Never | 指定是否在函数名和括号之间添加空格。可选选项:Never, Definitions, Calls, 或 Always |
block_newline_gaps | Never | 指定是否保留块的前导和尾随换行间隙。可选值:Never、Preserve |
collapse_simple_statement | Never | 指定是否折叠简单语句。可选值:Never、FunctionOnly、ConditionalOnly 或 Always |
默认 stylua.toml,请注意,如果您想使用默认值,则无需显式指定每个选项:
syntax = "All"
column_width = 120
line_endings = "Unix"
indent_type = "Tabs"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
collapse_simple_statement = "Never"
space_after_function_names = "Never"
block_newline_gaps = "Never"
[sort_requires]
enabled = false