3

I'm writing a tool to parse lua plugins created by other users. The only guarentee about the plugin is that it has a data.lua file in a known directory. Inside there users are free to do anything they wish. This particular plugin using require to load a file and that file loads another file. Both are relative paths but the second is relative to the location of the first file.

  • data.lua
  • foo/bar.lua
  • foo/baz.lua

data.lua:

require("foo.bar")

foo/bar.lua:

require("baz")

When I try to execute data.lua I get an error when foo/bar.lua tries to require "baz". None of the paths it tries are ./foo/.

Any idea how I can fix this? I could find any documentation specifically about this case, it seemed like I need to hard code /foo/ into the path but I don't know it ahead of time. This seems like something that should be automatic is there a setting I'm missing or am I running the wrong version of lua? I'm using NLua 4.0

Thanks

Ryan Badour
  • 584
  • 3
  • 14

2 Answers2

2

I tested this script using node-lua and it fixes the issue for me!

https://gist.github.com/hoelzro/1299679

Relavent code:

local oldrequire = require

function require(modname)
  local regular_loader = package.loaders[2]
  local loader = function(inner)
    if string.match(modname, '(.*)%.') then
      return regular_loader(string.match(modname, '(.*)%.') .. '.' .. inner)
    end
  end

  table.insert(package.loaders, 1, loader)
  local retval = oldrequire(modname)
  table.remove(package.loaders, 1)

  return retval
end

To get this to work with Lua 5.2 change all uses of package.loaders to package.searchers.

Also if you want to override the global require function you need this snippet as well:

_G.require = require
Ryan Badour
  • 584
  • 3
  • 14
1

You can alter the search behavior of require by changing the package.path variable.

Resources on package.path:

https://www.lua.org/manual/5.3/manual.html#pdf-package.path

http://lua-users.org/wiki/PackagePath

Example adding foo folder to search locations:

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

the ? character will be where the string passed to require is placed.


Alternatively you can add a default file to load, to the package.path:

package.path = package.path .. ';./nested_require.lua' 

Then define the behavior you would like within this file. You can use the global variable _REQUIREDNAME to reference the value passed to the require function.

The documentation for this method can be found here at the bottom of the page: https://www.lua.org/pil/8.1.html

Community
  • 1
  • 1
Nifim
  • 4,758
  • 2
  • 12
  • 31
  • I appreciate the help but the basic behaviour isn't sufficient as I need to dynamically change the path based on the file that contains the require statement. I added an answer when I found a gist with what I needed but the moderators deleted it. I just added it back with more detail. – Ryan Badour Dec 23 '18 at 16:38
  • I have edit my answer to reflect your comments. However redefining require is not something that should be done. Even in extreme cases simply changing the package.path to a specific default file would be a better option. – Nifim Dec 24 '18 at 19:22