v1.0.0 - Added Argentum as well as other major improvements and bugfixes.
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
local agcfg = {
|
||||||
|
["halyde"] = {
|
||||||
|
["maindir"] = "",
|
||||||
|
["version"] = "1.1.0",
|
||||||
|
["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.",
|
||||||
|
["directories"] = {
|
||||||
|
"halyde/apps",
|
||||||
|
"halyde/apps/helpdb",
|
||||||
|
"halyde/config",
|
||||||
|
"halyde/core",
|
||||||
|
"halyde/lib"
|
||||||
|
},
|
||||||
|
["files"] = {
|
||||||
|
"init.lua",
|
||||||
|
"halyde/apps/helpdb/cat.txt",
|
||||||
|
"halyde/apps/helpdb/cd.txt",
|
||||||
|
"halyde/apps/helpdb/clear.txt",
|
||||||
|
"halyde/apps/helpdb/cp.txt",
|
||||||
|
"halyde/apps/helpdb/default.txt",
|
||||||
|
"halyde/apps/helpdb/echo.txt",
|
||||||
|
"halyde/apps/helpdb/fetch.txt",
|
||||||
|
"halyde/apps/helpdb/help.txt",
|
||||||
|
"halyde/apps/helpdb/ls.txt",
|
||||||
|
"halyde/apps/helpdb/lua.txt",
|
||||||
|
"halyde/apps/helpdb/mv.txt",
|
||||||
|
"halyde/apps/helpdb/rm.txt",
|
||||||
|
"halyde/apps/cat.lua",
|
||||||
|
"halyde/apps/cd.lua",
|
||||||
|
"halyde/apps/clear.lua",
|
||||||
|
"halyde/apps/cp.lua",
|
||||||
|
"halyde/apps/download.lua",
|
||||||
|
"halyde/apps/echo.lua",
|
||||||
|
"halyde/apps/fetch.lua",
|
||||||
|
"halyde/apps/help.lua",
|
||||||
|
"halyde/apps/ls.lua",
|
||||||
|
"halyde/apps/lua.lua",
|
||||||
|
"halyde/apps/mv.lua",
|
||||||
|
"halyde/apps/rm.lua",
|
||||||
|
"halyde/config/shell.cfg",
|
||||||
|
"halyde/config/startupapps.cfg",
|
||||||
|
"halyde/core/boot.lua",
|
||||||
|
"halyde/core/cormgr.lua",
|
||||||
|
"halyde/core/datatools.lua",
|
||||||
|
"halyde/core/evmgr.lua",
|
||||||
|
"halyde/core/fullkb.lua",
|
||||||
|
"halyde/core/shell.lua",
|
||||||
|
"halyde/core/termlib.lua",
|
||||||
|
"halyde/lib/component.lua",
|
||||||
|
"halyde/lib/event.lua",
|
||||||
|
"halyde/lib/filesystem.lua",
|
||||||
|
"halyde/lib/raster.lua"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
["argentum"] = {
|
||||||
|
["maindir"] = "",
|
||||||
|
["version"] = "1.0.0",
|
||||||
|
["description"] = "The default package manager for Halyde.",
|
||||||
|
["directories"] = {
|
||||||
|
"argentum",
|
||||||
|
"argentum/store"
|
||||||
|
},
|
||||||
|
["files"] = {
|
||||||
|
"argentum/registry.cfg",
|
||||||
|
"halyde/apps/argentum.lua",
|
||||||
|
"halyde/apps/helpdb/argentum.txt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
["edit"] = {
|
||||||
|
["maindir"] = "",
|
||||||
|
["version"] = "1.1.0",
|
||||||
|
["description"] = "The default text editor for Halyde.",
|
||||||
|
["files"] = {
|
||||||
|
"halyde/apps/edit.lua",
|
||||||
|
"halyde/apps/helpdb/edit.txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return agcfg
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
local agregistry = {
|
||||||
|
["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||||
|
["edit"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||||
|
["argentum"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/"
|
||||||
|
}
|
||||||
|
|
||||||
|
return agregistry
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Aargentum/registry.cfg
|
||||||
|
Ahalyde/apps/argentum.lua
|
||||||
|
Ahalyde/apps/helpdb/argentum.txt
|
||||||
|
V1.0.0
|
||||||
|
Aargentum/
|
||||||
|
Aargentum/store/
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Ahalyde/apps/edit.lua
|
||||||
|
Ahalyde/apps/helpdb/edit.txt
|
||||||
|
V1.1.0
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
Ainit.lua
|
||||||
|
Ahalyde/apps/helpdb/cat.txt
|
||||||
|
Ahalyde/apps/helpdb/cd.txt
|
||||||
|
Ahalyde/apps/helpdb/clear.txt
|
||||||
|
Ahalyde/apps/helpdb/cp.txt
|
||||||
|
Ahalyde/apps/helpdb/default.txt
|
||||||
|
Ahalyde/apps/helpdb/echo.txt
|
||||||
|
Ahalyde/apps/helpdb/fetch.txt
|
||||||
|
Ahalyde/apps/helpdb/help.txt
|
||||||
|
Ahalyde/apps/helpdb/ls.txt
|
||||||
|
Ahalyde/apps/helpdb/lua.txt
|
||||||
|
Ahalyde/apps/helpdb/mv.txt
|
||||||
|
Ahalyde/apps/helpdb/rm.txt
|
||||||
|
Ahalyde/apps/cat.lua
|
||||||
|
Ahalyde/apps/cd.lua
|
||||||
|
Ahalyde/apps/clear.lua
|
||||||
|
Ahalyde/apps/cp.lua
|
||||||
|
Ahalyde/apps/download.lua
|
||||||
|
Ahalyde/apps/echo.lua
|
||||||
|
Ahalyde/apps/fetch.lua
|
||||||
|
Ahalyde/apps/help.lua
|
||||||
|
Ahalyde/apps/ls.lua
|
||||||
|
Ahalyde/apps/lua.lua
|
||||||
|
Ahalyde/apps/mv.lua
|
||||||
|
Ahalyde/apps/rm.lua
|
||||||
|
Ahalyde/config/shell.cfg
|
||||||
|
Ahalyde/config/startupapps.cfg
|
||||||
|
Ahalyde/core/boot.lua
|
||||||
|
Ahalyde/core/cormgr.lua
|
||||||
|
Ahalyde/core/datatools.lua
|
||||||
|
Ahalyde/core/evmgr.lua
|
||||||
|
Ahalyde/core/fullkb.lua
|
||||||
|
Ahalyde/core/shell.lua
|
||||||
|
Ahalyde/core/termlib.lua
|
||||||
|
Ahalyde/lib/component.lua
|
||||||
|
Ahalyde/lib/event.lua
|
||||||
|
Ahalyde/lib/filesystem.lua
|
||||||
|
Ahalyde/lib/raster.lua"
|
||||||
|
V1.0.0
|
||||||
|
Ahalyde/
|
||||||
|
Ahalyde/apps/
|
||||||
|
Ahalyde/apps/helpdb/
|
||||||
|
Ahalyde/config/
|
||||||
|
Ahalyde/core/
|
||||||
|
Ahalyde/lib/
|
||||||
@@ -0,0 +1,550 @@
|
|||||||
|
local packages = {...}
|
||||||
|
local command = packages[1]
|
||||||
|
table.remove(packages, 1)
|
||||||
|
local fs = import("filesystem")
|
||||||
|
local agReg = import("/argentum/registry.cfg")
|
||||||
|
if not command then
|
||||||
|
shell.run("help argentum")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not component.list("internet")() then
|
||||||
|
print("\27[91mThis program requires an internet card to run.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local internet = component.proxy(component.list("internet")())
|
||||||
|
local source
|
||||||
|
if table.find(packages, "-s") then
|
||||||
|
source = table.remove(packages, table.find(packages, "-s") + 1)
|
||||||
|
table.remove(packages, table.find(packages, "-s"))
|
||||||
|
print("Using " .. source .. " as package source")
|
||||||
|
elseif table.find(packages, "--source") then
|
||||||
|
source = table.remove(packages, table.find(packages, "--source") + 1)
|
||||||
|
table.remove(packages, table.find(packages, "--source"))
|
||||||
|
print("Using " .. source .. " as package source")
|
||||||
|
else
|
||||||
|
print("Using main registry as package source")
|
||||||
|
end
|
||||||
|
if source and source:sub(1, 1) == "/" and source:sub(-1, -1) ~= "/" then
|
||||||
|
source = source .. "/"
|
||||||
|
end
|
||||||
|
local packageList = table.copy(packages)
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
if path:sub(1,1) == "/" then
|
||||||
|
if not fs.exists(path) then
|
||||||
|
return false, "file does not exist"
|
||||||
|
end
|
||||||
|
local handle, data, tmpdata = fs.open(path, "r"), "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
return data
|
||||||
|
else
|
||||||
|
local request, data, tmpdata = nil, "", nil
|
||||||
|
local status, errorMessage = pcall(function()
|
||||||
|
request = internet.request(path)
|
||||||
|
request:finishConnect()
|
||||||
|
end)
|
||||||
|
if not status then
|
||||||
|
return false, errorMessage
|
||||||
|
end
|
||||||
|
local responseCode = request:response()
|
||||||
|
if responseCode and responseCode ~= 200 then
|
||||||
|
return false, responseCode
|
||||||
|
end
|
||||||
|
repeat
|
||||||
|
tmpdata = request.read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local i = 1
|
||||||
|
|
||||||
|
local function getAgConfig(package, source)
|
||||||
|
source = source or agReg[package]
|
||||||
|
local data, errorMessage = getFile(source .. "argentum.cfg")
|
||||||
|
if not data or data == "" then
|
||||||
|
print("\27[91mCould not fetch Ag config: " .. (errorMessage or "returned nil data"))
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local func, errorMessage = load(data, "=argentum.cfg", "bt", {})
|
||||||
|
if not func then
|
||||||
|
print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local agcfg
|
||||||
|
local status, errorMessage = pcall(function()
|
||||||
|
agcfg = func()
|
||||||
|
end)
|
||||||
|
if not status then
|
||||||
|
print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not agcfg[package] or not agcfg[package].maindir or not agcfg[package].directories or not agcfg[package].files or not agcfg[package].version then
|
||||||
|
local response = ("\27[91mAg config of " .. package .. " is improperly configured.\nPlease contact the package owner.")
|
||||||
|
end
|
||||||
|
return agcfg
|
||||||
|
end
|
||||||
|
|
||||||
|
local function doChecks(package)
|
||||||
|
if not agReg[package] and not source then
|
||||||
|
print("\27[91mPackage " .. package .. " does not exist.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if fs.exists("/argentum/store/" .. package) then
|
||||||
|
print("\27[91mPackage " .. package .. " is already installed.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
agcfg = getAgConfig(package, source)
|
||||||
|
if not agcfg then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if agcfg[package].dependencies then
|
||||||
|
for _, dependency in ipairs(agcfg[package].dependencies) do
|
||||||
|
if not agReg[dependency] and not agcfg[dependency] then
|
||||||
|
local response = read(nil, "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]")
|
||||||
|
if response:lower() ~= "s" then
|
||||||
|
fs.remove("/argentum/store/" .. package)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, dependency in pairs(agcfg[package].dependencies) do
|
||||||
|
print(package .. " depends on " .. dependency)
|
||||||
|
if not table.find(packages, dependency) and doChecks(dependency) then
|
||||||
|
table.insert(packages, table.find(packages, package), dependency)
|
||||||
|
table.insert(packageList, dependency)
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function installPackage(package)
|
||||||
|
print("Installing " .. package .. "...")
|
||||||
|
local agcfg = getAgConfig(package, source)
|
||||||
|
if not agcfg then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local source = source or agReg[package]
|
||||||
|
local packageStore = "V" .. agcfg[package].version
|
||||||
|
if agcfg[package].dependencies then
|
||||||
|
for _, dependency in ipairs(agcfg[package].dependencies) do
|
||||||
|
if not agReg[dependency] and not agcfg[dependency] then
|
||||||
|
local response = read(nil, "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]")
|
||||||
|
if response:lower() ~= "s" then
|
||||||
|
fs.remove("/argentum/store/" .. package)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, dependency in pairs(agcfg[package].dependencies) do
|
||||||
|
if agReg[dependency] or agcfg[dependency] then
|
||||||
|
--installPackage(dependency)
|
||||||
|
packageStore = packageStore .. "\nD" .. dependency
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if agcfg[package].directories then
|
||||||
|
for _, directory in pairs(agcfg[package].directories) do
|
||||||
|
if directory:sub(-1, -1) ~= "/" then
|
||||||
|
directory = directory .. "/"
|
||||||
|
end
|
||||||
|
packageStore = "A" .. directory .. "\n" .. packageStore
|
||||||
|
if not fs.exists(directory) then
|
||||||
|
fs.makeDirectory(directory)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, file in ipairs(agcfg[package].files) do
|
||||||
|
::retry::
|
||||||
|
print(" Downloading " .. file .. "...")
|
||||||
|
local data, errorMessage = getFile(source .. agcfg[package].maindir .. file)
|
||||||
|
if not data then
|
||||||
|
local response = read(nil, "\27[91mCould not fetch " .. file .. ": " .. errorMessage .. "\n\27[0m[a - Abort/R - Retry/s - Skip]")
|
||||||
|
if response:lower() == "a" then
|
||||||
|
fs.remove("/argentum/store/" .. package)
|
||||||
|
return false
|
||||||
|
elseif response:lower() == "s" then
|
||||||
|
goto skip
|
||||||
|
else
|
||||||
|
goto retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if fs.exists(file) then
|
||||||
|
if not fs.exists("/argentum/store/" .. package .. "/files/" .. file:match("(.*/)")) then
|
||||||
|
fs.makeDirectory("/argentum/store/" .. package .. "/files/" .. file:match("(.*/)"))
|
||||||
|
end
|
||||||
|
fs.copy(file, "/argentum/store/" .. package .. "/files/" .. file)
|
||||||
|
packageStore = packageStore .. "\nM" .. file
|
||||||
|
else
|
||||||
|
packageStore = packageStore .. "\nA" .. file
|
||||||
|
end
|
||||||
|
local handle = fs.open(file, "w")
|
||||||
|
handle:write(data)
|
||||||
|
handle:close()
|
||||||
|
::skip::
|
||||||
|
end
|
||||||
|
fs.makeDirectory("/argentum/store/" .. package)
|
||||||
|
local handle = fs.open("/argentum/store/" .. package .. "/package.cfg", "w")
|
||||||
|
handle:write(packageStore)
|
||||||
|
handle:close()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function removePackage(package)
|
||||||
|
print("Removing " .. package .. "...")
|
||||||
|
if not fs.exists("/argentum/store/" .. package .. "/package.cfg") then
|
||||||
|
print("\27[91mLocal Ag config of " .. package .. " does not exist.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
for line in (data.."\n"):gmatch("(.-)\n") do
|
||||||
|
if line:sub(1, 1) == "A" then
|
||||||
|
::retry::
|
||||||
|
print(" Removing " .. line:sub(2) .. "...")
|
||||||
|
if line:sub(-1, -1) == "/" and fs.list(line:sub(2))[1] then
|
||||||
|
print(" There are still files in " .. line:sub(2) .. ". Skipping.")
|
||||||
|
else
|
||||||
|
local result, errorMessage = fs.remove(line:sub(2))
|
||||||
|
if not result then
|
||||||
|
local response = read(nil, "\27[91mFailed to remove " .. line:sub(2) .. ": " .. errorMessage .. "\n\27[0m[a - Abort/r - Retry/S - Skip]")
|
||||||
|
if response:lower() == "a" then
|
||||||
|
return false
|
||||||
|
elseif response:lower() == "r" then
|
||||||
|
goto retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif line:sub(1, 1) == "M" then
|
||||||
|
::retry::
|
||||||
|
print(" Reverting " .. line:sub(2) .. "...")
|
||||||
|
local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/files/" .. line:sub(2), "r"), "", nil
|
||||||
|
if not handle then
|
||||||
|
local response = read(nil, "\27[91mFailed to revert " .. line:sub(2) .. ": " .. data .. "\n\27[0m[a - Abort/R - Retry/s - Skip]") -- this is pretty stupid but i think the error message would get pushed to data
|
||||||
|
if response:lower() == "a" then
|
||||||
|
return false
|
||||||
|
elseif response:lower() == "s" then
|
||||||
|
goto skip
|
||||||
|
else
|
||||||
|
goto retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
local handle = fs.open(line:sub(2), "w")
|
||||||
|
handle:write(data)
|
||||||
|
handle:close()
|
||||||
|
::skip::
|
||||||
|
end
|
||||||
|
end
|
||||||
|
fs.remove("/argentum/store/" .. package .. "/")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update registry
|
||||||
|
local fails = {}
|
||||||
|
if command == "install" then
|
||||||
|
if not packages or not packages[1] then
|
||||||
|
print("Please specify packages to install.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
if not doChecks(packages[i]) then
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
if i > #packages then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local answer
|
||||||
|
if #fails == 0 then
|
||||||
|
print("Packages that will be installed: " .. table.concat(packageList, ", "))
|
||||||
|
if read(nil, "Would you like to proceed? [Y/n] "):lower() == "n" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
elseif #packageList == 0 then
|
||||||
|
print("None of the packages can be installed.")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
print("Some packages cannot be installed.")
|
||||||
|
print("Packages that will be installed: " .. table.concat(packageList, ", "))
|
||||||
|
print("Packages that cannot be installed: " .. table.concat(fails, ", "))
|
||||||
|
if read(nil, "Would you like to proceed? [y/N] "):lower() ~= "y" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, failedPackage in pairs(fails) do
|
||||||
|
table.remove(packages, table.find(packages, failedPackage))
|
||||||
|
end
|
||||||
|
fails = {}
|
||||||
|
for _, package in ipairs(packages) do
|
||||||
|
if not installPackage(package) then
|
||||||
|
table.insert(fails, package)
|
||||||
|
table.remove(packageList, table.find(packageList, package))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #fails == 0 then
|
||||||
|
print("Installation completed successfully.")
|
||||||
|
print("Packages installed: " .. table.concat(packageList, ", "))
|
||||||
|
elseif #packageList == 0 then
|
||||||
|
print("All packages failed to install.")
|
||||||
|
print("Packages that could not be installed: " .. table.concat(fails, ", "))
|
||||||
|
else
|
||||||
|
print("Some packages failed to install.")
|
||||||
|
print("Packages installed: " .. table.concat(packageList, ", "))
|
||||||
|
print("Packages that could not be installed: " .. table.concat(fails, ", "))
|
||||||
|
end
|
||||||
|
elseif command == "remove" then
|
||||||
|
if not packages or not packages[1] then
|
||||||
|
print("Please specify packages to remove.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
if not fs.exists("/argentum/store/" .. packages[i]) then
|
||||||
|
print("\27[91mPackage " .. packages[i] .. " is not installed.")
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
table.remove(packages, table.find(packages, packages[i]))
|
||||||
|
i = i - 1
|
||||||
|
elseif packages[i] == "halyde" then -- yes, this stuff is hard-coded.
|
||||||
|
print("\27[91mFor obvious reasons, you can't uninstall Halyde.")
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
table.remove(packages, table.find(packages, packages[i]))
|
||||||
|
i = i - 1
|
||||||
|
elseif packages[i] == "argentum" then
|
||||||
|
print("\27[91mFor obvious reasons, you can't uninstall Argentum.")
|
||||||
|
print("\27[91mFor obvious reasons, you can't uninstall Halyde.")
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
table.remove(packages, table.find(packages, packages[i]))
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
if i > #packages then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- do dependency checks
|
||||||
|
local packagesInstalled = fs.list("/argentum/store")
|
||||||
|
for _, currentPackage in pairs(packagesInstalled) do
|
||||||
|
if currentPackage:sub(-1, -1) == "/" and fs.exists("/argentum/store/" .. currentPackage .. "package.cfg") then
|
||||||
|
local handle, data, tmpdata = fs.open("/argentum/store/" .. currentPackage .. "package.cfg", "r"), "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
for line in (data.."\n"):gmatch("(.-)\n") do
|
||||||
|
for i = 1, #packages do
|
||||||
|
if line == "D" .. packages[i] then
|
||||||
|
print(packages[i] .. " depends on " .. currentPackage:sub(1, -2))
|
||||||
|
if not table.find(packages, currentPackage:sub(1, -2)) then
|
||||||
|
table.insert(packages, table.find(packages, packages[i]), currentPackage:sub(1, -2))
|
||||||
|
table.insert(packageList, currentPackage:sub(1, -2))
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local answer
|
||||||
|
if #fails == 0 then
|
||||||
|
print("Packages that will be removed: " .. table.concat(packageList, ", "))
|
||||||
|
if read(nil, "Would you like to proceed? [Y/n] "):lower() == "n" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
elseif #packageList == 0 then
|
||||||
|
print("None of the packages can be removed.")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
print("Some packages cannot be removed.")
|
||||||
|
print("Packages that will be removed: " .. table.concat(packageList, ", "))
|
||||||
|
print("Packages that cannot be removed: " .. table.concat(fails, ", "))
|
||||||
|
if read(nil, "Would you like to proceed? [y/N] "):lower() ~= "y" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, failedPackage in pairs(fails) do
|
||||||
|
table.remove(packages, table.find(packages, failedPackage))
|
||||||
|
end
|
||||||
|
fails = {}
|
||||||
|
for _, package in ipairs(packages) do
|
||||||
|
if not removePackage(package) then
|
||||||
|
table.insert(fails, package)
|
||||||
|
table.remove(packageList, table.find(packageList, package))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #fails == 0 then
|
||||||
|
print("Removal completed successfully.")
|
||||||
|
print("Packages removed: " .. table.concat(packageList, ", "))
|
||||||
|
elseif #packageList == 0 then
|
||||||
|
print("All packages failed to be removed.")
|
||||||
|
print("Packages that could not be removed: " .. table.concat(fails, ", "))
|
||||||
|
else
|
||||||
|
print("Some packages failed to be removed.")
|
||||||
|
print("Packages removed: " .. table.concat(packageList, ", "))
|
||||||
|
print("Packages that could not be removed: " .. table.concat(fails, ", "))
|
||||||
|
end
|
||||||
|
elseif command == "update" then
|
||||||
|
if not packages[1] then
|
||||||
|
local packagesInstalled = fs.list("/argentum/store/")
|
||||||
|
for _, currentPackage in pairs(packagesInstalled) do
|
||||||
|
if currentPackage:sub(-1, -1) == "/" and fs.exists("/argentum/store/" .. currentPackage .. "package.cfg") then
|
||||||
|
table.insert(packages, currentPackage:sub(1, -2))
|
||||||
|
table.insert(packageList, currentPackage:sub(1, -2))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
if not fs.exists("/argentum/store/" .. packages[i]) then
|
||||||
|
print("\27[91mPackage " .. packages[i] .. " is not installed.")
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
table.remove(packages, table.find(packages, packages[i]))
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
if i > #packages then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local answer
|
||||||
|
if #fails == 0 then
|
||||||
|
print("Packages that will be updated: " .. table.concat(packageList, ", "))
|
||||||
|
if read(nil, "Would you like to proceed? [Y/n] "):lower() == "n" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
elseif #packageList == 0 then
|
||||||
|
print("None of the packages can be updated.")
|
||||||
|
return
|
||||||
|
else
|
||||||
|
print("Some packages cannot be updated.")
|
||||||
|
print("Packages that will be updated: " .. table.concat(packageList, ", "))
|
||||||
|
print("Packages that cannot be updated: " .. table.concat(fails, ", "))
|
||||||
|
if read(nil, "Would you like to proceed? [y/N] "):lower() ~= "y" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, failedPackage in pairs(fails) do
|
||||||
|
table.remove(packages, table.find(packages, failedPackage))
|
||||||
|
end
|
||||||
|
fails = {}
|
||||||
|
for _, package in pairs(packages) do
|
||||||
|
local agcfg = getAgConfig(package, source)
|
||||||
|
if not agcfg then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
local version = "0.0.0"
|
||||||
|
for line in (data.."\n"):gmatch("(.-)\n") do
|
||||||
|
if line:sub(1, 1) == "V" then
|
||||||
|
version = line:sub(2)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
local version = "0.0.0"
|
||||||
|
for line in (data.."\n"):gmatch("(.-)\n") do
|
||||||
|
if line:sub(1, 1) == "V" then
|
||||||
|
version = line:sub(2)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if agcfg[package].version == version then
|
||||||
|
print(package .. " is up to date")
|
||||||
|
goto skip
|
||||||
|
end
|
||||||
|
if not removePackage(package) then
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
table.remove(packages, table.find(packages, packages[i]))
|
||||||
|
goto skip
|
||||||
|
end
|
||||||
|
if not installPackage(package) then
|
||||||
|
table.insert(fails, packages[i])
|
||||||
|
table.remove(packageList, table.find(packageList, packages[i]))
|
||||||
|
table.remove(packages, table.find(packages, packages[i]))
|
||||||
|
goto skip
|
||||||
|
end
|
||||||
|
::skip::
|
||||||
|
end
|
||||||
|
if #fails == 0 then
|
||||||
|
print("Update completed successfully.")
|
||||||
|
print("Packages updated: " .. table.concat(packageList, ", "))
|
||||||
|
elseif #packageList == 0 then
|
||||||
|
print("All packages failed to update.")
|
||||||
|
print("Packages that could not update: " .. table.concat(fails, ", "))
|
||||||
|
else
|
||||||
|
print("Some packages failed to update.")
|
||||||
|
print("Packages updated: " .. table.concat(packageList, ", "))
|
||||||
|
print("Packages that could not update: " .. table.concat(fails, ", "))
|
||||||
|
end
|
||||||
|
elseif command == "info" then
|
||||||
|
if not packages[1] then
|
||||||
|
print("Please specify a package to show information about.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not agReg[packages[1]] and not source then
|
||||||
|
print("\27[91mPackage " .. packages[1] .. " does not exist.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local agcfg = getAgConfig(packages[1], source)
|
||||||
|
if not agcfg then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
print("\27[93m" .. packages[1] .. "\27[0m v" .. agcfg[packages[1]].version .. "\n " .. (agcfg[packages[1]].description or "No description."):gsub("\n", " \n"))
|
||||||
|
elseif command == "search" then
|
||||||
|
if not packages[1] then
|
||||||
|
print("Please specify a search term.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local searchResults = {}
|
||||||
|
for packageName, _ in pairs(agReg) do
|
||||||
|
if packageName:find(packages[1], 1, true) then
|
||||||
|
table.insert(searchResults, packageName)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not searchResults[1] then
|
||||||
|
print("No search results found for " .. packages[1] .. ".")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
table.sort(searchResults)
|
||||||
|
print("Search results: \n " .. table.concat(searchResults, "\n "))
|
||||||
|
elseif command == "list" then
|
||||||
|
local sortedPackages = {}
|
||||||
|
for packageName, _ in pairs(agReg) do
|
||||||
|
table.insert(sortedPackages, packageName)
|
||||||
|
end
|
||||||
|
table.sort(sortedPackages)
|
||||||
|
print("List of available Ag packages: \n " .. table.concat(sortedPackages, "\n "))
|
||||||
|
else
|
||||||
|
shell.run("help ag")
|
||||||
|
end
|
||||||
@@ -183,7 +183,7 @@ local function processEvent(args)
|
|||||||
changesMade = true
|
changesMade = true
|
||||||
cursorRenderFlag = true
|
cursorRenderFlag = true
|
||||||
cursorWhite = true
|
cursorWhite = true
|
||||||
if cursorPosY + scrollPosY - 1 > 1 then
|
if cursorPosX == 1 and cursorPosY + scrollPosY - 1 > 1 then
|
||||||
cursorPosY = cursorPosY - 1
|
cursorPosY = cursorPosY - 1
|
||||||
if cursorPosY < 1 then
|
if cursorPosY < 1 then
|
||||||
scrollPosY = scrollPosY - 1
|
scrollPosY = scrollPosY - 1
|
||||||
@@ -256,7 +256,11 @@ local function save()
|
|||||||
end
|
end
|
||||||
local handle, errorMessage = fs.open(savepath, "w")
|
local handle, errorMessage = fs.open(savepath, "w")
|
||||||
if handle then
|
if handle then
|
||||||
|
if table.concat(tmpdata, "\n"):sub(-1, -1) == "\n" then
|
||||||
handle:write(table.concat(tmpdata, "\n"))
|
handle:write(table.concat(tmpdata, "\n"))
|
||||||
|
else
|
||||||
|
handle:write(table.concat(tmpdata, "\n") .. "\n") -- add a newline at the end to follow POSIX standards
|
||||||
|
end
|
||||||
handle:close()
|
handle:close()
|
||||||
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
|
rawset(1, height - 1, "\27[107m\27[30m" .. filestring .. string.rep(" ", width))
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ print("\27[92mComponents\27[0m: "..tostring(componentCounter))
|
|||||||
termlib.cursorPosX = 17
|
termlib.cursorPosX = 17
|
||||||
print("\27[92mCoroutines\27[0m: "..tostring(#cormgr.corList))
|
print("\27[92mCoroutines\27[0m: "..tostring(#cormgr.corList))
|
||||||
termlib.cursorPosX = 17
|
termlib.cursorPosX = 17
|
||||||
print("\27[92mBattery\27[0m: "..tostring(math.floor(computer.maxEnergy() / computer.energy() * 1000 + 0.5) / 10).."%")
|
print("\27[92mBattery\27[0m: "..tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10).."%")
|
||||||
termlib.cursorPosX = 17
|
termlib.cursorPosX = 17
|
||||||
local totalMemory = computer.totalMemory()
|
local totalMemory = computer.totalMemory()
|
||||||
local usedMemory = computer.totalMemory() - computer.freeMemory()
|
local usedMemory = computer.totalMemory() - computer.freeMemory()
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
Usage: argentum [COMMAND] [PACKAGES]
|
||||||
|
Uses the Argentum package manager.
|
||||||
|
|
||||||
|
COMMAND Specifies the operation for Ag to do.
|
||||||
|
install Installs packages.
|
||||||
|
remove Removes packages.
|
||||||
|
update Updates packages.
|
||||||
|
list Lists all available packages.
|
||||||
|
search Searches all available packages.
|
||||||
|
info Shows information on a specific package.
|
||||||
|
PACKAGES* Packages to apply operations to.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
ag install hal-draw Installs the hal-draw package.
|
||||||
|
ag list Lists all packages.
|
||||||
|
ag info hal-draw Shows information about hal-draw.
|
||||||
|
ag update hal-draw Updates the hal-draw package if it's not at the newest version.
|
||||||
|
ag update Updates all packages.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
All current Halyde shell commands:
|
All default Halyde shell commands:
|
||||||
cat Concatenates and prints a file.
|
cat Concatenates and prints a file.
|
||||||
cd Changes directory.
|
cd Changes directory.
|
||||||
clear Clears the screen.
|
clear Clears the screen.
|
||||||
@@ -11,6 +11,7 @@ All current Halyde shell commands:
|
|||||||
mv Moves/renames a file.
|
mv Moves/renames a file.
|
||||||
rm Deletes a file.
|
rm Deletes a file.
|
||||||
edit Opens the text editor.
|
edit Opens the text editor.
|
||||||
|
argentum Uses the Argentum package manager.
|
||||||
|
|
||||||
You can get additional information on any app or command by running:
|
You can get additional information on any app or command by running:
|
||||||
help [COMMAND]
|
help [COMMAND]
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Usage: mkdir [PATH]
|
||||||
|
Removes files and directories.
|
||||||
|
|
||||||
|
PATH Specifies the path to create the directory in.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
mkdir a Creates a directory named a in the current shell working directory.
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
Usage: rm [FLAGS] [PATH]
|
Usage: rm [PATH]
|
||||||
Removes files and directories.
|
Removes files and directories.
|
||||||
|
|
||||||
-r, --recursive Removes directories and their contents recursively.
|
|
||||||
-f, --force Ignores nonexistent files or directories.
|
|
||||||
PATH Specifies the file to be moved/renamed.
|
PATH Specifies the file to be moved/renamed.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
rm a.txt Removes a.txt in the current shell working directory.
|
rm a.txt Removes a.txt in the current shell working directory.
|
||||||
rm -r -f /halyde/core/ Removes everything in /halyde/core/ forcedly and recursively.
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
local args = {...}
|
||||||
|
local directory = args[1]
|
||||||
|
args = nil
|
||||||
|
local fs = import("filesystem")
|
||||||
|
|
||||||
|
if not directory then
|
||||||
|
shell.run("help mkdir")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if directory:sub(1, 1) ~= "/" then
|
||||||
|
directory = shell.workingDirectory .. directory
|
||||||
|
end
|
||||||
|
if fs.exists(file) then
|
||||||
|
print("\27[91mAn object already exists at the specified path.")
|
||||||
|
end
|
||||||
|
fs.makeDirectory(file)
|
||||||
+24
-4
@@ -1,6 +1,6 @@
|
|||||||
local shellcfg = {
|
local shellcfg = {
|
||||||
["startupMessage"] = "\n │\n │ ".._OSVERSION..'\n │ Welcome! Type "help" to get started.\n │\n ', -- message shown on startup
|
["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. example: "%s > " turns to "/current/working/directory > "
|
["prompt"] = "\x1b[92m%s > \x1b[0m", -- shell prompt. %s will be replaced with working directory.
|
||||||
["path"] = { -- default locations where programs will be run from
|
["path"] = { -- default locations where programs will be run from
|
||||||
"/halyde/apps/"
|
"/halyde/apps/"
|
||||||
}, ["aliases"] = { -- shell command aliases
|
}, ["aliases"] = { -- shell command aliases
|
||||||
@@ -14,8 +14,28 @@ local shellcfg = {
|
|||||||
["del"] = "rm",
|
["del"] = "rm",
|
||||||
["delete"] = "rm",
|
["delete"] = "rm",
|
||||||
["remove"] = "rm",
|
["remove"] = "rm",
|
||||||
[".."] = "cd .."
|
[".."] = "cd ..",
|
||||||
}, ["defaultWorkingDirectory"] = "/home/" -- the working directory that gets set when halyde starts
|
["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
|
return shellcfg
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local loadfile = ...
|
local loadfile = ...
|
||||||
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
|
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
|
||||||
|
|
||||||
_G._OSVERSION = "Halyde 0.10.1"
|
_G._OSVERSION = "Halyde 1.0.0"
|
||||||
|
|
||||||
function _G.import(module, ...)
|
function _G.import(module, ...)
|
||||||
local args = table.pack(...)
|
local args = table.pack(...)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local shellcfg = import("/halyde/config/shell.cfg")
|
local shellcfg = import("/halyde/config/shell.cfg")
|
||||||
import("/halyde/core/termlib.lua")
|
import("/halyde/core/termlib.lua")
|
||||||
local event = import("event")
|
local event = import("event")
|
||||||
--local ocelot = component.proxy(component.list("ocelot")())
|
local ocelot = component.proxy(component.list("ocelot")())
|
||||||
local filesystem = import("filesystem")
|
local filesystem = import("filesystem")
|
||||||
local gpu = component.proxy(component.list("gpu")())
|
local gpu = component.proxy(component.list("gpu")())
|
||||||
|
|
||||||
@@ -55,14 +55,14 @@ function _G.shell.run(command)
|
|||||||
if not args[1] then
|
if not args[1] then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if filesystem.exists(args[1]) then
|
if filesystem.exists(args[1]) and not filesystem.isDirectory(args[1]) then
|
||||||
foundfile = true
|
foundfile = true
|
||||||
local path = args[1]
|
local path = args[1]
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
runAsCoroutine(path, table.unpack(args))
|
runAsCoroutine(path, table.unpack(args))
|
||||||
else
|
else
|
||||||
for _, item in pairs(shellcfg["path"]) do
|
for _, item in pairs(shellcfg["path"]) do
|
||||||
if filesystem.exists(item..args[1]) then
|
if filesystem.exists(item..args[1]) and not filesystem.isDirectory(item .. args[1]) then
|
||||||
foundfile = true
|
foundfile = true
|
||||||
local path = item..args[1]
|
local path = item..args[1]
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
@@ -71,7 +71,7 @@ function _G.shell.run(command)
|
|||||||
else -- try to look for it without the file extension
|
else -- try to look for it without the file extension
|
||||||
local files = filesystem.list(item)
|
local files = filesystem.list(item)
|
||||||
for _, file in pairs(files) do
|
for _, file in pairs(files) do
|
||||||
if args[1] == file:match("(.+)%.[^%.]+$") then
|
if args[1] == file:match("(.+)%.[^%.]+$") and not filesystem.isDirectory(item .. file) then
|
||||||
foundfile = true
|
foundfile = true
|
||||||
table.remove(args, 1)
|
table.remove(args, 1)
|
||||||
runAsCoroutine(item .. file, table.unpack(args))
|
runAsCoroutine(item .. file, table.unpack(args))
|
||||||
@@ -86,14 +86,14 @@ function _G.shell.run(command)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
print(shellcfg["startupMessage"])
|
print(shellcfg["startupMessage"]:format(shellcfg.splashMessages[math.random(1, #shellcfg.splashMessages)]))
|
||||||
while true do
|
while true do
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
-- print(shell.workingDirectory .. " >")
|
-- print(shell.workingDirectory .. " >")
|
||||||
--print(shellcfg["prompt"]:format(shell.workingDirectory),false)
|
--print(shellcfg["prompt"]:format(shell.workingDirectory),false)
|
||||||
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
|
-- termlib.cursorPosX = #(shell.workingDirectory .. " > ")
|
||||||
-- termlib.cursorPosY = termlib.cursorPosY - 1
|
-- termlib.cursorPosY = termlib.cursorPosY - 1
|
||||||
local shellCommand = read("shell", shellcfg["prompt"]:format(shell.workingDirectory))
|
local shellCommand = read("shell", shellcfg.prompt:format(shell.workingDirectory))
|
||||||
shell.run(shellCommand)
|
shell.run(shellCommand)
|
||||||
gpu.freeAllBuffers()
|
gpu.freeAllBuffers()
|
||||||
end
|
end
|
||||||
|
|||||||
+12
-4
@@ -70,20 +70,23 @@ local function parseCodeNumbers(code)
|
|||||||
return o
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
function _G.print(text, endNewLine, wordWrap)
|
function _G.print(text, endNewLine, textWrap)
|
||||||
|
|
||||||
-- you don't know how tiring this was just for ANSI escape code support
|
-- you don't know how tiring this was just for ANSI escape code support
|
||||||
|
|
||||||
if endNewLine == nil then
|
if endNewLine == nil then
|
||||||
endNewLine = true
|
endNewLine = true
|
||||||
end
|
end
|
||||||
if wordWrap == nil then
|
if textWrap == nil then
|
||||||
wordWrap = true
|
textWrap = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if not text or not tostring(text) then
|
if not text or not tostring(text) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if text:find("\a") then
|
||||||
|
computer.beep()
|
||||||
|
end
|
||||||
text = "\27[0m" .. text:gsub("\t", " ")
|
text = "\27[0m" .. text:gsub("\t", " ")
|
||||||
text = tostring(text)
|
text = tostring(text)
|
||||||
readBreak = 0
|
readBreak = 0
|
||||||
@@ -95,10 +98,15 @@ function _G.print(text, endNewLine, wordWrap)
|
|||||||
if #section==0 then
|
if #section==0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
while true do
|
||||||
gpu.set(termlib.cursorPosX,termlib.cursorPosY,section)
|
gpu.set(termlib.cursorPosX,termlib.cursorPosY,section)
|
||||||
termlib.cursorPosX = termlib.cursorPosX+unicode.wlen(section)
|
termlib.cursorPosX = termlib.cursorPosX+unicode.wlen(section)
|
||||||
if termlib.cursorPosX>width and wordWrap then
|
if unicode.wlen(section) > width and textWrap then
|
||||||
newLine()
|
newLine()
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
section = section:sub(width + 1)
|
||||||
end
|
end
|
||||||
section = ""
|
section = ""
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -170,4 +170,13 @@ function filesystem.remove(path)
|
|||||||
return component.invoke(address, "remove", absPath)
|
return component.invoke(address, "remove", absPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function filesystem.makeDirectory(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
local address, absPath = filesystem.processPath(path)
|
||||||
|
if not address then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return component.invoke(address, "makeDirectory", absPath)
|
||||||
|
end
|
||||||
|
|
||||||
return(filesystem)
|
return(filesystem)
|
||||||
|
|||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
local component = require("component")
|
||||||
|
if not component.isAvailable("internet") then
|
||||||
|
io.stderr.write("This program requires an internet card to run.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local internet = component.internet
|
||||||
|
local computer = require("computer")
|
||||||
|
local fs = require("filesystem")
|
||||||
|
local installLocation
|
||||||
|
local drives = {}
|
||||||
|
for drive in fs.list("/mnt/") do
|
||||||
|
table.insert(drives, drive)
|
||||||
|
end
|
||||||
|
if #drives == 1 and not component.invoke(component.get(drives[1]:sub(1, 3), "filesystem"), "isReadOnly") then
|
||||||
|
installLocation = drives[1]
|
||||||
|
elseif #drives == 1 then
|
||||||
|
io.stderr.write("All drives are read-only.\nHalyde cannot be installed.")
|
||||||
|
else
|
||||||
|
local installDrivesText = "Possible drives to install to:"
|
||||||
|
for i = 1, #drives do
|
||||||
|
local address = component.get(drives[i]:sub(1, 3), "filesystem")
|
||||||
|
local fsComponent = component.proxy(address)
|
||||||
|
if not fsComponent.isReadOnly() then
|
||||||
|
local label = fsComponent.getLabel()
|
||||||
|
if label then
|
||||||
|
installDrivesText = installDrivesText .. "\n " .. tostring(i) .. ". - " .. label .. "(" .. address:sub(1, 5) .. "...)"
|
||||||
|
else
|
||||||
|
installDrivesText = installDrivesText .. "\n " .. tostring(i) .. ". - " .. address:sub(1, 5) .. "..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
io.write(installDrivesText .. "\nPlease select a drive by entering its number or \"q\" to quit. ")
|
||||||
|
local answer
|
||||||
|
while true do
|
||||||
|
answer = io.read()
|
||||||
|
if tonumber(answer) and tonumber(answer) >= 1 and tonumber(answer) <= #drives then
|
||||||
|
break
|
||||||
|
elseif answer == "q" then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
print("Answer invalid, try again.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
installLocation = "/mnt/" .. drives[tonumber(answer)]
|
||||||
|
end
|
||||||
|
if not installLocation then
|
||||||
|
print("All drives are read-only.\nHalyde cannot be installed.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
io.write("Are you sure you would like to install Halyde to " .. installLocation .. "? This will erase all data on this disk. [Y/n] ")
|
||||||
|
if io.read():lower() == "n" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- installation
|
||||||
|
local computer = require("computer")
|
||||||
|
local oldFiles = {}
|
||||||
|
for oldFile in fs.list(installLocation) do
|
||||||
|
if oldFile ~= "home/" then
|
||||||
|
table.insert(oldFiles, oldFile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function getFile(url)
|
||||||
|
local request, data, tmpdata = nil, "", nil
|
||||||
|
local status, errorMessage = pcall(function()
|
||||||
|
request = internet.request(url)
|
||||||
|
request:finishConnect()
|
||||||
|
end)
|
||||||
|
if not status then
|
||||||
|
return false, errorMessage
|
||||||
|
end
|
||||||
|
local responseCode = request:response()
|
||||||
|
if responseCode and responseCode ~= 200 then
|
||||||
|
return false, responseCode
|
||||||
|
end
|
||||||
|
repeat
|
||||||
|
tmpdata = request.read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getFile(path)
|
||||||
|
if path:sub(1,1) == "/" then
|
||||||
|
if not fs.exists(path) then
|
||||||
|
return false, "file does not exist"
|
||||||
|
end
|
||||||
|
local handle, data, tmpdata = fs.open(path, "r"), "", nil
|
||||||
|
repeat
|
||||||
|
tmpdata = handle:read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
handle:close()
|
||||||
|
return data
|
||||||
|
else
|
||||||
|
local request, data, tmpdata = nil, "", nil
|
||||||
|
local status, errorMessage = pcall(function()
|
||||||
|
request = internet.request(path)
|
||||||
|
request:finishConnect()
|
||||||
|
end)
|
||||||
|
if not status then
|
||||||
|
return false, errorMessage
|
||||||
|
end
|
||||||
|
local responseCode = request:response()
|
||||||
|
if responseCode and responseCode ~= 200 then
|
||||||
|
return false, responseCode
|
||||||
|
end
|
||||||
|
repeat
|
||||||
|
tmpdata = request.read(math.huge)
|
||||||
|
data = data .. (tmpdata or "")
|
||||||
|
until not tmpdata
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("a")
|
||||||
|
local webInstallConfig = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/argentum.cfg")
|
||||||
|
print("a")
|
||||||
|
webInstallConfig = load(webInstallConfig)
|
||||||
|
print("a")
|
||||||
|
webInstallConfig = webInstallConfig()
|
||||||
|
print("a")
|
||||||
|
installationOrder = {"halyde", "edit", "argentum"}
|
||||||
|
for i = 1, 3 do
|
||||||
|
local webInstallConfig = webInstallConfig[installationOrder[i]]
|
||||||
|
print("a")
|
||||||
|
if webInstallConfig.directories then
|
||||||
|
for _, directory in pairs(webInstallConfig.directories) do
|
||||||
|
print("Creating " .. directory .. "...")
|
||||||
|
fs.makeDirectory(installLocation .. directory)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, file in pairs(webInstallConfig.files) do
|
||||||
|
print("Downloading " .. file .. "...")
|
||||||
|
local handle = fs.open(installLocation .. file, "w")
|
||||||
|
handle:write(getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/" .. file))
|
||||||
|
handle:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
computer.shutdown(true)
|
||||||
Reference in New Issue
Block a user