--[[ XChip's NodeMCU IDE Original Source: http://www.esp8266.com/viewtopic.php?f=19&t=1549 Petr Stehlik found the source in October 2016 and gave it a new home at https://github.com/joysfera/nodemcu-web-ide under the GPL license. Then updated it for new async socket send(), fixed, cleaned up, added external editor with syntax highlighting and further improves it. Dirk van den Brink, Jr. added minor tweaks Jan. 2019 --]] local function pairsByKeys (t, f) local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, f) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end local function editor(aceEnabled) -- feel free to disable the shiny Ajax.org Cloud Editor local AceEnabled = aceEnabled == nil and true or aceEnabled srv = net.createServer(net.TCP) srv:listen(80, function(conn) local rnrn = 0 local Status = 0 local DataToGet = 0 local method = "" local url = "" local vars = "" conn:on("receive", function(sck, payload) if Status == 0 then _, _, method, url, vars = string.find(payload, "([A-Z]+) /([^?]*)%??(.*) HTTP") -- print("Method, URL, vars: ", method, url, vars) end if method == "POST" then if Status == 0 then -- print("status", Status) _, _, DataToGet, payload = string.find(payload, "Content%-Length: (%d+)(.+)") if DataToGet then DataToGet = tonumber(DataToGet) -- print("DataToGet = "..DataToGet) rnrn = 1 Status = 1 else print("bad length") end end -- find /r/n/r/n if Status == 1 then -- print("status", Status) local payloadlen = string.len(payload) local mark = "\r\n\r\n" local i for i=1, payloadlen do if string.byte(mark, rnrn) == string.byte(payload, i) then rnrn = rnrn + 1 if rnrn == 5 then payload = string.sub(payload, i+1, payloadlen) file.open(url, "w") file.close() Status = 2 break end else rnrn = 1 end end if Status == 1 then return end end if Status == 2 then -- print("status", Status) if payload then DataToGet = DataToGet - string.len(payload) --print("DataToGet:", DataToGet, "payload len:", string.len(payload)) file.open(url, "a+") file.write(payload) file.close() else sck:send("HTTP/1.1 200 OK\r\n\r\nERROR") Status = 0 end if DataToGet == 0 then sck:send("HTTP/1.1 200 OK\r\n\r\nOK") Status = 0 end end return end -- end of POST method handling DataToGet = -1 if url == "favicon.ico" then -- print("favicon.ico handler sends 404") sck:send("HTTP/1.1 404 file not found\r\nServer: NodeMCU IDE\r\nContent-Type: text/html\r\n\r\n
" local function output_CB(opipe) -- upval: sck for line in opipe:reader() do sen = sen .. line .. "\n" end end node.output(output_CB, 0) ok, result = pcall(dofile, url) --delay the output capture by 1000 milliseconds to give some time to the user routine in pcall() tmr.create():alarm(1000, tmr.ALARM_SINGLE, function() node.output() if result then local outp = tostring(result):sub(1,1300) -- to fit in one send() packet result = nil sen = sen .. outp end sen = sen .. "
Name | Size | Edit | Compile | Delete | Run |
---|---|---|---|---|---|
" ..k.. " | " ..v.. " | " local editable = k:sub(-4, -1) == ".lua" or k:sub(-4, -1) == ".css" or k:sub(-5, -1) == ".html" or k:sub(-5, -1) == ".json" or k:sub(-4, -1) == ".txt" or k:sub(-4, -1) == ".csv" or k:sub(-3, -1) == ".md" if editable then line = line .. "edit" end line = line .. " | " if k:sub(-4, -1) == ".lua" then line = line .. "compile" end line = line .. " | delete | " if ((k:sub(-4, -1) == ".lua") or (k:sub(-3, -1) == ".lc")) then line = line .. "run |