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