|
|
@ -6,11 +6,11 @@ |
|
|
|
|
|
|
|
## 目录 |
|
|
|
|
|
|
|
- [在 neovim 中使用 Lua](#在-neovim-中使用-lua) |
|
|
|
- [在 Neovim 中使用 Lua](#在-neovim-中使用-lua) |
|
|
|
- [目录](#目录) |
|
|
|
- [简介](#简介) |
|
|
|
- [学习 Lua](#学习-lua) |
|
|
|
- [现有的一些在 neovim 中使用 Lua 的教程](#现有的一些在-neovim-中使用-lua-的教程) |
|
|
|
- [现有的一些在 Neovim 中使用 Lua 的教程](#现有的一些在-neovim-中使用-lua-的教程) |
|
|
|
- [相关插件](#相关插件) |
|
|
|
- [Lua 文件位置](#lua-文件位置) |
|
|
|
- [警告](#警告) |
|
|
@ -59,21 +59,21 @@ |
|
|
|
|
|
|
|
## 简介 |
|
|
|
|
|
|
|
Lua 作为 Neovim 中的一等语言的集成正在成为它的杀手级特性之一。 然而,学习如何用 Lua 编写插件的教程数量并不像用 Vimscript 编写插件那样多。 这是一种尝试,试图提供一些基本信息,让人们可以使用 Lua 编写 neovim 插件。 |
|
|
|
本指南假定您使用的是最新的 Neovim[Nighly build](https://github.com/neovim/neovim/releases/tag/nightly)]。 由于 Neovim 的 0.5 版本是开发版本,请记住,正在积极开发的一些 API 并不十分稳定, |
|
|
|
在发布之前可能会发生变化。 |
|
|
|
Lua 作为 Neovim 中的一等语言的集成正在成为它的杀手级特性之一。然而,学习如何用 Lua 编写插件的教程数量并不像用 Vimscript 编写插件那样多。这是一种尝试,试图提供一些基本信息,让人们可以使用 Lua 编写 Neovim 插件。 |
|
|
|
|
|
|
|
本指南假定您使用的是最新的 Neovim [Nighly build](https://github.com/neovim/neovim/releases/tag/nightly)。由于 Neovim 的 0.5 版本是开发版本,请记住,正在积极开发的一些 API 并不十分稳定,在发布之前可能会发生变化。 |
|
|
|
|
|
|
|
### 学习 Lua |
|
|
|
|
|
|
|
不同于原版教程,一下资源适用于国内用户: |
|
|
|
不同于原版教程,以下资源适用于国内用户: |
|
|
|
- [在 Y 分钟内学习 X 关于 Lua 的页面](https://learnxinyminutes.com/docs/lua/) |
|
|
|
- [Lua 菜鸟教程](https://www.runoob.com/lua/lua-tutorial.html) |
|
|
|
- [Lua 用户维基](http://lua-users.org/wiki/LuaDirectory) |
|
|
|
- [Lua 的官方参考手册](https://www.lua.org/manual/5.1/) |
|
|
|
|
|
|
|
Lua 是一种非常干净和简单的语言。 它很容易学习,特别是如果你有其他编程语言基础的例如 typescript/javascript 等,会更加容易上手 Lua。注意:Neovim 嵌入的 Lua 版本是 LuaJIT 2.1.0,它与 Lua 5.1 保持兼容(带有几个 5.2 扩展) |
|
|
|
Lua 是一种非常干净和简单的语言。它很容易学习,特别是如果你有其他编程语言基础的例如 TypeScript / JavaScript 等,会更加容易上手 Lua。注意:Neovim 嵌入的 Lua 版本是 LuaJIT 2.1.0,它与 Lua 5.1 保持兼容(带有几个 5.2 扩展) |
|
|
|
|
|
|
|
### 现有的一些在 neovim 中使用 Lua 的教程 |
|
|
|
### 现有的一些在 Neovim 中使用 Lua 的教程 |
|
|
|
|
|
|
|
已经编写了一些教程来帮助人们用 Lua 编写插件。他们中的一些人在写这本指南时提供了不少的帮助。非常感谢它们的作者。 |
|
|
|
|
|
|
@ -123,7 +123,7 @@ require('myluamodule') |
|
|
|
|
|
|
|
注意没有 `.lua` 扩展名。 |
|
|
|
|
|
|
|
类似地,加载`ther_module/anthermodule e.lua`的过程如下: |
|
|
|
类似地,加载 `other_modules/anothermodule.lua` 的过程如下: |
|
|
|
|
|
|
|
```lua |
|
|
|
require('other_modules.anothermodule') |
|
|
@ -168,7 +168,7 @@ packadd! foo |
|
|
|
lua require('bar') |
|
|
|
``` |
|
|
|
|
|
|
|
在`Packadd`后附加`!`表示 Neovim 会将包放在`runtimepath`中,而不会在其`plugin`或`ftDetect`目录下寻找任何脚本。 |
|
|
|
在 `Packadd` 后附加 `!` 表示 Neovim 会将包放在 `runtimepath` 中,而不会在其 `plugin` 或 `ftDetect` 目录下寻找任何脚本。 |
|
|
|
|
|
|
|
See also: |
|
|
|
- `:help :packadd` |
|
|
@ -208,7 +208,7 @@ See also: |
|
|
|
|
|
|
|
#### 警告 |
|
|
|
|
|
|
|
在 vim 文件中编写 Lua 时,您不会得到正确的语法突出显示。 使用`:lua`命令作为需要外部 Lua 文件的入口点可能会更方便。 |
|
|
|
在 Vim 文件中编写 Lua 时,您不会得到正确的语法突出显示。使用 `:lua` 命令作为需要外部 Lua 文件的入口点可能会更方便。 |
|
|
|
|
|
|
|
### :luado |
|
|
|
|
|
|
@ -238,7 +238,7 @@ See also: |
|
|
|
:luafile ~/foo/bar/baz/myluafile.lua |
|
|
|
``` |
|
|
|
|
|
|
|
类似于 vim 的`:source`命令或 Lua 内置的`dofile()`函数。 |
|
|
|
类似于 Vim 的 `:source` 命令或 Lua 内置的 `dofile()` 函数。 |
|
|
|
|
|
|
|
See also: |
|
|
|
|
|
|
@ -251,13 +251,13 @@ See also: |
|
|
|
- `require()`: |
|
|
|
- 是内置的 Lua 函数,它允许你使用 Lua 的模块系统。 |
|
|
|
- 使用 `Package.path` 变量搜索模块(如前所述,您可以使用 `runtimepath` 中的 `lua/` 文件夹内的 `required()` lua 脚本) |
|
|
|
- 跟踪已加载的模块,并防止第二次解析和执行脚本。 如果您更改包含某个模块代码的文件,并在 Neovim 运行时再次尝试‘required()’,则该模块实际上不会更新。 |
|
|
|
- 跟踪已加载的模块,并防止第二次解析和执行脚本。如果您更改包含某个模块代码的文件,并在 Neovim 运行时再次尝试 `required()`,则该模块实际上不会更新。 |
|
|
|
- `:luafile`: |
|
|
|
- 是一个执行命令,它不支持模块。 |
|
|
|
- 采用相对于当前窗口的工作目录的绝对或相对路径 |
|
|
|
- 执行脚本的内容,而不管该脚本以前是否执行过 |
|
|
|
|
|
|
|
如果您想运行您正在处理的 Lua 文件,`:luafile`很有用: |
|
|
|
如果您想运行您正在处理的 Lua 文件,`:luafile` 很有用: |
|
|
|
|
|
|
|
```vim |
|
|
|
:luafile % |
|
|
@ -276,15 +276,15 @@ let concat = luaeval('"Lua".." is ".."awesome"') |
|
|
|
echo concat |
|
|
|
" 'Lua is awesome' |
|
|
|
|
|
|
|
" Lua 中的 table 数组转成成 vimscript 的 list |
|
|
|
" Lua 中的 table 数组转成成 Vimscript 的 list |
|
|
|
let list = luaeval('{1, 2, 3, 4}') |
|
|
|
echo list[0] |
|
|
|
" 1 |
|
|
|
echo list[1] |
|
|
|
" 2 |
|
|
|
" 注意 vimscript 的数组索引下标与 Lua 不同是从 0 开始的,Lua 中是从 1 开始 |
|
|
|
" 注意 Vimscript 的数组索引下标与 Lua 不同是从 0 开始的,Lua 中是从 1 开始 |
|
|
|
|
|
|
|
" Lua 中类似 dict 的 table 会被转成 vimscript 中的 dict |
|
|
|
" Lua 中类似 dict 的 table 会被转成 Vimscript 中的 dict |
|
|
|
let dict = luaeval('{foo = "bar", baz = "qux"}') |
|
|
|
echo dict.foo |
|
|
|
" 'bar' |
|
|
@ -391,18 +391,18 @@ echo map([1, 2, 3], v:lua.global_callback) |
|
|
|
|
|
|
|
## Vim 命名空间 |
|
|
|
|
|
|
|
Neovim 会暴露一个全局的`vim`变量来作为 lua 调用 vim 的 APIs 的入口。它还提供给用户一些额外的函数和子模块“标准库” |
|
|
|
Neovim 会暴露一个全局的 `vim` 变量来作为 Lua 调用 Vim 的 APIs 的入口。它还提供给用户一些额外的函数和子模块“标准库” |
|
|
|
|
|
|
|
一些比较实用的函数和子模块如下: |
|
|
|
|
|
|
|
- `vim.inspect`: 把 lua 对象以更易读的方式打印(在打印 lua table 是会很有用) |
|
|
|
- `vim.regex`: 在 lua 中使用 vim 寄存器 |
|
|
|
- `vim.inspect`: 把 Lua 对象以更易读的方式打印(在打印 Lua table 时会很有用) |
|
|
|
- `vim.regex`: 在 Lua 中使用 Vim 寄存器 |
|
|
|
- `vim.api`: 暴露 vim 的 API(`:h API`) 的模块(别的远程调用也是调用同样的 API) |
|
|
|
- `vim.loop`: Neovim 的 event lopp 模块(使用 LibUV) |
|
|
|
- `vim.lsp`: 控制内置 LSP 客户端的模块 |
|
|
|
- `vim.treesitter`: 暴露 tree-sitter 库中一些实用函数的模块 |
|
|
|
|
|
|
|
上面列举功能的并不全面。如果你想知道更多可行的操作可以看:`:help lua-stdlib`和`help lua-vim`。你也可以通过`:lua print(vim.inspect(vim))`所有可用模块 |
|
|
|
上面列举功能的并不全面。如果你想知道更多可行的操作可以看:`:help lua-stdlib` 和 `help lua-vim`。你也可以通过 `:lua print(vim.inspect(vim))` 获得所有可用模块 |
|
|
|
|
|
|
|
#### Tips |
|
|
|
|
|
|
@ -582,14 +582,14 @@ See also: |
|
|
|
**WARNING**:以下部分基于我做的几个实验。文档似乎没有提到这种行为,我也没有检查源代码来验证我的声明。 |
|
|
|
**TODO**:有谁能确认一下吗? |
|
|
|
|
|
|
|
如果您只使用`:set`命令处理过选项,那么某些选项的行为可能会让您大吃一惊。 |
|
|
|
如果您只使用 `:set` 命令处理过选项,那么某些选项的行为可能会让您大吃一惊。 |
|
|
|
本质上,选项可以是全局的、缓冲区 / 窗口的局部的,或者同时具有全局和局部值。 |
|
|
|
|
|
|
|
`:setglobal` 命令用于设置选项的全局值。 |
|
|
|
`:setlocal` 命令用于设置选项的本地值。 |
|
|
|
`:set` 命令用于设置选项的全局和局部值。 |
|
|
|
|
|
|
|
这是`:help:setglobal`的简易表格: |
|
|
|
这是 `:help :setglobal` 的简易表格: |
|
|
|
|
|
|
|
| Command | global value | local value | |
|
|
|
|-------------------------|--------------|-------------| |
|
|
@ -598,14 +598,14 @@ See also: |
|
|
|
| :setglobal option=value | set | - | |
|
|
|
|
|
|
|
Lua 中没有 `:set` 命令的等价命令,可以全局设置,也可以本地设置。 |
|
|
|
您可能认为`number‘选项是全局的,但文档将其描述为`Windows-local`。 这样的选项实际上是“粘性的”:当您打开一个新窗口时,它们的值是从当前窗口复制过来的。 |
|
|
|
您可能认为 `number` 选项是全局的,但文档将其描述为 `Windows-local`。这样的选项实际上是“粘性的”:当您打开一个新窗口时,它们的值是从当前窗口复制过来的。 |
|
|
|
因此,如果您要从您的 `init.lua` 设置选项,您应该这样做: |
|
|
|
|
|
|
|
```lua |
|
|
|
vim.wo.number = true |
|
|
|
``` |
|
|
|
|
|
|
|
`shiftwidth`、`expandtab`、`undofile`等`本地到缓冲区`的选项更容易混淆。 假设您的`init.lua`包含以下代码: |
|
|
|
`shiftwidth`、`expandtab`、`undofile` 等本地到缓冲区的选项更容易混淆。假设您的 `init.lua` 包含以下代码: |
|
|
|
|
|
|
|
```lua |
|
|
|
vim.bo.expandtab = true |
|
|
@ -659,8 +659,8 @@ See also: |
|
|
|
- `vim.api.nvim_set_vvar()` |
|
|
|
- `vim.api.nvim_get_vvar()` |
|
|
|
|
|
|
|
除了预定义的 Vim 变量外,还可以删除它们(等同于 vimscript 中的`:unlet`)。 局部变量 (`l:`)、脚本变量 (s:`) 和函数参数 (`a:`) 不能操作,因为它们只在 Vim 脚本上下文中有意义,Lua 有自己的作用域规则。 |
|
|
|
如果您不熟悉这些变量的作用,请参考`:help internal-variables`对其进行详细介绍。 |
|
|
|
除了预定义的 Vim 变量外,还可以删除它们(等同于 Vimscript 中的 `:unlet`)。局部变量 (`l:`)、脚本变量 (`s:`) 和函数参数 (`a:`) 不能操作,因为它们只在 Vim 脚本上下文中有意义,Lua 有自己的作用域规则。 |
|
|
|
如果您不熟悉这些变量的作用,请参考 `:help internal-variables` 对其进行详细介绍。 |
|
|
|
这些函数接受一个字符串,该字符串包含要设置 / 获取 / 删除的变量的名称以及要将其设置为的值。 |
|
|
|
|
|
|
|
```lua |
|
|
@ -776,11 +776,11 @@ See also: |
|
|
|
|
|
|
|
#### Tips |
|
|
|
|
|
|
|
Neovim 有一个强大的内置函数库,这些函数对插件非常有用。 按字母顺序排列的函数列表参见`:help vim-function`,按主题分组的函数列表参见`:help function-list`。 |
|
|
|
Neovim 有一个强大的内置函数库,这些函数对插件非常有用。按字母顺序排列的函数列表参见 `:help vim-function`,按主题分组的函数列表参见 `:help function-list`。 |
|
|
|
|
|
|
|
#### Caveats |
|
|
|
|
|
|
|
一些应该返回布尔值的 Vim 函数返回`1`或`0`。 这在 Vimscript 中不是问题,因为`1‘是真的,而`0’是假的,支持如下结构: |
|
|
|
一些应该返回布尔值的 Vim 函数返回 `1` 或 `0`。这在 Vimscript 中不是问题,因为 `1` 是真的,而 `0` 是假的,支持如下结构: |
|
|
|
|
|
|
|
```vim |
|
|
|
if has('nvim') |
|
|
@ -829,7 +829,7 @@ Neovim 提供了一系列的 api 函数来设置获取和删除映射: |
|
|
|
|
|
|
|
第三个参数是包含映射右侧(要执行的命令)的字符串。 |
|
|
|
|
|
|
|
最后一个参数是一个表,包含`:help:map-arguments`中定义的映射的布尔值选项(包括`noremap`,不包括`buffer`)。 |
|
|
|
最后一个参数是一个表,包含 `:help :map-arguments` 中定义的映射的布尔值选项(包括 `noremap`,不包括 `buffer`)。 |
|
|
|
|
|
|
|
缓冲区-本地映射也将缓冲区编号作为其第一个参数(`0` 设置当前缓冲区的映射)。 |
|
|
|
|
|
|
@ -879,7 +879,7 @@ vim.api.nvim_buf_del_keymap(0, 'i', '<Tab>') |
|
|
|
|
|
|
|
## 定义自动命令 |
|
|
|
|
|
|
|
AUGROUP 和 AUTOCOMMAND 还没有接口,但正在处理: |
|
|
|
AUGROUP 和 AUTOCOMMAND 还没有接口,但正在处理 |
|
|
|
|
|
|
|
- [Pull request #12378](https://github.com/neovim/neovim/pull/12378) |
|
|
|
|
|
|
@ -899,7 +899,7 @@ vim.api.nvim_command('augroup end') |
|
|
|
|
|
|
|
`vim.api.nvim_buf_add_highlight` 为 buffer 指定的行和位置添加高亮 |
|
|
|
|
|
|
|
neovim 0.5 集成 treesitter,对于语法高亮相比之前使用正则的方式更加的高效,[nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) |
|
|
|
Neovim 0.5 集成 treesitter,对于语法高亮相比之前使用正则的方式更加的高效,[nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) |
|
|
|
|
|
|
|
- `:help lua-treesitter` |
|
|
|
|
|
|
|