StyLua
相关工具推荐
| 工具 | 说明 |
|---|---|
| Luacheck | Lua 代码质量检查工具,与 StyLua 互补 |
| Pre-commit | Git pre-commit 钩子管理框架 |
1. 简介
StyLua 是一个确定性(Deterministic)的 Lua 代码格式化工具,灵感来源于 Prettier。它使用 full-moon Lua 解析器将源代码解析为 AST,再由内置格式化引擎重新输出格式统一的代码,确保同一份源码在任何时间、任何机器上执行后输出完全一致。
StyLua 主要遵循 Roblox Lua Style Guide,在此基础上做了少量调整。支持 Lua 5.1、5.2、5.3、5.4、LuaJIT、Luau 以及 CfxLua/FiveM Lua 等多种 Lua 方言。
- 主要检查语言:Lua 5.x、Luau
- 主要检查能力:格式化 Lua 代码(缩进、换行、对齐);涵盖代码格式化
- 核心检查原理:基于 Lua AST 解析进行格式化
- 检查规则/选项:10 个主配置选项(如 syntax、column_width、line_endings、indent_type、quote_style 等)外加 1 个子表选项,全量配置选项
- GitHub 仓库:https://github.com/JohnnyMorganz/StyLua(2,226 stars)
- 开源协议:MPL-2.0
- 最新稳定版本:v0.20.0
- 运行环境要求:无(独立二进制)
- 误报率:无
2. 官方文档
| 文档 | 链接 |
|---|---|
| GitHub 仓库(主文档) | https://github.com/JohnnyMorganz/StyLua |
| GitHub Releases | https://github.com/JohnnyMorganz/StyLua/releases |
| VS Code 扩展 | https://marketplace.visualstudio.com/items?itemName=JohnnyMorganz.stylua |
| GitHub Action(stylua-action) | https://github.com/JohnnyMorganz/stylua-action |
| Marketplace 页面 | https://github.com/marketplace/actions/stylua |
| npm 包(二进制) | https://www.npmjs.com/package/@johnnymorganz/stylua-bin |
| Docker Hub | https://hub.docker.com/r/johnnymorganz/stylua |
| crates.io | https://crates.io/crates/stylua |
| full-moon 解析器 | https://github.com/Kampfkarren/full-moon |
| Roblox Lua Style Guide | https://roblox.github.io/lua-style-guide/ |
配置选项完整文档
StyLua 的所有配置选项详见官方 README 的 Configuration 和 Options 章节。
| 选项 | 默认值 | 说明 |
|---|---|---|
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 |
call_parentheses |
"Always" |
函数调用括号:Always、NoSingleString、NoSingleTable、None、Input |
space_after_function_names |
"Never" |
函数名与括号间空格:Never、Definitions、Calls、Always |
collapse_simple_statement |
"Never" |
简单语句折叠:Never、FunctionOnly、ConditionalOnly、Always |
block_newline_gaps |
"Never" |
是否保留块首尾空行:Never、Preserve |
3. 社区优秀实践
3.1 Neovim(neovim/neovim)
- 仓库:https://github.com/neovim/neovim
- 集成方式:项目根目录维护 .stylua.toml 配置文件,使用 2 空格缩进、100 列宽、
AutoPreferSingle引号风格、Input括号模式。另有 .styluaignore 文件排除构建产物、自动生成文件和特殊测试文件。Neovim 还维护了 .stylua2.toml 用于部分需要更宽列宽(140)的测试文件。CI 流水线中使用 StyLua 检查确保所有 PR 的 Lua 代码符合格式规范。 - 配置文件:.stylua.toml
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
call_parentheses = "Input"
3.2 LazyVim(LazyVim/LazyVim)
- 仓库:https://github.com/LazyVim/LazyVim
- 集成方式:LazyVim 是 Neovim 最流行的配置框架之一,项目根目录维护 stylua.toml 配置文件,使用 2 空格缩进、120 列宽,并启用 require 语句排序。LazyVim 通过 conform.nvim 集成 StyLua 作为 Lua 文件的默认格式化器,CI 中通过 GitHub Actions 运行 StyLua 检查。
- 配置文件:stylua.toml
indent_type = "Spaces"
indent_width = 2
column_width = 120
[sort_requires]
enabled = true
3.3 NvChad(NvChad/NvChad)
- 仓库:https://github.com/NvChad/NvChad
- 集成方式:NvChad 是另一个广受欢迎的 Neovim 配置框架,项目根目录维护 .stylua.toml 配置文件,使用 2 空格缩进、120 列宽,并设置
call_parentheses = "None"以去除单参数函数调用的括号。 - 配置文件:.stylua.toml
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
call_parentheses = "None"
4. 工具配置说明
StyLua 是代码格式化工具,以下提供几套适合不同场景的配置供参考。
4.1 配置文件说明
StyLua 涉及以下配置文件:
| 配置文件 | 用途 | 使用场景 |
|---|---|---|
stylua.toml |
StyLua 主配置文件(TOML 格式) | 所有项目,控制 Lua 代码格式化行为 |
.stylua.toml |
StyLua 备用配置文件名 | 与 stylua.toml 等价,部分项目采用点文件命名约定 |
.editorconfig |
EditorConfig 配置文件(备选) | 未提供 stylua.toml 时作为格式化参数来源 |
配置文件查找顺序(从被格式化文件所在目录开始向上搜索):
stylua.toml.stylua.toml.editorconfig(如果未找到stylua.toml)- 内置默认配置
可通过 --config-path <path> 显式指定配置文件路径,或使用 --search-parent-directories 向上递归搜索。
4.2 stylua.toml 配置详解
stylua.toml 是 StyLua 的主配置文件,用于控制 Lua 代码格式化行为。
配置项说明:
| 配置项 | 类型 | 说明 |
|---|---|---|
syntax |
string | 语法变体(Lua、Lua5.2、Luau、All),默认 All |
column_width |
int | 最大列宽(默认 120) |
line_endings |
string | 换行符风格(Unix、Windows) |
indent_type |
string | 缩进类型(Tabs、Spaces) |
indent_width |
int | 缩进宽度(indent_type = "Spaces" 时为空格数,Tabs 时为 tab 显示宽度) |
quote_style |
string | 引号风格(AutoPreferDouble、AutoPreferSingle、ForceDouble、ForceSingle) |
call_parentheses |
string | 函数调用括号(Always、NoSingleTable、NoTables、None) |
collapse_simple_statement |
string | 简单语句折叠(Always、FunctionOnly、ConditionalOnly、Never) |
space_after_function_names |
string | 函数名后空格(Always、OnlyString、OnlyTables、Never) |
block_newline_gaps |
string | 块间空行(Always、Inner、Outer、Never) |
sort_requires.enabled |
bool | 是否对连续 require 调用按变量名字典序排序 |
推荐配置示例:
Neovim 插件项目:
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
[sort_requires]
enabled = true
Neovim 社区普遍使用 2 空格缩进,并启用 require 语句排序以保持依赖导入的整洁。此配置与 LazyVim 项目的实践一致。
通用 Lua 项目:
column_width = 120
line_endings = "Unix"
indent_type = "Tabs"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
使用 StyLua 默认的 Tab 缩进,适合非 Neovim 生态的通用 Lua 项目。
Roblox / Luau 项目:
syntax = "Luau"
column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
显式指定
syntax = "Luau"以避免 Lua 5.2 的::label::语法与 Luau 的类型断言语法冲突。
完整配置示例(包含所有配置项的参考):
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
5. 主流集成方式
以下配置均基于 StyLua v2.5.2 最新稳定版本。
5.1 pre-commit 集成
StyLua 官方仓库内置了 pre-commit 钩子定义(.pre-commit-hooks.yaml),提供三种钩子:
| 钩子 ID | language |
说明 |
|---|---|---|
stylua |
rust |
通过 cargo 安装,需要 Rust 工具链 |
stylua-system |
system |
使用系统 PATH 中已有的 StyLua 二进制,需预先安装 |
stylua-github |
python |
自动从 GitHub Releases 下载预编译二进制 |
.pre-commit-config.yaml 配置示例(使用 stylua-github):
repos:
- repo: https://github.com/JohnnyMorganz/StyLua
rev: v2.5.2
hooks:
- id: stylua-github
说明:
stylua-github钩子会自动下载对应平台的预编译二进制,无需手动安装 StyLua 或 Rust 工具链- pre-commit 框架默认只对 Git 暂存区的变更文件运行钩子,天然支持文件级增量检查
- 如需全量检查,可手动运行
pre-commit run stylua-github --all-files
5.2 IDE 集成
VS Code
- 扩展名称:StyLua(扩展 ID:
JohnnyMorganz.stylua) - 安装:在 VS Code 扩展市场搜索 "StyLua" 安装
settings.json 配置示例:
{
"[lua]": {
"editor.defaultFormatter": "JohnnyMorganz.stylua",
"editor.formatOnSave": true
},
"[luau]": {
"editor.defaultFormatter": "JohnnyMorganz.stylua",
"editor.formatOnSave": true
}
}
Neovim
方案一:conform.nvim(推荐)
return {
"stevearc/conform.nvim",
opts = {
formatters_by_ft = {
lua = { "stylua" },
},
},
}
方案二:LSP 模式
StyLua 自 v2.2.0 起支持 Language Server 模式,可直接作为格式化 LSP 使用:
vim.lsp.config.stylua = {
cmd = { "stylua", "--lsp" },
filetypes = { "lua", "luau" },
root_markers = { ".stylua.toml", "stylua.toml" },
}
vim.lsp.enable("stylua")
方案三:stylua-nvim 插件
社区插件 stylua-nvim 提供了更细粒度的 StyLua 集成。
Sublime Text
社区维护的 Sublime-Pretty-Lua 包提供了 StyLua 集成。
Zed
Zed 编辑器内置了 StyLua 格式化支持,详见 Zed Lua 文档。
5.3 命令行使用方式
常用命令
# 格式化文件(写入模式)
stylua src/ foo.lua bar.lua
# 格式化整个项目
stylua .
# 检查文件(不修改,仅报告差异)
stylua --check src/
# 验证格式化后代码的 AST 一致性
stylua --verify src/
# 指定配置文件
stylua --config-path .stylua.toml src/
# 使用 glob 过滤文件
stylua --glob '**/*.luau' -- src
stylua -g '*.lua' -g '!*.spec.lua' -- .
# 从 stdin 读取并格式化
cat src/file.lua | stylua -
# 指定 stdin 文件路径(用于编辑器集成,可配合 --respect-ignores)
stylua --stdin-filepath src/foo.lua -
检查模式 vs 修复模式
| 模式 | 命令 | 行为 | 适用场景 |
|---|---|---|---|
| 检查模式 | stylua --check . |
不修改文件,输出差异到 stdout。有不符合格式的文件时返回退出码 1 | CI/CD 流水线、pre-commit 检查 |
| 修复模式 | stylua . |
直接修改文件为格式化后的内容 | 本地开发、手动修复 |
--check 模式支持多种输出格式:
| 参数 | 说明 |
|---|---|
--output-format=standard |
自定义差异输出(默认) |
--output-format=unified |
统一差异格式,可用于 patch 或 delta |
--output-format=json |
JSON 格式输出,适合机器解析 |
--output-format=summary |
仅列出不符合格式的文件路径 |
常用参数
| 参数 | 说明 |
|---|---|
--check / -c |
检查格式(不修改文件) |
--verify |
验证格式化后代码的 AST 与原始代码一致 |
--config-path <path> |
指定配置文件路径 |
--syntax <variant> |
指定 Lua 语法变体 |
--glob <pattern> / -g |
指定 glob 匹配模式 |
--stdin-filepath <path> |
指定 stdin 输入的文件路径 |
--respect-ignores |
对直接传入的文件也尊重 .styluaignore 规则 |
--no-ignore-vcs |
不跳过 .gitignore 中的文件 |
--search-parent-directories |
向上搜索父目录查找配置文件 |
--no-editorconfig |
禁用 EditorConfig 支持 |
--cache |
启用缓存加速格式化 |
--range-start <num> |
格式化起始行(含) |
--range-end <num> |
格式化结束行(含) |
--lsp |
以 Language Server 模式运行 |
增量检查:StyLua 接受文件路径列表作为输入参数,可结合 git diff 筛选变更文件实现增量检查:
# 格式化暂存区的 Lua 文件
git diff --name-only --cached --diff-filter=ACMR | grep -E '\.(lua|luau)$' | xargs stylua
# 检查相对于 main 分支变更的 Lua 文件
git diff --name-only origin/main...HEAD -- '*.lua' '*.luau' | xargs stylua --check
# 检查工作区中已修改但未暂存的 Lua 文件
git diff --name-only --diff-filter=ACMR | grep -E '\.(lua|luau)$' | xargs stylua --check
CI 脚本调用:在 CI 环境中通过脚本调用 StyLua 进行格式化检查。
GitHub Actions(手动安装)
jobs:
stylua:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install StyLua
run: |
curl -fsSL https://github.com/JohnnyMorganz/StyLua/releases/download/v2.5.2/stylua-linux-x86_64.zip -o stylua.zip
unzip stylua.zip && chmod +x stylua
sudo mv stylua /usr/local/bin/
- name: Check formatting
run: stylua --check .
GitLab CI
stages:
- lint
stylua-check:
stage: lint
image: alpine:latest
before_script:
- apk add --no-cache curl unzip
- curl -fsSL https://github.com/JohnnyMorganz/StyLua/releases/download/v2.5.2/stylua-linux-x86_64-musl.zip -o stylua.zip
- unzip stylua.zip && chmod +x stylua
- mv stylua /usr/local/bin/
script:
- stylua --check .
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"
增量检查:GitHub Actions 中基于 git diff 仅检查变更的 Lua 文件:
- name: Check formatting of changed files
run: |
CHANGED_FILES=$(git diff --name-only origin/main...HEAD -- '*.lua' '*.luau')
if [ -n "$CHANGED_FILES" ]; then
echo "$CHANGED_FILES" | xargs stylua --check
else
echo "No Lua files changed."
fi
GitLab CI 中基于 git diff 仅检查变更的 Lua 文件:
script:
- |
CHANGED_FILES=$(git diff --name-only ${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$CI_DEFAULT_BRANCH}...HEAD -- '*.lua' '*.luau')
if [ -n "$CHANGED_FILES" ]; then
echo "$CHANGED_FILES" | xargs stylua --check
else
echo "No Lua files changed."
fi
5.4 GitHub Action 插件
通过专用 GitHub Action 插件 stylua-action 在 CI 中集成 StyLua 格式化检查。stylua-action 从 GitHub Releases 下载预编译二进制并缓存,避免每次构建都重新下载。
name: Format Check
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
stylua:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: JohnnyMorganz/stylua-action@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
version: 2.5.2
args: --check .
5.5 二进制安装(生态主流方式)
StyLua 作为独立的 CLI 工具,最主流的集成方式是直接下载预编译二进制文件,然后在编辑器、CI 或 Git Hook 中调用。
GitHub Releases(推荐)
从 GitHub Releases 下载对应平台的预编译二进制。默认构建包含所有 Lua 语法变体支持。
Homebrew(macOS)
brew install stylua
Cargo(需要 Rust 工具链)
# 安装基础版本(仅 Lua 5.1)
cargo install stylua
# 安装指定 Lua 版本支持
cargo install stylua --features lua54
cargo install stylua --features luajit
cargo install stylua --features luau
# 安装所有 Lua 方言支持
cargo install stylua --features lua52,lua53,lua54,luajit,luau
npm
# 通过 npx 直接使用
npx @johnnymorganz/stylua-bin --help
# 安装到项目
npm install --save-dev @johnnymorganz/stylua-bin
pip / uv(Python)
pip install git+https://github.com/johnnymorganz/stylua
uv tool install git+https://github.com/johnnymorganz/stylua
Docker
COPY --from=JohnnyMorganz/StyLua:2.5.2 /stylua /usr/bin/stylua
Aftman(Roblox 开发者工具链管理器)
aftman add johnnymorganz/stylua@2.5.2
6. 告警抑制(屏蔽)方法
6.1 通过 .styluaignore 文件屏蔽
官方文档:Filtering using .styluaignore
在项目根目录创建 .styluaignore 文件,语法与 .gitignore 相同。StyLua 在遍历目录时会自动遵循其中的规则。
.styluaignore 示例:
# 第三方代码
vendor/
third_party/
# 自动生成的文件
generated/
*.generated.lua
# 构建产物
build/
dist/
如果直接传入文件路径(如
stylua foo.lua),默认会覆盖.styluaignore规则。使用--respect-ignores参数可强制遵循忽略规则。
6.2 通过 pre-commit 框架屏蔽
在 .pre-commit-config.yaml 中,可通过 pre-commit 框架的文件匹配机制控制 StyLua 的作用范围:
repos:
- repo: https://github.com/JohnnyMorganz/StyLua
rev: v2.5.2
hooks:
- id: stylua-github
files: '^src/.*\.lua$' # 只检查 src 目录下的 .lua 文件
exclude: "^src/vendor/" # 排除 src/vendor 目录
pre-commit 框架支持的匹配字段包括:files(正则匹配文件路径)、exclude(正则排除)、types(文件类型,StyLua 默认为 lua)、exclude_types。
6.3 通过工具命令行参数屏蔽(glob 过滤)
官方文档:Glob Filtering
使用 --glob / -g 参数通过 glob 模式过滤需要格式化的文件:
# 只格式化 src 目录下的 Lua 文件
stylua --glob '**/*.lua' -- src
# 格式化所有 Lua 文件,排除测试文件
stylua -g '*.lua' -g '!*.spec.lua' -g '!*.test.lua' -- .
# 格式化 Luau 文件
stylua --glob '**/*.luau' -- .
6.4 通过代码注释屏蔽
StyLua 支持在 Lua 代码中使用注释指令跳过格式化。
单行忽略
-- stylua: ignore
local matrix = {
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
}
块级忽略
local foo = true
-- stylua: ignore start
local bar = false
local baz = 0
-- stylua: ignore end
local foobar = false
-- stylua: ignore start和-- stylua: ignore end之间的代码不会被格式化,但不能跨越作用域边界。