local net = require "net" local md = require "mdparse" local event = require "event" local fs = require "filesystem" local computer = require "computer" local home = "file:///usr/doc/mdbrowse.md" local url = home local cline = 1 local lines, links, listeners, history = {}, {}, {}, {} local width, height = 80, 23 local run = true local function pushhistory(url) history[#history+1] = url end local function pophistory() local rurl = history[#history] or home history[#history] = nil return rurl end local function parseurl(url) local proto,addr = url:match("(.-)://(.+)") addr = addr or url local hp, path = addr:match("(.-)(/.*)") hp, path = hp or addr, path or "/" local host, port = hp:match("(.+):(.+)") host = host or hp path = fs.canonical(path) return proto, host, port, path end function addButton(x,y,l,a) local len = l:len() + 2 local function hf(_,_,tx,ty) if y == ty and tx >= x and tx <= x+len then io.write("\a") computer.pushSignal("mdbrowsebutton",a) end end event.listen("touch",hf) listeners[#listeners+1] = hf end function dropButtons() for k,v in pairs(listeners) do event.ignore("touch",v) end end function loadpage() local protocol, host, port, path = parseurl(url) protocol = protocol or "file" if protocol == "file" then local f = io.open(host..path,"rb") if not f then url = pophistory() return false, "not found" end lines, links = md.reflow(f:read("*a"),width) f:close() return true elseif protocol == "fget" then port = tonumber(port) or 70 local socket = net.open(host,port) if socket then io.write("\27[u\27[2KConnection established.") local buf = "" socket:write("t"..path.."\n") local c = socket:read(1) repeat c = socket:read(1) os.sleep(0.5) until c ~= "" if c == "n" then buf = path..": Not found.\n" elseif c == "f" then buf = "Failure: \n" elseif c == "d" then buf = "# Directory listing for "..path.."\n" end repeat l = socket:read(1024) buf = buf .. l io.write("\27[u\27[2KRead "..tonumber(buf:len()).." bytes") os.sleep(0.5) until socket.state == "closed" and l == "" if c == "d" then local first, nbuf = false, "" for line in buf:gmatch("[^\n]+") do if first then line = "- ["..line.."]("..line..")" end nbuf = nbuf .. line .. "\n" first = true end buf = nbuf end lines, links = md.reflow(buf,width) return true else url = pophistory() return false, "unable to load" end end end function drawpage() dropButtons() if cline < 1 then cline = 1 elseif cline > #lines then cline = #lines end io.write("\27[2J\27[H") for i = cline, cline+height do print((lines[i] or ""):sub(1,width)) end for k,v in pairs(links) do if v[1] >= cline and v[1] <= height+cline then addButton(v[2],(v[1])-cline+1,v[3],v[4]) end end local lstring = tostring(cline).."-"..tostring(cline+height).."/"..tostring(#lines) io.write("\27[s"..lstring.." "..url) end function gourl(nurl) pushhistory(url) -- check for a protocol:// part if nurl:match(".+://") then url = nurl -- check for a / -- root relative elseif nurl:sub(1,1) == "/" then url = (url:match(".+://.-/" or url:match(".+://.+/?").."/")) .. nurl -- fail and assume relative else local host = (url:match(".+://.-/") or url:match(".+://.+/?").."/") local path = url:sub(host:len()+1) local tPath = fs.segments(path) local ntPath = fs.segments(nurl) if path:sub(path:len(),path:len()) ~= "/" then tPath[#tPath] = nil end for k,v in ipairs(ntPath) do tPath[#tPath+1] = v end url = host:sub(1,-2) for k,v in ipairs(tPath) do url = url .. "/" .. v end if nurl:sub(nurl:len(),nurl:len()) == "/" then url = url .. "/" end end end loadpage() drawpage() while run do local tev = {event.pull()} if tev[1] == "key_down" then if tev[3] == 0 and tev[4] == 200 then -- up cline = cline - 1 drawpage() elseif tev[3] == 0 and tev[4] == 208 then -- down cline = cline + 1 drawpage() elseif tev[3] == 0 and tev[4] == 203 then -- left url = pophistory() cline = 1 loadpage() drawpage() elseif tev[3] == 0 and tev[4] == 209 then -- page down cline = cline + height drawpage() elseif tev[3] == 0 and tev[4] == 201 then -- page up cline = cline - height drawpage() elseif tev[3] == 113 and tev[4] == 16 then -- q run = false elseif tev[3] == 111 then -- o io.write("\27[u\27[2K\27[sURL: ") gourl(io.read()) cline = 1 loadpage() drawpage() end elseif tev[1] == "mdbrowsebutton" then gourl(tev[2]) cline = 1 loadpage() drawpage() end end dropButtons() io.write("\27[2J\27[H")