英文:
How to require a file with a dot in the name?
问题
我正在尝试使用 "config/lsp.rc.lua"
,但使用 require("config.lsp.rc")
会导致错误。
英文:
I am trying to require "config/lsp.rc.lua"
, but doing require("config.lsp.rc")
gives an error.
答案1
得分: 0
以下是翻译好的部分:
问题很简单:负责的require
加载器将使用目录分隔符(Unix上的/
)替换每个点。
请注意,不应在require
中使用/
,因为它是特定于平台的目录分隔符(实际上,Windows也会支持它)。
您最好的选择是简单地重命名文件,将点替换为下划线或类似的方式,以遵循Lua的约定。
但是,如果这超出了您的控制范围,您还可以对require
进行猴子补丁以支持您的用例。
我们可以使用/
代替.
作为目录分隔符。
为此,我们必须实现自己的搜索器:
这个表中的每个条目都是搜索器函数。在查找模块时,
require
按升序调用这些搜索器中的每一个,其参数是模块名称(提供给require
的参数)。如果搜索器找到了模块,它将返回另一个函数,即模块加载程序,以及一个额外的值,加载程序数据,它将传递给加载程序,并由require
作为第二个结果返回。如果找不到模块,它将返回一个解释为为什么找不到的字符串(或者如果没有什么可说的话,则返回nil)。
幸运的是,我们可以利用package.searchpath
来为我们完成大部分工作:
local function searcher(module_name)
-- 使用"/"代替".作为目录分隔符
local path, err = package.searchpath(module_name, package.path, "/")
if path then
return assert(loadfile(path))
end
return err
end
现在我们只需将其插入到package.searchers
中,以供require
使用。我们可以将其插入到首位、末位或任何位置,都无所谓,所以让我们将其插入到末位,以便仅当所有内置搜索器失败时才尝试我们的搜索器:
table.insert(package.searchers, searcher)
用法:
local lsp_rc = require("config/lsp.rc")
然后将按预期工作。
如果您不希望全局修补require
,您可以实现一个本地的require
,只在Lua路径中搜索,使用您的约定:
local function myrequire(module_name)
return assert(loadfile(assert(package.searchpath(module_name, package.path, "/")))
end
local lsp_rc = myrequire("config/lsp.rc")
英文:
The problem is simple: The responsible require
loader will replace each dot with the directory separator (/
on Unix).
Note that you should not use /
in require
since it is a platform-specific directory separator (in practice it will be supported by Windows though).
Your best option would be to simply rename the file, replacing the dot with an underscore or the like to abide by Lua's conventions here.
However, if this is out of your control, you may also monkey-patch require
to support your use case.
Instead of using .
as directory separator, we may use /
.
For that, we have to implement our own searcher:
> Each entry in this table is a searcher function. When looking for a module, require calls each of these searchers in ascending order, with the module name (the argument given to require) as its sole argument. If the searcher finds the module, it returns another function, the module loader, plus an extra value, a loader data, that will be passed to that loader and returned as a second result by require. If it cannot find the module, it returns a string explaining why (or nil if it has nothing to say).
Luckily we can leverage package.searchpath
to do most of the work for us:
local function searcher(module_name)
-- Use "/" instead of "." as directory separator
local path, err = package.searchpath(module_name, package.path, "/")
if path then
return assert(loadfile(path))
end
return err
end
Now we just have to pluck this into package.searchers
for require
to use it. We could insert it first, last, wherever, doesn't matter, so let's insert it last, such that only if all builtin searchers fail our searcher is tried:
table.insert(package.searchers, searcher)
Usage:
local lsp_rc = require("config/lsp.rc")
will then work as expected.
If you do not want to globally patch require
, you could implement a local require
that just searches in the Lua path, using your conventions:
local function myrequire(module_name)
return assert(loadfile(assert(package.searchpath(module_name, package.path, "/"))))
end
local lsp_rc = myrequire("config/lsp.rc")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论