added mdbrowse and mdparse.
This commit is contained in:
parent
555081ca98
commit
b54cf24294
14
README.md
14
README.md
@ -1,3 +1,15 @@
|
|||||||
# mdgopher
|
# mdgopher
|
||||||
|
|
||||||
Gopher + Markdown. Kinda defeats the purpose but hey whatever.
|
Gopher + Markdown. Kinda defeats the purpose but hey whatever.
|
||||||
|
|
||||||
|
## mdbrowse
|
||||||
|
A terrible lua-curses and luasocket based markdown browser.
|
||||||
|
|
||||||
|
Gopher menu support is experimental but markdown support should work fairly well.
|
||||||
|
|
||||||
|
### keybinds
|
||||||
|
- j and k for scrolling
|
||||||
|
- f to follow a link (marked by a [number])
|
||||||
|
- o to open a URL
|
||||||
|
- s for settings (terminal size and etc.)
|
||||||
|
- q to quit
|
||||||
|
245
mdbrowse.lua
Normal file
245
mdbrowse.lua
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
local curses = require "curses"
|
||||||
|
local md = require "mdparse"
|
||||||
|
local socket = require "socket"
|
||||||
|
local surl = require "socket.url"
|
||||||
|
|
||||||
|
local sx,sy,pc = 80, 25, "@"
|
||||||
|
|
||||||
|
local function pgopher(gm)
|
||||||
|
local s = ""
|
||||||
|
for line in gm:gmatch("[^\n]+") do
|
||||||
|
local t = line:sub(1,1)
|
||||||
|
if t == "i" then
|
||||||
|
if line:find("\t") then
|
||||||
|
line=line:sub(1,line:find("\t"))
|
||||||
|
end
|
||||||
|
s=s..line:sub(2).."\n"
|
||||||
|
elseif t == "0" or t == "1" then
|
||||||
|
line=line:gsub("(.)(.+)\t/?([%w%./]+)\t([%w%.]+)\t(%d+)","%1 [%2](gopher://%4:%5/%3")..")" -- we gsub now
|
||||||
|
line=line:gsub("\n","")
|
||||||
|
s=s..line.."\n"
|
||||||
|
else
|
||||||
|
s=s..line.."\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
local function geturl(url)
|
||||||
|
local ds = {}
|
||||||
|
ds.scheme = "gopher"
|
||||||
|
ds.port = "70"
|
||||||
|
ds.path = ""
|
||||||
|
local c = ""
|
||||||
|
local ourl = url
|
||||||
|
tURL = surl.parse(url,ds)
|
||||||
|
if not tURL.host then tURL.host = tURL.path tURL.path = "" end
|
||||||
|
local dn, po, pt = tURL.host, tURL.port, tURL.path
|
||||||
|
print(dn,po,pt)
|
||||||
|
if dn and po then
|
||||||
|
local s=socket.tcp()
|
||||||
|
s:connect(dn,po)
|
||||||
|
s:send(pt.."\n")
|
||||||
|
c=s:receive("*a")
|
||||||
|
s:close()
|
||||||
|
local w,tpg = pcall(pgopher,c)
|
||||||
|
if w then
|
||||||
|
print(tpg)
|
||||||
|
c=tpg
|
||||||
|
end
|
||||||
|
else
|
||||||
|
c="Unable to load URL "..ourl
|
||||||
|
end
|
||||||
|
--[[--
|
||||||
|
else
|
||||||
|
local f=io.open(url,"rb")
|
||||||
|
if not f then
|
||||||
|
return "\r\nPage could not be loaded."
|
||||||
|
end
|
||||||
|
c=f:read("*a")
|
||||||
|
print(c)
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
--]]--
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
local function settings()
|
||||||
|
while true do
|
||||||
|
local scr = curses.initscr ()
|
||||||
|
|
||||||
|
curses.cbreak ()
|
||||||
|
curses.echo (false) -- not noecho !
|
||||||
|
curses.nl (false) -- not nonl !
|
||||||
|
local selection = 1
|
||||||
|
while true do
|
||||||
|
local menu = {"Screen width: "..tostring(sx),"Screen height: "..tostring(sy),"Back"}
|
||||||
|
scr:clear()
|
||||||
|
scr:refresh()
|
||||||
|
for k,v in ipairs(menu) do
|
||||||
|
if k == selection then
|
||||||
|
io.write(" * ")
|
||||||
|
end
|
||||||
|
print("\t"..v.."\r")
|
||||||
|
end
|
||||||
|
local ch = scr:getch()
|
||||||
|
if ch == 66 then
|
||||||
|
selection = selection + 1
|
||||||
|
elseif ch == 65 then
|
||||||
|
selection = selection - 1
|
||||||
|
elseif ch == 13 then break
|
||||||
|
end
|
||||||
|
if selection > #menu then
|
||||||
|
selection = #menu
|
||||||
|
elseif selection < 1 then
|
||||||
|
selection = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if selection == 1 then
|
||||||
|
scr:clear()
|
||||||
|
scr:refresh()
|
||||||
|
scr:addstr("New screen width: ")
|
||||||
|
curses.echo (true)
|
||||||
|
scr:refresh()
|
||||||
|
sx = tonumber(scr:getstr()) or 80
|
||||||
|
curses.echo (false)
|
||||||
|
elseif selection == 2 then
|
||||||
|
scr:clear()
|
||||||
|
scr:refresh()
|
||||||
|
scr:addstr("New screen height: ")
|
||||||
|
curses.echo (true)
|
||||||
|
scr:refresh()
|
||||||
|
sy = tonumber(scr:getstr()) or 80
|
||||||
|
curses.echo (false)
|
||||||
|
else
|
||||||
|
scr:close()
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function main ()
|
||||||
|
local scr = curses.initscr ()
|
||||||
|
local mode = 1
|
||||||
|
local p = false
|
||||||
|
local sc = "#"
|
||||||
|
local history = {}
|
||||||
|
|
||||||
|
curses.cbreak ()
|
||||||
|
curses.echo(false) -- not noecho !
|
||||||
|
curses.nl(false) -- not nonl !
|
||||||
|
|
||||||
|
cy = 1
|
||||||
|
local ts = [[
|
||||||
|
**SKS Markdown Gopher Client**
|
||||||
|
|
||||||
|
See the [SKS gopher hole](gopher://shadowkat.net) for more info.
|
||||||
|
|
||||||
|
Use *f* to follow a link, *o* to open a URL directly, *j* and *k* to scroll, and *s* for settings.
|
||||||
|
|
||||||
|
Scrolling test:
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
g
|
||||||
|
h
|
||||||
|
i
|
||||||
|
j
|
||||||
|
k
|
||||||
|
l
|
||||||
|
m
|
||||||
|
n
|
||||||
|
o
|
||||||
|
p
|
||||||
|
q
|
||||||
|
r
|
||||||
|
s
|
||||||
|
t
|
||||||
|
u
|
||||||
|
v
|
||||||
|
w
|
||||||
|
x
|
||||||
|
y
|
||||||
|
z]]
|
||||||
|
local url = "homepage"
|
||||||
|
local lt = {}
|
||||||
|
while true do
|
||||||
|
scr:clear()
|
||||||
|
scr:refresh()
|
||||||
|
local ds = ""
|
||||||
|
local dt = {}
|
||||||
|
lt = md.parse(ts).l
|
||||||
|
for k,v in ipairs(md.parse(ts)) do
|
||||||
|
--[[--
|
||||||
|
if v.bold then -- note to self: fix bold
|
||||||
|
v.content = "\27[n1"..v.content.."\27[n0"
|
||||||
|
end
|
||||||
|
--]]--
|
||||||
|
if v.addrid then
|
||||||
|
ds=ds.."["..tostring(v.addrid).."]"..v.content
|
||||||
|
else
|
||||||
|
ds=ds..v.content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for line in ds:gmatch("[^\n]*") do
|
||||||
|
while line:len() > 0 do
|
||||||
|
dt[#dt+1] = line:sub(1,sx)
|
||||||
|
line = line:sub(sx+1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if sy < #dt then
|
||||||
|
ms = sy
|
||||||
|
else
|
||||||
|
ms = #dt
|
||||||
|
end
|
||||||
|
for i = cy, cy+ms do
|
||||||
|
io.write((dt[i] or "").."\r\n")
|
||||||
|
end
|
||||||
|
print("\r\n["..url.." "..tostring(cy).."/"..tostring(#dt).." "..tostring(ts:len()).."]\r")
|
||||||
|
ch = scr:getch() or 0
|
||||||
|
if ch < 256 then
|
||||||
|
if string.char(ch) == "q" then
|
||||||
|
break
|
||||||
|
elseif string.char(ch) == "s" then
|
||||||
|
settings()
|
||||||
|
elseif string.char(ch) == "o" then
|
||||||
|
scr:addstr("\rURL: ")
|
||||||
|
curses.echo(true)
|
||||||
|
scr:refresh()
|
||||||
|
local nurl = scr:getstr()
|
||||||
|
local w,nts=pcall(geturl,nurl)
|
||||||
|
--print(w,nts)
|
||||||
|
if w then ts = nts url=nurl end
|
||||||
|
local nurl = scr:getstr()
|
||||||
|
elseif string.char(ch) == "f" then
|
||||||
|
scr:addstr("\rLink: ")
|
||||||
|
curses.echo(true)
|
||||||
|
scr:refresh()
|
||||||
|
local nurl = lt[tonumber(scr:getstr())]
|
||||||
|
local w,nts=pcall(geturl,nurl)
|
||||||
|
if w then ts = nts url=nurl end
|
||||||
|
scr:refresh()
|
||||||
|
elseif string.char(ch) == "j" then
|
||||||
|
if cy < #dt then
|
||||||
|
cy = cy + 1
|
||||||
|
end
|
||||||
|
elseif string.char(ch) == "k" then
|
||||||
|
if cy > 1 then
|
||||||
|
cy = cy - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function err (err)
|
||||||
|
curses.endwin ()
|
||||||
|
print "Caught an error:"
|
||||||
|
print (debug.traceback (err, 2))
|
||||||
|
os.exit (2)
|
||||||
|
end
|
||||||
|
|
||||||
|
xpcall (main, err)
|
50
mdparse.lua
Normal file
50
mdparse.lua
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
local md = {}
|
||||||
|
function md.parse(md)
|
||||||
|
local it = {}
|
||||||
|
it.l = {}
|
||||||
|
it[#it+1] = {["content"]="",["bold"]=false,["italic"]=false}
|
||||||
|
local lc,llc = "",""
|
||||||
|
local function newpart()
|
||||||
|
it[#it+1] = {["content"]="",["bold"]=it[#it].bold,["italic"]=it[#it].italic}
|
||||||
|
end
|
||||||
|
newpart()
|
||||||
|
local lm = false
|
||||||
|
for c in md:gmatch(".") do
|
||||||
|
if 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 == "[" then
|
||||||
|
newpart()
|
||||||
|
elseif c == "(" and lc == "]" then
|
||||||
|
lm = true
|
||||||
|
it[#it].content = it[#it].content:sub(1,-2)
|
||||||
|
it[#it].address = ""
|
||||||
|
elseif c == ")" and lm then
|
||||||
|
lm = false
|
||||||
|
it.l[#it.l+1] = it[#it].address
|
||||||
|
it[#it].addrid = #it.l
|
||||||
|
newpart()
|
||||||
|
else
|
||||||
|
if not lm then
|
||||||
|
it[#it].content = it[#it].content .. c
|
||||||
|
else
|
||||||
|
it[#it].address = it[#it].address .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
llc = lc
|
||||||
|
lc = c
|
||||||
|
end
|
||||||
|
for k,v in pairs(it) do
|
||||||
|
if v.content then
|
||||||
|
v.content = v.content:gsub("\n","\r\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return it
|
||||||
|
end
|
||||||
|
return md
|
Loading…
Reference in New Issue
Block a user