Lua 是一個輕量級腳本語言,1993 年在巴西開發,名字是葡萄牙語的「月亮」。整個直譯器約 300KB,設計目標是嵌入到其他程式當配置和擴展語言,不是當獨立的通用語言。

Hyprland(v0.55+ 的配置格式)、Neovim(整個 plugin 和配置生態)、WezTerm(terminal emulator 配置)都用 Lua 作為配置語言。在 dotfile 管理的脈絡裡,Lua 是讀懂和寫好這些工具配置的前提知識。

配置檔用到的核心語法

變數和型別

1local name = "hello"       -- 字串
2local count = 42            -- 數字
3local enabled = true        -- 布林
4local nothing = nil         -- 空值(類似其他語言的 null)

local 宣告區域變數。沒有 local 的變數是全域的,配置檔裡幾乎都該用 local

Table:唯一的複合資料結構

Lua 只有一種複合型別——table,同時當 array 和 dictionary 用:

 1-- 當 array(index 從 1 開始,不是 0)
 2local fruits = { "apple", "banana", "cherry" }
 3print(fruits[1])  -- "apple"
 4
 5-- 當 dictionary
 6local config = {
 7    gaps_in = 5,
 8    border_size = 2,
 9    layout = "dwindle",
10}
11print(config.gaps_in)  -- 5
12
13-- 巢狀 table(配置檔最常見的形式)
14local decoration = {
15    rounding = 8,
16    blur = {
17        enabled = true,
18        size = 5,
19        passes = 2,
20    },
21}

Hyprland 的 hl.config() 接收的就是一個巢狀 table:

1hl.config({
2    general = {
3        gaps_in = 5,
4        gaps_out = 10,
5    },
6    decoration = {
7        rounding = 8,
8    },
9})

Function

1local function greet(who)
2    return "hello " .. who   -- .. 是字串串接
3end
4
5-- 匿名 function(Neovim 配置常見)
6vim.keymap.set("n", "<leader>f", function()
7    require("telescope.builtin").find_files()
8end)

條件判斷

1if hostname == "work-laptop" then
2    -- 工作機設定
3elseif hostname == "home-desktop" then
4    -- 家裡桌機設定
5else
6    -- 預設
7end

只有 nilfalse 是 falsy。0"" 是 truthy(跟 Python 不同)。

迴圈

 1-- 數字 for(Hyprland 批次產生 workspace keybind)
 2for i = 1, 9 do
 3    hl.bind("SUPER", tostring(i), "workspace", tostring(i))
 4end
 5
 6-- 遍歷 table
 7local tools = { "zsh", "git", "nvim", "tmux" }
 8for _, tool in ipairs(tools) do
 9    print(tool)
10end

模組化(require)

1-- hyprland.lua 裡載入同目錄的其他 .lua 檔
2require("keybinds")     -- 載入 keybinds.lua
3require("rules")        -- 載入 rules.lua
4require("appearance")   -- 載入 appearance.lua

require() 是 Lua 原生的模組載入,取代了舊 Hyprland .conf 格式的 source = ... 指令。

為什麼配置工具選 Lua

Lua 被嵌入到配置層的原因是一組特定的 trade-off:

  • 比 JSON/TOML/YAML 強:有變數、迴圈、條件判斷。配置檔可以用 for 產生重複項目、用 if 處理機器差異,不需要外部 template engine
  • 比 Python/JavaScript 輕:300KB 的直譯器可以嵌入 C/C++ 程式,不需要拖一個完整的 runtime
  • 沙盒化容易:宿主程式可以控制 Lua 能存取哪些 API,限制配置檔的能力範圍

這也是 Neovim 從 VimScript 遷移到 Lua 的理由——plugin 生態需要一個真正的程式語言(有資料結構、有錯誤處理),但又不能讓配置檔變成一個安全隱患。

其他使用 Lua 的場景

場景用法
Neovim整個配置和 plugin 生態基於 Lua
WezTermterminal emulator 配置(wezterm.lua
Awesome WMX11 tiling WM 的配置和擴展
RedisEVAL 指令在 server 端執行 Lua script
Nginx/OpenResty用 Lua 寫高效能的 request 處理邏輯
遊戲World of Warcraft UI mod、Roblox、很多遊戲引擎的腳本層

共同模式:一個用 C/C++ 寫的高效能核心,把 Lua 嵌入進去當配置和擴展語言。

跟 Python/JavaScript 的差異速查

項目LuaPythonJavaScript
Array index 起始100
字串串接..++
不等於~=!=!==
邏輯運算and or notand or not&& || !
空值nilNonenull/undefined
Falsy 值nil, falseNone, False, 0, "", []null, undefined, false, 0, ""
沒有 +=x = x + 1x += 1x += 1
註解--#//
多行註解--[[ ... ]]""" ... """/* ... */

寫 Hyprland 或 Neovim 配置用到的 Lua 知識量很小——主要是 table(配置結構)、for loop(批次 keybind)、if-else(機器差異)、require(模組拆分)。不需要學 metatable、coroutine、metatmethod 這些進階功能。