Load Lua-files by relative path - lua

If I have a file structure like this:
./main.lua
./mylib/mylib.lua
./mylib/mylib-utils.lua
./mylib/mylib-helpers.lua
./mylib/mylib-other-stuff.lua
From main.lua the file mylib.lua can be loaded with full path require('mylib.mylib'). But inside mylib.lua I would also like to load other necessary modules and I don't feel like always specifying the full path (e.g. mylib.mylib-utils). If I ever decide to move the folder I'm going to have a lot of search and replace. Is there a way to use just the relative part of the path?
UPD. I'm using Lua with Corona SDK, if that matters.

There is a way of deducing the "local path" of a file (more concretely, the string that was used to load the file).
If you are requiring a file inside lib.foo.bar, you might be doing something like this:
require 'lib.foo.bar'
Then you can get the path to the file as the first element (and only) ... variable, when you are outside all functions. In other words:
-- lib/foo/bar.lua
local pathOfThisFile = ... -- pathOfThisFile is now 'lib.foo.bar'
Now, to get the "folder" you need to remove the filename. Simplest way is using match:
local folderOfThisFile = (...):match("(.-)[^%.]+$") -- returns 'lib.foo.'
And there you have it. Now you can prepend that string to other file names and use that to require:
require(folderOfThisFile .. 'baz') -- require('lib.foo.baz')
require(folderOfThisFile .. 'bazinga') -- require('lib.foo.bazinga')
If you move bar.lua around, folderOfThisFile will get automatically updated.

You can do
package.path = './mylib/?.lua;' .. package.path
Or
local oldreq = require
local require = function(s) return oldreq('mylib.' .. s) end
Then
-- 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

I'm using the following snippet. It should work both for files loaded with require, and for files called via the command line. Then use requireRel instead of require for those you wish to be loaded with a relative path.
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

Under the Conky's Lua environment I've managed to include my common.lua (in the same directory) as require(".common"). Note the leading dot . character.

Try this:Here is my findings:
module1= require(".\\moduleName")
module2= dofile("..\\moduleName2.lua")
module3 =loadfile("..\\module3.lua")
To load from current directory. Append a double backslash with a prefix of a fullstop.
To specify a directory above use a prefix of two fullstops and repeat this pattern for any such directory.e.g
module4=require("..\\..\\module4")

Related

Can you require a file directly from the /after/plugin folder?

I decided to spring-clean and update my nvim config files/plugins, and thought I’d make proper use of the after/plug folder.
While setting up LSP (with mason, mason-lspconfig, and lspconfig), I wanted to move all the lsp language server settings out from after/plugin/lsp/init.lua to their own files (now in after/plugin/lsp/settings).
The problem is I don’t seem to be able to require them into the init.lua file.
Things I’ve tried to no avail:
require(‘after/plugin/lsp/settings/sumneko_lua.lua’)
require(vim.fn.stdpath("config") .. "/after/plugin/lsp/settings/sumneko_lua”)
require(vim.fn.expand('%:h').. ‘/settings/sumneko_lua’)
The attempt using expand works when I resource the file in nvim; but causes an error when starting nvim.
I understand that all the files in after/plugin are automagically sourced at startup. So if I had a file shared.lua:
local M = {}
function M.greet()
vim.notify("Hello!”)
end
return M
in the same folder as after/plugin/lsp/init.lua, how can I get access to the greet() function from init.lua?
Any pointers would be greatly appreciated.
It turned out to be quite a simple solution in the end: I simply updated the paths to be searched in init.lua
-- nvim/init.lua
-- Allow require to look in after/plugin folder
local home_dir = os.getenv("HOME”)
package.path = home_dir .. "/.config/nvim/after/plugin/?.lua;" .. package.path
And then I can require any file inside the after/plugin folder
e.g - require(‘lsp/settings/sumneko’) or require(‘lsp/shared’).greet()

Lua Nested Require Path

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
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
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

require function can't see the module file

So this is my kek13 lua chunk file:
-- modules
-- a package is a collection of modules
local test = {}
function test.add(n1, n2) -- dont put local as the scope of this function
since you already added
-- a local to the 'test' table... doing so will return an error
return n1 + n2
end
function test.hi(name)
return "my name is " .. name
end
return test
.. and this is my kek13Part2Real lua chunk file:
print("===========================")
local dad = require("kek13")
print(dad.hi("A"))
print(dad.add(1, 5))
print("==============================")
require ("kek13")
print(dad.hi("ur mum"))
print(dad.add(2, 2))
print("========================================")
They are in the same folder, at least in the document folder.
The only problem is that this causes an error. Something like lua can't find or see the file. I'm using Zerobrane IDE for this by the way.
require does not check the folder where the calling script is located it.
Use dofile with a path or add the folder containing the desired script to your LUA_PATH environment variable or append it to package.path
This is not how require works. Please read manuals...
https://www.lua.org/manual/5.3/manual.html#pdf-require

How to use Lua require() function to access a module before the actual address?

Ex:
I'm on a folder called 'tuna' and want to require a file that is before 'tuna':
Ex: require "some-file.lua/tuna"
but I don't know how to do it.
You should learn how Lua searches for files when requiring.
package.path is a string that estabilishes where and how it should search for the file you required. It usually looks like this:
"/some/path/?.lua; /some/other/path/?.lua; ?.lua;"
When you call require("module"), Lua takes the first path contained in the string in package.path (the paths are separated by semicolons, so the first path would be /some/path/?.lua), and replaces the ? in the string with the string that was passed to require.
So Lua would first search your module at /some/path/module.lua.
If it finds that file, then it executes it, otherwise it moves on to the next path: it would search at /some/other/path/module.lua, and finally at module.lua.
Now if your directory looks like this:
Outer_dir = {
tuna = {
main.lua,
tuna.lua
},
module.lua
} --didn't know how to represent a tree lol
And, if from main.lua you usually access tuna.lua just typing require("tuna"), then your package.path must be like /Outer_dir/tuna/?.lua. To be sure you can require module.lua, which is "before" tuna.lua, you should either change your package.path string to /Outer_dir/?.lua (this mean you should use require("tuna/tuna") to access tuna.lua) or to/Outer_dir/tuna/?.lua; /Outer_dir/?.luaso that eitherrequire("tuna")andrequire("module")` will work perfectly.

How do I make require() take a direct path to a file

so I have the following code, and the problem is that when I loop through each file in my array and try to require the file path, it gives me an error of the module isn't found.
local Commands = {}
function getCommands()
local readdir = fs.readdir
local readdirRecursive = require('luvit-walk').readdirRecursive
readdirRecursive('./Desktop/Discord/ArtifexBot/Discordia/resources/commands/', function(k, files)
for i,v in pairs(files) do
if v:match(".lua") and not v:match("commands.lua") then
local cmd = v:match("([^/]-)%..-$")
fs.readlink(v,function(err,thing)
print(err,thing)
end)
Commands[cmd] = require(v)
end
end
end)
end
getCommands()
The recursive function works, and the files are just strings of the path. But after research, require() needs a relative path, not a direct path. So I think I need to do something with fs to make the file path a relative path instead? I couldn't find the answer anywhere.
Thanks!
require doesn't take a path at all. The standard loaders simply use the string you give it in a sequence of patterns, in accord with its algorithm.
What you want is to load and execute a given Lua script on disk. That's not spelled require; that's spelled dofile.

Resources