2012-02-04 2 views
28

Если у меня есть файл структура, как это:нагрузки Lua-файлы по относительному пути

./main.lua 
./mylib/mylib.lua 
./mylib/mylib-utils.lua 
./mylib/mylib-helpers.lua 
./mylib/mylib-other-stuff.lua 

Из main.lua файл mylib.lua может быть загружена полным путем require('mylib.mylib'). Но внутри mylib.lua Я также хотел бы загрузить другие необходимые модули, и я не чувствую, что всегда указываю полный путь (например, mylib.mylib-utils). Если я когда-нибудь решит переместить папку, у меня будет много поиска и замены. Есть ли способ использовать только относительную часть пути?

UPD. Я использую Lua с Corona SDK, если это имеет значение.

ответ

28

Существует способ выведения "локальный путь" файла (более конкретно, строка который использовался для загрузки файла).

Если требует файл внутри lib.foo.bar, вы могли бы делать что-то вроде этого:

require 'lib.foo.bar' 

Тогда вы можете получить путь к файлу в качестве первого элемента (и только) ... переменной, когда вы находятся вне всех функций. Другими словами:

-- lib/foo/bar.lua 
local pathOfThisFile = ... -- pathOfThisFile is now 'lib.foo.bar' 

Теперь, чтобы получить «папку», вам необходимо удалить имя файла. Самый простой способ - совпадение:

local folderOfThisFile = (...):match("(.-)[^%.]+$") -- returns 'lib.foo.' 

И вот он у вас есть. Теперь вы можете предварять эту строку с другими именами файлов и использовать, чтобы потребовать:

require(folderOfThisFile .. 'baz')  -- require('lib.foo.baz') 
require(folderOfThisFile .. 'bazinga') -- require('lib.foo.bazinga') 

Если двигаться bar.lua вокруг, folderOfThisFile будет обновляется автоматически.

+0

Спасибо, это сработало для загрузки файлов. Но когда я обращаюсь к публичным свойствам модуля, мне все равно нужно указать полный путь (например, 'lib.foo.bar.some_value'). – RocketR

+4

Это не имеет никакого отношения к загрузке файлов; он просто отражает то, как вы решили структурировать свой Lua.Вы можете (например) вернуть таблицу на каждый запрос и сохранить ее в локальном var: 'local baz = require (folderOfThisFile .. 'baz')', а затем сделать 'baz.some_value' – kikito

+1

Прохладный, я не сделал знать о '...' внешних функциях, являющихся строкой, которая использовалась для запроса файла. –

13

Вы можете сделать

package.path = './mylib/?.lua;' .. package.path 

Или

local oldreq = require 
local require = function(s) return oldreq('mylib.' .. s) end 

Тогда

-- do all the requires 
require('mylib-utils') 
require('mylib-helpers') 
require('mylib-other-stuff') 

-- and optionally restore the old require, if you did it the second way 
require = oldreq 
+0

Странно. Я попытался изменить 'package.path' уже и думал, что делаю что-то неправильно, потому что он говорит' no field package.preload ['mylib-utils'] ',' no file './Mylib/mylib-utils.lua''. Но я использую Lua внутри SDK Corona, возможно, у него есть некоторые особенности с загрузкой файлов. – RocketR

0

В среде Lua Conky мне удалось включить мой common.lua (в том же каталоге), что и require(".common"). Обратите внимание на ведущую точку ..

0

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

local requireRel 
if arg and arg[0] then 
    package.path = arg[0]:match("(.-)[^\\/]+$") .. "?.lua;" .. package.path 
    requireRel = require 
elseif ... then 
    local d = (...):match("(.-)[^%.]+$") 
    function requireRel(module) return require(d .. module) end 
end 
Смежные вопросы