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

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.

Related

Using io.tmpfile() with shell command, ran via io.popen, in Lua?

I'm using Lua in Scite on Windows, but hopefully this is a general Lua question.
Let's say I want to write a temporary string content to a temporary file in Lua - which I want to be eventually read by another program, - and I tried using io.tmpfile():
mytmpfile = assert( io.tmpfile() )
mytmpfile:write( MYTMPTEXT )
mytmpfile:seek("set", 0) -- back to start
print("mytmpfile" .. mytmpfile .. "<<<")
mytmpfile:close()
I like io.tmpfile() because it is noted in https://www.lua.org/pil/21.3.html :
The tmpfile function returns a handle for a temporary file, open in read/write mode. That file is automatically removed (deleted) when your program ends.
However, when I try to print mytmpfile, I get:
C:\Users\ME/sciteLuaFunctions.lua:956: attempt to concatenate a FILE* value (global 'mytmpfile')
>Lua: error occurred while processing command
I got the explanation for that here Re: path for io.tmpfile() ?:
how do I get the path used to generate the temp file created by io.tmpfile()
You can't. The whole point of tmpfile is to give you a file handle without
giving you the file name to avoid race conditions.
And indeed, on some OSes, the file has no name.
So, it will not be possible for me to use the filename of the tmpfile in a command line that should be ran by the OS, as in:
f = io.popen("python myprog.py " .. mytmpfile)
So my questions are:
Would it be somehow possible to specify this tmpfile file handle as the input argument for the externally ran program/script, say in io.popen - instead of using the (non-existing) tmpfile filename?
If above is not possible, what is the next best option (in terms of not having to maintain it, i.e. not having to remember to delete the file) for opening a temporary file in Lua?
You can get a temp filename with os.tmpname.
local n = os.tmpname()
local f = io.open(n, 'w+b')
f:write(....)
f:close()
os.remove(n)
If your purpose is sending some data to a python script, you can also use 'w' mode in popen.
--lua
local f = io.popen(prog, 'w')
f:write(....)
#python
import sys
data = sys.stdin.readline()

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

Lua, Specify where to create files for io.open?

How can I put the file created by io.open somewhere besides the folder the lua file is in.
local test = io.open("Test.html", "w")
test:write("Hello world.")
test:close()
Yoy simply supply a full path (or relative path) and not just a filename.
local test = io.open("c:\temp\Test.html", "w")

Load Lua-files by relative path

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

load file in lua

I have directory that contain multiple file
i need to load on specified file.
i know i can use loadfile(path) but how i need to specify which file to load
thank you
Jp
I'm not 100% sure I understand what you are asking, but here's my take on it. If you know the directory you need to load the file from, you'd just prefix it to the name of the file:
local f, error = loadfile(mydir .. "/my_file")
Note that this reads and parses the file. To actually execute it, you need to invoke the function you get back from loadfile() (so f() in this example). If there is an error, loadfile() returns nil and an error message.
path = "./path/to/a/file.lua"
local myreturn1, myreturn2 --[[etc]] = assert(loadfile(path))(myarg1, myarg2, myarg3 --[[etc]])

Resources