You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66RING c85718d191 update 4 years ago
LICENSE Initial commit 4 years ago
README.md update 4 years ago

README.md

在neovim中使用Lua

nvim-lua-guide 中文版.

目录

简介

Lua作为Neovim中的一流语言的集成正在成为它的杀手级特性之一。 然而,学习如何用Lua编写插件的教程数量并不像用Vimscript编写插件那样多。 这是一种尝试,试图提供一些基本信息,让人们可以使用Lua编写neovim插件。 本指南假定您使用的是最新的NeovimNighly build]。 由于Neovim的0.5版本是开发版本,请记住,正在积极开发的一些API并不十分稳定, 在发布之前可能会发生变化。

学习Lua

不同于原版教程,一下资源适用于国内用户:

Lua是一种非常干净和简单的语言。 它很容易学习,特别是如果你有其他编程语言基础的例如typescript/javascript等,会更加容易上手Lua。注意:Neovim嵌入的Lua版本是LuaJIT 2.1.0,它与Lua 5.1保持兼容(带有几个5.2扩展)

现有的一些在neovim中使用Lua的教程

已经编写了一些教程来帮助人们用Lua编写插件。 他们中的一些人在写这本指南时提供了不少的帮助。 非常感谢它们的作者。

相关插件

Lua 文件位置

Lua文件通常位于您的runtimepath中的lua/文件夹中(对于大多数用户来说,在*nix系统上为~/.config/nvim/lua,在Windows系统上为~/appdata/Local/nvim/lua)。 Package.pathPackage.cpath全局变量会自动调整为包含该文件夹下的Lua文件。 这意味着您可以require()这些文件作为Lua模块

我们以下面的文件夹结构为例:

📂 ~/.config/nvim
├── 📁 after
├── 📁 ftplugin
├── 📂 lua
│  ├── 🌑 myluamodule.lua
│  └── 📂 other_modules
│     ├── 🌑 anothermodule.lua
│     └── 🌑 init.lua
├── 📁 pack
├── 📁 plugin
├── 📁 syntax
└── 🇻 init.vim

下面的Lua代码将加载myluamodule.lua

require('myluamodule')

注意没有.lua扩展名。

类似地,加载ther_module/anthermodule e.lua的过程如下:

require('other_modules.anothermodule')
-- or
require('other_modules/anothermodule')

路径分隔符可以用点.表示,也可以用斜杠/表示。

文件夹如果包含init.lua文件,可以直接引用该文件夹而不必指定该文件的名称

require('other_modules') -- loads other_modules/init.lua

更多信息 :help lua-require

警告

与.vim文件不同,.lua文件不会自动从您的runtimepath目录中获取。 相反,您必须从Vimscript source/require 它们。 计划增加init.lua文件加载选项,替代init.vim

提示

多个Lua插件在它们的lua/文件夹中可能有相同的文件名。 这可能会导致命名空间冲突。如果两个不同的插件有一个lua/main.lua文件,那么执行require('main')是不明确的:我们想要加载哪个文件?最好将您的配置或插件命名为顶级文件夹, 例如这样的形式:lua/plugin_name/main.lua

包说明

如果您是package特性的用户或基于它的插件管理器例如packer.nvimminpacvim-packager,那么在使用Lua插件时需要注意一些事情。start文件夹中的包只有在源化您的init.vim之后才会加载。 这意味着只有在Neovim处理完文件之后,才会将包添加到runtimepath中。如果插件期望 require一个Lua模块或调用自动加载的函数,这可能会导致问题。假设包start/foo有一个lua/bar.lua文件,从您的init.vim执行此操作将引发错误,因为runtimepath尚未更新。

lua require('bar')

你需要使用packadd! foo命令在require 这个模块之前

packadd! foo
lua require('bar')

Packadd后附加表示Neovim会将包放在runtimepath中,而不会在其pluginftDetect目录下寻找任何脚本。

See also:

在Vimscript中使用Lua

:lua

该命令执行一段Lua代码

:lua require('myluamodule')

可以使用以下语法编写多行脚本:

echo "Here's a bigger chunk of Lua code"

lua << EOF
local mod = require('mymodule')
local tbl = {1, 2, 3}

for k, v in ipairs(tbl) do
    mod.method(v)
end

print(tbl)
EOF

See also:

  • :help :lua
  • :help :lua-heredoc

警告

在vim文件中编写Lua时,您不会得到正确的语法突出显示。 使用:lua命令作为需要外部Lua文件的入口点可能会更方便。

:luado

该命令执行一段Lua代码,该代码作用于当前缓冲区中的选中的行。 如果未指定范围,则改为使用整个缓冲区。 从块return的任何字符串都用于确定应该用什么替换每行。

以下命令会将当前缓冲区中的每一行替换为文本hello world

:luado return 'hello world'

提供了两个隐式的linelinenr变量。 line是被迭代的行的文本,而linenr是它的编号。 以下命令将可以被2整数的行转成大写:

:luado if linenr % 2 == 0 then return line:upper() end

See also:

  • :help :luado

:luafile

这个命令加载一个lua文件

:luafile ~/foo/bar/baz/myluafile.lua

类似于vim的:source命令或Lua内置的dofile()函数。

See also:

  • :help :luafile

luafile 对比 require():

您可能想知道lua request()luafile之间的区别是什么,以及您是否应该使用其中一个而不是另一个。 它们有不同的使用情形:

  • require():
    • 是内置的Lua函数,它允许你使用Lua的模块系统。
    • 使用Package.path变量搜索模块(如前所述,您可以使用runtimepath中的lua/文件夹内的required()lua脚本)
    • 跟踪已加载的模块,并防止第二次解析和执行脚本。 如果您更改包含某个模块代码的文件,并在Neovim运行时再次尝试‘required()’,则该模块实际上不会更新。
  • :luafile:
    • 是一个执行命令,它不支持模块。
    • 采用相对于当前窗口的工作目录的绝对或相对路径
    • 执行脚本的内容,而不管该脚本以前是否执行过

如果您想运行您正在处理的Lua文件,:luafile很有用:

:luafile %

Vim命名空间

Neovim会暴露一个全局的vim变量来作为lua调用vim的APIs的入口。它还提供给用户一些额外的函数和子模块“标准库”

一些比较实用的函数和子模块如下:

  • vim.inspect: 把lua对象以更易读的方式打印(在打印lua table是会很有用)
  • vim.regex: 在lua中使用vim寄存器
  • vim.api: 暴露vim的API(:h API)的模块(别的远程调用也是调用同样的API)
  • (TODO) vim.loop: module that exposes the functionality of Neovim's event-loop (using LibUV)
  • vim.lsp: 控制内置LSP客户端的模块
  • vim.treesitter: 暴露tree-sitter库中一些实用函数的模块

上面列举功能的并不全面。如果你想知道更多可行的操作可以看::help lua-stdlibhelp lua-vim。你也可以通过:lua print(vim.inspect(vim))所有可用模块

Tips

每次你想检查一个对象时到要用print(vim.inspect(x))是相当繁琐的。你可以你的配置中写一个全局的包装器函数来替代这个繁琐的过程

function _G.dump(...)
    local objects = vim.tbl_map(vim.inspect, {...})
    print(unpack(objects))
end

之后你就可以使用如下命令来快速检查对象内容了

dump({1, 2, 3})
:lua dump(vim.loop)

另外要注意的是,你可能会发现Lua会比其他语言少一些实用的内置函数(例如:os.clock(),返回以秒为单位,而不是以毫秒为单位的值)。仔细阅读Neovim提供的标准库和vim.fn(后续还会有更多内容),里面可以会有你想要的东西。