10 - Lua 配置与 API
“Lua is not just an alternative to VimScript — it’s Neovim’s superpower.”
10.1 为什么用 Lua
10.1.1 Lua vs VimScript
| 维度 | VimScript | Lua |
|---|
| 性能 | 较慢 | LuaJIT(极快) |
| 语法 | 独特、老旧 | 简洁、现代 |
| 数据结构 | list/dict | table(统一) |
| 异步 | 有限 | libuv 全面支持 |
| 调试 | 困难 | 标准工具链 |
| 生态 | 插件为主 | 代码为主 |
| 学习资源 | 丰富 | 快速增长 |
10.1.2 在 Neovim 中使用 Lua
" VimScript 中调用 Lua
lua print("Hello from Lua")
lua require("my_module")
lua << EOF
local msg = "Hello"
print(msg)
EOF
" Lua 代码中调用 Vim 命令
lua vim.cmd("echo 'hi'")
lua vim.cmd([[set number]])
10.2 init.lua 入口
10.2.1 基本结构
-- ~/.config/nvim/init.lua
-- 设置 Leader 键(必须在插件加载前)
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"
-- 加载配置模块
require("config.options")
require("config.keymaps")
require("config.autocmds")
-- 加载插件(lazy.nvim)
require("config.lazy")
10.2.2 模块化结构
~/.config/nvim/
├── init.lua
├── lua/
│ ├── config/
│ │ ├── options.lua -- 选项设置
│ │ ├── keymaps.lua -- 快捷键
│ │ ├── autocmds.lua -- 自动命令
│ │ └── lazy.lua -- lazy.nvim 配置
│ ├── plugins/
│ │ ├── colorscheme.lua
│ │ ├── editor.lua
│ │ ├── lsp.lua
│ │ └── ui.lua
│ └── utils/
│ └── helpers.lua
10.3 vim.opt — 选项设置
local opt = vim.opt
-- 行号
opt.number = true
opt.relativenumber = true
-- 缩进
opt.tabstop = 4
opt.shiftwidth = 4
opt.expandtab = true
opt.smartindent = true
-- 搜索
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = true
opt.incsearch = true
-- 外观
opt.termguicolors = true
opt.signcolumn = "yes"
opt.cursorline = true
opt.scrolloff = 8
opt.wrap = false
opt.showmode = false
-- 分割窗口
opt.splitbelow = true
opt.splitright = true
-- 性能
opt.updatetime = 250
opt.timeoutlen = 300
-- 文件
opt.swapfile = false
opt.backup = false
opt.undofile = true
opt.clipboard = "unnamedplus"
-- 补全
opt.completeopt = { "menu", "menuone", "noselect" }
opt.pumheight = 10
10.4 vim.keymap.set — 快捷键
10.4.1 基本用法
local map = vim.keymap.set
-- 普通模式
map("n", "<leader>w", "<cmd>w<CR>", { desc = "保存文件" })
map("n", "<leader>q", "<cmd>q<CR>", { desc = "退出" })
-- 插入模式
map("i", "jk", "<Esc>", { desc = "退出插入模式" })
-- 可视模式
map("v", "<", "<gv", { desc = "缩进后保持选中" })
map("v", ">", ">gv", { desc = "反缩进后保持选中" })
-- 命令模式
map("c", "<C-a>", "<Home>", { desc = "跳到行首" })
map("c", "<C-e>", "<End>", { desc = "跳到行尾" })
10.4.2 选项
map("n", "<leader>f", function()
vim.lsp.buf.format()
end, {
desc = "格式化文件", -- 描述(用于 which-key 等)
silent = true, -- 不显示命令
noremap = true, -- 非递归
nowait = true, -- 不等待后续按键
buffer = true, -- 仅当前缓冲区
expr = false, -- 是否表达式映射
})
10.4.3 Lua 函数映射
-- 直接使用 Lua 函数
map("n", "<leader>ff", function()
require("telescope.builtin").find_files()
end, { desc = "查找文件" })
-- 带参数的函数
map("n", "<leader>g", function()
local word = vim.fn.expand("<cword>")
vim.cmd("vimgrep " .. word .. " **/*")
end, { desc = "搜索单词" })
10.5 vim.api — 核心 API
10.5.1 常用 API
-- 获取当前行
local line = vim.api.nvim_get_current_line()
-- 设置当前行
vim.api.nvim_set_current_line("new content")
-- 获取光标位置 (0-indexed)
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
-- 设置光标位置
vim.api.nvim_win_set_cursor(0, {1, 0}) -- 第1行,第0列
-- 获取缓冲区行数
local line_count = vim.api.nvim_buf_line_count(0)
-- 获取缓冲区内容
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
-- 设置缓冲区内容
vim.api.nvim_buf_set_lines(0, 0, -1, false, {"line1", "line2"})
-- 获取当前缓冲区号
local buf = vim.api.nvim_get_current_buf()
-- 创建缓冲区
local buf = vim.api.nvim_create_buf(true, true) -- 列入缓冲区列表, 可修改
-- 删除缓冲区
vim.api.nvim_buf_delete(buf, { force = true })
10.5.2 窗口 API
-- 获取当前窗口
local win = vim.api.nvim_get_current_win()
-- 创建浮动窗口
local buf = vim.api.nvim_create_buf(false, true)
local win = vim.api.nvim_open_win(buf, true, {
relative = "editor",
width = 60,
height = 20,
row = 5,
col = 10,
style = "minimal",
border = "rounded",
})
-- 关闭窗口
vim.api.nvim_win_close(win, true)
10.5.3 选项 API
-- 获取选项
local ts = vim.api.nvim_get_option_value("tabstop", {})
-- 设置选项
vim.api.nvim_set_option_value("tabstop", 2, {})
-- 缓冲区局部选项
vim.api.nvim_set_option_value("shiftwidth", 2, { buf = 0 })
10.5.4 高亮 API
-- 创建高亮组
vim.api.nvim_set_hl(0, "MyHighlight", {
fg = "#ff0000",
bg = "#000000",
bold = true,
italic = true,
})
-- 获取高亮
local hl = vim.api.nvim_get_hl(0, { name = "Normal" })
10.6 vim.fn — Vim 函数
-- 调用 Vim 内置函数
local home = vim.fn.expand("~")
local files = vim.fn.glob("**/*.lua")
local file = vim.fn.expand("%:p")
local line_num = vim.fn.line(".")
local col_num = vim.fn.col(".")
local word = vim.fn.expand("<cword>")
-- 系统命令
local result = vim.fn.system("git status")
local branch = vim.fn.system("git branch --show-current"):gsub("\n", "")
-- 用户输入
local input = vim.fn.input("Enter value: ")
local choice = vim.fn.confirm("Continue?", "&Yes\n&No", 1)
-- 文件操作
vim.fn.mkdir(vim.fn.fnamemodify(file, ":h"), "p")
vim.fn.writefile({"line1", "line2"}, "/tmp/output.txt")
10.7 vim.cmd — Ex 命令
-- 单条命令
vim.cmd("echo 'Hello'")
vim.cmd("set number")
vim.cmd("colorscheme gruvbox")
-- 多行命令块
vim.cmd([[
highlight MyGroup guifg=#ff0000
autocmd BufWritePre * %s/\s\+$//e
]])
-- 带变量的命令
vim.cmd("colorscheme " .. colorscheme_name)
10.8 自动命令(Lua 方式)
-- 创建自动命令
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*.py",
callback = function()
vim.cmd("%s/\\s\\+$//e")
end,
desc = "保存时去除尾部空格",
})
-- 创建自动命令组
local group = vim.api.nvim_create_augroup("MyGroup", { clear = true })
vim.api.nvim_create_autocmd("FileType", {
group = group,
pattern = { "python", "javascript" },
callback = function()
vim.opt_local.tabstop = 2
vim.opt_local.shiftwidth = 2
end,
desc = "设置 Python/JS 缩进",
})
vim.api.nvim_create_autocmd("TextYankPost", {
group = group,
callback = function()
vim.highlight.on_yank({ higroup = "IncSearch", timeout = 500 })
end,
desc = "高亮复制的文本",
})
10.9 用户命令
-- 创建用户命令
vim.api.nvim_create_user_command("Greet", function(opts)
print("Hello, " .. opts.args .. "!")
end, {
nargs = 1,
desc = "打招呼",
})
-- 带补全的命令
vim.api.nvim_create_user_command("SetColor", function(opts)
vim.cmd("colorscheme " .. opts.args)
end, {
nargs = 1,
complete = function()
return { "gruvbox", "catppuccin", "tokyonight", "dracula" }
end,
desc = "设置颜色主题",
})
-- 调用
" :Greet World
" :SetColor catppuccin
10.10 Neovim 独有功能
10.10.1 虚拟文本(Virtual Text)
-- 在行末显示虚拟文本
local ns = vim.api.nvim_create_namespace("my_namespace")
vim.api.nvim_buf_set_extmark(0, ns, 0, -1, {
virt_text = {{"[info]", "Comment"}},
virt_text_pos = "eol",
})
10.10.2 浮动窗口
local function show_float(content)
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, content)
vim.api.nvim_open_win(buf, false, {
relative = "cursor",
width = 40,
height = #content,
row = 1,
col = 0,
style = "minimal",
border = "rounded",
focusable = false,
})
end
show_float({"Hello", "World", "From Float"})
10.10.3 vim.ui
-- 替换选择菜单
vim.ui.select({"Option A", "Option B", "Option C"}, {
prompt = "Choose:",
}, function(choice)
if choice then
print("Selected: " .. choice)
end
end)
-- 替换输入框
vim.ui.input({
prompt = "Enter value: ",
default = "default",
}, function(input)
if input then
print("Input: " .. input)
end
end)
10.10.4 绘图(Decorations)
-- 设置标记
local ns = vim.api.nvim_create_namespace("marks")
vim.api.nvim_buf_set_extmark(0, ns, 5, 0, {
sign_text = "➤",
sign_hl_group = "DiagnosticSignHint",
})
10.11 业务场景
| 场景 | Lua 方式 |
|---|
| 配置选项 | vim.opt.xxx = value |
| 键位映射 | vim.keymap.set(...) |
| 自动命令 | vim.api.nvim_create_autocmd(...) |
| 用户命令 | vim.api.nvim_create_user_command(...) |
| 浮动窗口 | vim.api.nvim_open_win(...) |
| 插件配置 | return { "plugin", opts = {...} } |
10.12 总结
| 模块 | 用途 |
|---|
vim.opt | 选项设置 |
vim.keymap | 快捷键映射 |
vim.api | Neovim 核心 API |
vim.fn | Vim 函数调用 |
vim.cmd | Ex 命令 |
vim.lsp | LSP 客户端 API |
vim.treesitter | Tree-sitter API |
vim.ui | UI 选择/输入 |
vim.diagnostic | 诊断 API |
下一步:第 11 章 - 插件管理 → 学习使用 lazy.nvim 管理 Neovim 插件生态。
扩展阅读