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 的 ConfigurationOptions 章节。

选项 默认值 说明
syntax "All" Lua 语法变体:AllLua51Lua52Lua53Lua54LuaJITLuauCfxLua
column_width 120 近似行宽限制(非硬性要求)
line_endings "Unix" 换行符风格:Unix(LF)或 Windows(CRLF)
indent_type "Tabs" 缩进类型:TabsSpaces
indent_width 4 缩进宽度(当 indent_typeTabs 时仅作为列宽启发值)
quote_style "AutoPreferDouble" 引号风格:AutoPreferDoubleAutoPreferSingleForceDoubleForceSingle
call_parentheses "Always" 函数调用括号:AlwaysNoSingleStringNoSingleTableNoneInput
space_after_function_names "Never" 函数名与括号间空格:NeverDefinitionsCallsAlways
collapse_simple_statement "Never" 简单语句折叠:NeverFunctionOnlyConditionalOnlyAlways
block_newline_gaps "Never" 是否保留块首尾空行:NeverPreserve

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 时作为格式化参数来源

配置文件查找顺序(从被格式化文件所在目录开始向上搜索):

  1. stylua.toml
  2. .stylua.toml
  3. .editorconfig(如果未找到 stylua.toml
  4. 内置默认配置

可通过 --config-path <path> 显式指定配置文件路径,或使用 --search-parent-directories 向上递归搜索。

4.2 stylua.toml 配置详解

stylua.toml 是 StyLua 的主配置文件,用于控制 Lua 代码格式化行为。

配置项说明

配置项 类型 说明
syntax string 语法变体(LuaLua5.2LuauAll),默认 All
column_width int 最大列宽(默认 120)
line_endings string 换行符风格(UnixWindows
indent_type string 缩进类型(TabsSpaces
indent_width int 缩进宽度(indent_type = "Spaces" 时为空格数,Tabs 时为 tab 显示宽度)
quote_style string 引号风格(AutoPreferDoubleAutoPreferSingleForceDoubleForceSingle
call_parentheses string 函数调用括号(AlwaysNoSingleTableNoTablesNone
collapse_simple_statement string 简单语句折叠(AlwaysFunctionOnlyConditionalOnlyNever
space_after_function_names string 函数名后空格(AlwaysOnlyStringOnlyTablesNever
block_newline_gaps string 块间空行(AlwaysInnerOuterNever
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 统一差异格式,可用于 patchdelta
--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-hooks.yaml

.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 通过代码注释屏蔽

官方文档:Ignoring parts of a file

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 之间的代码不会被格式化,但不能跨越作用域边界。