init
This commit is contained in:
commit
1b55bb0ba6
35 changed files with 1051 additions and 0 deletions
8
autoexec.lua
Normal file
8
autoexec.lua
Normal file
|
@ -0,0 +1,8 @@
|
|||
-- Autoexec for ErDOS
|
||||
--- (c) Er2 2022 <er2@dismail.de>
|
||||
--- Zlib License
|
||||
|
||||
-- Load default shell
|
||||
|
||||
loadapp 'ver'
|
||||
loadapp 'ersh'
|
19
license
Normal file
19
license
Normal file
|
@ -0,0 +1,19 @@
|
|||
Zlib License
|
||||
|
||||
Copyright (c) 2022 Er2 <er2@dismail.de>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgement in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
8
main.lua
Normal file
8
main.lua
Normal file
|
@ -0,0 +1,8 @@
|
|||
-- Startup
|
||||
|
||||
local con = require 'src.term.init'
|
||||
require 'src.os' (con)
|
||||
|
||||
require 'autoexec'
|
||||
|
||||
love.event.push 'quit'
|
48
src/async.lua
Normal file
48
src/async.lua
Normal file
|
@ -0,0 +1,48 @@
|
|||
|
||||
ACTIVE = true
|
||||
function __run()
|
||||
if love.event then
|
||||
love.event.pump()
|
||||
for n, a,b,c,d,e,f in love.event.poll() do
|
||||
if n == 'quit' or not ACTIVE then
|
||||
if not love.quit or not love.quit() then
|
||||
ACTIVE = false
|
||||
return a or 0
|
||||
end
|
||||
end
|
||||
love.handlers[n](a,b,c,d,e,f)
|
||||
end
|
||||
end
|
||||
|
||||
local dt = 0
|
||||
if love.timer
|
||||
then dt = love.timer.step() or love.timer.getDelta()
|
||||
end
|
||||
|
||||
if love.update then love.update(dt) end
|
||||
if love.graphics and love.graphics.isActive() then
|
||||
love.graphics.origin()
|
||||
love.graphics.clear(0, 0, 0)
|
||||
if love.draw then love.draw() end
|
||||
love.graphics.present()
|
||||
end
|
||||
if love.timer then love.timer.sleep(0.001) end
|
||||
end
|
||||
|
||||
function await(fn)
|
||||
while fn() ~= true do
|
||||
if not ACTIVE then break end
|
||||
__run()
|
||||
end
|
||||
end
|
||||
|
||||
function love.run()
|
||||
if love.timer then love.timer.step() end
|
||||
if love.getVersion() == 0
|
||||
then
|
||||
while ACTIVE do
|
||||
__run()
|
||||
end
|
||||
else return __run
|
||||
end
|
||||
end
|
83
src/baseshell.lua
Normal file
83
src/baseshell.lua
Normal file
|
@ -0,0 +1,83 @@
|
|||
return function(con)
|
||||
|
||||
local sh = {
|
||||
prompt = function() return '>' end,
|
||||
runs = true,
|
||||
env = {
|
||||
code = 0,
|
||||
path = 'sysapps:apps',
|
||||
}
|
||||
}
|
||||
|
||||
function sh:which(cmd)
|
||||
local file = cmd or ''
|
||||
if file:sub(-4) ~= '.lua'
|
||||
then file = file.. '.lua'
|
||||
end
|
||||
if fsHas(file)
|
||||
then return '', file end
|
||||
for path in self.env.path:gmatch '[^:]+' do
|
||||
if fsHas(path..'/'..file)
|
||||
then return path, '/'..file
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function sh:parseArgs(ln)
|
||||
local iq, buf, args = false, '', {}
|
||||
local qt, esc = nil, false
|
||||
|
||||
ln = ln:gsub('%$(%S+)%s*=%s*(.*)$', function(k, v)
|
||||
env[k] = self:parseArgs(v)[1]
|
||||
return ''
|
||||
end)
|
||||
|
||||
-- helper function
|
||||
local function psh()
|
||||
if buf:sub(1,1) == '$'
|
||||
then buf = tostring(self.env[buf:sub(2)] or '') end
|
||||
if #buf > 0 then table.insert(args, buf) end
|
||||
buf, qt = '', nil
|
||||
end
|
||||
|
||||
for i = 1, #ln + 1 do
|
||||
local v = ln:sub(i, i)
|
||||
if ((v == ' ' or v == '\n' or v == '\t') and not iq)
|
||||
or v == ''
|
||||
then psh()
|
||||
|
||||
elseif esc then esc, buf = false, buf.. v
|
||||
elseif v == '\\' then esc = true
|
||||
|
||||
elseif (not qt or qt == v)
|
||||
and (v == '"' or v == "'")
|
||||
then psh()
|
||||
qt, iq = v, not iq
|
||||
|
||||
else buf = buf.. v
|
||||
end
|
||||
end
|
||||
|
||||
return args
|
||||
end
|
||||
|
||||
function sh:run()
|
||||
return 'TODO'
|
||||
end
|
||||
|
||||
function sh:loop()
|
||||
await(function()
|
||||
con.print(self:prompt())
|
||||
local ln = con.getln()
|
||||
con.down()
|
||||
|
||||
local res = self:run(ln)
|
||||
if res then con.println(res) end
|
||||
|
||||
return not self.runs
|
||||
end)
|
||||
end
|
||||
|
||||
return sh
|
||||
|
||||
end
|
31
src/draw.lua
Normal file
31
src/draw.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
-- Drawing API
|
||||
--- (c) Er2 2021-2022
|
||||
--- Zlib License
|
||||
|
||||
local comp = {
|
||||
'system', 'transform',
|
||||
'color', 'figures', 'font',
|
||||
'line', 'picture', 'rcorn',
|
||||
'rrect',
|
||||
}
|
||||
|
||||
FILL, LINE = 1, 0
|
||||
|
||||
local draw = {}
|
||||
draw.__index = draw
|
||||
|
||||
function draw.new(w, h)
|
||||
assert(w > 0 and h > 0, 'cr must be greater than 0')
|
||||
local cr = setmetatable({}, draw)
|
||||
cr._cr = love.graphics.newCanvas(w, h)
|
||||
cr.w, cr.h = w, h
|
||||
cr:newFont()
|
||||
return cr
|
||||
end
|
||||
|
||||
for _, v in pairs(comp) do
|
||||
require('src.draw.'.. v)(draw)
|
||||
end
|
||||
|
||||
draw:newFont()
|
||||
return setmetatable({}, draw)
|
32
src/draw/color.lua
Normal file
32
src/draw/color.lua
Normal file
|
@ -0,0 +1,32 @@
|
|||
|
||||
local f = (love.getVersion or
|
||||
function() return love._version_major
|
||||
end)() == 0 and 1 or 255
|
||||
|
||||
return function(draw)
|
||||
|
||||
function draw:color(r, g, b, a)
|
||||
a = a or 255
|
||||
love.graphics.setColor(r / f, g / f, b / f, a / f)
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:colorT(t)
|
||||
return self:color(t[1], t[2], t[3], t[4])
|
||||
end
|
||||
|
||||
function draw:colorH(hex)
|
||||
hex = (tostring(hex) or ''):lower()
|
||||
local r, g, b, a = hex:match '#?(%x%x?)(%x%x?)(%x%x?)'
|
||||
r = #r == 1 and r..r or r
|
||||
g = #g == 1 and g..g or g
|
||||
b = #b == 1 and b..b or b
|
||||
if a then a = #a == 1 and a..a or a end
|
||||
return self:color(
|
||||
tonumber(r, 16), tonumber(g, 16),
|
||||
tonumber(b, 16),
|
||||
not a and 255 or tonumber(a, 16)
|
||||
)
|
||||
end
|
||||
|
||||
end
|
44
src/draw/figures.lua
Normal file
44
src/draw/figures.lua
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
local function gm(m)
|
||||
return m == FILL and 'fill' or 'line'
|
||||
end
|
||||
|
||||
return function(draw)
|
||||
|
||||
function draw:rect(m, x, y, w, h)
|
||||
love.graphics.rectangle(gm(m), x, y, w, h)
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:ellipse(m, x, y, rx, ry)
|
||||
love.graphics.ellipse(gm(m), x, y, rx, ry)
|
||||
if m == FILL then
|
||||
self:ellipse(LINE, x, y, rx, ry)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:circle(m, x, y, r)
|
||||
return self:ellipse(m, x, y, r, r)
|
||||
end
|
||||
|
||||
function draw:triang(m, x, y, ox1, oy1, ox2, oy2)
|
||||
if m == FILL then self:triang(LINE, x, y, ox1, oy1, ox2, oy2) end
|
||||
love.graphics.polygon(gm(m), x, y, x + ox1, y + oy1, x + ox2, y + oy2)
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:arc(m, cx, cy, r, sa, ea)
|
||||
love.graphics.arc(gm(m), m == FILL and 'pie' or 'open',
|
||||
cx, cy, r, sa, ea)
|
||||
if m == FILL then self:arc(LINE, cx, cy, r, sa, ea) end
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:text(t, x, y)
|
||||
love.graphics.setFont(self.f)
|
||||
love.graphics.print(t, x, y)
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
16
src/draw/font.lua
Normal file
16
src/draw/font.lua
Normal file
|
@ -0,0 +1,16 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:font(f)
|
||||
if f then self.f = f end
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:newFont(...)
|
||||
return self:font(love.graphics.newFont(...))
|
||||
end
|
||||
|
||||
function draw:getFText(t)
|
||||
return self.f:getWidth(t), self.f:getHeight(t)
|
||||
end
|
||||
|
||||
end
|
13
src/draw/line.lua
Normal file
13
src/draw/line.lua
Normal file
|
@ -0,0 +1,13 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:lineWidth(w)
|
||||
love.graphics.setLineWidth(w)
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:line(x1, y1, x2, y2)
|
||||
love.graphics.line(x1, y1, x2, y2)
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
13
src/draw/picture.lua
Normal file
13
src/draw/picture.lua
Normal file
|
@ -0,0 +1,13 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:img(im, x, y, r, sx, sy)
|
||||
love.graphics.draw(im, x, y, r, sx, sy)
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:cr(cr, x, y, r, sx, sy)
|
||||
if cr.fr then return end
|
||||
return self:img(cr._cr, x, y, r, sx, sy)
|
||||
end
|
||||
|
||||
end
|
33
src/draw/rcorn.lua
Normal file
33
src/draw/rcorn.lua
Normal file
|
@ -0,0 +1,33 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:rcorn(x, y, d, p)
|
||||
p = p or 1
|
||||
if p == 1 then self -- bot-right
|
||||
|
||||
:arc(LINE, x - d, y - d, d, 0, math.pi / 2)
|
||||
:triang(FILL, x, y - d, 0, d, -d/2, d)
|
||||
:triang(FILL, x - d, y, d / 1.5, -d / 4, d, 0)
|
||||
|
||||
elseif p == 2 then self -- bot-left
|
||||
|
||||
:arc(LINE, x + d, y - d, d, math.pi / 2, math.pi)
|
||||
:triang(FILL, x, y - d, 0, d, d/2, d)
|
||||
:triang(FILL, x, y, d / 1.5, -d / 4, d, 0)
|
||||
|
||||
elseif p == 3 then self -- top-right
|
||||
|
||||
:arc(LINE, x - d, y + d, d, math.pi * 1.5, math.pi * 2)
|
||||
:triang(FILL, x, y, 0, d, -d/2, 0)
|
||||
:triang(FILL, x - d, y, d / 1.5, d / 4, d, 0)
|
||||
|
||||
elseif p == 4 then self -- top-left
|
||||
|
||||
:arc(LINE, x + d, y + d, d, math.pi, math.pi * 1.5)
|
||||
:triang(FILL, x, y, 0, d, d/2, 0)
|
||||
:triang(FILL, x, y, d / 1.5, d / 4, d, 0)
|
||||
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
33
src/draw/rrect.lua
Normal file
33
src/draw/rrect.lua
Normal file
|
@ -0,0 +1,33 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:rrect(m, x, y, w, h, r)
|
||||
local rtl, rtr, rbl, rbr = r[1] or 8, r[2], r[3], r[4]
|
||||
rtr = rtr or rtl
|
||||
rbl = rbl or rtl
|
||||
rbr = rbr or rbl
|
||||
|
||||
local ml, mr, Ml, Mr, Mt, Mb =
|
||||
math.min(rtl, rbl), math.min(rtr, rbr),
|
||||
math.max(rtl, rbl), math.max(rtr, rbr),
|
||||
math.max(rtl, rtr), math.max(rbl, rbr)
|
||||
if m == FILL then self
|
||||
:rect(m, x + Ml, y + Mt, w - Ml - Mr, h - Mt - Mb)
|
||||
:rect(m, x + rtl, y, w - rtl - rtr, Mt) -- top
|
||||
:rect(m, x + rbl, y + h - Mb, w - rbl - rbr, Mb) -- bottom
|
||||
:rect(m, x, y + rtl, Ml, h - rtl - rbl) -- left
|
||||
:rect(m, x + w - Mr, y + rtr, Mr, h - rtr - rbr) -- right
|
||||
end
|
||||
self
|
||||
:line(x + rtl, y, x + w - rtr, y)
|
||||
:line(x, y + rtl, x, y + h - rbl)
|
||||
:line(x + rbl, y + h, x + w - rbr, y + h)
|
||||
:line(x + w, y + rtr, x + w, y + h - rbr)
|
||||
|
||||
:arc(m, x + rtl, y + rtl, rtl, math.pi, math.pi * 1.5)
|
||||
:arc(m, x + w - rtr, y + rtr, rtr, math.pi * 1.5, math.pi * 2)
|
||||
:arc(m, x + w - rbr, y + h - rbr, rbr, 0, math.pi / 2)
|
||||
:arc(m, x + rbl, y + h - rbl, rbl, math.pi / 2, math.pi)
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
36
src/draw/system.lua
Normal file
36
src/draw/system.lua
Normal file
|
@ -0,0 +1,36 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:free(f)
|
||||
if self.fr then return end
|
||||
self.fr = true
|
||||
--if self._cr then self._cr:release() end
|
||||
if f then draw:freeFont() end
|
||||
collectgarbage 'collect'
|
||||
end
|
||||
function draw:freeFont()
|
||||
if self.f then self.f:release() end
|
||||
end
|
||||
|
||||
function draw:give()
|
||||
if self.fr then return end
|
||||
self.pc = love.graphics.getCanvas()
|
||||
if self.pc ~= self.cr then
|
||||
love.graphics.push()
|
||||
love.graphics.origin()
|
||||
love.graphics.setCanvas(self._cr)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:back()
|
||||
love.graphics.setCanvas(self.pc)
|
||||
love.graphics.pop()
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:full(full)
|
||||
love.window.setFullscreen(full or false)
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
18
src/draw/transform.lua
Normal file
18
src/draw/transform.lua
Normal file
|
@ -0,0 +1,18 @@
|
|||
return function(draw)
|
||||
|
||||
function draw:orig()
|
||||
love.graphics.origin()
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:move(x, y)
|
||||
love.graphics.translate(x, y)
|
||||
return self
|
||||
end
|
||||
|
||||
function draw:scale(sx, sy)
|
||||
love.graphics.scale(sx, sy)
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
31
src/fs.lua
Normal file
31
src/fs.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
return function()
|
||||
|
||||
local lfs = love.filesystem
|
||||
|
||||
function fsLs(path)
|
||||
return lfs.getDirectoryItems(path)
|
||||
end
|
||||
|
||||
function fsHas(file)
|
||||
if lfs.getInfo
|
||||
then return not not lfs.getInfo(file) end
|
||||
return lfs.exists(file)
|
||||
end
|
||||
|
||||
function fsInfo(file)
|
||||
if lfs.getInfo
|
||||
then return lfs.getInfo(file)
|
||||
end
|
||||
if not fsHas(file)
|
||||
then return end
|
||||
local info = {}
|
||||
if lfs.isFile(file) then info.type = 'file'
|
||||
elseif lfs.isDirectory(file) then info.type = 'directory'
|
||||
elseif lfs.isSymlink(file) then info.type = 'symlink'
|
||||
else info.type = 'other' end
|
||||
info.size = lfs.getSize(file)
|
||||
info.modtime = lfs.getLastModified(file)
|
||||
return info
|
||||
end
|
||||
|
||||
end
|
28
src/gui.lua
Normal file
28
src/gui.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
local nlv = {}
|
||||
for k, v in pairs(love) do
|
||||
nlv[k] = v
|
||||
end
|
||||
|
||||
local gui = {}
|
||||
|
||||
function gui.init()
|
||||
love.draw = gui.draw
|
||||
love.update = gui.update
|
||||
|
||||
love.keypressed = nil
|
||||
love.keyreleased = nil
|
||||
love.textedited = nil
|
||||
love.textinput = nil
|
||||
end
|
||||
|
||||
function gui.update(dt)
|
||||
updM()
|
||||
end
|
||||
|
||||
function gui.stop()
|
||||
for k, v in pairs(nlv) do
|
||||
love[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return gui
|
BIN
src/hack.ttf
Normal file
BIN
src/hack.ttf
Normal file
Binary file not shown.
53
src/mouse.lua
Normal file
53
src/mouse.lua
Normal file
|
@ -0,0 +1,53 @@
|
|||
return function(con)
|
||||
|
||||
local mob = love.system.getOS() == 'Android'
|
||||
|
||||
m = {
|
||||
x = 0, y = 0,
|
||||
mx = 0, my = 0,
|
||||
b = 0, pb = 0,
|
||||
t = os.time(),
|
||||
}
|
||||
function updM()
|
||||
local x, y = love.mouse.getPosition()
|
||||
m.mx, m.my = x - m.x, y - m.y
|
||||
m.x, m.y = x, y
|
||||
|
||||
m.pb = m.b
|
||||
if love.mouse.isDown(1) then m.b = 1
|
||||
elseif love.mouse.isDown(2) then m.b = 2
|
||||
elseif love.mouse.isDown(3) then m.b = 3
|
||||
else m.b = 0 end
|
||||
|
||||
if m.b ~= 0 and m.pb == 0
|
||||
then m.t = os.time() end
|
||||
|
||||
if m.pb == 0 and m.b ~= 0
|
||||
then m.mx, m.my = 0, 0
|
||||
end
|
||||
end
|
||||
|
||||
function love.update(dt)
|
||||
updM()
|
||||
|
||||
if m.b == 0 and m.pb ~= 0 then
|
||||
if os.time() - m.t < 1 then
|
||||
if mob
|
||||
then love.keyboard.setTextInput(
|
||||
not love.keyboard.hasTextInput(),
|
||||
0, con.th + con.oy,
|
||||
con.w * con.cw, con.ch)
|
||||
end
|
||||
con.down()
|
||||
end
|
||||
end
|
||||
|
||||
if m.b == 1
|
||||
then con.move(m.my) end
|
||||
end
|
||||
|
||||
function love.wheelmoved(x, y)
|
||||
con.move(y * con.ch)
|
||||
end
|
||||
|
||||
end
|
55
src/os.lua
Normal file
55
src/os.lua
Normal file
|
@ -0,0 +1,55 @@
|
|||
VER = '0.1'
|
||||
|
||||
return function(con)
|
||||
|
||||
love.keyboard.setKeyRepeat(true)
|
||||
|
||||
require 'src.mouse' (con)
|
||||
require 'src.fs' ()
|
||||
require 'src.async'
|
||||
draw = require 'src.draw'
|
||||
|
||||
local w, h
|
||||
function love.resize(x, y)
|
||||
w, h = math.max(32, x), math.max(32, y)
|
||||
draw:newFont('src/hack.ttf', math.min(w, h) / 32)
|
||||
local cw, ch = draw:getFText 'A'
|
||||
collectgarbage 'collect'
|
||||
con:emit('res', w, h, cw, ch)
|
||||
end
|
||||
love.resize(love.graphics.getDimensions())
|
||||
love.window.setMode(w, h, {
|
||||
resizable = true,
|
||||
minwidth = 32,
|
||||
minheight = 32
|
||||
})
|
||||
|
||||
love.textinput = con.type
|
||||
love.keypressed = con.keydown
|
||||
|
||||
function love.draw()
|
||||
draw:color(100, 255, 0)
|
||||
con.forText(function(l, x, y)
|
||||
local cw, ch = draw:getFText(l)
|
||||
if not (
|
||||
l == '\n'
|
||||
or l == '\r'
|
||||
or l == '\v'
|
||||
or l == '\t'
|
||||
)
|
||||
then draw:text(l, x * con.cw + (con.cw - cw) / 2, y * con.ch + con.oy)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function loadapp(name, ...)
|
||||
local succ, msg = pcall(require, 'sysapps.'.. name)
|
||||
if not succ then
|
||||
con.println('ERROR: '.. msg)
|
||||
print(msg)
|
||||
else
|
||||
msg({...}, con)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
51
src/term/events.lua
Normal file
51
src/term/events.lua
Normal file
|
@ -0,0 +1,51 @@
|
|||
--[[ Events library
|
||||
-- (c) Er2 2021 <er2@dismail.de>
|
||||
-- Zlib License
|
||||
--]]
|
||||
|
||||
local events = {}
|
||||
events.__index = events
|
||||
|
||||
function events:_add(t, n, f)
|
||||
table.insert(self._ev_, {
|
||||
type = t,
|
||||
name = n,
|
||||
fn = f,
|
||||
})
|
||||
end
|
||||
|
||||
function events:on(n,f) self:_add('on', n,f) end
|
||||
function events:once(n,f) self:_add('once', n,f) end
|
||||
|
||||
function events:off(f)
|
||||
for k, v in pairs(self._ev_) do
|
||||
if v.fn == f then
|
||||
table.remove(self._ev_, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function events:_ev(t, i, name, ...)
|
||||
local v = t[i]
|
||||
if v.name == name then
|
||||
v.fn(...)
|
||||
if v.type == 'once' then table.remove(t, i) end
|
||||
end
|
||||
end
|
||||
|
||||
function events:emit(name, ...)
|
||||
local t = self._ev_
|
||||
for i = 1, #t do
|
||||
local v = t[i] or {}
|
||||
if type(v) == 'table'
|
||||
and type(v.name) == 'string'
|
||||
and type(v.type) == 'string'
|
||||
and type(v.fn) == 'function'
|
||||
then self:_ev(t, i, name, ...) end
|
||||
end
|
||||
end
|
||||
|
||||
return function(t)
|
||||
t._ev_ = {}
|
||||
return setmetatable(t, events)
|
||||
end
|
43
src/term/get.lua
Normal file
43
src/term/get.lua
Normal file
|
@ -0,0 +1,43 @@
|
|||
return function(con)
|
||||
|
||||
function con.getch(tout)
|
||||
local t, ch = os.time(), nil
|
||||
con.usebs = false
|
||||
con:once('type', function(text)
|
||||
ch = text:sub(1, 1)
|
||||
end)
|
||||
await(function() return
|
||||
ch ~= nil
|
||||
or (tout and os.time() - t >= tout)
|
||||
end)
|
||||
con.usebs = true
|
||||
return ch
|
||||
end
|
||||
|
||||
function con.getln()
|
||||
local ln, du = '', true
|
||||
local function _ln(text)
|
||||
ln = ln .. text
|
||||
end
|
||||
local function _dwn(k)
|
||||
if k == 'backspace' then
|
||||
if #ln == 0 then con.usebs = false
|
||||
else
|
||||
con.usebs = true
|
||||
ln = con.bs(ln)
|
||||
end
|
||||
end
|
||||
end
|
||||
con:on('type', _ln)
|
||||
con:on('down', _dwn)
|
||||
con:once('return', function()
|
||||
con:off(_ln)
|
||||
con:off(_dwn)
|
||||
con.usebs = true
|
||||
du = false
|
||||
end)
|
||||
await(function() return not du end)
|
||||
return ln
|
||||
end
|
||||
|
||||
end
|
24
src/term/init.lua
Normal file
24
src/term/init.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
utf8 = require 'utf8'
|
||||
|
||||
-- Model
|
||||
local con = {
|
||||
text = {''},
|
||||
w = 0, h = 0,
|
||||
cw = 0, ch = 0,
|
||||
oy = 0, th = 0,
|
||||
usebs = true,
|
||||
}
|
||||
|
||||
local m = {
|
||||
'events', -- REQUIRED!
|
||||
'loop',
|
||||
'resize', 'type', 'get',
|
||||
}
|
||||
|
||||
for _, v in pairs(m) do
|
||||
require('src.term.'.. v)(con)
|
||||
end
|
||||
|
||||
con:emit('init')
|
||||
|
||||
return con
|
27
src/term/loop.lua
Normal file
27
src/term/loop.lua
Normal file
|
@ -0,0 +1,27 @@
|
|||
return function(con)
|
||||
|
||||
function con.forLine(l, fn, oy)
|
||||
local x, y = 0, 0
|
||||
for j, l in utf8.codes(con.text[l]) do
|
||||
l = utf8.char(l)
|
||||
if fn then fn(l, x, y + oy) end
|
||||
if l == '\t' then x = x + 8 - (x % 8)
|
||||
elseif l == '\v' then y = y + 1
|
||||
elseif l == '\r' then x = 0
|
||||
else x = x + 1
|
||||
end
|
||||
if x + 1 > con.w
|
||||
then x, y = 0, y + 1 end
|
||||
end
|
||||
return y
|
||||
end
|
||||
|
||||
function con.forText(fn)
|
||||
local y = 0
|
||||
for i = 1, #con.text do
|
||||
y = y + 1 + con.forLine(i, fn, y)
|
||||
end
|
||||
return y
|
||||
end
|
||||
|
||||
end
|
31
src/term/resize.lua
Normal file
31
src/term/resize.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
return function(con)
|
||||
|
||||
con:on('res', function(w, h, cw, ch)
|
||||
con.cw, con.ch = cw or con.cw, ch or con.ch
|
||||
con.w, con.h =
|
||||
math.floor(w / cw),
|
||||
math.floor(h / ch)
|
||||
con:emit('resT')
|
||||
end)
|
||||
|
||||
con:on('resT', function()
|
||||
local y = con.forText()
|
||||
con.th = y * con.ch
|
||||
end)
|
||||
|
||||
function con.down()
|
||||
con.oy = 0
|
||||
con.move(-math.huge)
|
||||
end
|
||||
|
||||
function con.move(oy)
|
||||
con.oy = con.oy + oy
|
||||
con.oy = math.max(
|
||||
-(con.th - con.ch * con.h / 1.2),
|
||||
math.min(con.oy, 0)
|
||||
)
|
||||
if con.th < (con.ch - 1) * con.h
|
||||
then con.oy = 0 end
|
||||
end
|
||||
|
||||
end
|
67
src/term/type.lua
Normal file
67
src/term/type.lua
Normal file
|
@ -0,0 +1,67 @@
|
|||
return function(con)
|
||||
|
||||
function con.curln(of)
|
||||
return con.text[#con.text - (of or 0)]
|
||||
end
|
||||
|
||||
function con.setln(v, of)
|
||||
con.text[#con.text - (of or 0)] = tostring(v)
|
||||
return v
|
||||
end
|
||||
|
||||
function con.bs(oth)
|
||||
if not con.usebs then return end
|
||||
local s = oth or con.curln()
|
||||
local off = utf8.offset(s, -1)
|
||||
if off then
|
||||
s = s:sub(1, off - 1)
|
||||
end
|
||||
if not oth then con.setln(s) end
|
||||
return s
|
||||
end
|
||||
|
||||
function con.cls()
|
||||
con.text = {''}
|
||||
con.oy = 0
|
||||
end
|
||||
|
||||
function con.print(text)
|
||||
for i, v in utf8.codes(tostring(text)) do
|
||||
v = utf8.char(v)
|
||||
if v == '\n' then con.ret()
|
||||
elseif v == '\b' then con.bs()
|
||||
-- \r\t\v is in loop
|
||||
else con.puts(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function con.puts(text)
|
||||
con.setln(con.curln().. text)
|
||||
con:emit('resT')
|
||||
end
|
||||
|
||||
function con.println(text)
|
||||
con.print(tostring(text).. '\n')
|
||||
end
|
||||
|
||||
function con.ret()
|
||||
table.insert(con.text, '')
|
||||
end
|
||||
|
||||
function con.type(text)
|
||||
con.puts(text)
|
||||
con:emit('type', text)
|
||||
end
|
||||
|
||||
function con.keydown(k)
|
||||
con:emit('down', k)
|
||||
if k == 'backspace' then con.bs()
|
||||
elseif k == 'return' then
|
||||
con.ret()
|
||||
con.down()
|
||||
con:emit('return')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
54
src/win.lua
Normal file
54
src/win.lua
Normal file
|
@ -0,0 +1,54 @@
|
|||
local gui = require 'src.gui'
|
||||
|
||||
local wins = {
|
||||
{x = 64, y = 64, w = 64, h = 64},
|
||||
}
|
||||
|
||||
local bw, th = 8, 16
|
||||
|
||||
function gui.draw()
|
||||
draw:color(0, 100, 150)
|
||||
:rect(FILL, 0, 0, gui.w, gui.h)
|
||||
:color(255, 255, 255)
|
||||
:text('This is a demo of GUI in ErDOS', gui.w / 4, gui.h / 2)
|
||||
for i = #wins, 1, -1 do
|
||||
local v = wins[i]
|
||||
draw
|
||||
:color(100, 100, 100)
|
||||
:rrect(FILL,
|
||||
v.x - bw, v.y - bw - th,
|
||||
v.w + bw * 2, v.h + bw * 2 + th,
|
||||
{bw}
|
||||
)
|
||||
:color(255, 255, 255)
|
||||
:rect(FILL, v.x, v.y, v.w, v.h)
|
||||
end
|
||||
end
|
||||
|
||||
function AABB(x1, y1, w1, h1, x2, y2, w2, h2)
|
||||
return
|
||||
x1 + w1 > x2
|
||||
and x2 + w2 > x1
|
||||
and y1 + h1 > y2
|
||||
and y2 + h2 > y1
|
||||
end
|
||||
|
||||
function gui.update(dt)
|
||||
updM()
|
||||
for i = 1, #wins do
|
||||
local v = wins[i]
|
||||
if AABB(m.x, m.y, 0, 0,
|
||||
v.x - bw, v.y - bw - th,
|
||||
v.w + bw * 2, v.h + bw * 2 + th
|
||||
) then
|
||||
gui.stop()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return function(w, h)
|
||||
gui.init()
|
||||
gui.w, gui.h =
|
||||
w or gui.w or 0,
|
||||
h or gui.h or 0
|
||||
end
|
35
sysapps/choise.lua
Normal file
35
sysapps/choise.lua
Normal file
|
@ -0,0 +1,35 @@
|
|||
return function(argv, con)
|
||||
-- /Ckeys /S text
|
||||
local ch = {'Y', 'N'}
|
||||
local cs = false
|
||||
local i = 2
|
||||
while argv[i] do
|
||||
local v = argv[i]:upper()
|
||||
if v:sub(1,1) == '/'
|
||||
then table.remove(argv, i)
|
||||
else i = i + 1
|
||||
end
|
||||
if v:sub(1, 2) == '/C'
|
||||
and #v > 2 then
|
||||
ch = {}
|
||||
for l in v:sub(3):gmatch '.' do table.insert(ch, l) end
|
||||
elseif v == '/S' then cs = true
|
||||
end
|
||||
end
|
||||
con.print(table.concat(argv, ' ', 2))
|
||||
con.print(' ['.. table.concat(ch, ',') ..'] ')
|
||||
con.print('('.. ch[1] ..') ')
|
||||
local chr = con.getch(10)
|
||||
if not chr then chr = ch[1] end
|
||||
|
||||
local ret = 0
|
||||
for k, v in pairs(ch) do
|
||||
if v == chr
|
||||
or (not cs and v:upper() == chr:upper())
|
||||
then ret = k end
|
||||
end
|
||||
|
||||
con.print '\n'
|
||||
|
||||
return ret
|
||||
end
|
3
sysapps/cls.lua
Normal file
3
sysapps/cls.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
return function(argv, con)
|
||||
con.cls()
|
||||
end
|
31
sysapps/dir.lua
Normal file
31
sysapps/dir.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
return function(argv, con)
|
||||
local dir = argv[2] or ''
|
||||
con.print(' Listing of '..dir ..'\n\n')
|
||||
local d = fsLs(dir)
|
||||
local dirs, files, tb = 0, 0, 0
|
||||
for _, v in pairs(d) do
|
||||
local i = fsInfo(dir..'/'..v)
|
||||
con.print(os.date('%m/%d/%Y %I:%M %p ', i.modtime))
|
||||
if i.type == 'directory' then con.print '<DIR>'
|
||||
elseif i.type == 'symlink' then con.print '<SYM>'
|
||||
elseif i.type == 'other' then con.print '<OTH>'
|
||||
else con.print ' ' end
|
||||
if i.type == 'directory' then
|
||||
dirs = dirs + 1
|
||||
con.print ' '
|
||||
else
|
||||
files = files + 1
|
||||
tb = tb + i.size
|
||||
con.print ' '
|
||||
local s = tostring(i.size)
|
||||
con.print((' '):rep(7 - #s))
|
||||
con.print(s)
|
||||
con.print ' '
|
||||
end
|
||||
|
||||
con.println(v)
|
||||
end
|
||||
con.println(('%d File(s)\n%d Dir(s)\n%d Bytes total')
|
||||
:format(files, dirs, tb))
|
||||
con.print '\n'
|
||||
end
|
3
sysapps/echo.lua
Normal file
3
sysapps/echo.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
return function(argv, con)
|
||||
con.println(table.concat(argv, ' ', 2))
|
||||
end
|
65
sysapps/ersh.lua
Normal file
65
sysapps/ersh.lua
Normal file
|
@ -0,0 +1,65 @@
|
|||
return function(argv, con)
|
||||
|
||||
if argv[2] == '-v'
|
||||
then
|
||||
con.println 'Er2Shell 0.5'
|
||||
return
|
||||
end
|
||||
|
||||
local sh = require 'src.baseshell' (con)
|
||||
|
||||
function sh:prompt()
|
||||
return ('%d > '):format(self.env.code)
|
||||
end
|
||||
|
||||
function sh:run(ln)
|
||||
local argv = self:parseArgs(ln)
|
||||
|
||||
if not argv[1] then -- nothing
|
||||
|
||||
elseif argv[1] == 'exit' then
|
||||
self.runs = false
|
||||
|
||||
elseif argv[1] == 'which' then
|
||||
local fnd, snd = self:which(argv[2])
|
||||
if not fnd then self.env.code = 1
|
||||
else self.env.code = 0
|
||||
return fnd..snd
|
||||
end
|
||||
|
||||
elseif argv[1] == 'env' then
|
||||
local ls = ''
|
||||
for k, v in pairs(self.env) do
|
||||
k, v = tostring(k), tostring(v)
|
||||
ls=ls.. ('$%s=%s\n')
|
||||
:format(k, v:match '%s' and '"'..v..'"' or v)
|
||||
end
|
||||
self.env.code = 0
|
||||
return ls:sub(1, -2)
|
||||
|
||||
else
|
||||
local fnd, snd = self:which(argv[1])
|
||||
if not fnd then
|
||||
self.env.code = 127
|
||||
return argv[1].. ': command not found'
|
||||
else self.env.code = 0
|
||||
local succ, msg = pcall(select(2, pcall(loadfile, fnd..snd)))
|
||||
if not succ then
|
||||
print(msg)
|
||||
self.env.code = 126
|
||||
return argv[1].. ': file error'
|
||||
else
|
||||
local succ, msg = pcall(msg, argv, con, self.env)
|
||||
if not succ then
|
||||
self.env.code = self.env.code ~= 0 and self.env.code or 1
|
||||
return argv[1].. ': '.. tostring(msg)
|
||||
else self.env.code = tonumber(msg) or 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sh:loop()
|
||||
|
||||
end
|
7
sysapps/run.lua
Normal file
7
sysapps/run.lua
Normal file
|
@ -0,0 +1,7 @@
|
|||
return function(argv, con)
|
||||
local pr = print
|
||||
print = con.println
|
||||
local suc, ret = pcall(load(table.concat(argv, ' ', 2)))
|
||||
print(ret)
|
||||
print = pr
|
||||
end
|
5
sysapps/ver.lua
Normal file
5
sysapps/ver.lua
Normal file
|
@ -0,0 +1,5 @@
|
|||
return function(argv, con)
|
||||
con.println('ErDOS version '.. VER)
|
||||
con.println('Runs on\vLove2D '.. table.concat({love.getVersion()}, '.', 1, 3))
|
||||
con.println('(c) Er2 2022\tZlib License\n')
|
||||
end
|
3
sysapps/win.lua
Normal file
3
sysapps/win.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
return function(argv, con)
|
||||
require 'src.win' (con.w * con.cw, con.h * con.ch)
|
||||
end
|
Loading…
Reference in a new issue