Как заставить lua искать модули, находящиеся в одной папке с модулем, в котором вызывается require? - PullRequest
2 голосов
/ 05 апреля 2020

скажем, у меня есть папка проекта, например:

mxn:lab axn$ tree .
.
├── lib
│   ├── a.lua
│   └── b.lua
└── main.lua

, где main.lua:

require("lib.a")

, а в a.lua я просто использую строку "b", пытаясь lua - найти файл с именем b.lua в той же папке, что и a.lua first:

require("b")

и b.lua:

print('b loaded!')

, затем I запустите команду lua main.lua и получите ошибку:

[Running] lua "/Users/axn/lab/main.lua"
lua: ./lib/a.lua:1: module 'b' not found:
    no field package.preload['b']
    no file './b.lua'
    no file '/usr/local/share/lua/5.1/b.lua'
    no file '/usr/local/share/lua/5.1/b/init.lua'
    no file '/usr/local/lib/lua/5.1/b.lua'
    no file '/usr/local/lib/lua/5.1/b/init.lua'
    no file './b.so'
    no file '/usr/local/lib/lua/5.1/b.so'
    no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
    [C]: in function 'require'
    ./lib/a.lua:1: in main chunk
    [C]: in function 'require'
    /Users/axn/lab/main.lua:1: in main chunk
    [C]: ?

Я знаю такие решения, как package.path = package.path..';'..'lib/?.lua', но что если структура изменится на:

.
├── foo
│   └── lib
│       ├── a.lua
│       └── b.lua
└── main.lua

Я не хочу изменять опять package.path. Независимо от структуры, require("b") в a.lua всегда заставит lua искать b в той же папке, что и a.lua вначале.

Ответы [ 2 ]

0 голосов
/ 06 апреля 2020

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

package.path существует именно по этой причине. Вы можете просто сделать что-то вроде этого:

package.path = './lib/?.lua;./lib/?/init.lua;' .. package.path

И Lua теперь будет искать модули в каталоге lib (в дополнение к тому, что обычно делается).

Вы можете также используйте переменную окружения LUA_PATH, чтобы сделать это, прежде чем даже запускать Lua.


В противном случае, если вы действительно не хотите использовать «правильный» способ используя package.path, попробуйте поставить это в верхнюю часть a.lua:

print(...)

, и оно должно напечатать что-то вроде

lib.a ./lib/a.lua

Это должно привести вас к желаемому результату. работа.

0 голосов
/ 06 апреля 2020

Вместо того, чтобы переписывать require и влиять на поведение всего кода везде, лучше создать специальную функцию для этой цели:

--Utility function for Lua 5.1, which table.pack can do in 5.2+
function pack_params(...)
    return {n = select("#", ...), ...}
end

local curr_local_path = ""

function require_local_path(local_path, ...)
    --Store the old paths on the stack.
    local old_path = package.path
    local old_local_path = curr_local_path

    --Build the new search path and add it to the front of the package.path.
    curr_local_path = curr_local_path .. local_path
    package.path = "./" .. curr_local_path .. "?.lua;" .. package.path

    --Perform the require, storing the results temporarily.
    local rets = pack_params(require(...))

    --Fix the prior paths.
    package.path = old_path
    curr_local_path = old_local_path

    return unpack(rets, 1, rets.n)
end

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...