I forget
This commit is contained in:
parent
2b99c43a94
commit
9bad03be52
@ -2,7 +2,4 @@
|
||||
A markdown FRequest browser for OpenComputers.
|
||||
|
||||
## mdparse
|
||||
mdparse is the Markdown parsing library used for mdbrowser. It works under standard Lua as well as OpenComputers.
|
||||
|
||||
- `mdparse.parse(text:string): - table` Parses *text* into a table of tables. Each table should contain a .contents string, and if it is a link, then an .address string.
|
||||
- `mdparse.reflow(text:string, linewidth:number): table, table` - Returns a table of formatted lines, and a table of links, as `{x, y, label, address}`.
|
||||
|
196
mdbrowse.lua
Normal file
196
mdbrowse.lua
Normal file
@ -0,0 +1,196 @@
|
||||
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")
|
35
mdparse.lua
35
mdparse.lua
@ -6,7 +6,7 @@ function md.parse(md)
|
||||
it[#it+1] = {["content"]="",["bold"]=false,["italic"]=false}
|
||||
local lc,llc = "",""
|
||||
local function newpart()
|
||||
it[#it+1] = {["content"]=""}
|
||||
it[#it+1] = {["content"]="",["bold"]=it[#it].bold,["italic"]=it[#it].italic}
|
||||
end
|
||||
newpart()
|
||||
local lm = false
|
||||
@ -24,6 +24,15 @@ function md.parse(md)
|
||||
it.l[#it.l+1] = it[#it].address
|
||||
it[#it].addrid = #it.l
|
||||
newpart()
|
||||
elseif c == "*" then
|
||||
if lc == "*" then
|
||||
it[#it].italic = false
|
||||
it[#it].italic = it[#it-1].italic
|
||||
it[#it].bold = not it[#it].bold
|
||||
else
|
||||
newpart()
|
||||
it[#it].italic = not it[#it].italic
|
||||
end
|
||||
elseif c == "\n" and lc == "\n" then
|
||||
if it[#it-1].content == "\n" then
|
||||
table.remove(it,#it-1)
|
||||
@ -33,11 +42,15 @@ function md.parse(md)
|
||||
newpart()
|
||||
elseif c == "\n" then
|
||||
local line = md:sub(1,cc):match(".+\n(.+)") or it[#it].content
|
||||
if line:sub(1,1) == "-" then
|
||||
if line:sub(line:find("%S")) == "-" then
|
||||
newpart()
|
||||
it[#it].content = "\n"
|
||||
newpart()
|
||||
elseif line:sub(1,1) == "#" then
|
||||
elseif line:sub(line:find("%S")) == "#" then
|
||||
newpart()
|
||||
it[#it].content = "\n"
|
||||
newpart()
|
||||
elseif line:find("%s-%d+%.") == 1 then
|
||||
newpart()
|
||||
it[#it].content = "\n"
|
||||
newpart()
|
||||
@ -58,13 +71,27 @@ function md.parse(md)
|
||||
end
|
||||
|
||||
function md.reflow(text,len)
|
||||
local words, lines, links = {}, {""}, {}
|
||||
local words, lines, links, lastitalic, lastbold = {}, {""}, {}, false, false
|
||||
for k,v in ipairs(md.parse(text)) do
|
||||
if v.content == "\n\n" or v.content == "\n" then
|
||||
words[#words+1] = {v.content}
|
||||
elseif not v.address then
|
||||
for word in v.content:gmatch("%S+") do
|
||||
words[#words+1] = {word}
|
||||
if v.italic and not lastitalic then
|
||||
words[#words][1] = "\27[30;47m"..words[#words][1]
|
||||
lastitalic = not lastitalic
|
||||
elseif not v.italic and lastitalic then
|
||||
words[#words-1][1] = words[#words-1][1].."\27[0m"
|
||||
lastitalic = not lastitalic
|
||||
end
|
||||
if v.bold and not lastbold then
|
||||
words[#words][1] = "\27[31m"..words[#words][1]
|
||||
lastbold = not lastbold
|
||||
elseif not v.bold and lastbold then
|
||||
words[#words-1][1] = words[#words-1][1].."\27[0m"
|
||||
lastbold = not lastbold
|
||||
end
|
||||
end
|
||||
else
|
||||
words[#words+1] = {v.content,v.address}
|
||||
|
Loading…
Reference in New Issue
Block a user