diff --git a/argentum.cfg b/argentum.cfg index ddf468d..dc8f248 100644 --- a/argentum.cfg +++ b/argentum.cfg @@ -1,12 +1,12 @@ local agcfg = { ["halyde"] = { ["maindir"] = "", - ["version"] = "1.7.2", + ["version"] = "1.8.0", ["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.", ["directories"] = { "halyde/apps", "halyde/apps/helpdb", - "halyde/config", + "halyde/config/generate", "halyde/core", "halyde/lib", "home" @@ -38,8 +38,8 @@ local agcfg = { "halyde/apps/mv.lua", "halyde/apps/rm.lua", "halyde/config/oslogo.ans", - "halyde/config/shell.cfg", - "halyde/config/startupapps.cfg", + "halyde/config/generate/shell.cfg", + "halyde/config/generate/startupapps.cfg", "halyde/core/boot.lua", "halyde/core/cormgr.lua", "halyde/core/datatools.lua", @@ -51,6 +51,7 @@ local agcfg = { "halyde/lib/computer.lua", "halyde/lib/event.lua", "halyde/lib/filesystem.lua", + "halyde/lib/json.lua", "halyde/lib/raster.lua" } }, diff --git a/argentum/store/halyde/package.cfg b/argentum/store/halyde/package.cfg index cc5c601..dc51824 100644 --- a/argentum/store/halyde/package.cfg +++ b/argentum/store/halyde/package.cfg @@ -1,10 +1,10 @@ Ahome/ Ahalyde/lib/ Ahalyde/core/ -Ahalyde/config/ +Ahalyde/config/generate/ Ahalyde/apps/helpdb/ Ahalyde/apps/ -V1.7.2 +V1.8.0 Ainit.lua Ahalyde/apps/helpdb/cat.txt Ahalyde/apps/helpdb/cd.txt @@ -31,8 +31,8 @@ Ahalyde/apps/mkdir.lua Ahalyde/apps/mv.lua Ahalyde/apps/rm.lua Ahalyde/config/oslogo.ans -Ahalyde/config/shell.cfg -Ahalyde/config/startupapps.cfg +Ahalyde/config/generate/shell.cfg +Ahalyde/config/generate/startupapps.cfg Ahalyde/core/boot.lua Ahalyde/core/cormgr.lua Ahalyde/core/datatools.lua @@ -44,4 +44,5 @@ Ahalyde/lib/component.lua Ahalyde/lib/computer.lua Ahalyde/lib/event.lua Ahalyde/lib/filesystem.lua +Ahalyde/lib/json.lua Ahalyde/lib/raster.lua diff --git a/halyde/config/generate/shell.json b/halyde/config/generate/shell.json new file mode 100644 index 0000000..b081fb2 --- /dev/null +++ b/halyde/config/generate/shell.json @@ -0,0 +1 @@ +{"prompt":"\u001b[92m%s > \u001b[0m","aliases":{"move":"mv","copy":"cp","ag":"argentum","rename":"mv","..":"cd ..","man":"help","del":"rm","delete":"rm","ren":"mv","remove":"rm","list":"ls","wget":"download","dir":"ls"},"splashMessages":["Made by John Haly- I mean Cerulean Blue.","Welcome! Type \"help\" to get started.","Also try KOCOS!","Welcome back, Commander. We have no idea what we're doing.","99.9% bug-free. The remaining 0.1% are features.","0 days since last error.","Everything is fine. The fire is decorative.","Please don't feed the background processes.","Also has fetch!","Anything red is no man's land. Trust me.","Machine...","Abort, Retry, Fail?","What's the deal with /argentum/store?","So cutting-edge you can't hold it in your hand.","Americans are the reason you see colors on-screen. I'm talking about ANSI escape codes, not politics.","Shoutout to Ponali!"],"path":["/halyde/apps/"],"startupMessage":"\n │\n │ Halyde 1.8.0\n │ %s\n │\n ","defaultWorkingDirectory":"/home/"} \ No newline at end of file diff --git a/halyde/config/generate/startupapps.json b/halyde/config/generate/startupapps.json new file mode 100644 index 0000000..d5955d9 --- /dev/null +++ b/halyde/config/generate/startupapps.json @@ -0,0 +1 @@ +["/halyde/core/fullkb.lua","/halyde/core/evmgr.lua","/halyde/core/shell.lua"] diff --git a/halyde/config/shell.cfg b/halyde/config/shell.cfg deleted file mode 100644 index d31972f..0000000 --- a/halyde/config/shell.cfg +++ /dev/null @@ -1,41 +0,0 @@ -local shellcfg = { - ["startupMessage"] = "\n │\n │ ".._OSVERSION..'\n │ %s\n │\n ', -- message shown on startup. %s will be replaced with splash message. - ["prompt"] = "\x1b[92m%s > \x1b[0m", -- shell prompt. %s will be replaced with working directory. - ["path"] = { -- default locations where programs will be run from - "/halyde/apps/" - }, ["aliases"] = { -- shell command aliases - ["copy"] = "cp", - ["move"] = "mv", - ["rename"] = "mv", - ["ren"] = "mv", - ["dir"] = "ls", - ["list"] = "ls", - ["man"] = "help", - ["del"] = "rm", - ["delete"] = "rm", - ["remove"] = "rm", - [".."] = "cd ..", - ["wget"] = "download", - ["ag"] = "argentum" - }, ["defaultWorkingDirectory"] = "/home/", -- the working directory that gets set when halyde starts - ["splashMessages"] = { -- messages shown on startup - "Made by John Haly- I mean Cerulean Blue.", - 'Welcome! Type "help" to get started.', - "Also try KOCOS!", - "Welcome back, Commander. We have no idea what we're doing.", - "99.9% bug-free. The remaining 0.1% are features.", - "0 days since last error.", - "Everything is fine. The fire is decorative.", - "Please don't feed the background processes.", - "Also has fetch!", - "Anything red is no man's land. Trust me.", - "Machine...", - "Abort, Retry, Fail?", - "What's the deal with /argentum/store?", - "So cutting-edge you can't hold it in your hand.", - "Americans are the reason you see colors on-screen. I'm talking about ANSI escape codes, not politics.", - "Shoutout to Ponali!" - } -} - -return shellcfg diff --git a/halyde/config/startupapps.cfg b/halyde/config/startupapps.cfg deleted file mode 100644 index 6bc43df..0000000 --- a/halyde/config/startupapps.cfg +++ /dev/null @@ -1,3 +0,0 @@ -/halyde/core/fullkb.lua -/halyde/core/evmgr.lua -/halyde/core/shell.lua diff --git a/halyde/core/boot.lua b/halyde/core/boot.lua index 436e139..c89076c 100644 --- a/halyde/core/boot.lua +++ b/halyde/core/boot.lua @@ -1,7 +1,7 @@ local loadfile = ... local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile) -_G._OSVERSION = "Halyde 1.7.2" +_G._OSVERSION = "Halyde 1.8.0" _G._OSLOGO = "" local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil repeat @@ -84,5 +84,14 @@ preload("computer") --local handle = assert(filesystem.open("/bazinga.txt", "w")) --assert(handle:write("Bazinga!")) --handle:close() + +local fs = import("filesystem") +if not fs.exists("/halyde/config/shell.json") then + fs.copy("/halyde/config/generate/shell.json", "/halyde/config/shell.json") +end +if not fs.exists("/halyde/config/startupapps.json") then + fs.copy("/halyde/config/generate/startupapps.json", "/halyde/config/startupapps.json") +end +fs = nil import("/halyde/core/cormgr.lua") diff --git a/halyde/core/cormgr.lua b/halyde/core/cormgr.lua index 938cd0c..0b64b33 100644 --- a/halyde/core/cormgr.lua +++ b/halyde/core/cormgr.lua @@ -5,6 +5,7 @@ _G.cormgr.corList = {} local component = import("component") local filesystem = import("filesystem") +local json = import("json") local gpu = component.proxy(component.list("gpu")()) function _G.cormgr.loadCoroutine(path, ...) @@ -55,14 +56,13 @@ local function runCoroutines() end end -local handle = filesystem.open("/halyde/config/startupapps.cfg", "r") -local data = "" -local tmpdata +local handle, data, tmpdata = filesystem.open("/halyde/config/startupapps.json", "r"), "", nil repeat tmpdata = handle:read(math.huge or math.maxinteger) data = data .. (tmpdata or "") until not tmpdata -for line in data:gmatch("([^\n]*)\n?") do +handle:close() +for _, line in ipairs(json.decode(data)) do if line ~= "" then --[[ if _G.print then print(line) diff --git a/halyde/core/evmgr.lua b/halyde/core/evmgr.lua index 13cb13b..59ca5e2 100644 --- a/halyde/core/evmgr.lua +++ b/halyde/core/evmgr.lua @@ -12,13 +12,12 @@ keyboard.altDown = false while true do local args repeat - args = {computer.pullSignal(0)} - if args and args[1] then - --ocelot.log("Sending signal "..args..","..computer.uptime()) + args = {computer.uptime(), computer.pullSignal(0)} + if args and args[2] then table.insert(evmgr.eventQueue, args) if keyboard then - if args[1] == "key_down" then - local keycode = args[4] + if args[2] == "key_down" then + local keycode = args[5] local key = keyboard.keys[keycode] if key == "lcontrol" then keyboard.ctrlDown = true @@ -30,8 +29,8 @@ while true do end cormgr.corList[#cormgr.corList] = nil end - elseif args[1] == "key_up" then - local keycode = args[4] + elseif args[2] == "key_up" then + local keycode = args[5] local key = keyboard.keys[keycode] if key == "lcontrol" then keyboard.ctrlDown = false diff --git a/halyde/core/shell.lua b/halyde/core/shell.lua index f4a9f8d..aac1b9d 100644 --- a/halyde/core/shell.lua +++ b/halyde/core/shell.lua @@ -1,7 +1,14 @@ -local shellcfg = import("/halyde/config/shell.cfg") +local fs = import("filesystem") +local json = import("json") +local handle, data, tmpdata = fs.open("/halyde/config/shell.json", "r"), "", nil +repeat + tmpdata = handle:read(math.huge) + data = data .. (tmpdata or "") +until not tmpdata +handle:close() +local shellcfg = json.decode(data) import("/halyde/core/termlib.lua") local event = import("event") -local filesystem = import("filesystem") local component = import("component") local gpu = component.proxy(component.list("gpu")()) @@ -51,39 +58,36 @@ function _G.shell.run(command) end end -- execute the program - local foundfile = false + local PATH = table.copy(shellcfg.path) + table.insert(PATH, shell.workingDirectory) if not args[1] then return end - if filesystem.exists(args[1]) and not filesystem.isDirectory(args[1]) then - foundfile = true + if fs.exists(args[1]) and not fs.isDirectory(args[1]) then local path = args[1] table.remove(args, 1) runAsCoroutine(path, table.unpack(args)) - else - for _, item in pairs(shellcfg["path"]) do - if filesystem.exists(item..args[1]) and not filesystem.isDirectory(item .. args[1]) then - foundfile = true - local path = item..args[1] - table.remove(args, 1) - runAsCoroutine(path, table.unpack(args)) - break - else -- try to look for it without the file extension - local files = filesystem.list(item) - for _, file in pairs(files) do - if args[1] == file:match("(.+)%.[^%.]+$") and not filesystem.isDirectory(item .. file) then - foundfile = true - table.remove(args, 1) - runAsCoroutine(item .. file, table.unpack(args)) - break - end + return + end + for _, item in pairs(PATH) do + if fs.exists(item..args[1]) and not fs.isDirectory(item .. args[1]) then + local path = fs.concat(item, args[1]) + table.remove(args, 1) + runAsCoroutine(path, table.unpack(args)) + return + else -- try to look for it without the file extension + local files = fs.list(item) + for _, file in pairs(files) do + -- previous pattern: (.+)%.[^%.]+$ + if args[1] == file:match("(.+)%.[^%.]+$") and not fs.isDirectory(item .. file) then + table.remove(args, 1) + runAsCoroutine(item .. file, table.unpack(args)) + return end end end end - if not foundfile then - print("No such file or command: "..args[1]) - end + print("No such file or command: "..args[1]) end print(shellcfg["startupMessage"]:format(shellcfg.splashMessages[math.random(1, #shellcfg.splashMessages)])) diff --git a/halyde/core/termlib.lua b/halyde/core/termlib.lua index 6194b18..2ff1ffb 100644 --- a/halyde/core/termlib.lua +++ b/halyde/core/termlib.lua @@ -208,8 +208,8 @@ function _G.read(readHistoryType, prefix, defaultText) while true do --ocelot.log(curtext) termlib.cursorPosX = termlib.cursorPosX - 1 - local args = {event.pull("key_down", 0.5)} - if args[4] then + local args = {event.pull("key_down", "clipboard", 0.5)} + if args[1] == "key_down" and args[4] then cursorWhite = true local keycode = args[4] local key = keyboard.keys[keycode] @@ -258,6 +258,8 @@ function _G.read(readHistoryType, prefix, defaultText) end termlib.cursorPosX, termlib.cursorPosY = cursorPosX, cursorPosY termlib.write(prefix .. curtext) + elseif args[1] == "clipboard" then + else cursorWhite = not cursorWhite end diff --git a/halyde/lib/event.lua b/halyde/lib/event.lua index 65eefc9..70b18fd 100644 --- a/halyde/lib/event.lua +++ b/halyde/lib/event.lua @@ -4,39 +4,38 @@ local event = {} --local ocelot = component.proxy(component.list("ocelot")()) function event.pull(...) local args = {...} - local evtype, timeout + local evtypes, timeout = {}, nil - if #args == 0 then - -- No arguments, wait for any event indefinitely - evtype = nil - timeout = nil - elseif #args == 1 then - -- If one argument is provided, it could be either the event type or timeout - if type(args[1]) == "number" then - -- It's a timeout - evtype = nil - timeout = args[1] - else - -- It's an event type - evtype = args[1] - timeout = nil + for _, arg in pairs(args) do + if type(arg) == "number" and not timeout then -- It's a timeout + timeout = arg + else -- It's an event type + table.insert(evtypes, tostring(arg)) end - else - -- Both event type and timeout provided - evtype = args[1] - timeout = args[2] end local startTime = computer.uptime() - local result = {} - repeat + while true do -- Check event queue for matching event for i = 1, #evmgr.eventQueue do - if not evtype or evmgr.eventQueue[i][1] == evtype then + local foundevent = false + for _, evtype in pairs(evtypes) do + if evtypes[1] then -- event type(s) specified + if evmgr.eventQueue[i][2] == evtype and evmgr.eventQueue[i][1] >= startTime then + foundevent = true + end + else -- event type(s) not specified + if evmgr.eventQueue[i][1] >= startTime then + foundevent = true + end + end + end + if foundevent then -- Found matching event (or any event if no type specified) - result = table.copy(evmgr.eventQueue[i]) + local result = table.copy(evmgr.eventQueue[i]) table.remove(evmgr.eventQueue, i) + table.remove(result, 1) -- remove the time of event argument return table.unpack(result) end end @@ -48,7 +47,7 @@ function event.pull(...) -- Yield to allow other processes to run and more events to be added coroutine.yield() - until false -- Loop until we find an event or timeout + end end return event diff --git a/halyde/lib/json.lua b/halyde/lib/json.lua new file mode 100644 index 0000000..3aa0b76 --- /dev/null +++ b/halyde/lib/json.lua @@ -0,0 +1,4 @@ +-- json.lua by rxi +-- Minified with luamin +-- Original: https://github.com/rxi/json.lua +local a={_version="0.1.2"}local b;local c={["\\"]="\\",["\""]="\"",["\b"]="b",["\f"]="f",["\n"]="n",["\r"]="r",["\t"]="t"}local d={["/"]="/"}for e,f in pairs(c)do d[f]=e end;local function g(h)return"\\"..(c[h]or string.format("u%04x",h:byte()))end;local function i(j)return"null"end;local function k(j,l)local m={}l=l or{}if l[j]then error("circular reference")end;l[j]=true;if rawget(j,1)~=nil or next(j)==nil then local n=0;for e in pairs(j)do if type(e)~="number"then error("invalid table: mixed or invalid key types")end;n=n+1 end;if n~=#j then error("invalid table: sparse array")end;for o,f in ipairs(j)do table.insert(m,b(f,l))end;l[j]=nil;return"["..table.concat(m,",").."]"else for e,f in pairs(j)do if type(e)~="string"then error("invalid table: mixed or invalid key types")end;table.insert(m,b(e,l)..":"..b(f,l))end;l[j]=nil;return"{"..table.concat(m,",").."}"end end;local function p(j)return'"'..j:gsub('[%z\1-\31\\"]',g)..'"'end;local function q(j)if j~=j or j<=-math.huge or j>=math.huge then error("unexpected number value '"..tostring(j).."'")end;return string.format("%.14g",j)end;local r={["nil"]=i,["table"]=k,["string"]=p,["number"]=q,["boolean"]=tostring}b=function(j,l)local s=type(j)local t=r[s]if t then return t(j,l)end;error("unexpected type '"..s.."'")end;function a.encode(j)return b(j)end;local u;local function v(...)local m={}for o=1,select("#",...)do m[select(o,...)]=true end;return m end;local w=v(" ","\t","\r","\n")local x=v(" ","\t","\r","\n","]","}",",")local y=v("\\","/",'"',"b","f","n","r","t","u")local z=v("true","false","null")local A={["true"]=true,["false"]=false,["null"]=nil}local function B(C,D,E,F)for o=D,#C do if E[C:sub(o,o)]~=F then return o end end;return#C+1 end;local function G(C,D,H)local I=1;local J=1;for o=1,D-1 do J=J+1;if C:sub(o,o)=="\n"then I=I+1;J=1 end end;error(string.format("%s at line %d col %d",H,I,J))end;local function K(n)local t=math.floor;if n<=0x7f then return string.char(n)elseif n<=0x7ff then return string.char(t(n/64)+192,n%64+128)elseif n<=0xffff then return string.char(t(n/4096)+224,t(n%4096/64)+128,n%64+128)elseif n<=0x10ffff then return string.char(t(n/262144)+240,t(n%262144/4096)+128,t(n%4096/64)+128,n%64+128)end;error(string.format("invalid unicode codepoint '%x'",n))end;local function L(M)local N=tonumber(M:sub(1,4),16)local O=tonumber(M:sub(7,10),16)if O then return K((N-0xd800)*0x400+O-0xdc00+0x10000)else return K(N)end end;local function P(C,o)local m=""local Q=o+1;local e=Q;while Q<=#C do local R=C:byte(Q)if R<32 then G(C,Q,"control character in string")elseif R==92 then m=m..C:sub(e,Q-1)Q=Q+1;local h=C:sub(Q,Q)if h=="u"then local S=C:match("^[dD][89aAbB]%x%x\\u%x%x%x%x",Q+1)or C:match("^%x%x%x%x",Q+1)or G(C,Q-1,"invalid unicode escape in string")m=m..L(S)Q=Q+#S else if not y[h]then G(C,Q-1,"invalid escape char '"..h.."' in string")end;m=m..d[h]end;e=Q+1 elseif R==34 then m=m..C:sub(e,Q-1)return m,Q+1 end;Q=Q+1 end;G(C,o,"expected closing quote for string")end;local function T(C,o)local R=B(C,o,x)local M=C:sub(o,R-1)local n=tonumber(M)if not n then G(C,o,"invalid number '"..M.."'")end;return n,R end;local function U(C,o)local R=B(C,o,x)local V=C:sub(o,R-1)if not z[V]then G(C,o,"invalid literal '"..V.."'")end;return A[V],R end;local function W(C,o)local m={}local n=1;o=o+1;while 1 do local R;o=B(C,o,w,true)if C:sub(o,o)=="]"then o=o+1;break end;R,o=u(C,o)m[n]=R;n=n+1;o=B(C,o,w,true)local X=C:sub(o,o)o=o+1;if X=="]"then break end;if X~=","then G(C,o,"expected ']' or ','")end end;return m,o end;local function Y(C,o)local m={}o=o+1;while 1 do local Z,j;o=B(C,o,w,true)if C:sub(o,o)=="}"then o=o+1;break end;if C:sub(o,o)~='"'then G(C,o,"expected string for key")end;Z,o=u(C,o)o=B(C,o,w,true)if C:sub(o,o)~=":"then G(C,o,"expected ':' after key")end;o=B(C,o+1,w,true)j,o=u(C,o)m[Z]=j;o=B(C,o,w,true)local X=C:sub(o,o)o=o+1;if X=="}"then break end;if X~=","then G(C,o,"expected '}' or ','")end end;return m,o end;local _={['"']=P,["0"]=T,["1"]=T,["2"]=T,["3"]=T,["4"]=T,["5"]=T,["6"]=T,["7"]=T,["8"]=T,["9"]=T,["-"]=T,["t"]=U,["f"]=U,["n"]=U,["["]=W,["{"]=Y}u=function(C,D)local X=C:sub(D,D)local t=_[X]if t then return t(C,D)end;G(C,D,"unexpected character '"..X.."'")end;function a.decode(C)if type(C)~="string"then error("expected argument of type string, got "..type(C))end;local m,D=u(C,B(C,1,w,true))D=B(C,D,w,true)if D<=#C then G(C,D,"trailing garbage")end;return m end;return a