Как организовать путь к модулю 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"
но если я это сделаю, мне придется изменять эти файлы каждый раз, когда я изменяю структуру папок.
Итак, мои вопросы:
- как исправить проблему module path без жестких путей кода в файлах модуля?
- почему Lua не использует правило поиска модуля узла.js, который выглядит легче?
4 ответов
когда вы require
модуль, строковый параметр из require
передается в модуль, к которому вы можете получить доступ с помощью синтаксиса переменных аргументов ...
. Вы можете использовать это, чтобы включить другие зависимые модули, которые находятся в тот же путь как текущий модульrequire
ed, не делая его зависимым от фиксированного жестко закодированного имени модуля.
для вашего примера, вместо того, чтобы делать:
-- 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"
Примечание
require
s в (корень проекта) будет искать файлы за пределами корня проекта, что нежелательно.
лучший способ использовать некоторую библиотеку (например:пути, пальчиковые), чтобы разрешить абсолютный путь и добавить его вместо этого:
-- 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"