lua-projects

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Lua Projects

Lua 项目

Scope: Lua 5.4 (with LuaJIT notes where relevant). Targets config-driven projects like Neovim distributions, SketchyBar setups, and general Lua modules.
适用范围:Lua 5.4(相关LuaJIT说明会单独标注)。面向配置驱动型项目,如Neovim发行版、SketchyBar配置及通用Lua模块。

Style and Formatting

编码风格与格式化

Naming

命名规范

  • snake_case
    for variables, functions, and file names
  • PascalCase
    only for class-like constructor tables (rare)
  • UPPER_SNAKE
    for true constants
  • Prefix unused variables with
    _
    (e.g.,
    for _, v in ipairs(t)
    )
  • 变量、函数及文件名使用
    snake_case
    命名法
  • 仅类构造器表使用
    PascalCase
    命名法(少见场景)
  • 真正的常量使用
    UPPER_SNAKE
    命名法
  • 未使用的变量前缀加
    _
    (例如:
    for _, v in ipairs(t)

Indentation and Layout

缩进与布局

  • Use 2 spaces (common in Neovim/LazyVim ecosystem) or tabs (SketchyBar default) -- be consistent within a project
  • Wrap lines at 100 characters; hard limit 120
  • Trailing commas in multi-line tables are encouraged
  • No spaces inside
    {}
    ,
    ()
    , or
    []
    ; spaces after commas and around operators
  • 使用2个空格(Neovim/LazyVim生态通用)或制表符(SketchyBar默认)——同一项目内保持一致
  • 行宽限制为100字符,硬上限120字符
  • 多行表中建议使用 trailing commas
  • {}
    ()
    []
    内部不添加空格;逗号后及运算符两侧需添加空格

Formatter: StyLua

格式化工具:StyLua

StyLua (v2.4+) is the standard Lua formatter. Configure via
stylua.toml
at the project root:
toml
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
For SketchyBar configs using tabs:
toml
indent_type = "Tabs"
Run:
stylua .
or integrate as a pre-commit hook / editor format-on-save.
StyLua(v2.4+)是标准的Lua格式化工具。在项目根目录通过
stylua.toml
配置:
toml
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
对于使用制表符的SketchyBar配置:
toml
indent_type = "Tabs"
运行命令:
stylua .
或集成到pre-commit钩子/编辑器自动格式化功能中。

Linting

代码检查

Selene (recommended)

Selene(推荐)

Modern Lua linter written in Rust. Actively maintained (v0.30+). Provides rich diagnostics with named lint rules.
Config file
selene.toml
:
toml
std = "lua54"
For Neovim configs, use the
vim
standard library definition so globals like
vim
are recognized:
toml
std = "lua54+vim"
Run:
selene .
基于Rust开发的现代Lua代码检查工具,维护活跃(v0.30+),提供带有命名规则的丰富诊断信息。
配置文件
selene.toml
toml
std = "lua54"
对于Neovim配置,使用
vim
标准库定义,以便识别
vim
等全局变量:
toml
std = "lua54+vim"
运行命令:
selene .

Luacheck (legacy)

Luacheck(遗留工具)

Still detects some things Selene does not (uninitialized vars, unreachable code), but has been unmaintained since 2018. Use as a secondary pass if needed.
Config file
.luacheckrc
:
lua
std = "lua54"
globals = { "vim" }
仍能检测部分Selene未覆盖的问题(如未初始化变量、不可达代码),但自2018年起未再维护。必要时可作为二次检查工具。
配置文件
.luacheckrc
lua
std = "lua54"
globals = { "vim" }

Language Server: LuaLS

语言服务器:LuaLS

lua-language-server (
LuaLS
) provides diagnostics, completion, hover, and type checking.
Settings file
.luarc.json
at project root:
json
{
  "runtime": { "version": "Lua 5.4" },
  "diagnostics": { "globals": ["vim"] },
  "workspace": {
    "library": [],
    "checkThirdParty": false
  }
}
For SketchyBar projects, add the SbarLua install path to
workspace.library
so LuaLS resolves the
sketchybar
module:
json
"workspace": {
  "library": ["~/.local/share/sketchybar_lua"]
}
lua-language-server(
LuaLS
)提供诊断、自动补全、悬停提示及类型检查功能。
在项目根目录创建配置文件
.luarc.json
json
{
  "runtime": { "version": "Lua 5.4" },
  "diagnostics": { "globals": ["vim"] },
  "workspace": {
    "library": [],
    "checkThirdParty": false
  }
}
对于SketchyBar项目,将SbarLua安装路径添加到
workspace.library
,以便LuaLS解析
sketchybar
模块:
json
"workspace": {
  "library": ["~/.local/share/sketchybar_lua"]
}

Type Annotations

类型注解

LuaLS supports EmmyLua-style annotations. Use them for public API surfaces:
lua
---@param name string
---@param opts? { padding?: number, icon?: string }
---@return table item
local function add_item(name, opts)
  -- ...
end
LuaLS支持EmmyLua风格的类型注解,建议在公共API表面使用:
lua
---@param name string
---@param opts? { padding?: number, icon?: string }
---@return table item
local function add_item(name, opts)
  -- ...
end

Module Patterns

模块模式

The Return-Table Pattern

返回表模式

Every module file should
return
a table (or a single value). Avoid polluting globals.
lua
local M = {}

function M.greet(name)
  return "hello " .. name
end

return M
每个模块文件应
return
一个表(或单个值),避免污染全局命名空间。
lua
local M = {}

function M.greet(name)
  return "hello " .. name
end

return M

Init Modules

初始化模块

A directory with an
init.lua
is requireable by its directory name. Use
init.lua
to re-export or orchestrate sub-modules:
items/
  init.lua      -- require("items") loads this
  apple.lua
  calendar.lua
lua
-- items/init.lua
require("items.apple")
require("items.calendar")
包含
init.lua
的目录可通过目录名直接引用。使用
init.lua
重新导出或协调子模块:
items/
  init.lua      -- require("items") 会加载此文件
  apple.lua
  calendar.lua
lua
-- items/init.lua
require("items.apple")
require("items.calendar")

Avoid Globals

避免全局变量

lua
-- BAD: implicit global
sbar = require("sketchybar")

-- GOOD: local binding (use upvalues or pass explicitly)
local sbar = require("sketchybar")
Exception: SketchyBar's example config sets
sbar
as a global in
init.lua
because sub-modules reference it without an explicit require path. If following that convention, document it clearly and configure your linter to allow it:
toml
undefined
lua
-- 不良实践:隐式全局变量
sbar = require("sketchybar")

-- 良好实践:局部绑定(使用upvalue或显式传递)
local sbar = require("sketchybar")
例外情况:SketchyBar示例配置在
init.lua
中设置
sbar
为全局变量,因为子模块无需显式引用路径即可访问它。若遵循此约定,需清晰文档说明,并配置代码检查工具允许该全局变量:
toml
undefined

selene.toml

selene.toml

[lints] global_usage = "allow"
undefined
[lints] global_usage = "allow"
undefined

Project Structure Patterns

项目结构模式

Neovim Config (LazyVim / lazy.nvim)

Neovim 配置(LazyVim / lazy.nvim)

~/.config/nvim/
  init.lua                -- minimal bootstrap: vim.loader.enable(), require("config.lazy")
  lua/
    config/
      lazy.lua            -- lazy.nvim bootstrap and setup
      options.lua
      keymaps.lua
      autocmds.lua
    plugins/
      lsp.lua
      treesitter.lua
      ui.lua
      editor.lua
Key conventions:
  • init.lua
    stays minimal -- call
    vim.loader.enable()
    then require config
  • One plugin spec per file (or group related specs) in
    lua/plugins/
  • lazy.nvim auto-loads everything in
    lua/plugins/
  • Use
    opts
    table merging over
    config
    functions when possible
Plugin spec pattern:
lua
return {
  "author/plugin.nvim",
  event = "VeryLazy",
  dependencies = { "nvim-lua/plenary.nvim" },
  opts = {
    setting = true,
  },
  keys = {
    { "<leader>x", "<cmd>PluginAction<cr>", desc = "Do thing" },
  },
}
~/.config/nvim/
  init.lua                -- 最小化启动脚本:vim.loader.enable(), require("config.lazy")
  lua/
    config/
      lazy.lua            -- lazy.nvim 启动与设置
      options.lua
      keymaps.lua
      autocmds.lua
    plugins/
      lsp.lua
      treesitter.lua
      ui.lua
      editor.lua
核心约定:
  • init.lua
    保持极简——调用
    vim.loader.enable()
    后加载配置
  • lua/plugins/
    目录下每个文件对应一个插件配置(或一组相关插件)
  • lazy.nvim 自动加载
    lua/plugins/
    下的所有内容
  • 优先使用
    opts
    表合并而非
    config
    函数
插件配置示例:
lua
return {
  "author/plugin.nvim",
  event = "VeryLazy",
  dependencies = { "nvim-lua/plenary.nvim" },
  opts = {
    setting = true,
  },
  keys = {
    { "<leader>x", "<cmd>PluginAction<cr>", desc = "执行操作" },
  },
}

SketchyBar Config (SbarLua)

SketchyBar 配置(SbarLua)

~/.config/sketchybar/
  sketchybarrc              -- shell entry: sketchybar --config init.lua (or similar)
  init.lua                  -- requires sbar, wraps in begin_config/end_config, runs event_loop
  bar.lua                   -- bar-level properties
  default.lua               -- default item properties
  colors.lua                -- color palette table
  icons.lua                 -- icon constants (SF Symbols / Nerd Font)
  settings.lua              -- shared settings (paddings, fonts)
  items/
    init.lua                -- requires each item module
    spaces.lua
    front_app.lua
    media.lua
    ...
  helpers/
    init.lua
    app_icons.lua
    default_font.lua
    event_providers/        -- native helpers (C compiled)
Key conventions:
  • Wrap all setup between
    sbar.begin_config()
    /
    sbar.end_config()
    for batching
  • Always call
    sbar.event_loop()
    at the end of
    init.lua
  • Use
    sbar.exec()
    instead of
    os.execute()
    to avoid blocking the event handler
  • Properties use sub-tables instead of dot notation:
    icon = { y_offset = 10 }
    not
    icon.y_offset
  • Color values are
    0xAARRGGBB
    hex integers
  • Keep color/icon/settings as pure data modules that return a table
~/.config/sketchybar/
  sketchybarrc              -- Shell入口:sketchybar --config init.lua(或类似命令)
  init.lua                  -- 引入sbar,包裹在begin_config/end_config中,运行事件循环
  bar.lua                   -- 状态栏级属性配置
  default.lua               -- 项目默认属性配置
  colors.lua                -- 调色板表
  icons.lua                 -- 图标常量(SF Symbols / Nerd Font)
  settings.lua              -- 共享设置(内边距、字体)
  items/
    init.lua                -- 引入各个项目模块
    spaces.lua
    front_app.lua
    media.lua
    ...
  helpers/
    init.lua
    app_icons.lua
    default_font.lua
    event_providers/        -- 原生辅助工具(C语言编译)
核心约定:
  • 所有配置代码包裹在
    sbar.begin_config()
    /
    sbar.end_config()
    之间以批量执行
  • init.lua
    末尾必须调用
    sbar.event_loop()
  • 使用
    sbar.exec()
    替代
    os.execute()
    以避免阻塞事件处理器
  • 属性使用子表而非点语法:
    icon = { y_offset = 10 }
    而非
    icon.y_offset
  • 颜色值使用
    0xAARRGGBB
    十六进制整数
  • 将颜色/图标/设置作为纯数据模块,仅返回表

Common Patterns

通用模式

Safe Require

安全引入模块

lua
local ok, mod = pcall(require, "optional_module")
if not ok then
  return
end
lua
local ok, mod = pcall(require, "optional_module")
if not ok then
  return
end

Metatables for OOP-ish Tables

面向对象风格的元表

lua
local Item = {}
Item.__index = Item

function Item.new(name)
  return setmetatable({ name = name }, Item)
end

function Item:display()
  return self.name
end
lua
local Item = {}
Item.__index = Item

function Item.new(name)
  return setmetatable({ name = name }, Item)
end

function Item:display()
  return self.name
end

Config Merging

配置合并

lua
local defaults = { padding = 4, color = 0xffffffff }

local function apply(user_opts)
  local cfg = {}
  for k, v in pairs(defaults) do cfg[k] = v end
  for k, v in pairs(user_opts or {}) do cfg[k] = v end
  return cfg
end
For deep merging in Neovim:
vim.tbl_deep_extend("force", defaults, user_opts)
.
lua
local defaults = { padding = 4, color = 0xffffffff }

local function apply(user_opts)
  local cfg = {}
  for k, v in pairs(defaults) do cfg[k] = v end
  for k, v in pairs(user_opts or {}) do cfg[k] = v end
  return cfg
end
在Neovim中进行深度合并:
vim.tbl_deep_extend("force", defaults, user_opts)

Testing

测试

Busted

Busted

The standard Lua test framework. Install via luarocks:
bash
luarocks install busted
lua
-- spec/greet_spec.lua
describe("greet", function()
  local mod = require("mymod")

  it("returns greeting", function()
    assert.are.equal("hello world", mod.greet("world"))
  end)

  it("handles nil", function()
    assert.has_error(function() mod.greet(nil) end)
  end)
end)
Run:
busted
or
busted spec/
标准Lua测试框架,通过luarocks安装:
bash
luarocks install busted
lua
-- spec/greet_spec.lua
describe("greet", function()
  local mod = require("mymod")

  it("返回问候语", function()
    assert.are.equal("hello world", mod.greet("world"))
  end)

  it("处理nil参数", function()
    assert.has_error(function() mod.greet(nil) end)
  end)
end)
运行命令:
busted
busted spec/

Neovim Plugin Testing

Neovim 插件测试

Use
plenary.nvim
's test harness for Neovim-specific tests:
bash
nvim --headless -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua'}"
使用
plenary.nvim
的测试框架进行Neovim专属测试:
bash
nvim --headless -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua'}"

Performance Notes

性能优化提示

  • local
    lookups are register-based; global lookups go through
    _ENV
    hash. Always localize hot-path references.
  • Pre-size tables with known lengths:
    local t = table.create and table.create(n) or {}
  • String concatenation in loops: accumulate in a table and
    table.concat()
    at the end
  • Prefer
    ipairs
    over
    pairs
    when iterating sequential arrays (faster and order-guaranteed)
  • In LuaJIT (Neovim): avoid NYI (Not Yet Implemented) operations in tight loops -- check https://wiki.luajit.org/NYI
  • local
    变量查找基于寄存器;全局变量查找需遍历
    _ENV
    哈希表。热路径中的引用始终使用局部变量。
  • 已知长度的表提前预分配:
    local t = table.create and table.create(n) or {}
  • 循环中的字符串拼接:先将内容存入表,最后使用
    table.concat()
    合并
  • 遍历顺序数组时优先使用
    ipairs
    而非
    pairs
    (速度更快且保证顺序)
  • 在LuaJIT(Neovim)中:避免在密集循环中使用NYI(尚未实现)操作——参考https://wiki.luajit.org/NYI

Lua 5.4 Specifics

Lua 5.4 专属特性

Features available in 5.4 that older references may not cover:
  • Integer subtype: integers and floats are distinct;
    type(1)
    is
    "number"
    but
    math.type(1)
    is
    "integer"
  • Bitwise operators:
    &
    ,
    |
    ,
    ~
    (xor),
    ~
    (unary not),
    <<
    ,
    >>
    -- no need for
    bit32
    or
    bit
    libraries
  • Integer for-loop:
    for i = 1, n
    uses native integers
  • Generational GC:
    collectgarbage("generational")
    for lower-latency collection
  • <const>
    and
    <close>
    : local attributes for immutability and deterministic cleanup
lua
local path <const> = "/tmp/data"
local f <close> = io.open(path, "r")
Note: Neovim uses LuaJIT (Lua 5.1 compatible), so 5.4 features are not available in Neovim configs. Use 5.4 features only in standalone Lua or SketchyBar (if built against Lua 5.4).
5.4版本新增的特性,旧版参考文档可能未覆盖:
  • 整数子类型:整数与浮点数是不同类型;
    type(1)
    返回
    "number"
    math.type(1)
    返回
    "integer"
  • 位运算符
    &
    |
    ~
    (异或)、
    ~
    (一元非)、
    <<
    >>
    ——无需使用
    bit32
    bit
  • 整数for循环
    for i = 1, n
    使用原生整数
  • 分代垃圾回收
    collectgarbage("generational")
    实现低延迟回收
  • <const>
    <close>
    :局部变量属性,用于不可变性和确定性清理
lua
local path <const> = "/tmp/data"
local f <close> = io.open(path, "r")
注意:Neovim使用LuaJIT(兼容Lua 5.1),因此Neovim配置中无法使用5.4特性。仅在独立Lua环境或基于Lua 5.4构建的SketchyBar中使用5.4特性。

Debugging

调试

  • print(vim.inspect(t))
    in Neovim for table inspection
  • print(require("inspect")(t))
    in standalone Lua (install via luarocks)
  • SketchyBar logs to
    ~/.local/share/sketchybar/
    -- check there for Lua errors
  • LuaLS diagnostics surface most type/require errors before runtime
  • Neovim中使用
    print(vim.inspect(t))
    查看表结构
  • 独立Lua环境中使用
    print(require("inspect")(t))
    (需通过luarocks安装inspect)
  • SketchyBar日志存储于
    ~/.local/share/sketchybar/
    ——可在此查看Lua错误
  • LuaLS诊断可在运行前发现大多数类型/依赖错误

Tooling Summary

工具链汇总

ToolPurposeConfig FileInstall
StyLuaFormatter
stylua.toml
cargo install stylua
or npm
SeleneLinter
selene.toml
cargo install selene
LuaLSLanguage server
.luarc.json
via Mason or package manager
BustedTest framework
.busted
luarocks install busted
LuarocksPackage manager
*.rockspec
system package manager
工具用途配置文件安装方式
StyLua代码格式化
stylua.toml
cargo install stylua
或 npm
Selene代码检查
selene.toml
cargo install selene
LuaLS语言服务器
.luarc.json
通过Mason或包管理器安装
Busted测试框架
.busted
luarocks install busted
Luarocks包管理器
*.rockspec
系统包管理器

Reference Projects

参考项目

ProjectURLFocus
LazyVimhttps://github.com/LazyVim/LazyVimNeovim distribution, plugin orchestration
lazy.nvimhttps://github.com/folke/lazy.nvimPlugin manager, spec system
SbarLuahttps://github.com/FelixKratz/SbarLuaSketchyBar Lua bindings
SketchyBarhttps://github.com/FelixKratz/SketchyBarmacOS bar, config examples
nvim-lspconfighttps://github.com/neovim/nvim-lspconfigLSP client configs
plenary.nvimhttps://github.com/nvim-lua/plenary.nvimNeovim Lua utilities and test harness
telescope.nvimhttps://github.com/nvim-telescope/telescope.nvimFuzzy finder, well-structured plugin
项目链接关注点
LazyVimhttps://github.com/LazyVim/LazyVimNeovim发行版、插件编排
lazy.nvimhttps://github.com/folke/lazy.nvim插件管理器、配置规范系统
SbarLuahttps://github.com/FelixKratz/SbarLuaSketchyBar Lua绑定
SketchyBarhttps://github.com/FelixKratz/SketchyBarmacOS状态栏、配置示例
nvim-lspconfighttps://github.com/neovim/nvim-lspconfigLSP客户端配置
plenary.nvimhttps://github.com/nvim-lua/plenary.nvimNeovim Lua工具库与测试框架
telescope.nvimhttps://github.com/nvim-telescope/telescope.nvim模糊查找器、结构良好的插件示例

Additional Resources

额外资源