2151 posts
Location
Auckland, New Zealand
Posted 15 March 2013 - 10:05 AM
Essentially what I am trying to do is make a custom include function so that if I include the file 'One' and that contains an include to file 'Two', Two becomes One.Two
For example:
Startup or whatever
include("One")
print(One.Two) --should be Testing123
One
include("Two")
Two
return "Testing123"
So essentially rather than two being _G.Two I would like it to be _G.One.Two
The way I've been trying to do it doesn't really work. Anyone have a suggestion on how to do this?
8543 posts
Posted 15 March 2013 - 10:14 AM
Try customizing os.loadAPI. It nearly has the functionality you're looking for. getfenv() maaay be able to get you the rest of the way there.
2151 posts
Location
Auckland, New Zealand
Posted 15 March 2013 - 10:21 AM
Try customizing os.loadAPI. It nearly has the functionality you're looking for. getfenv() maaay be able to get you the rest of the way there.
That's what I've tried. It's setting the key for
_G[…] = tAPI that I can't get.
Here's the (rather messy) code I have at the moment:
function include(_sPath)
-- the os.loadAPI slightly modified
local sName = fs.getName( _sPath )
local tEnv = {
include = include
}
setmetatable( tEnv, { __index = _G } )
local fnAPI, err = loadfile( _sPath )
if fnAPI then
setfenv( fnAPI, tEnv )
includeStack[#includeStack + 1] = sName
print(#includeStack)
fnAPI()
else
error("Failed to include '"..sName.."'. "..err)
return false
end
local tAPI = {}
for k,v in pairs( tEnv ) do
tAPI[k] = v
end
--[[
--another failed attempt
local tTbl = _G
for _,v in ipairs( includeStack ) do
if tTbl == nil then
tTbl = {}
end
tTbl = tTbl[v]
end]]--
kStr = "_G"
for _,v in ipairs( includeStack ) do
kStr = kStr.."."..v
print(kStr)
end
tTbl = loadstring(kStr)
--this should just be replacing the load string, how do i set the key?
tTbl = tAPI
includeStack[#includeStack] = nil
return true
end
871 posts
Posted 15 March 2013 - 10:39 AM
some fiddling, using loadAPI as a base, came up with this, which seemed to work
local isIncluding = {}
local includeContext={_G}
function include(_sPath)
local sName = fs.getName( _sPath )
if isIncluding[sName] == true then
printError( "circular inclusion detected!" )
return false
end
isIncluding[sName] = true
local tAPI = {}
local myEnv=getfenv(1)
local tEnv = {}
setmetatable( tEnv, { __index = _G } )
local fnAPI, err = loadfile( _sPath )
if fnAPI then
setfenv( fnAPI, tEnv )
includeContext[#includeContext+1]=tAPI
fnAPI()
table.remove(includeContext)
else
printError( err )
isIncluding[sName] = nil
return false
end
for k,v in pairs( tEnv ) do
tAPI[k] = v
end
includeContext[#includeContext][sName] = tAPI
isIncluding[sName] = nil
return true
end
The test code I used:
Spoiler
file "a"
include.include("b")
function foo()
print("lib a")
end
file "b"
function foo()
print("lib b")
end
file "test"
os.loadAPI("include")
include.include("a")
a.foo()
a.b.foo()
2151 posts
Location
Auckland, New Zealand
Posted 15 March 2013 - 11:03 AM
some fiddling, using loadAPI as a base, came up with this, which seemed to work
local isIncluding = {}
local includeContext={_G}
function include(_sPath)
local sName = fs.getName( _sPath )
if isIncluding[sName] == true then
printError( "circular inclusion detected!" )
return false
end
isIncluding[sName] = true
local tAPI = {}
local myEnv=getfenv(1)
local tEnv = {}
setmetatable( tEnv, { __index = _G } )
local fnAPI, err = loadfile( _sPath )
if fnAPI then
setfenv( fnAPI, tEnv )
includeContext[#includeContext+1]=tAPI
fnAPI()
table.remove(includeContext)
else
printError( err )
isIncluding[sName] = nil
return false
end
for k,v in pairs( tEnv ) do
tAPI[k] = v
end
includeContext[#includeContext][sName] = tAPI
isIncluding[sName] = nil
return true
end
The test code I used:
Spoiler
file "a"
include.include("b")
function foo()
print("lib a")
end
file "b"
function foo()
print("lib b")
end
file "test"
os.loadAPI("include")
include.include("a")
a.foo()
a.b.foo()
Cheers, this looks good. I'll try it out soon.
871 posts
Posted 15 March 2013 - 11:09 AM
just noticed I forgot to remove that "myEnv=getfenv(1)" line. It is meaningless and should be snipped.