Simple Gist Loader

If everything you need is to anonymously load code from gist into a project then you might use this script.

No GitHub login required. Loads multi-file gists. Tries to split single-file gists if in Codea project format. Requires Codea 1.5.


-- Simple gist loader
--
-- Usage:
-- Create a new project in Codea.
-- Go back to this script.
-- Type URL of gist in |defaulturl| below or edit entry box after running
--   this script.
-- Type name of newly created project in |projectName|.
-- Hit create and observe the messages in the output window.
--
-- Stephan Effelsberg, 2013
-- Public domain

-- Example: Cider Controls 1.5 from Mark
defaulturl = "https://gist.github.com/devilstower/3927497"
-- Name of local target project
projectName = ""

function setup()
    parameter.text("url", defaulturl)
    parameter.text("projectName")
    parameter.action("create", createFromGist)
end

function draw()
    runGistStateMachine()
end

-- Remove CR from text, we only need LF.
function removeCR(text)
    return string.gsub(text, "\\r", "")
end

-- Extract raw links from a gist.
-- Return list with links, may be empty.
function extractRawLinks(text)
    print("Extracting raw links")
    local links = {}
    for pat in string.gfind(text, [[title="View Raw" href="(.-)"]]) do
        print(pat)
        -- get tab name
        local start, stop, tab = string.find(pat, ".*/(.*)")
        -- strip .lua extension if found at end of name
        if string.find(tab, ".lua$") then
            tab = string.sub(tab, 1, -5)
        end
        table.insert(links, {link=pat, tab=tab})
    end
    if #links == 1 then
        links[1].tab = "Main"
    end
    for i, l in ipairs(links) do
        print("link= "..l.link.."  tab= "..l.tab)
    end
    return links
end

-- Split data into tabs by parsing it in Codea project format.
-- Returns a list of tabs with each entry containing
-- {<name of tab>, <contents of tab>}.
-- May return empty list if Codea project format is not recognized.
function splitIntoTabs(data)
    local tabs = {}
    -- current TAB header start, end, name
    local ts, te, tname = string.find(data, "\
%-%-# (%w+)\
")
    while tname ~= nil do
        -- find NEXT start, end, name
        local ns, ne, nname = string.find(data, "\
%-%-# (%w+)\
", te)
        local eod
        if ns ~= nil then
            eod = ns - 1
        else
            eod = -1
        end
        local tdata = string.sub(data, te + 1, eod)
        table.insert(tabs, {tname, tdata})
        te = ne
        tname = nname
    end
    return tabs
end

-- -- ---- ------ ---------- ----------------
--
-- Request
--
-- -- ---- ------ ---------- ----------------

reqResult = 0
reqData = nil

-- Request a URL.
-- Handles GitHub quirks.
-- Observe variable |reqResult| afterwards:
--   1: done, result in |reqData|
--   0: ongoing request
--  -1: HTTP error
--  -2: Network error
function request(url)
    reqResult = 0
    -- GitHub may serve files with escapes if an iPad is recognized,
    -- even if raw files are requested.
    http.request(url, reqSuccess, reqFailure, {useragent = ""})
end

function reqSuccess(data, status)
    print("status = " .. status)
    if status == 200 then
        reqData = data
        reqResult = 1
    else
        print("Communication error")
        reqResult = -1
    end
end

function reqFailure(err)
    print("Network error")
    print(err)
    reqResult = -2
end

-- -- ---- ------ ---------- ----------------
--
-- Gist State Machine
--
-- -- ---- ------ ---------- ----------------

-- List of links in a gist
glinks = nil
-- Count of handled gists
gcount = 0
-- State of the Gist State Machine
state = "idle"

function createFromGist()
    if state == "idle" then
        state = "makebasereq"
    else
        print("Not idle")
    end
end

function runGistStateMachine()
    if state == "idle" then
        -- tunix
    elseif state == "makebasereq" then
        request(url)
        state = "waitforbaseresponse"
    elseif state == "waitforbaseresponse" then
        if reqResult > 0 then
            glinks = extractRawLinks(reqData)
            gcount = 1
            state = "requestpart"
        elseif reqResult < 0 then
            state = "error"
        else
            -- wait
        end
    elseif state == "requestpart" then
        local link = glinks[gcount].link
        link = string.gsub(link, " ", "%%20")
        print("Requesting " .. link)
        request("https://gist.github.com" .. link)
        state = "waitpart"
    elseif state == "waitpart" then
        if reqResult > 0 then
            local data = removeCR(reqData)
            if #glinks == 1 then
                -- Only 1 file, try splitting it as if it's in
                -- Codea project format.
                local tabs = splitIntoTabs(data)
                if #tabs == 0 then
                    -- Not in Codea project format
                    local tab = glinks[gcount].tab
                    saveProjectTab(projectName .. ":" .. tab, data)
                    print("Updating " .. projectName .. ":" .. tab)
                else
                    -- Save each tab
                    for i, t in ipairs(tabs) do
                        saveProjectTab(projectName .. ":" .. t[1], t[2])
                        print("Updating " .. projectName .. ":" .. t[1])
                    end
                end
            else
                local tab = glinks[gcount].tab
                saveProjectTab(projectName .. ":" .. tab, data)
                print("Updating " .. projectName .. ":" .. tab)
            end
            gcount = gcount + 1
            if gcount > #glinks then
                print("All done")
                state = "idle"
            else
                state = "requestpart"
            end
        elseif reqResult < 0 then
            state = "error"
        else
            -- wait
        end
    elseif state == "error" then
        print("An HTTP error occurred ... resetting")
        state = "idle"
    else
        print("ERROR: Unknown state ... resetting")
        state = "idle"
    end
end

This is great, love that it can handle multiple files and split the Codea “project” format. Adding it to the FAQ.

Thanks @codeslinger. I have put your file in my repo : http://jmv38.comze.com/CODEAbis/server.php#GIST

What could another example for a URL be? I am always coming up with a 404 error

URl:
https://gist.github.com/CayDay47/17258
(Note, this url was a random url with my name and with the github website)

Sorry, I had it all wrong, ignore my previous comment and carry on. Good day!

Lol you have no idea how frusterating it is to not know what any of this means lol #IamN00b

Everybody starts as a noob, but if you keep reading and practising, you’ll learn fast

Thanks @Ignatz :smiley: