Как организовать путь к модулю Lua и написать "require" вызовы без потери гибкости?

скажем, у меня есть проект, структура папок которого выглядит следующим образом:

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

модель/а.Луа requries модель/Б.Луа: require "b"

view / a.Луа!--9--> requries view / b.Луа!--9-->: require "b"

main.Луа!--9--> необходимо файлы модель и посмотреть.


теперь у меня есть проблема, чтобы получить эти модули правильно. Я знаю, что могу исправить это, изменив требуют вызовы:

модель/а.Луа: require "model.b"

view / a.Луа!--9-->: require "view.b"

но если я это сделаю, мне придется изменять эти файлы каждый раз, когда я изменяю структуру папок.

Итак, мои вопросы:

  1. как исправить проблему module path без жестких путей кода в файлах модуля?
  2. почему Lua не использует правило поиска модуля узла.js, который выглядит легче?

4 ответов


когда вы require модуль, строковый параметр из require передается в модуль, к которому вы можете получить доступ с помощью синтаксиса переменных аргументов .... Вы можете использовать это, чтобы включить другие зависимые модули, которые находятся в тот же путь как текущий модульrequireed, не делая его зависимым от фиксированного жестко закодированного имени модуля.

для вашего примера, вместо того, чтобы делать:

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

и

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

вы можете do:

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

и

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

теперь, если вы измените структуру каталогов, например. двигайся!--8--> что-то вроде control/subcontrol/foobar, потом control/subcontrol/foobar/a.lua (ранее view/a.lua) теперь попробуем требовать control/subcontrol/foobar/b.lua и "Поступай правильно".

конечно main.lua все равно нужно будет полностью квалифицировать пути, так как вам нужен какой-то способ устранить двусмысленность между model/a.lua и view/a.lua.


Как исправить проблему module path без жестких путей кода в файлах модуля?

У меня нет лучшего кросс-платформенного решения, возможно, вам следует планировать структуру папок на раннем этапе.

почему Lua не использует правило поиска модуля узла.JS, что выглядит проще?

потому что Lua изо всех сил старается полагаться только на ANSI C, который действительно успешен. И в ANSI C нет такой концепции каталогов.


есть несколько подходов, которые можно использовать.

вы можете добавить относительные пути к package.path а в это так ответ. В вашем случае вы хотите добавить пути в main.lua которые соответствуют различным способам доступа к файлам. Это сохраняет все изменения, необходимые при изменении локальной структуры каталогов в один файл.

вы можете добавить абсолютные пути к package.pathС помощью debug.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

решение: добавить папку main.lua (корень проекта)package.path на main.lua.

наивный способ поддержки папок глубиной 1 уровня:

-- main.lua
package.path = package.path .. ";../?.lua"

Примечание requires в (корень проекта) будет искать файлы за пределами корня проекта, что нежелательно.

лучший способ использовать некоторую библиотеку (например:пути, пальчиковые), чтобы разрешить абсолютный путь и добавить его вместо этого:

-- 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"

и

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