library import hack

If you’re willing to break the lua sandbox, here’s a bit of code that makes library management easier. This allows you to write import(“myProject”) to load another project. DISCLAIMER: it uses unsupported features and will likely break on future updates.

Anyway, this will execute the tabs in the order they appear in the codea editor. Note that if “myProject” defines global functions like setup() and draw(), this will end up overriding those functions.

Replace Codea.app/LuaSandbox.lua with:

Edit: improved error messages and added a check so that it doesn’t load the same project twice. I’m thinking you just add import(“myProject”) at the top in each tab that uses that project

-- This file is loaded before any user scripts, removing unsafe environment functions

------------------------------------------------
-- Block out any dangerous or insecure functions
------------------------------------------------

arg=nil

__loadedProjects = {}
import = function(projectName)
	if __loadedProjects[projectName] then return nil end -- prevents re-loading of a project
	__loadedProjects[projectName]=1
	
    -- load Info.plist
    local home = os.getenv("HOME")
    local dir = home.."/Documents/"..projectName..".codea/"
    local info_fname = dir.."Info.plist"
    local info_file = io.open(info_fname,"r")
    assert(info_file~=nil,"Could not open "..info_fname.." in "..projectName)
    local contents = ""
    for line in io.lines(info_fname) do
        contents = contents..line.."\
"
    end
    
    -- find the buffer order
    local bufferKey = "<key>Buffer Order</key>"
    local idx = contents:find(bufferKey)
    assert(idx~=nil,"Could not find buffer order in "..info_fname.." in "..projectName)
    contents = contents:sub(idx)
    
    -- find the end of the buffer order
    local idx2 = contents:find("</array>")
    assert(idx2~=nil,"Could not find the end of the buffer order in "..info_fname.." in "..projectName)
    contents = contents:sub(1,idx2)
    
    -- fin the buffer names
    local buffers = {}
    for buff in contents:gmatch("<string>([%a%s%d]+)</string>") do
        table.insert(buffers,buff)
    end
    
    -- load each buffer
    for _,buff in ipairs(buffers) do
        local buff_fname = dir..buff..".lua"
        local f = loadfile(buff_fname)
		assert(f~=nil,"Could not load file "..buff..".lua in "..projectName)
        f()
    end
end

--[[
rawget=nil
rawset=nil
rawequal=nil
setfenv=nil
getfenv=nil
string.dump=nil
dofile=nil
io={write=io.write}

load=nil
loadfile=nil

os.execute=nil
os.getenv=nil
os.remove=nil
os.rename=nil
os.tmpname=nil
os.exit=nil
--]]
--[[
-- We allow:
os.time
os.setlocale
os.difftime
os.date
os.clock
--]]
--[[
package.loaded.io=io
package.loaded.package=nil
package=nil
require=nil
--]]

This is great! I’ve tried it and works perfectly. Why isn’t this standard in Codea?

looks like it’s in the plans http://twolivesleft.com/Codea/Talk/discussion/1047/feature-request%3A-common-code-between-projects/p1

But yes this works really well for me too, and I’ve been using it since. It even gives line numbers of files in the imported project when there’s an error. The downside is switching back and forth between projects when developing, for example when you want to add or modify a library.

@Simeon maybe when you add project importing to codea have a way to quickly go to a library from your main project

Hi, great example. Do you know if there’s any chance to browse/load text files also from dropbox? does it exists a similar env name (like “HOME”) that allows to browse the dropbox synched files?