in lua (love2D), i want to import a library in a subfolder, the file in there will not find the next module it requires - lua

So in lua, i want to import a module.
I want to have my "polygon" lib in a subfolder, so i reference it like this
local polygon = require('polygon.polygon')
however, it needs another module called 'delaunay', it cannot find it as it checks the main folder
Is there anyway short of editing my library, to get this to work? (some kind of ability to add search paths?)
Thanks

To know where to look for modules, Lua's require uses the variables package.path (.lua) and package.cpath (.so/.dll). You can change them in your program to look in the directory you have it in. For consistency's sake, you can look at their contents to know which OS-specific separator to use. For example:
local sep = package.path:find("\\") and "\\" or "/"
package.path = package.path .. ";." .. sep .. "polygon" .. sep .. "?.lua"
This would include ./polygon/?.lua into the search path, and a call to require "delaunay" would therefore have the require function look for ./polygon/delaunay.lua in addition to existing paths. Bear in mind that in require strings, . denotes a separator as far as file searching is concerned, so calling require "polygon.delaunay" in this scenario will mean searching for ./polygon/polygon/delaunay.lua.
From what I understand of your question, changing the package.path variable to include the path to where your delaunay library is stored would solve your issue, although to give a specific solution more information about your project and directory structure is required.

All what loaded into package.loaded can be load with require() because require() looks first in package.loaded...
-- Lua 5.3 ( lua -i )
> package.loaded.code=load(code.dump)()
> test=require('code')
> test
function: 0x565cb820
So you can use load() or loadfile('/path/to/your_code.lua') to do this. Another nice feature of this method is to load dumped code...
> package.loaded.shell=loadfile('shell.bin')
> shell=require('shell')
> shell('cat shell.bin')
uaS�
�
xV(w#F#�d�#��F�#G���d#��F�#G���d#&�typestringoexecute
/bin/bash>

In any way, it appears that you will have to deal with the subfolders explicitly.
As in, either the module polygon will have to import delaunay as polygon.delaunay.
Or module names will have to be appended to package.path so that lua could search through subfolders for filenames:
package.path=package.path..";./polygon/?.lua"
More info is here.
It is pointed out in comments, you'd probably want to ensure that path concatenation happens only once.
Also, one should be wary of name shadowing.
Finally, while we are at stirring up the past, a pretty nifty trick to solve the issue was proposed here five years before the question.

Related

Require looks for .dll files instead of my modules?

So i've been trying to figure this out, im doing the following
main.lua:
package.path = io.popen("cd"):read'*all' -- to set the path the same as main.lua (for exporting)
local u = require("utilities") -- this is the line that dosent work
utilities.lua:
local u = {}
function u.GetService(s)
return require(tostring(s))
end
function u.Wait(s)
local ntime = os.clock() + s/10
repeat until os.clock() > ntime
end
function u.NPWait(s)
local ntime = os.time() + s
repeat until os.time() > ntime
end
return u
The error:
module 'utilities' not found:
Then here goes a search that DOES look in the correct folder, however it looks for .dll files
Require has never been something I've been good at, Sometimes I get it to work, sometimes it breaks like this, if someone can help me understand how to fix this then thank you, as this has been annoying me every so often
You're misunderstanding package.path.
Unlike the PATH variable used by windows and linux, in Lua you don't just tell it what directory to look in but also what the files should look like.
What you're doing is erasing the default search paths completely and replacing it with a broken path that won't find any files.
Generally speaking, to add a new directory to your path, you should add both C:\path\to\your\files\?.lua, and C:\path\to\your\files\?\init.lua, which are the two ways Lua loads modules by default.
You also shouldn't replace package.path, because you're keeping modules from being loaded elsewhere.
Your code should look somewhat like this:
local cd = io.popen("cd")
package.path = cd:read('*line') .. "\\?.lua;" .. package.path
cd:close()
The reason why it's still looking for DLL files is that package.cpath is separate, so you're not changing that.
require("utilities.lua") should work.
You have to specify how to get from the required name to the file. For example by adding a path and a file extension to it.
If you want to require c:\folder\script.lua with require("script") your package.path must contain something like c:\folder\?.lua where ? is replaced by the required name.
If you have your module in a folder with its name and let's say a init.lua for that module the path is c:\folder\?\init.lua
Just print the original package.path and see what's inside befor you overwrite it.
Refer to Lua Reference Manual 6.3 Modules: package.searchpath
A path is a string containing a sequence of templates separated by
semicolons. For each template, the function replaces each
interrogation mark (if any) in the template with a copy of name
wherein all occurrences of sep (a dot, by default) were replaced by
rep (the system's directory separator, by default), and then tries to
open the resulting file name.
For instance, if the path is the string
"./?.lua;./?.lc;/usr/local/?/init.lua" the search for the name foo.a will try to open the files ./foo/a.lua, ./foo/a.lc, and
/usr/local/foo/a/init.lua, in that order.

Is there any way that prevent lua from translating 'a.b' to 'a/b' when I require 'a.b'?

For example:
require('a.b.c/foo.lua')
Lua engine will translate 'a.b.c/...' to 'a/b/c/...' to search file in the pattern list, right?
Will there be any problem when 'a.b.c' are real folder name? If so, how to solve that?
If your module is located in a directory that contains . as part of its name, pulling it in with require will be difficult since there's no way to 'escape' that . so the \ substitution isn't done.
However, it may still be possible to point lua to look in the right place indirectly by playing with the package.path:
local restorepath = package.path
package.path = "./a.b.c/?.lua"
require 'foo'
package.path = restorepath
But I'd recommend that you try to reorg your project directory structure first so it better works with lua's require. Otherwise you'll have to do keep doing the above dance with other modules you might have.
Such translation is not on the spec, as far as I know. So it might work, but it might also not work. It might break on some platforms (i.e. work on Linux and Mac and not on Windows). It might work in one version of Lua and not on the next. So I would not recommend it.
The way to make sure you stay platform-agnostic is using dots everywhere. Also, I would recommend not putting the .lua part at the end, require does not always resolve that well either:
require('a.b.c.foo')

how to load modules in different folders

I have following folder structure
--folder1
------main.lua
------sub_folder
---------func1.lua
--folder2
------func2.lua
I want to load func1.lua and func2.lua in main.lua by require command
PS:what does the init.lua in a folder do
In vanilla lua, you'd load them like this:
local func1 = loadfile "sub_folder/func1.lua"
local func2 = loadfile "../folder2/func2.lua"
See: Pil Chapter 8
If you're using Lua embedded in some other application (i.e, a game, software, etc.), then you need to let us know what this is, or we can't help you. This goes for your P.S question as well. But generally, init.lua is usually the first file to be executed, i.e, it'll load other files, etc.
The func1.lua is easily loaded via
require 'sub_folder.func1'
because sub_folder is in the same folder as main.lua.
For func2.lua, there is no way to tell require to search "one level up", so you must tell Lua how to find the required modules. This can be done at least two ways:
via LUA_PATH environment variable:
append path/to/folder2/?.lua to it, then main.lua can do require "func2".
OR append path/to/parent-of-folder2/?.lua to it, then main.lua can do require "folder2.func2".
by editing package.path in your script:
package.path = package.path .. ';../?.lua'
require 'func2'
or
package.path = package.path .. ';../../?.lua'
require 'folder2.func2'
The first method is more "permanent" since the setting is in the OS environment; it will work even if you move folder1 to some other place on your system, without moving folder2. The second method is dynamic so it will work regardless of where you place your folder structure, i.e., if folder2 is always sibling folder of folder1 the method 2 works, method 1 fails (or requires that you edit the LUA_PATH).

Lua: require fails to find submodule, but searchpath succeeds?

usually when I have a question about something remotely software related I find that someone else has already asked the very same thing, and gotten good answers that works for me too.
This time, though, I've failed to find an answer to my predicament.
Here we go:
I'm currently trying to move up my Lua-programming a notch or three and want to use modules. So, I've got a structure like this:
main.lua
foo/bar.lua
Now, in main.lua I do
require("foo.bar")
which fails,
main.lua:1 module 'foo.bar' not found:
no field package.preload['foo.bar']
no file 'foo.bar.lua'
no file 'foo.bar.lua'
no file 'foo.lua'
Ok, something might be wrong with my package.path so I use package.searchpath("foo.bar", package.path) to see what I', doing wrong.
The problem is that package.searchpath resolves foo.bar to foo/bar.lua which is exactly right.
As I've understood it, package.searchpath tries to find the module in the same way as require, but there seems to be som glitch in my case.
What strikes me as odd is the repetition of the no file 'foo.bar.lua' in the error output
Have I misunderstood the use of require?
I'm using LuaJIT-2.0.0 to run my chunks
Update:
I'm using LuaJIT-2.0.0 to run my chunks <- This was the reason for my problem, stock Lua-5.2.2 behaves as expected
package.path = debug.getinfo(1,"S").source:match[[^#?(.*[\/])[^\/]-$]] .."?.lua;".. package.path
require("foo.bar")
This line causes require to look in the same directory as the
current file when asked to load other files. If you want it to instead
search a directory relative to the current directory, insert the
relative path between " and ?.lua
Here is part of require description:
[...] Otherwise require searches for a Lua loader using the path stored in
package.path. If that also fails, it searches for a C loader using the
path stored in package.cpath. If that also fails, it tries an
all-in-one loader (see package.loaders).
Default path for package.path is always the .exe that executes specified script.

Do file only once in Lua

I was wondering if there's a way to do a lua file only once and have any subsequent attempts to do that lua file will result in a no-op.
I've already thought about doing something akin to C++ header's #if/else/endif trick. I'm wondering if there's a standard way to implement this.
James
well, require pretty much does that.
require "file" -- runs "file.lua"
require "file" -- does not run the "file" again
The only problem with require is that it works on module names, not file names. In particular, require does not handle names with paths (although it does use package.path and package.cpath to locate modules in the file system).
If you want to handle names with paths you can write a simple wrapper to dofile as follows:
do
local cache={}
local olddofile=dofile
function dofile(x)
if cache[x]==nil then
olddofile(x)
cache[x]=true
end
end
end
based on lhf's answer, but utilising package, you can also do this once:
package.preload["something"]=dofile "/path/to/your/file.lua"
and then use:
local x=require "something"
to get the preloaded package again. but that's a bit abusive...

Resources