aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhạm Bình An <111893501+brianhuster@users.noreply.github.com>2025-03-18 05:41:07 +0700
committerGitHub <noreply@github.com>2025-03-17 15:41:07 -0700
commit08c328b8b079334e7fb38472339c4f8ba1a0df3b (patch)
treefc1fcbd553ad90486af0a016ca96739b7f09fbd7
parent063b69bab4ab64b614e31ab0c93279fdbebb40b7 (diff)
downloadrneovim-08c328b8b079334e7fb38472339c4f8ba1a0df3b.tar.gz
rneovim-08c328b8b079334e7fb38472339c4f8ba1a0df3b.tar.bz2
rneovim-08c328b8b079334e7fb38472339c4f8ba1a0df3b.zip
feat(runtime): Lua ftplugin 'includeexpr' #32719
Problem: Current `'includeexpr'` in runtime/ftplugin/lua.vim doesn't work with Nvim Lua. Solution: Provide an improved 'includeexpr' for Lua in "ftplugin/lua.lua". Closes: https://github.com/neovim/neovim/issues/32490
-rw-r--r--runtime/doc/news.txt2
-rw-r--r--runtime/ftplugin/lua.lua3
-rw-r--r--runtime/lua/vim/_ftplugin/lua.lua26
-rw-r--r--test/functional/editor/ftplugin_spec.lua85
4 files changed, 115 insertions, 1 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index f7f86237f6..9c3ae3706c 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -326,6 +326,8 @@ LUA
`vim.o`, `vim.wo`, `vim.bo`, `vim.opt`, `vim.opt_local`, `vim.opt_global`,
and `vim.fn`.
• Documentation for |lua-bit|.
+• |gf| in Lua buffers can go to module in same repo, |runtime-search-path| and
+ |package.path|.
• |vim.fs.rm()| can delete files and directories.
• |vim.validate()| now has a new signature which uses less tables,
is more performant and easier to read.
diff --git a/runtime/ftplugin/lua.lua b/runtime/ftplugin/lua.lua
index e0f7e95cf6..ef8f126fab 100644
--- a/runtime/ftplugin/lua.lua
+++ b/runtime/ftplugin/lua.lua
@@ -1,9 +1,10 @@
-- use treesitter over syntax
vim.treesitter.start()
+vim.bo.includeexpr = 'v:lua.require"vim._ftplugin.lua".includeexpr()'
vim.bo.omnifunc = 'v:lua.vim.lua_omnifunc'
vim.wo[0][0].foldexpr = 'v:lua.vim.treesitter.foldexpr()'
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
.. '\n call v:lua.vim.treesitter.stop()'
- .. '\n setl omnifunc< foldexpr<'
+ .. '\n setl omnifunc< foldexpr< includeexpr<'
diff --git a/runtime/lua/vim/_ftplugin/lua.lua b/runtime/lua/vim/_ftplugin/lua.lua
new file mode 100644
index 0000000000..588433409b
--- /dev/null
+++ b/runtime/lua/vim/_ftplugin/lua.lua
@@ -0,0 +1,26 @@
+local M = {}
+
+--- @param module string
+---@return string
+function M.includeexpr(module)
+ ---@param fname string
+ ---@return boolean
+ local function filereadable(fname)
+ return vim.fn.filereadable(fname) == 1
+ end
+
+ local fname = module:gsub('%.', '/')
+
+ local root = vim.fs.root(vim.api.nvim_buf_get_name(0), 'lua') or vim.fn.getcwd()
+ for _, suf in ipairs { '.lua', '/init.lua' } do
+ local path = vim.fs.joinpath(root, 'lua', fname .. suf)
+ if filereadable(path) then
+ return path
+ end
+ end
+
+ local modInfo = vim.loader.find(module)[1]
+ return modInfo and modInfo.modpath or module
+end
+
+return M
diff --git a/test/functional/editor/ftplugin_spec.lua b/test/functional/editor/ftplugin_spec.lua
new file mode 100644
index 0000000000..5b57f98d92
--- /dev/null
+++ b/test/functional/editor/ftplugin_spec.lua
@@ -0,0 +1,85 @@
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local exec_lua = n.exec_lua
+local command = n.command
+local eq = t.eq
+
+---@param type string
+---@return string
+local function stdpath(type)
+ return exec_lua(([[return vim.fs.normalize(vim.fn.stdpath("%s"))]]):format(type))
+end
+
+---@return string
+local function vimruntime()
+ return exec_lua [[ return vim.fs.normalize(vim.env.VIMRUNTIME) ]]
+end
+
+---@param module string
+---@return string
+local function lua_includeexpr(module)
+ return exec_lua(([[return require('vim._ftplugin.lua').includeexpr("%s")]]):format(module))
+end
+
+local root = exec_lua [[ return vim.fs.normalize(vim.fn.getcwd()) ]]
+
+describe("Lua 'includeexpr'", function()
+ setup(n.clear)
+ local temp_dir = t.tmpname(false)
+ before_each(function()
+ command(([[
+ edit `=stdpath('config') .. '/lua/user-foo/init.lua'`
+ write ++p
+ edit `=stdpath('config') .. '/lua/user-foo/bar.lua'`
+ write ++p
+ edit `=stdpath('data') .. '/site/pack/packer/start/plugin-foo/lua/plugin-foo/init.lua'`
+ write ++p
+ edit `=stdpath('data') .. '/site/pack/packer/start/plugin-foo/lua/plugin-foo/bar.lua'`
+ write ++p
+
+ edit runtime/lua/foo/init.lua
+ write ++p
+ edit runtime/lua/foo/bar/init.lua
+ write ++p
+
+ edit %s/lua/runtime-foo/init.lua
+ write ++p
+ edit %s/lua/runtime-foo/bar.lua
+ write ++p
+ ]]):format(temp_dir, temp_dir))
+ end)
+
+ it('finds module in current repo', function()
+ command [[ edit runtime/lua/vim/_ftplugin/lua.lua ]]
+ eq(root .. '/runtime/lua/vim/_ftplugin/lua.lua', lua_includeexpr('vim._ftplugin.lua'))
+ eq(root .. '/runtime/lua/editorconfig.lua', lua_includeexpr('editorconfig'))
+ eq(root .. '/runtime/lua/foo/init.lua', lua_includeexpr('foo'))
+ eq(root .. '/runtime/lua/foo/bar/init.lua', lua_includeexpr('foo.bar'))
+ end)
+
+ it('find module in packpath/start', function()
+ eq(
+ stdpath('data') .. '/site/pack/packer/start/plugin-foo/lua/plugin-foo/init.lua',
+ lua_includeexpr('plugin-foo')
+ )
+ eq(
+ stdpath('data') .. '/site/pack/packer/start/plugin-foo/lua/plugin-foo/bar.lua',
+ lua_includeexpr('plugin-foo.bar')
+ )
+ end)
+
+ it('finds module in $VIMRUNTIME', function()
+ command('edit ' .. root)
+ eq(vimruntime() .. '/lua/vim/_ftplugin/lua.lua', lua_includeexpr('vim._ftplugin.lua'))
+ eq(vimruntime() .. '/lua/editorconfig.lua', lua_includeexpr('editorconfig'))
+ end)
+
+ it('find module in runtimepath', function()
+ eq(stdpath('config') .. '/lua/user-foo/init.lua', lua_includeexpr('user-foo'))
+ eq(stdpath('config') .. '/lua/user-foo/bar.lua', lua_includeexpr('user-foo.bar'))
+ command('set rtp+=' .. temp_dir)
+ eq(temp_dir .. '/lua/runtime-foo/init.lua', lua_includeexpr('runtime-foo'))
+ eq(temp_dir .. '/lua/runtime-foo/bar.lua', lua_includeexpr('runtime-foo.bar'))
+ end)
+end)