forked from izaya/OC-PsychOS2
Compare commits
No commits in common. "56af6d1ade673edf13a8121dd6558f07ed4d0aa6" and "e09650276a19bc3b02442fcdbfaab0c474368862" have entirely different histories.
56af6d1ade
...
e09650276a
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
|
apidoc.md
|
||||||
|
apidoc.html
|
||||||
*.cpio
|
*.cpio
|
||||||
*.af
|
*.af
|
||||||
/target
|
/target
|
||||||
/doc
|
|
||||||
|
7
build.sh
7
build.sh
@ -1,14 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
LUA=${LUA:-lua}
|
LUA=${LUA:-lua}
|
||||||
rm -r target/*
|
rm -r target/*
|
||||||
mkdir -p target/doc &>/dev/null
|
mkdir target &>/dev/null
|
||||||
$LUA luapreproc.lua module/init.lua target/init.lua
|
$LUA luapreproc.lua module/init.lua target/init.lua
|
||||||
echo _OSVERSION=\"PsychOS 2.0a2-$(git rev-parse --short HEAD)\" > target/version.lua
|
echo _OSVERSION=\"PsychOS 2.0a2-$(git rev-parse --short HEAD)\" > target/version.lua
|
||||||
cat target/version.lua target/init.lua > target/tinit.lua
|
cat target/version.lua target/init.lua > target/tinit.lua
|
||||||
mv target/tinit.lua target/init.lua
|
mv target/tinit.lua target/init.lua
|
||||||
cp -r service/ lib/ cfg/ target/
|
cp -r service/ lib/ cfg/ target/
|
||||||
|
$LUA finddesc.lua $(find module/ -type f) $(find lib/ -type f) > apidoc.md
|
||||||
rm target/version.lua
|
rm target/version.lua
|
||||||
rm -r doc/ &>/dev/null
|
|
||||||
$LUA finddesc.lua doc/ $(find lib/ module/ -type f|sort)
|
|
||||||
$LUA gendoc.lua target/doc/kernel.dict $(find module/ -type f|sort)
|
|
||||||
pandoc doc/apidoc.md docs-metadata.yml --template=template.tex -o doc/apidoc.pdf
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'PsychOS API Documentation'
|
|
||||||
---
|
|
75
finddesc.lua
75
finddesc.lua
@ -1,60 +1,27 @@
|
|||||||
#!/usr/bin/env lua
|
|
||||||
local doc = require "lib/doc"
|
|
||||||
local tA = {...}
|
local tA = {...}
|
||||||
|
local docfiles = {}
|
||||||
local outpath = table.remove(tA,1)
|
for _,file in pairs(tA) do
|
||||||
|
docfiles[file] = {}
|
||||||
print(outpath)
|
local f = io.open(file)
|
||||||
|
local lines = {}
|
||||||
local function formatDocs(fd)
|
for l in f:read("*a"):gmatch("[^\n]+") do
|
||||||
local rs = ""
|
if l:find("function") and not l:find("local") then
|
||||||
for name,finfo in pairs(fd) do
|
lines[#lines+1] = l
|
||||||
if rs:len() > 0 then
|
|
||||||
rs = rs .. "\n\n"
|
|
||||||
end
|
end
|
||||||
local as = ""
|
|
||||||
for k,v in pairs(finfo.args) do
|
|
||||||
if k > 1 then
|
|
||||||
as = as .. ", "
|
|
||||||
end
|
|
||||||
as = as .. v[1]
|
|
||||||
if v[2] then
|
|
||||||
as = as .. "^"..v[2].."^"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local rt = ""
|
|
||||||
for k,v in pairs(finfo.outtypes or {}) do
|
|
||||||
if rt:len() > 0 then
|
|
||||||
rt = rt .. ", "
|
|
||||||
else
|
|
||||||
rt = ": "
|
|
||||||
end
|
|
||||||
rt = rt .. v
|
|
||||||
end
|
|
||||||
rs = string.format("%s## %s(%s)%s\n%s",rs,name,as,rt,finfo.description)
|
|
||||||
end
|
end
|
||||||
return rs
|
for k,v in pairs(lines) do
|
||||||
end
|
local name, args, desc = v:match("function%s+(.+)%s*%((.*)%)%s*%-%-%s*(.+)")
|
||||||
|
if name and args and desc then
|
||||||
os.execute("sh -c 'mkdir -p "..outpath .. "'")
|
docfiles[file][#docfiles[file]+1] = string.format("## %s(%s)\n%s\n",name,args,desc)
|
||||||
if outpath:sub(#outpath) == "/" then outpath = outpath:sub(1, #outpath - 1) end
|
end
|
||||||
local ad = io.open(outpath.."/apidoc.md","w")
|
|
||||||
|
|
||||||
for k,v in pairs(tA) do
|
|
||||||
local fd = doc.parsefile(v)
|
|
||||||
local ds = formatDocs(fd)
|
|
||||||
print(string.format("%s: %i",v,ds:len()))
|
|
||||||
if ds and ds:len() > 0 then
|
|
||||||
os.execute("sh -c 'mkdir -p $(dirname \""..outpath.."/"..v.."\")'")
|
|
||||||
local f = io.open(outpath.."/"..v:gsub("%.lua$",".md"),"wb")
|
|
||||||
f:write(string.format("# %s\n\n",v))
|
|
||||||
f:write(ds)
|
|
||||||
f:write("\n\n")
|
|
||||||
f:close()
|
|
||||||
ad:write(string.format("# %s\n\n",v))
|
|
||||||
ad:write(ds)
|
|
||||||
ad:write("\n\n")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ad:close()
|
for k,v in pairs(docfiles) do
|
||||||
|
if #v > 0 then
|
||||||
|
print("\n# "..k)
|
||||||
|
for l,m in pairs(v) do
|
||||||
|
print(m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
51
gendoc.lua
51
gendoc.lua
@ -1,51 +0,0 @@
|
|||||||
#!/usr/bin/env lua
|
|
||||||
local doc = require "lib/doc"
|
|
||||||
local ser = require "lib/serialization"
|
|
||||||
local tA = {...}
|
|
||||||
|
|
||||||
local outpath = table.remove(tA,1)
|
|
||||||
|
|
||||||
print(outpath)
|
|
||||||
|
|
||||||
local function formatDocs(fd)
|
|
||||||
local rs = ""
|
|
||||||
for name,finfo in pairs(fd) do
|
|
||||||
if rs:len() > 0 then
|
|
||||||
rs = rs .. "\n\n"
|
|
||||||
end
|
|
||||||
local as = ""
|
|
||||||
for k,v in pairs(finfo.args) do
|
|
||||||
if k > 1 then
|
|
||||||
as = as .. ", "
|
|
||||||
end
|
|
||||||
as = as .. v[1]
|
|
||||||
if v[2] then
|
|
||||||
as = as .. "^"..v[2].."^"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local rt = ""
|
|
||||||
for k,v in pairs(finfo.outtypes or {}) do
|
|
||||||
if rt:len() > 0 then
|
|
||||||
rt = rt .. ", "
|
|
||||||
else
|
|
||||||
rt = ": "
|
|
||||||
end
|
|
||||||
rt = rt .. v
|
|
||||||
end
|
|
||||||
rs = string.format("%s## %s(%s)%s\n%s",rs,name,as,rt,finfo.description)
|
|
||||||
end
|
|
||||||
return rs
|
|
||||||
end
|
|
||||||
|
|
||||||
local ad = io.open(outpath,"wb")
|
|
||||||
|
|
||||||
for k,v in pairs(tA) do
|
|
||||||
local fd = doc.parsefile(v)
|
|
||||||
local ds = ser.serialize(fd)
|
|
||||||
local tn = v:match("/(.+)$")
|
|
||||||
if ds:len() > 3 then
|
|
||||||
ad:write(tn.."\t"..ds:gsub("\n",""):gsub(", +",",").."\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ad:close()
|
|
15
lib/doc.lua
15
lib/doc.lua
@ -1,4 +1,3 @@
|
|||||||
local _,serial = pcall(require,"serialization")
|
|
||||||
local doc = {}
|
local doc = {}
|
||||||
doc.searchers = {}
|
doc.searchers = {}
|
||||||
doc.tctab = {
|
doc.tctab = {
|
||||||
@ -97,20 +96,6 @@ function doc.searchers.lib(name) -- string -- string string -- Tries to find a d
|
|||||||
if not dt then return false, "unable to find documentation for "..tostring(name) end
|
if not dt then return false, "unable to find documentation for "..tostring(name) end
|
||||||
return doc.format(dt)
|
return doc.format(dt)
|
||||||
end
|
end
|
||||||
function doc.searchers.cdoc(topic) -- string -- string string -- Searches for documentation labelled as *topic* in .dict files under /boot/doc/
|
|
||||||
if not serial then return end
|
|
||||||
for k,v in ipairs(fs.list("/boot/doc")) do
|
|
||||||
if v:sub(-5) == ".dict" then
|
|
||||||
local f=io.open("/boot/doc/"..v,"rb")
|
|
||||||
for line in f:lines() do
|
|
||||||
local mname, docs = line:match("^(.-)\t(.+)$")
|
|
||||||
if mname == topic or mname == topic..".lua" then
|
|
||||||
return doc.format(serial.unserialize(docs))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function doc.docs(topic) -- string -- boolean -- Displays the documentation for *topic*, returning true, or errors. Also callable as just doc().
|
function doc.docs(topic) -- string -- boolean -- Displays the documentation for *topic*, returning true, or errors. Also callable as just doc().
|
||||||
local lib = os.getenv("LIB") or "/boot/lib"
|
local lib = os.getenv("LIB") or "/boot/lib"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
local event = {}
|
local event = {}
|
||||||
function event.pull(t,...) -- number -- -- return an event, optionally with timeout *t* and filter *...*.
|
function event.pull(t,...) -- return an event, optionally with timeout *t* and filter *...*.
|
||||||
local tA = {...}
|
local tA = {...}
|
||||||
if type(t) == "string" then
|
if type(t) == "string" then
|
||||||
table.insert(tA,1,t)
|
table.insert(tA,1,t)
|
||||||
@ -26,7 +26,7 @@ function event.pull(t,...) -- number -- -- return an event, optionally with time
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function event.listen(e,f) -- string function -- -- run function *f* for every occurance of event *e*
|
function event.listen(e,f) -- run function *f* for every occurance of event *e*
|
||||||
os.spawn(function() while true do
|
os.spawn(function() while true do
|
||||||
local tEv = {coroutine.yield()}
|
local tEv = {coroutine.yield()}
|
||||||
if tEv[1] == e then
|
if tEv[1] == e then
|
||||||
@ -36,7 +36,7 @@ function event.listen(e,f) -- string function -- -- run function *f* for every o
|
|||||||
end end,string.format("[%d] %s listener",os.pid(),e))
|
end end,string.format("[%d] %s listener",os.pid(),e))
|
||||||
end
|
end
|
||||||
|
|
||||||
function event.ignore(e,f) -- string function -- -- stop function *f* running for every occurance of event *e*
|
function event.ignore(e,f) -- stop function *f* running for every occurance of event *e*
|
||||||
computer.pushSignal("unlisten",e,tostring(f))
|
computer.pushSignal("unlisten",e,tostring(f))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ net.minport = 32768
|
|||||||
net.maxport = 65535
|
net.maxport = 65535
|
||||||
net.openports = {}
|
net.openports = {}
|
||||||
|
|
||||||
function net.genPacketID() -- -- string -- generate a random 16-character string, for use in packet IDs
|
function net.genPacketID() -- generate a random 16-character string, for use in packet IDs
|
||||||
local npID = ""
|
local npID = ""
|
||||||
for i = 1, 16 do
|
for i = 1, 16 do
|
||||||
npID = npID .. string.char(math.random(32,126))
|
npID = npID .. string.char(math.random(32,126))
|
||||||
@ -20,11 +20,11 @@ function net.genPacketID() -- -- string -- generate a random 16-character string
|
|||||||
return npID
|
return npID
|
||||||
end
|
end
|
||||||
|
|
||||||
function net.usend(to,port,data,npID) -- string number string string -- -- send an unreliable packet to host *to* on port *port* with data *data*, optionally with the packet ID *npID*
|
function net.usend(to,port,data,npID) -- send an unreliable packet to host *to* on port *port* with data *data*, optionally with the packet ID *npID*
|
||||||
computer.pushSignal("net_send",0,to,port,data,npID)
|
computer.pushSignal("net_send",0,to,port,data,npID)
|
||||||
end
|
end
|
||||||
|
|
||||||
function net.rsend(to,port,data,block) -- string number string boolean -- boolean -- send a reliable packet to host *to* on port *port* with data *data*, with *block* set to true to disable blocking
|
function net.rsend(to,port,data,block) -- send a reliable packet to host *to* on port *port* with data *data*, with *block* set to true to disable blocking
|
||||||
local pid, stime = net.genPacketID(), computer.uptime() + net.streamdelay
|
local pid, stime = net.genPacketID(), computer.uptime() + net.streamdelay
|
||||||
computer.pushSignal("net_send",1,to,port,data,pid)
|
computer.pushSignal("net_send",1,to,port,data,pid)
|
||||||
if block then return false end
|
if block then return false end
|
||||||
@ -37,7 +37,7 @@ end
|
|||||||
|
|
||||||
-- ordered packet delivery, layer 4?
|
-- ordered packet delivery, layer 4?
|
||||||
|
|
||||||
function net.send(to,port,ldata) -- string number string -- boolean -- send arbitrary data *ldata* reliably to host *to* on port *port*
|
function net.send(to,port,ldata) -- send arbitrary data *ldata* reliably to host *to* on port *port*
|
||||||
local tdata = {}
|
local tdata = {}
|
||||||
if ldata:len() > net.mtu then
|
if ldata:len() > net.mtu then
|
||||||
for i = 1, ldata:len(), net.mtu do
|
for i = 1, ldata:len(), net.mtu do
|
||||||
@ -112,7 +112,7 @@ local function socket(addr,port,sclose)
|
|||||||
return conn
|
return conn
|
||||||
end
|
end
|
||||||
|
|
||||||
function net.open(to,port) -- string number -- buffer -- open a socket to host *to* on port *port*
|
function net.open(to,port) -- open a socket to host *to* on port *port*
|
||||||
if not net.rsend(to,port,"openstream") then return false, "no ack from host" end
|
if not net.rsend(to,port,"openstream") then return false, "no ack from host" end
|
||||||
local st = computer.uptime()+net.streamdelay
|
local st = computer.uptime()+net.streamdelay
|
||||||
local est = false
|
local est = false
|
||||||
@ -139,7 +139,7 @@ function net.open(to,port) -- string number -- buffer -- open a socket to host *
|
|||||||
return socket(to,data,sclose)
|
return socket(to,data,sclose)
|
||||||
end
|
end
|
||||||
|
|
||||||
function net.listen(port) -- number -- buffer -- listen for connections on port *port* in a blocking manner
|
function net.listen(port) -- listen for connections on port *port* in a blocking manner
|
||||||
repeat
|
repeat
|
||||||
_, from, rport, data = event.pull("net_msg")
|
_, from, rport, data = event.pull("net_msg")
|
||||||
until rport == port and data == "openstream"
|
until rport == port and data == "openstream"
|
||||||
@ -150,7 +150,7 @@ function net.listen(port) -- number -- buffer -- listen for connections on port
|
|||||||
return socket(from,nport,sclose)
|
return socket(from,nport,sclose)
|
||||||
end
|
end
|
||||||
|
|
||||||
function net.flisten(port,listener) -- number function -- function -- run function *listener* on a connection to *port*
|
function net.flisten(port,listener) -- run function *listener* on a connection to *port*
|
||||||
local function helper(_,from,rport,data)
|
local function helper(_,from,rport,data)
|
||||||
if rport == port and data == "openstream" then
|
if rport == port and data == "openstream" then
|
||||||
local nport = math.random(net.minport,net.maxport)
|
local nport = math.random(net.minport,net.maxport)
|
||||||
|
12
lib/rc.lua
12
lib/rc.lua
@ -22,7 +22,7 @@ local function saveConfig()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function rc.load(name,force) -- string boolean -- table -- Attempts to load service *name*, and if *force* is true, replaces the current instance.
|
function rc.load(name,force)
|
||||||
if force then
|
if force then
|
||||||
rc.stop(name)
|
rc.stop(name)
|
||||||
service[name] = nil
|
service[name] = nil
|
||||||
@ -35,7 +35,7 @@ function rc.load(name,force) -- string boolean -- table -- Attempts to load serv
|
|||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
|
||||||
function rc.stop(name,...) -- string -- boolean string -- Stops service *name*, supplying *...* to the stop function. Returns false and a reason if this fails.
|
function rc.stop(name,...)
|
||||||
if not service[name] then return false, "service not found" end
|
if not service[name] then return false, "service not found" end
|
||||||
if service[name].stop then
|
if service[name].stop then
|
||||||
service[name].stop(...)
|
service[name].stop(...)
|
||||||
@ -47,7 +47,7 @@ function rc.stop(name,...) -- string -- boolean string -- Stops service *name*,
|
|||||||
rc.pids[name] = nil
|
rc.pids[name] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function rc.start(name,...) -- string -- boolean string -- Stops service *name*, supplying *...* to the stop function. Returns false and a reason if this fails.
|
function rc.start(name,...)
|
||||||
rc.load(name)
|
rc.load(name)
|
||||||
if not service[name] then return false, "service not found" end
|
if not service[name] then return false, "service not found" end
|
||||||
local rv = {service[name].start(...)}
|
local rv = {service[name].start(...)}
|
||||||
@ -56,19 +56,19 @@ function rc.start(name,...) -- string -- boolean string -- Stops service *name*,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function rc.restart(name) -- string -- -- Restarts service *name* using rc.stop and rc.start.
|
function rc.restart(name)
|
||||||
rc.stop(name)
|
rc.stop(name)
|
||||||
rc.start(name)
|
rc.start(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
function rc.enable(name) -- string -- -- Enables service *name* being started on startup.
|
function rc.enable(name)
|
||||||
for k,v in pairs(cfg.enabled) do
|
for k,v in pairs(cfg.enabled) do
|
||||||
if v == name then return false end
|
if v == name then return false end
|
||||||
end
|
end
|
||||||
cfg.enabled[#cfg.enabled+1] = name
|
cfg.enabled[#cfg.enabled+1] = name
|
||||||
saveConfig()
|
saveConfig()
|
||||||
end
|
end
|
||||||
function rc.disable(name) -- string -- -- Disables service *name* being started on startup.
|
function rc.disable(name)
|
||||||
local disabled = false
|
local disabled = false
|
||||||
for k,v in pairs(cfg.enabled) do
|
for k,v in pairs(cfg.enabled) do
|
||||||
if v == name then table.remove(cfg.enabled,k) disabled = true break end
|
if v == name then table.remove(cfg.enabled,k) disabled = true break end
|
||||||
|
@ -27,7 +27,7 @@ function rpcf.list()
|
|||||||
return rt
|
return rt
|
||||||
end
|
end
|
||||||
|
|
||||||
function rpc.call(hostname,fn,...) -- string string -- boolean -- Calls exported function *fn* on host *hostname*, with parameters *...*, returning whatever the function returns, or false.
|
function rpc.call(hostname,fn,...)
|
||||||
if hostname == "localhost" then
|
if hostname == "localhost" then
|
||||||
return rpcf[fn](...)
|
return rpcf[fn](...)
|
||||||
end
|
end
|
||||||
@ -44,7 +44,7 @@ function rpc.call(hostname,fn,...) -- string string -- boolean -- Calls exported
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
function rpc.proxy(hostname,filter) -- string string -- table -- Returns a component.proxy()-like table from the functions on *hostname* with names matching *filter*.
|
function rpc.proxy(hostname,filter)
|
||||||
filter=(filter or "").."(.+)"
|
filter=(filter or "").."(.+)"
|
||||||
local fnames = rpc.call(hostname,"list")
|
local fnames = rpc.call(hostname,"list")
|
||||||
if not fnames then return false end
|
if not fnames then return false end
|
||||||
@ -59,7 +59,7 @@ function rpc.proxy(hostname,filter) -- string string -- table -- Returns a compo
|
|||||||
end
|
end
|
||||||
return rt
|
return rt
|
||||||
end
|
end
|
||||||
function rpc.register(name,fn) -- string function -- -- Registers a function to be exported by the RPC library.
|
function rpc.register(name,fn)
|
||||||
local rpcrunning = false
|
local rpcrunning = false
|
||||||
for k,v in pairs(os.tasks()) do
|
for k,v in pairs(os.tasks()) do
|
||||||
if os.taskInfo(v).name == "rpc daemon" then
|
if os.taskInfo(v).name == "rpc daemon" then
|
||||||
|
@ -3,7 +3,7 @@ local local_pairs=function(tbl)
|
|||||||
local mt=getmetatable(tbl)
|
local mt=getmetatable(tbl)
|
||||||
return (mt and mt.__pairs or pairs)(tbl)
|
return (mt and mt.__pairs or pairs)(tbl)
|
||||||
end
|
end
|
||||||
function serial.serialize(value,af) -- boolean -- string -- serialize *value* into a string. If *af* is true, allow functions. This breaks unserialization.
|
function serial.serialize(value,af) -- serialize *value* into a string. If *af* is true, allow functions. This breaks unserialization.
|
||||||
local kw={["and"]=true,["break"]=true,["do"]=true,["else"]=true,["elseif"]=true,["end"]=true,["false"]=true,["for"]=true,["function"]=true,["goto"]=true,["if"]=true,["in"]=true,["local"]=true,["nil"]=true,["not"]=true,["or"]=true,["repeat"]=true,["return"]=true,["then"]=true,["true"]=true,["until"]=true,["while"]=true}
|
local kw={["and"]=true,["break"]=true,["do"]=true,["else"]=true,["elseif"]=true,["end"]=true,["false"]=true,["for"]=true,["function"]=true,["goto"]=true,["if"]=true,["in"]=true,["local"]=true,["nil"]=true,["not"]=true,["or"]=true,["repeat"]=true,["return"]=true,["then"]=true,["true"]=true,["until"]=true,["while"]=true}
|
||||||
local id="^[%a_][%w_]*$"
|
local id="^[%a_][%w_]*$"
|
||||||
local ts={}
|
local ts={}
|
||||||
@ -40,7 +40,7 @@ function serial.serialize(value,af) -- boolean -- string -- serialize *value* in
|
|||||||
else error("ut "..t) end end
|
else error("ut "..t) end end
|
||||||
return s(value, 1)
|
return s(value, 1)
|
||||||
end
|
end
|
||||||
function serial.unserialize(data) -- string -- -- return *data*, but unserialized
|
function serial.unserialize(data) -- return *data*, but unserialized
|
||||||
checkArg(1, data, "string")
|
checkArg(1, data, "string")
|
||||||
local result, reason = load("return " .. data, "=data", _, {math={huge=math.huge}})
|
local result, reason = load("return " .. data, "=data", _, {math={huge=math.huge}})
|
||||||
if not result then return nil, reason end
|
if not result then return nil, reason end
|
||||||
|
@ -19,7 +19,7 @@ local function wrapUnits(n)
|
|||||||
return tostring(math.floor(n))..(scale[count] or "")
|
return tostring(math.floor(n))..(scale[count] or "")
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.import(lib) -- string -- boolean -- Imports the functions from library *lib* into the shell environment.
|
function shutil.import(lib)
|
||||||
local cE = os.getenv("INCLUDE") or shell.include
|
local cE = os.getenv("INCLUDE") or shell.include
|
||||||
local nE = {}
|
local nE = {}
|
||||||
for k,v in pairs(cE) do
|
for k,v in pairs(cE) do
|
||||||
@ -31,7 +31,7 @@ function shutil.import(lib) -- string -- boolean -- Imports the functions from l
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.unimport(lib) -- string -- boolean -- Removes the functions from *lib* from the shell environment.
|
function shutil.unimport(lib)
|
||||||
local cE = os.getenv("INCLUDE") or shell.include
|
local cE = os.getenv("INCLUDE") or shell.include
|
||||||
local nE = {}
|
local nE = {}
|
||||||
for k,v in pairs(cE) do
|
for k,v in pairs(cE) do
|
||||||
@ -43,7 +43,7 @@ function shutil.unimport(lib) -- string -- boolean -- Removes the functions from
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.ls(...) -- string -- -- Prints contents of directories specified as *...*.
|
function shutil.ls(...)
|
||||||
local tA = {...}
|
local tA = {...}
|
||||||
if not tA[1] then tA[1] = "." end
|
if not tA[1] then tA[1] = "." end
|
||||||
for _,d in ipairs(tA) do
|
for _,d in ipairs(tA) do
|
||||||
@ -56,7 +56,7 @@ function shutil.ls(...) -- string -- -- Prints contents of directories specified
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.cat(...) -- string -- -- Outputs the contents of files specified in *...* to the standard output.
|
function shutil.cat(...)
|
||||||
for _,fn in ipairs({...}) do
|
for _,fn in ipairs({...}) do
|
||||||
local f = io.open(fn,"rb")
|
local f = io.open(fn,"rb")
|
||||||
io.write(f:read("*a"))
|
io.write(f:read("*a"))
|
||||||
@ -64,7 +64,7 @@ function shutil.cat(...) -- string -- -- Outputs the contents of files specified
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.ps() -- Prints the processes running on the system.
|
function shutil.ps()
|
||||||
print("PID# Parent | Name")
|
print("PID# Parent | Name")
|
||||||
for k,v in pairs(os.tasks()) do
|
for k,v in pairs(os.tasks()) do
|
||||||
local t = os.taskInfo(v)
|
local t = os.taskInfo(v)
|
||||||
@ -72,7 +72,7 @@ function shutil.ps() -- Prints the processes running on the system.
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.df() -- Prints free disk space.
|
function shutil.df()
|
||||||
local mt = fs.mounts()
|
local mt = fs.mounts()
|
||||||
local ml = 0
|
local ml = 0
|
||||||
for k,v in pairs(mt) do
|
for k,v in pairs(mt) do
|
||||||
@ -88,7 +88,7 @@ function shutil.df() -- Prints free disk space.
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.mount(addr,path) -- string string -- boolean string -- Mounts filesystem component with address *addr* to *path* in the filesystem.
|
function shutil.mount(addr,path)
|
||||||
if not addr then
|
if not addr then
|
||||||
local mt = fs.mounts()
|
local mt = fs.mounts()
|
||||||
for k,v in pairs(mt) do
|
for k,v in pairs(mt) do
|
||||||
@ -114,7 +114,7 @@ function shutil.mount(addr,path) -- string string -- boolean string -- Mounts fi
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function shutil.free() -- Displays used and free memory.
|
function shutil.free()
|
||||||
print("Total Used Free")
|
print("Total Used Free")
|
||||||
print(string.format("%5s %5s %5s",wrapUnits(computer.totalMemory()),wrapUnits(computer.totalMemory()-computer.freeMemory()),wrapUnits(computer.freeMemory())))
|
print(string.format("%5s %5s %5s",wrapUnits(computer.totalMemory()),wrapUnits(computer.totalMemory()-computer.freeMemory()),wrapUnits(computer.freeMemory())))
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,7 @@ local function normalise(path)
|
|||||||
return table.concat(fs.segments(path),"/")
|
return table.concat(fs.segments(path),"/")
|
||||||
end
|
end
|
||||||
|
|
||||||
function unionfs.create(...) -- string -- table -- Returns a unionfs object of the directories specified in *...*.
|
function unionfs.create(...)
|
||||||
local paths,fids,fc = {...}, {}, 0
|
local paths,fids,fc = {...}, {}, 0
|
||||||
for k,v in pairs(paths) do
|
for k,v in pairs(paths) do
|
||||||
paths[k] = "/"..normalise(v)
|
paths[k] = "/"..normalise(v)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
local vtansi = {}
|
local vtansi = {}
|
||||||
function vtansi.vtemu(gpu) -- table -- function -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal
|
function vtansi.vtemu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal
|
||||||
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF}
|
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF}
|
||||||
local mx, my = gpu.maxResolution()
|
local mx, my = gpu.maxResolution()
|
||||||
local cx, cy = 1, 1
|
local cx, cy = 1, 1
|
||||||
@ -142,7 +142,7 @@ function vtansi.vtemu(gpu) -- table -- function -- takes GPU component proxy *gp
|
|||||||
return termwrite
|
return termwrite
|
||||||
end
|
end
|
||||||
|
|
||||||
function vtansi.vtsession(gpua,scra) -- string string -- table -- creates a process to handle the GPU and screen address combination *gpua*/*scra*. Returns read, write and "close" functions.
|
function vtansi.vtsession(gpua,scra) -- creates a process to handle the GPU and screen address combination *gpua*/*scra*. Returns read, write and "close" functions.
|
||||||
local gpu = component.proxy(gpua)
|
local gpu = component.proxy(gpua)
|
||||||
gpu.bind(scra)
|
gpu.bind(scra)
|
||||||
local write = vtansi.vtemu(gpu)
|
local write = vtansi.vtemu(gpu)
|
||||||
|
@ -181,7 +181,6 @@ env:process(arg[1])
|
|||||||
local tmpfile = os.tmpname()
|
local tmpfile = os.tmpname()
|
||||||
if tmpfile:sub(#tmpfile) == "." then tmpfile = tmpfile:sub(1, #tmpfile - 1) end
|
if tmpfile:sub(#tmpfile) == "." then tmpfile = tmpfile:sub(1, #tmpfile - 1) end
|
||||||
local tmpf = io.open(tmpfile, "wb")
|
local tmpf = io.open(tmpfile, "wb")
|
||||||
env.code = env.code:gsub("%-%-.-\n","\n"):gsub("\n\n","\n")
|
|
||||||
tmpf:write(env.code)
|
tmpf:write(env.code)
|
||||||
tmpf:close()
|
tmpf:close()
|
||||||
--if (os.execute("lua minify.lua "..tmpfile.." > "..arg[2])) then
|
--if (os.execute("lua minify.lua "..tmpfile.." > "..arg[2])) then
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
buffer = {}
|
buffer = {}
|
||||||
|
|
||||||
function buffer.new(mode, stream) -- string table -- table -- create a new buffer in mode *mode* backed by stream object *stream*
|
function buffer.new(mode, stream) -- create a new buffer in mode *mode* backed by stream object *stream*
|
||||||
local result = {
|
local result = {
|
||||||
mode = {},
|
mode = {},
|
||||||
stream = stream,
|
stream = stream,
|
||||||
|
@ -64,7 +64,7 @@ end
|
|||||||
devfs.component.address = "devfs"
|
devfs.component.address = "devfs"
|
||||||
devfs.component.type = "devfs"
|
devfs.component.type = "devfs"
|
||||||
|
|
||||||
function devfs.register(fname,fopen) -- string function -- -- Register a new devfs node with the name *fname* that will run the function *fopen* when opened. This function should return a function for read, a function for write, function for close, and optionally, a function for seek, in that order.
|
function devfs.register(fname,fopen) -- Register a new devfs node with the name *fname* that will run the function *fopen* when opened. This function should return a function for read, a function for write, function for close, and optionally, a function for seek, in that order.
|
||||||
devfs.files[fname] = fopen
|
devfs.files[fname] = fopen
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@ fs = {}
|
|||||||
local fsmounts = {}
|
local fsmounts = {}
|
||||||
|
|
||||||
-- basics
|
-- basics
|
||||||
function fs.segments(path) -- string -- table -- Splits *path* on each /
|
function fs.segments(path) -- splits *path* on each /
|
||||||
local segments = {}
|
local segments = {}
|
||||||
for segment in path:gmatch("[^/]+") do
|
for segment in path:gmatch("[^/]+") do
|
||||||
segments[#segments+1] = segment
|
segments[#segments+1] = segment
|
||||||
end
|
end
|
||||||
return segments
|
return segments
|
||||||
end
|
end
|
||||||
function fs.resolve(path) -- string -- string string -- Resolves *path* to a specific filesystem mount and path
|
function fs.resolve(path) -- resolves *path* to a specific filesystem mount and path
|
||||||
if not path or path == "." then path = os.getenv("PWD") end
|
if not path or path == "." then path = os.getenv("PWD") end
|
||||||
if path:sub(1,1) ~= "/" then path=(os.getenv("PWD") or "").."/"..path end
|
if path:sub(1,1) ~= "/" then path=(os.getenv("PWD") or "").."/"..path end
|
||||||
local segments, rpath, rfs= fs.segments(path)
|
local segments, rpath, rfs= fs.segments(path)
|
||||||
@ -44,7 +44,7 @@ local function fclose(self)
|
|||||||
return fsmounts[self.fs].close(self.fid)
|
return fsmounts[self.fs].close(self.fid)
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.open(path,mode) -- string string -- table -- Opens file *path* with mode *mode*, returning a file object.
|
function fs.open(path,mode) -- opens file *path* with mode *mode*
|
||||||
mode = mode or "rb"
|
mode = mode or "rb"
|
||||||
local fsi,path = fs.resolve(path)
|
local fsi,path = fs.resolve(path)
|
||||||
if not fsmounts[fsi] then return false end
|
if not fsmounts[fsi] then return false end
|
||||||
@ -62,7 +62,7 @@ function fs.open(path,mode) -- string string -- table -- Opens file *path* with
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.copy(from,to) -- string string -- boolean -- copies a file from *from* to *to*
|
function fs.copy(from,to) -- copies a file from *from* to *to*
|
||||||
local of = fs.open(from,"rb")
|
local of = fs.open(from,"rb")
|
||||||
local df = fs.open(to,"wb")
|
local df = fs.open(to,"wb")
|
||||||
if not of or not df then
|
if not of or not df then
|
||||||
@ -71,34 +71,33 @@ function fs.copy(from,to) -- string string -- boolean -- copies a file from *fro
|
|||||||
df:write(of:read("*a"))
|
df:write(of:read("*a"))
|
||||||
df:close()
|
df:close()
|
||||||
of:close()
|
of:close()
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.rename(from,to) -- string string -- boolean -- Moves file *from* to *to*
|
function fs.rename(from,to) -- moves file *from* to *to*
|
||||||
local ofsi, opath = fs.resolve(from)
|
local ofsi, opath = fs.resolve(from)
|
||||||
local dfsi, dpath = fs.resolve(to)
|
local dfsi, dpath = fs.resolve(to)
|
||||||
if ofsi == dfsi then
|
if ofsi == dfsi then
|
||||||
fsmounts[ofsi].rename(opath,dpath)
|
fsmounts[ofsi].rename(opath,dpath)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
if not fs.copy(from,to) then return false end
|
fs.copy(from,to)
|
||||||
if not fs.remove(from) then return false end
|
fs.remove(from)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.mount(path,proxy) -- string table -- boolean -- Mounts the filesystem *proxy* to the mount point *path* if it is a directory. BYO proxy.
|
function fs.mount(path,proxy) -- mounts the filesystem *proxy* to the mount point *path* if it is a directory. BYO proxy.
|
||||||
if fs.isDirectory(path) and not fsmounts[table.concat(fs.segments(path),"/")] then
|
if fs.isDirectory(path) and not fsmounts[table.concat(fs.segments(path),"/")] then
|
||||||
fsmounts[table.concat(fs.segments(path),"/")] = proxy
|
fsmounts[table.concat(fs.segments(path),"/")] = proxy
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false, "path is not a directory"
|
return false, "path is not a directory"
|
||||||
end
|
end
|
||||||
function fs.umount(path) -- string -- -- Unmounts filesystem from *path*.
|
function fs.umount(path)
|
||||||
local fsi,_ = fs.resolve(path)
|
local fsi,_ = fs.resolve(path)
|
||||||
fsmounts[fsi] = nil
|
fsmounts[fsi] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.mounts() -- -- table -- Returns a table containing the mount points of all mounted filesystems
|
function fs.mounts() -- returns a table containing the mount points of all mounted filesystems
|
||||||
local rt = {}
|
local rt = {}
|
||||||
for k,v in pairs(fsmounts) do
|
for k,v in pairs(fsmounts) do
|
||||||
rt[#rt+1] = k,v.address or "unknown"
|
rt[#rt+1] = k,v.address or "unknown"
|
||||||
@ -106,11 +105,11 @@ function fs.mounts() -- -- table -- Returns a table containing the mount points
|
|||||||
return rt
|
return rt
|
||||||
end
|
end
|
||||||
|
|
||||||
function fs.address(path) -- string -- string -- Returns the address of the filesystem at a given path, if applicable; do not expect a sensical response
|
function fs.address(path) -- returns the address of the filesystem at a given path, if applicable; do not expect a sensical response
|
||||||
local fsi,_ = fs.resolve(path)
|
local fsi,_ = fs.resolve(path)
|
||||||
return fsmounts[fsi].address
|
return fsmounts[fsi].address
|
||||||
end
|
end
|
||||||
function fs.type(path) -- string -- string -- Returns the component type of the filesystem at a given path, if applicable
|
function fs.type(path) -- returns the component type of the filesystem at a given path, if applicable
|
||||||
local fsi,_ = fs.resolve(path)
|
local fsi,_ = fs.resolve(path)
|
||||||
return fsmounts[fsi].type or "filesystem"
|
return fsmounts[fsi].type or "filesystem"
|
||||||
end
|
end
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
io = {}
|
io = {}
|
||||||
|
|
||||||
function io.open(path,mode) -- string string -- table -- Open file *path* in *mode*. Returns a buffer object.
|
function io.open(path,mode) -- Open file *path* in *mode*. Returns a buffer object.
|
||||||
local f,e = fs.open(path, mode)
|
local f,e = fs.open(path, mode)
|
||||||
if not f then return false, e end
|
if not f then return false, e end
|
||||||
return buffer.new(mode,f)
|
return buffer.new(mode,f)
|
||||||
end
|
end
|
||||||
|
|
||||||
function io.input(fd) -- table -- table -- Sets the default input stream to *fd* if provided, either as a buffer as a path. Returns the default input stream.
|
function io.input(fd) -- Sets the default input stream to *fd* if provided, either as a buffer as a path. Returns the default input stream.
|
||||||
if type(fd) == "string" then
|
if type(fd) == "string" then
|
||||||
fd=io.open(fd,"rb")
|
fd=io.open(fd,"rb")
|
||||||
end
|
end
|
||||||
@ -15,7 +15,7 @@ function io.input(fd) -- table -- table -- Sets the default input stream to *fd*
|
|||||||
end
|
end
|
||||||
return os.getenv("STDIN")
|
return os.getenv("STDIN")
|
||||||
end
|
end
|
||||||
function io.output(fd) -- table -- table -- Sets the default output stream to *fd* if provided, either as a buffer as a path. Returns the default output stream.
|
function io.output(fd) -- Sets the default output stream to *fd* if provided, either as a buffer as a path. Returns the default output stream.
|
||||||
if type(fd) == "string" then
|
if type(fd) == "string" then
|
||||||
fd=io.open(fd,"wb")
|
fd=io.open(fd,"wb")
|
||||||
end
|
end
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
function loadfile(p) -- string -- function -- reads file *p* and returns a function if possible
|
function loadfile(p) -- reads file *p* and returns a function if possible
|
||||||
local f = io.open(p,"rb")
|
local f = io.open(p,"rb")
|
||||||
local c = f:read("*a")
|
local c = f:read("*a")
|
||||||
f:close()
|
f:close()
|
||||||
return load(c,p,"t")
|
return load(c,p,"t")
|
||||||
end
|
end
|
||||||
function runfile(p,...) -- string -- -- runs file *p* with arbitrary arguments in the current thread
|
function runfile(p,...) -- runs file *p* with arbitrary arguments in the current thread
|
||||||
return loadfile(p)(...)
|
return loadfile(p)(...)
|
||||||
end
|
end
|
||||||
function os.spawnfile(p,n,...) -- string string -- number -- spawns a new process from file *p* with name *n*, with arguments following *n*.
|
function os.spawnfile(p,n,...) -- spawns a new process from file *p* with name *n*, with arguments following *n*.
|
||||||
local tA = {...}
|
local tA = {...}
|
||||||
return os.spawn(function() local res={pcall(loadfile(p), table.unpack(tA))} computer.pushSignal("process_finished", os.pid(), table.unpack(res)) dprint(table.concat(res)) end,n or p)
|
return os.spawn(function() local res={pcall(loadfile(p), table.unpack(tA))} computer.pushSignal("process_finished", os.pid(), table.unpack(res)) dprint(table.concat(res)) end,n or p)
|
||||||
end
|
end
|
||||||
_G.package = {}
|
_G.package = {}
|
||||||
package.loaded = {computer=computer,component=component,fs=fs,buffer=buffer}
|
package.loaded = {computer=computer,component=component,fs=fs,buffer=buffer}
|
||||||
function require(f,force) -- string boolean -- table -- searches for a library with name *f* and returns what the library returns, if possible. if *force* is set, loads the library even if it is cached
|
function require(f,force) -- searches for a library with name *f* and returns what the library returns, if possible. if *force* is set, loads the library even if it is cached
|
||||||
if not package.loaded[f] or force then
|
if not package.loaded[f] or force then
|
||||||
local lib = os.getenv("LIB") or "/boot/lib"
|
local lib = os.getenv("LIB") or "/boot/lib"
|
||||||
for d in lib:gmatch("[^\n]+") do
|
for d in lib:gmatch("[^\n]+") do
|
||||||
@ -29,6 +29,6 @@ function require(f,force) -- string boolean -- table -- searches for a library w
|
|||||||
end
|
end
|
||||||
error("library not found: "..f)
|
error("library not found: "..f)
|
||||||
end
|
end
|
||||||
function reload(f) -- string -- table -- Reloads library *f* from disk into memory.
|
function reload(f)
|
||||||
return require(f,true)
|
return require(f,true)
|
||||||
end
|
end
|
||||||
|
141
module/nvt100.lua
Normal file
141
module/nvt100.lua
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
function vt100emu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal
|
||||||
|
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF}
|
||||||
|
local mx, my = gpu.maxResolution()
|
||||||
|
local cx, cy = 1, 1
|
||||||
|
local pc = " "
|
||||||
|
local lc = ""
|
||||||
|
local mode = 0 -- 0 normal, 1 escape, 2 command
|
||||||
|
local lw = true
|
||||||
|
local sx, sy = 1,1
|
||||||
|
local cs = ""
|
||||||
|
local bg, fg = 0, 0xFFFFFF
|
||||||
|
|
||||||
|
-- setup
|
||||||
|
gpu.setResolution(mx,my)
|
||||||
|
gpu.fill(1,1,mx,my," ")
|
||||||
|
local function checkCursor()
|
||||||
|
if cx > mx and lw then
|
||||||
|
cx, cy = 1, cy+1
|
||||||
|
end
|
||||||
|
if cy > my then
|
||||||
|
gpu.copy(1,2,mx,my-1,0,-1)
|
||||||
|
gpu.fill(1,my,mx,1," ")
|
||||||
|
cy=my
|
||||||
|
end
|
||||||
|
if cy < 1 then cy = 1 end
|
||||||
|
if cx < 1 then cx = 1 end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function termwrite(s)
|
||||||
|
local wb = ""
|
||||||
|
local lb, ec = nil, nil
|
||||||
|
local function flushwb()
|
||||||
|
while wb:len() > 0 do
|
||||||
|
checkCursor()
|
||||||
|
local wl = wb:sub(1,mx-cx+1)
|
||||||
|
wb = wb:sub(wl:len()+1)
|
||||||
|
gpu.set(cx, cy, wl)
|
||||||
|
cx = cx + wl:len()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local rs = ""
|
||||||
|
s=s:gsub("\8","\27[D")
|
||||||
|
pc = gpu.get(cx,cy)
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
gpu.set(cx,cy,pc)
|
||||||
|
for cc in s:gmatch(".") do
|
||||||
|
if mode == 0 then
|
||||||
|
if cc == "\n" then
|
||||||
|
flushwb()
|
||||||
|
cx,cy = 1, cy+1
|
||||||
|
elseif cc == "\t" then
|
||||||
|
wb=wb..(" "):rep(8*((cx+9)//8))
|
||||||
|
elseif cc == "\27" then
|
||||||
|
flushwb()
|
||||||
|
mode = 1
|
||||||
|
else
|
||||||
|
wb = wb .. cc
|
||||||
|
end
|
||||||
|
elseif mode == 1 then
|
||||||
|
if cc == "[" then
|
||||||
|
mode = 2
|
||||||
|
else
|
||||||
|
mode = 0
|
||||||
|
end
|
||||||
|
elseif mode == 2 then
|
||||||
|
if cc:match("[%d;]") then
|
||||||
|
cs = cs .. cc
|
||||||
|
else
|
||||||
|
mode = 0
|
||||||
|
local tA = {}
|
||||||
|
for s in cs:gmatch("%d+") do
|
||||||
|
tA[#tA+1] = tonumber(s)
|
||||||
|
end
|
||||||
|
if cc == "H" then
|
||||||
|
cx, cy = tA[1] or 1, tA[2] or 1
|
||||||
|
elseif cc == "A" then
|
||||||
|
cy = cy - (tA[1] or 1)
|
||||||
|
elseif cc == "B" then
|
||||||
|
cy = cy + (tA[1] or 1)
|
||||||
|
elseif cc == "C" then
|
||||||
|
cx = cx + (tA[1] or 1)
|
||||||
|
elseif cc == "D" then
|
||||||
|
cx = cx - (tA[1] or 1)
|
||||||
|
elseif cc == "s" then
|
||||||
|
sx, sy = cx, cy
|
||||||
|
elseif cc == "u" then
|
||||||
|
cx, cy = sx, sy
|
||||||
|
elseif cc == "n" and tA[1] == 6 then
|
||||||
|
rs = string.format("%s\27[%d;%dR",rs,cx,cy)
|
||||||
|
elseif cc == "K" and tA[1] == 1 then
|
||||||
|
gpu.fill(1,cy,cx,1," ")
|
||||||
|
elseif cc == "K" and tA[1] == 2 then
|
||||||
|
gpu.fill(cx,cy,mx,1," ")
|
||||||
|
elseif cc == "K" then
|
||||||
|
gpu.fill(1,cy,mx,1," ")
|
||||||
|
elseif cc == "J" and tA[1] == 1 then
|
||||||
|
gpu.fill(1,1,mx,cy," ")
|
||||||
|
elseif cc == "J" and tA[1] == 2 then
|
||||||
|
gpu.fill(1,1,mx,my," ")
|
||||||
|
cx, cy = 1, 1
|
||||||
|
elseif cc == "J" then
|
||||||
|
gpu.fill(1,cy,mx,my," ")
|
||||||
|
elseif cc == "m" then
|
||||||
|
for _,num in ipairs(tA) do
|
||||||
|
if num == 0 then
|
||||||
|
fg,bg,ec,lb = 0xFFFFFF,0,true,true
|
||||||
|
elseif num == 7 then
|
||||||
|
local nfg,nbg = bg, fg
|
||||||
|
fg, bg = nfg, nbg
|
||||||
|
elseif num > 29 and num < 38 then
|
||||||
|
fg = colours[num-29]
|
||||||
|
elseif num > 39 and num < 48 then
|
||||||
|
bg = colours[num-39]
|
||||||
|
elseif num == 100 then -- disable local echo
|
||||||
|
ec = false
|
||||||
|
elseif num == 101 then -- disable line mode
|
||||||
|
lb = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
end
|
||||||
|
cs = ""
|
||||||
|
checkCursor()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
flushwb()
|
||||||
|
checkCursor()
|
||||||
|
pc = gpu.get(cx,cy)
|
||||||
|
gpu.setForeground(bg)
|
||||||
|
gpu.setBackground(fg)
|
||||||
|
gpu.set(cx,cy,pc)
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
return rs, lb, ec
|
||||||
|
end
|
||||||
|
|
||||||
|
return termwrite
|
||||||
|
end
|
@ -1,4 +1,4 @@
|
|||||||
function os.chdir(p) -- string -- boolean string -- changes the current working directory of the calling process to the directory specified in *p*, returning true or false, error
|
function os.chdir(p) -- changes the current working directory of the calling process to the directory specified in *p*, returning true or false, error
|
||||||
if not (p:sub(1,1) == "/") then
|
if not (p:sub(1,1) == "/") then
|
||||||
local np = {}
|
local np = {}
|
||||||
for k,v in pairs(fs.segments(os.getenv("PWD").."/"..p)) do
|
for k,v in pairs(fs.segments(os.getenv("PWD").."/"..p)) do
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
do
|
do
|
||||||
local tTasks,nPid,nTimeout,cPid = {},1,0.25,0 -- table of tasks, next process ID, event timeout, current PID
|
local tTasks,nPid,nTimeout,cPid = {},1,0.25,0 -- table of tasks, next process ID, event timeout, current PID
|
||||||
function os.spawn(f,n) -- function string -- number -- creates a process from function *f* with name *n*
|
function os.spawn(f,n) -- creates a process from function *f* with name *n*
|
||||||
tTasks[nPid] = {
|
tTasks[nPid] = {
|
||||||
c=coroutine.create(f), -- actual coroutine
|
c=coroutine.create(f), -- actual coroutine
|
||||||
n=n, -- process name
|
n=n, -- process name
|
||||||
@ -16,20 +16,20 @@ function os.spawn(f,n) -- function string -- number -- creates a process from fu
|
|||||||
nPid = nPid + 1
|
nPid = nPid + 1
|
||||||
return nPid - 1
|
return nPid - 1
|
||||||
end
|
end
|
||||||
function os.kill(pid) -- number -- -- removes process *pid* from the task list
|
function os.kill(pid) -- removes process *pid* from the task list
|
||||||
tTasks[pid] = nil
|
tTasks[pid] = nil
|
||||||
end
|
end
|
||||||
function os.pid() -- -- number -- returns the current process' PID
|
function os.pid() -- returns the current process' PID
|
||||||
return cPid
|
return cPid
|
||||||
end
|
end
|
||||||
function os.tasks() -- -- table -- returns a table of process IDs
|
function os.tasks() -- returns a table of process IDs
|
||||||
local rt = {}
|
local rt = {}
|
||||||
for k,v in pairs(tTasks) do
|
for k,v in pairs(tTasks) do
|
||||||
rt[#rt+1] = k
|
rt[#rt+1] = k
|
||||||
end
|
end
|
||||||
return rt
|
return rt
|
||||||
end
|
end
|
||||||
function os.taskInfo(pid) -- number -- table -- returns info on process *pid* as a table with name and parent values
|
function os.taskInfo(pid) -- returns info on process *pid* as a table with name and parent values
|
||||||
pid = pid or os.pid()
|
pid = pid or os.pid()
|
||||||
if not tTasks[pid] then return false end
|
if not tTasks[pid] then return false end
|
||||||
return {name=tTasks[pid].n,parent=tTasks[pid].P}
|
return {name=tTasks[pid].n,parent=tTasks[pid].P}
|
||||||
|
@ -9,7 +9,6 @@ syslog.notice = 5
|
|||||||
syslog.info = 6
|
syslog.info = 6
|
||||||
syslog.debug = 7
|
syslog.debug = 7
|
||||||
|
|
||||||
-- function syslog(msg, level, service) -- string number string -- -- Output *msg* to the system log, with severity *level*, from *service*.
|
|
||||||
local rdprint=dprint or function() end
|
local rdprint=dprint or function() end
|
||||||
setmetatable(syslog,{__call = function(_,msg, level, service)
|
setmetatable(syslog,{__call = function(_,msg, level, service)
|
||||||
level, service = level or syslog.info, service or (os.taskInfo(os.pid()) or {}).name or "unknown"
|
level, service = level or syslog.info, service or (os.taskInfo(os.pid()) or {}).name or "unknown"
|
||||||
|
5
module/term.lua
Normal file
5
module/term.lua
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
--#include "module/vt-task.lua"
|
||||||
|
do
|
||||||
|
local r,w = vtemu(component.list("gpu")(),component.list("screen")())
|
||||||
|
devfs.register("tty0", function() return r,w,function() end end)
|
||||||
|
end
|
58
module/vt-task.lua
Normal file
58
module/vt-task.lua
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
do
|
||||||
|
--#include "module/nvt100.lua"
|
||||||
|
function vtemu(gpua,scra) -- creates a process to handle the GPU and screen address combination *gpua*/*scra*. Returns read, write and "close" functions.
|
||||||
|
local gpu = component.proxy(gpua)
|
||||||
|
gpu.bind(scra)
|
||||||
|
local write = vt100emu(gpu)
|
||||||
|
local kba = {}
|
||||||
|
for k,v in ipairs(component.invoke(scra,"getKeyboards")) do
|
||||||
|
kba[v]=true
|
||||||
|
end
|
||||||
|
local buf, lbuf, echo = "", true, true
|
||||||
|
os.spawn(function() dprint(pcall(function()
|
||||||
|
while true do
|
||||||
|
local ty,ka,ch = coroutine.yield()
|
||||||
|
if ty == "key_down" and kba[ka] then
|
||||||
|
if ch == 13 then ch = 10 end
|
||||||
|
if ch == 8 then
|
||||||
|
if buf:len() > 0 then
|
||||||
|
if echo then write("\8 \8") end
|
||||||
|
buf = buf:sub(1,-2)
|
||||||
|
end
|
||||||
|
elseif ch > 0 then
|
||||||
|
if echo then write(string.char(ch)) end
|
||||||
|
buf=buf..string.char(ch)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)) end,string.format("ttyd[%s:%s]",gpua:sub(1,8),scra:sub(1,8)))
|
||||||
|
local function bread(n)
|
||||||
|
local r
|
||||||
|
if lbuf then
|
||||||
|
while not buf:find("\n") do
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
local n = buf:find("\n")
|
||||||
|
r, buf = buf:sub(1,n), buf:sub(n+1)
|
||||||
|
else
|
||||||
|
r = buf
|
||||||
|
buf = ""
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
local function bwrite(d)
|
||||||
|
local ba, lb, ec = write(d)
|
||||||
|
buf = buf .. ba
|
||||||
|
if lb ~= nil then
|
||||||
|
dprint("local buffer mode: "..tostring(lb))
|
||||||
|
lbuf = lb
|
||||||
|
end
|
||||||
|
if ec ~= nil then
|
||||||
|
dprint("echo mode: "..tostring(ec))
|
||||||
|
echo = ec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return bread, bwrite, function() io.write("\27[2J\27[H") end
|
||||||
|
end
|
||||||
|
end
|
148
module/vt100.lua
Normal file
148
module/vt100.lua
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
function vt100emu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal
|
||||||
|
local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF}
|
||||||
|
local mx, my = gpu.maxResolution()
|
||||||
|
local cx, cy = 1, 1
|
||||||
|
local pc = " "
|
||||||
|
local lc = ""
|
||||||
|
local mode = "n"
|
||||||
|
local lw = true
|
||||||
|
local sx, sy = 1,1
|
||||||
|
local cs = ""
|
||||||
|
local bg, fg = 0, 0xFFFFFF
|
||||||
|
|
||||||
|
-- setup
|
||||||
|
gpu.setResolution(mx,my)
|
||||||
|
gpu.fill(1,1,mx,my," ")
|
||||||
|
|
||||||
|
local function termwrite(s)
|
||||||
|
local rs = ""
|
||||||
|
s=s:gsub("\8","\27[D")
|
||||||
|
pc = gpu.get(cx,cy)
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
gpu.set(cx,cy,pc)
|
||||||
|
for i = 1, s:len() do
|
||||||
|
local cc = s:sub(i,i)
|
||||||
|
|
||||||
|
if mode == "n" then
|
||||||
|
if cc == "\n" then -- line feed
|
||||||
|
cx, cy = 1, cy+1
|
||||||
|
elseif cc == "\r" then -- cursor home
|
||||||
|
cx = 1
|
||||||
|
elseif cc == "\27" then -- escape
|
||||||
|
mode = "e"
|
||||||
|
elseif cc == "\t" then
|
||||||
|
cx = 8*((cx+9)//8)
|
||||||
|
elseif string.byte(cc) > 31 and string.byte(cc) < 127 then -- printable, I guess
|
||||||
|
gpu.set(cx, cy, cc)
|
||||||
|
cx = cx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif mode == "e" then
|
||||||
|
if cc == "[" then
|
||||||
|
mode = "v"
|
||||||
|
cs = ""
|
||||||
|
elseif cc == "D" then -- scroll down
|
||||||
|
gpu.copy(1,2,mx,my-1,0,-1)
|
||||||
|
gpu.fill(1,my,mx,1," ")
|
||||||
|
cy=cy+1
|
||||||
|
mode = "n"
|
||||||
|
elseif cc == "M" then -- scroll up
|
||||||
|
gpu.copy(1,1,mx,my-1,0,1)
|
||||||
|
gpu.fill(1,1,mx,1," ")
|
||||||
|
mode = "n"
|
||||||
|
else
|
||||||
|
mode = "n"
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif mode == "v" then
|
||||||
|
mode = "n"
|
||||||
|
if cc == "s" then -- save cursor
|
||||||
|
sx, sy = cx, cy
|
||||||
|
elseif cc == "u" then -- restore cursor
|
||||||
|
cx, cy = sx, sy
|
||||||
|
elseif cc == "H" then -- cursor home or to
|
||||||
|
local tx, ty = cs:match("(%d+);(%d+)")
|
||||||
|
tx, ty = tx or "1", ty or "1"
|
||||||
|
cx, cy = tonumber(tx), tonumber(ty)
|
||||||
|
elseif cc == "A" then -- cursor up
|
||||||
|
cy = cy - (tonumber(cs) or 1)
|
||||||
|
elseif cc == "B" then -- cursor down
|
||||||
|
cy = cy + (tonumber(cs) or 1)
|
||||||
|
elseif cc == "C" then -- cursor right
|
||||||
|
cx = cx + (tonumber(cs) or 1)
|
||||||
|
elseif cc == "D" then -- cursor left
|
||||||
|
cx = cx - (tonumber(cs) or 1)
|
||||||
|
elseif cc == "h" and lc == "7" then -- enable line wrap
|
||||||
|
lw = true
|
||||||
|
elseif cc == "l" and lc == "7" then -- disable line wrap
|
||||||
|
lw = false
|
||||||
|
elseif cc == "c" then
|
||||||
|
rs = string.format("%s\27[%d;%d0c",rs,mx,my)
|
||||||
|
elseif cc == "n" and lc == "6" then
|
||||||
|
rs = string.format("%s\27[%d;%dR",rs,cx,cy)
|
||||||
|
elseif cc == "K" then
|
||||||
|
if lc == "1" then
|
||||||
|
gpu.fill(1,cy,cx,1," ")
|
||||||
|
elseif lc == "2" then
|
||||||
|
gpu.fill(cx,cy,mx,1," ")
|
||||||
|
else
|
||||||
|
gpu.fill(1,cy,mx,1," ")
|
||||||
|
end
|
||||||
|
elseif cc == "J" then
|
||||||
|
if lc == "1" then
|
||||||
|
gpu.fill(1,1,mx,cy," ")
|
||||||
|
elseif lc == "2" then
|
||||||
|
gpu.full(1,1,mx,my," ")
|
||||||
|
cx,cy = 1, 1
|
||||||
|
else
|
||||||
|
gpu.fill(1,cy,mx,my," ")
|
||||||
|
end
|
||||||
|
elseif cc == "m" then
|
||||||
|
for num in cs:gmatch("%d+") do
|
||||||
|
num=tonumber(num)
|
||||||
|
if num == 0 then
|
||||||
|
fg,bg = 0xFFFFFF,0
|
||||||
|
elseif num == 7 then
|
||||||
|
local nfg,nbg = bg, fg
|
||||||
|
fg, bg = nfg, nbg
|
||||||
|
elseif num > 29 and num < 38 then
|
||||||
|
fg = colours[num-29]
|
||||||
|
elseif num > 39 and num < 48 then
|
||||||
|
bg = colours[num-39]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
else
|
||||||
|
cs = cs .. cc
|
||||||
|
if cc:match("[%d;]") then
|
||||||
|
mode = "v"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if cx > mx and lw then
|
||||||
|
cx, cy = 1, cy+1
|
||||||
|
end
|
||||||
|
if cy > my then
|
||||||
|
gpu.copy(1,2,mx,my-1,0,-1)
|
||||||
|
gpu.fill(1,my,mx,1," ")
|
||||||
|
cy=my
|
||||||
|
end
|
||||||
|
if cy < 1 then cy = 1 end
|
||||||
|
if cx < 1 then cx = 1 end
|
||||||
|
|
||||||
|
lc = cc
|
||||||
|
end
|
||||||
|
pc = gpu.get(cx,cy)
|
||||||
|
gpu.setForeground(bg)
|
||||||
|
gpu.setBackground(fg)
|
||||||
|
gpu.set(cx,cy,pc)
|
||||||
|
gpu.setForeground(fg)
|
||||||
|
gpu.setBackground(bg)
|
||||||
|
return rs
|
||||||
|
end
|
||||||
|
|
||||||
|
return termwrite
|
||||||
|
end
|
46
template.tex
46
template.tex
@ -1,46 +0,0 @@
|
|||||||
\documentclass[11pt,twoside,a4paper]{article}
|
|
||||||
\usepackage{hyperref}
|
|
||||||
\usepackage{multicol}
|
|
||||||
\usepackage{standalone}
|
|
||||||
\usepackage{graphicx}
|
|
||||||
\usepackage{pdfpages}
|
|
||||||
\usepackage{listings}
|
|
||||||
\usepackage{color}
|
|
||||||
\usepackage{sectsty}
|
|
||||||
\usepackage[cm]{fullpage}
|
|
||||||
\lstset{
|
|
||||||
commentstyle=\color{cyan}, % comment style
|
|
||||||
keywordstyle=\color{cyan}, % keyword style
|
|
||||||
stringstyle=\color{red}, % string literal style
|
|
||||||
numbers=left, % where to put the line-numbers; possible values are (none, left, right)
|
|
||||||
numbersep=5pt, % how far the line-numbers are from the code
|
|
||||||
numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers
|
|
||||||
}
|
|
||||||
\hypersetup{
|
|
||||||
colorlinks=true
|
|
||||||
}
|
|
||||||
|
|
||||||
\subsectionfont{\ttfamily}
|
|
||||||
|
|
||||||
% pandoc stuff
|
|
||||||
\providecommand{\tightlist}{%
|
|
||||||
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
|
||||||
|
|
||||||
\let\stdsection\section
|
|
||||||
\renewcommand\section{\newpage\stdsection}
|
|
||||||
|
|
||||||
\lstset{basicstyle=\footnotesize\ttfamily,breaklines=true}
|
|
||||||
\newcommand{\ignore}[1]{}
|
|
||||||
\title{$title$$if(thanks)$\thanks{$thanks$}$endif$}
|
|
||||||
\author{$for(author)$$author$$sep$ \and $endfor$}
|
|
||||||
\date{}
|
|
||||||
\begin{document}
|
|
||||||
\pagenumbering{gobble}
|
|
||||||
\maketitle
|
|
||||||
\newpage
|
|
||||||
\pagenumbering{alph}
|
|
||||||
\tableofcontents
|
|
||||||
\newpage
|
|
||||||
\pagenumbering{arabic}
|
|
||||||
$body$
|
|
||||||
\end{document}
|
|
Loading…
Reference in New Issue
Block a user