Skip to content

Instantly share code, notes, and snippets.

@XanDDemoX
Last active December 19, 2015 17:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save XanDDemoX/5989154 to your computer and use it in GitHub Desktop.
Save XanDDemoX/5989154 to your computer and use it in GitHub Desktop.
---------------------------------------------------------
-- Include --
-- Dynamically loads a codea tab or project into and --
-- isolated enviroment or _G --
-- Written by XanDDemoX --
-- Version 1.01 --
---------------------------------------------------------
include = {}
-- create meta table
local includemeta = {}
-- debugging setup
local _debug = false
local _debugstring = ""
local function _dbgmsg(...)
if _debug == true then for i,v in ipairs(arg) do _debugstring=_debugstring..tostring(v) end
_debugstring=_debugstring.."\r\n\r\n"
end end
-- access to _G from isolated project/tab enviroments
local _defaultMT = {__index = _G}
-- cache
local _loaded = {}
includemeta.__call= function (self,...)
-- check params table
if arg == nil then return {} end if #arg == 0 then return {} end
local items = {}
local valid = true
-- validate items
for i,v in ipairs(arg) do
if valid and type(v) ~= "string" then valid = false end
-- check its not the main file
if valid and string.match(v,"[%a%d_]:Main") then valid = false end
if valid then
-- check whether its a class key filename format
if string.match(v,"[%a%d_]:[%a%d_]") then table.insert(items,v)-- add it too the list if it matches
elseif string.match(v,"[%a%d_]") then
-- otherwise assume project and get tabs list
local tabs = listProjectTabs(v)
if tabs == nil then _dbgmsg("Invalid project: ",v)
elseif #tabs == 0 then _dbgmsg("Invalid project: ",v)
else for ii,vv in ipairs(tabs) do if vv ~= "Main" then table.insert(items,v..":"..vv) end end
end
end
else _dbgmsg("Invalid tab or project: ",v) end
valid = true
end
-- check if anything was valid
if #items == 0 then return items end
-- load each item in order from the list of items
local namespace ={}
local tabs = {}
for i,v in ipairs(items) do
local projname,tabname = string.match(v,"([%a%d_]+):([%a%d_]+)")
-- create project cache
local proj = _loaded[projname]
if proj == nil then
proj = {}
proj.__meta=setmetatable({}, proj.__meta and { __index = proj.__meta } or _defaultMT)
_loaded[projname] = proj
end
-- create tab cache
if _loaded[projname][tabname] == nil then
local t = readProjectTab(v)
if t ~= nil then
-- load tab if read was successful
local func,err = loadstring("return function() "..t.." end")
if func ~= nil then -- set enviroment and fully load tab
local md = setmetatable({}, md and {__index = md} or {__index = proj.__meta} or _defaultMT)
if xpcall(setfenv(func(),md),function() _dbgmsg("Error in tab: ",v) end) then
-- try and call tab load if successful shallow copy into project meta table
-- and put reference tab meta table into cache
for kk,vv in pairs(md) do proj.__meta[kk]=vv end
_loaded[projname][tabname] = md
_dbgmsg("Successfully loaded tab: ",v)
end
end
end
end -- get tab from cache and shallow copy into return value
local tabmeta = _loaded[projname][tabname]
if tabmeta ~= nil then
for k,v in pairs(tabmeta) do
tabs[k] = v
namespace[projname] = namespace[projname] or {}
namespace[projname][k]=v
end
end
end
-- return tabs copied from cache
return tabs,namespace
end
function xinclude(...)
local ts,ns = include(...)
return ns
end
--setup include function
setmetatable(include,includemeta)
-- expose debug messages
include.debugstring=function() return _debugstring end
-- import the result from include into _G
function import(...) local tabs = include(...) for k,v in pairs(tabs) do _G[k]=v end return tabs end
function ximport(...) local ts,ns = include(...) for k,v in pairs(ns) do _G[k]=_G[k] or {}
for kk,vv in pairs(v) do _G[k][kk]=vv end
end end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment