如何组织Lua模块路径并编写“require”调用而不失灵活性?

时间:2013-08-09 16:19:15

标签: module lua

假设我有一个项目,其文件夹结构如下所示:

| main.lua
|
|---<model> // this is a folder
|    |a.lua
|    |b.lua
|
|---<view>
     |a.lua
     |b.lua

model / a.lua requries model / b.lua require "b"

view / a.lua requries view / b.lua require "b"

main.lua 需要模型视图中的文件。


现在我有问题让这些模块正确加载。我知道我可以通过将require调用更改为:

来解决它

model / a.lua require "model.b"

查看/ a.lua require "view.b"

但是,如果我这样做,每次更改文件夹结构时都必须修改这些文件。

所以我的问题是:

  1. 如何修复模块文件中没有硬代码路径的模块路径问题?
  2. 为什么Lua不使用Node.js的模块搜索规则,这看起来更容易?

4 个答案:

答案 0 :(得分:7)

当您require模块时,来自require的字符串参数将传递到您可以使用变量参数语法...访问的模块中。您可以使用它来包含驻留在相同路径中的其他相关模块,而不是当前模块require,而不依赖于固定的硬编码模块名称。

对于您的示例,而不是:

-- model/a.lua
require "model.b"

-- view/a.lua
require "view.b"

你可以这样做:

-- model/a.lua
local thispath = select('1', ...):match(".+%.") or ""
require(thispath.."b")

-- view/a.lua
local thispath = select('1', ...):match(".+%.") or ""
require(thispath.."b")

现在,如果您更改目录结构,例如。将view移至类似control/subcontrol/foobar的内容,然后control/subcontrol/foobar/a.lua(以前称为view/a.lua)现在会尝试control/subcontrol/foobar/b.lua代替{em>做正确的事情< / EM>”。

当然main.lua仍然需要完全限定路径,因为您需要某种方法来消除model/a.luaview/a.lua之间的歧义。

答案 1 :(得分:2)

  

如何在模块文件中没有硬代码路径的情况下解决模块路径问题?

我没有更好的跨平台解决方案,也许您应该尽早规划文件夹结构。

  

为什么Lua不使用Node.js的模块搜索规则,这看起来更容易?

因为Lua尽力只依赖ANSI C,这是非常成功的。在ANSI C中,没有这样的目录概念。

答案 2 :(得分:2)

您可以使用几种方法。

您可以像this SO answer一样添加package.path的相对路径。在您的情况下,您希望在main.lua中添加与您可能访问文件的各种方式相对应的路径。这样可以在将目录结构本地更改为一个文件时保留所需的所有更改。

您可以使用package.pathdebug.getinfo添加绝对路径 - 这可能会更容易,因为您不需要考虑所有相关访问,但您仍需要执行此操作main.lua更改目录结构时,需要对debug.getinfo返回的值进行字符串操作,以删除模块名称并添加子目录名称。

> lunit = require "lunit"
> info = debug.getinfo(lunit.run, "S")
> =info.source
@/usr/local/share/lua/5.2/lunit.lua
> =info.short_src
/usr/local/share/lua/5.2/lunit.lua

答案 3 :(得分:1)

解决方案是将alias bg cd command fc fg getopts hash jobs read type ulimit umask unalias wait(项目根目录)的文件夹添加到main.lua中的package.path

支持1级深层文件夹的天真方式:

main.lua
  

注意(项目根目录)中的-- main.lua package.path = package.path .. ";../?.lua" 将查找项目根目录之外的文件,这是不可取的。

使用某个库(例如:pathspenlight)更好的方法来解析绝对路径并添加它:

require

然后在您的源中使用文件夹名称来定位文件:

-- main.lua
local projectRoot = lib.abspath(".")
package.path = package.path .. ";" .. projectRoot .. "/?.lua"

-- model/a.lua
require "model.b"
-- you can even do this
require "view.b"