Make shit less ass fuck shit fuck ass shit ass bruh what is this code

This commit is contained in:
2026-06-06 19:00:37 +03:00
parent 202f6d42ac
commit 4d6dbadc32
87 changed files with 1497 additions and 954 deletions
+5 -1
View File
@@ -1,3 +1,4 @@
local agregistry = { local agregistry = {
["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/", ["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
["edit"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/", ["edit"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
@@ -8,7 +9,10 @@ local agregistry = {
["hextra"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/", ["hextra"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
["utape"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/", ["utape"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
["libctif"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/", ["libctif"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
["ctif-viewer"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/" ["ctif-viewer"] = "https://raw.githubusercontent.com/Ponali/ArgentumPackages/refs/heads/master/",
["libsha256"] = "https://raw.githubusercontent.com/tema5002/ag-packages/refs/heads/main/",
["sha256sum"] = "https://raw.githubusercontent.com/tema5002/ag-packages/refs/heads/main/",
["base64"] = "https://raw.githubusercontent.com/mcplayer3/AgPackages/refs/heads/main/"
} }
return agregistry return agregistry
+28 -28
View File
@@ -106,15 +106,15 @@ do
if parsed.flags.u or parsed.flags["update-registry"] then if parsed.flags.u or parsed.flags["update-registry"] then
terminal.write("Updating registry...") terminal.write("Updating registry...")
result, data = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/Pre-Alpha-3.0.0/ag2/registry.json") result, data = getFile("https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/Pre-Alpha-3.0.0/ag2/registry.json")
check(result, "\27[91mFailed to get registry: " .. data) check(result, "\27[91mFailed to get registry: " .. data .. "\27[0m")
local handle, errorMessage = fs.open("/ag2/registry.json", "w") local handle, errorMessage = fs.open("/ag2/registry.json", "w")
check(handle, "\27[91mFailed to open write handle to registry: " .. errorMessage) check(handle, "\27[91mFailed to open write handle to registry: " .. errorMessage .. "\27[0m")
local success, errorMessage = handle:write(data) local success, errorMessage = handle:write(data)
check(success, "\27[91mFailed to write to registry: " .. errorMessage) check(success, "\27[91mFailed to write to registry: " .. errorMessage .. "\27[0m")
handle:close() handle:close()
else else
result, data = getFile("/ag2/registry.json") result, data = getFile("/ag2/registry.json")
check(result, "\27[91mFailed to get registry: " .. data) check(result, "\27[91mFailed to get registry: " .. data .. "\27[0m")
end end
end end
@@ -129,16 +129,16 @@ end
local function getServersidePackageConfig(source, package) local function getServersidePackageConfig(source, package)
local success, data = getFile(fs.concat(source, "/ag2.json")) local success, data = getFile(fs.concat(source, "/ag2.json"))
if not success then if not success then
return false, ("\27[91mFailed to get package config (ag2.json) of package '%s': " .. data):format(package) return false, ("\27[91mFailed to get package config (ag2.json) of package '%s': " .. data .. "\27[0m"):format(package)
end end
local success, packageConfig = pcall(function() local success, packageConfig = pcall(function()
return json.decode(data) return json.decode(data)
end) end)
if not success then if not success then
return false, ("\27[91mFailed to parse package config (ag2.json) of package '%s': " .. packageConfig):format(package) return false, ("\27[91mFailed to parse package config (ag2.json) of package '%s': " .. packageConfig .. "\27[0m"):format(package)
end end
if not packageConfig[package] then if not packageConfig[package] then
return false, ("\27[91mRepository package config (ag2.json) does not contain package '%s'."):format(package) return false, ("\27[91mRepository package config (ag2.json) does not contain package '%s'.\27[0m"):format(package)
end end
return packageConfig[package] return packageConfig[package]
end end
@@ -158,7 +158,7 @@ if command == "install" then
table.remove(otherPackages, i) table.remove(otherPackages, i)
-- This is to check if the package can be found in the others, or in other words, checking for duplicates -- This is to check if the package can be found in the others, or in other words, checking for duplicates
if table.find(otherPackages, packages[i]) then if table.find(otherPackages, packages[i]) then
print(("\27[93mDuplicate package specified (%s), skipping"):format(packages[i])) print(("\27[93mDuplicate package specified (%s), skipping\27[0m"):format(packages[i]))
table.remove(packages, i) table.remove(packages, i)
i = i - 1 i = i - 1
goto SKIP goto SKIP
@@ -170,7 +170,7 @@ if command == "install" then
source = registry[packages[i]] source = registry[packages[i]]
end end
if not source then if not source then
print("\27[91mCould not find package in registry and no source provided: " .. packages[i]) print("\27[91mCould not find package in registry and no source provided: " .. packages[i] .. "\27[0m")
failure = true failure = true
goto SKIP goto SKIP
end end
@@ -212,7 +212,7 @@ if command == "install" then
goto SKIP goto SKIP
end end
if fs.exists(("/ag2/pkg/%s.json"):format(packages[i])) then if fs.exists(("/ag2/pkg/%s.json"):format(packages[i])) then
print(("\27[93mPackage %s is already installed, skipping"):format(packages[i])) print(("\27[93mPackage %s is already installed, skipping\27[0m"):format(packages[i]))
table.remove(packages, i) table.remove(packages, i)
i = i - 1 i = i - 1
goto SKIP goto SKIP
@@ -248,7 +248,7 @@ elseif command == "remove" then
end end
end end
end end
print(("\27[93mPackage %s is not installed, skipping"):format(packages[i])) print(("\27[93mPackage %s is not installed, skipping\27[0m"):format(packages[i]))
table.remove(packages, i) table.remove(packages, i)
i = i - 1 i = i - 1
::GOAHEAD:: ::GOAHEAD::
@@ -299,7 +299,7 @@ elseif command == "remove" then
-- Listen, I'm so sorry for this abhorrent bullshit code, but the newly added packages have to get checked one way or another and hopefully this is readable enough. -- Listen, I'm so sorry for this abhorrent bullshit code, but the newly added packages have to get checked one way or another and hopefully this is readable enough.
else else
-- The Pyramids of Giza were built entirely out of silver. No they weren't... -- The Pyramids of Giza were built entirely out of silver. No they weren't...
print(("\27[93mPackage %s is depended on by %s, cannot uninstall without --cascade"):format(dependency, packageName)) print(("\27[93mPackage %s is depended on by %s, cannot uninstall without --cascade\27[0m"):format(dependency, packageName))
failure = true failure = true
end end
end end
@@ -324,9 +324,9 @@ end
if command == "install" then if command == "install" then
if dependencyCounter == 1 then if dependencyCounter == 1 then
print("\27[93m1 dependency pulled in.") print("\27[93m1 dependency pulled in.\27[0m")
elseif dependencyCounter >= 2 then elseif dependencyCounter >= 2 then
print(("\27[93m%d dependencies pulled in."):format(dependencyCounter)) print(("\27[93m%d dependencies pulled in.\27[0m"):format(dependencyCounter))
end end
print("Packages that will be installed:") print("Packages that will be installed:")
print(table.concat(packages, ", ")) print(table.concat(packages, ", "))
@@ -359,13 +359,13 @@ if command == "install" then
local success, data = getFile(fs.concat(source, file)) local success, data = getFile(fs.concat(source, file))
if not success then if not success then
print(("\27[91mFailed to get file '%s' of package '%s': " .. data):format(file, package)) print(("\27[91mFailed to get file '%s' of package '%s': " .. data .. "\27[0m"):format(file, package))
local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"}) local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"})
if answer:lower() == "a" then if answer:lower() == "a" then
print("Exiting.") print("Exiting.")
return return
elseif answer:lower() == "s" then elseif answer:lower() == "s" then
print((" \27[93mSkipped file %s."):format(file)) print((" \27[93mSkipped file %s.\27[0m"):format(file))
goto SKIP goto SKIP
else else
goto RETRY goto RETRY
@@ -373,26 +373,26 @@ if command == "install" then
end end
if fs.exists(file) then if fs.exists(file) then
print(("\27[93mFile '%s' already exists."):format(file)) print(("\27[93mFile '%s' already exists.\27[0m"):format(file))
local answer = terminal.read({prefix = "Abort, Overwrite, Skip? [a/O/s]"}) local answer = terminal.read({prefix = "Abort, Overwrite, Skip? [a/O/s]"})
if answer:lower() == "a" then if answer:lower() == "a" then
print("Exiting.") print("Exiting.")
return return
elseif answer:lower() == "s" then elseif answer:lower() == "s" then
print((" \27[93mSkipped file %s."):format(file)) print((" \27[93mSkipped file %s.\27[0m"):format(file))
goto SKIP goto SKIP
end end
end end
local handle, errorMessage = fs.open(file, "w") local handle, errorMessage = fs.open(file, "w")
if not handle then if not handle then
print(("\27[91mFailed to open write handle to file '%s': " .. errorMessage):format(file)) print(("\27[91mFailed to open write handle to file '%s': " .. errorMessage .. "\27[0m"):format(file))
local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"}) local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"})
if answer:lower() == "a" then if answer:lower() == "a" then
print("Exiting.") print("Exiting.")
return return
elseif answer:lower() == "s" then elseif answer:lower() == "s" then
print((" \27[93mSkipped file %s."):format(file)) print((" \27[93mSkipped file %s.\27[0m"):format(file))
goto SKIP goto SKIP
else else
goto RETRY goto RETRY
@@ -402,13 +402,13 @@ if command == "install" then
local success, errorMessage = handle:write(data) local success, errorMessage = handle:write(data)
if not success then if not success then
handle:close() handle:close()
print(("\27[91mFailed to write to file '%s': " .. errorMessage):format(file)) print(("\27[91mFailed to write to file '%s': " .. errorMessage .. "\27[0m"):format(file))
local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"}) local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"})
if answer:lower() == "a" then if answer:lower() == "a" then
print("Exiting.") print("Exiting.")
return return
elseif answer:lower() == "s" then elseif answer:lower() == "s" then
print((" \27[93mSkipped file %s."):format(file)) print((" \27[93mSkipped file %s.\27[0m"):format(file))
goto SKIP goto SKIP
else else
goto RETRY goto RETRY
@@ -431,13 +431,13 @@ if command == "install" then
::RETRY:: ::RETRY::
local handle, errorMessage = fs.open(("/ag2/pkg/%s.json"):format(package), "w") local handle, errorMessage = fs.open(("/ag2/pkg/%s.json"):format(package), "w")
if not handle then if not handle then
print(("\27[91mFailed to open write handle to file '/ag2/pkg/%s.json': " .. errorMessage):format(package)) print(("\27[91mFailed to open write handle to file '/ag2/pkg/%s.json': " .. errorMessage .. "\27[0m"):format(package))
local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"}) local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"})
if answer:lower() == "a" then if answer:lower() == "a" then
print("Exiting.") print("Exiting.")
return return
elseif answer:lower() == "s" then elseif answer:lower() == "s" then
print((" \27[93mSkipped file /ag2/pkg/%s.json."):format(package)) print((" \27[93mSkipped file /ag2/pkg/%s.json.\27[0m"):format(package))
goto SKIP goto SKIP
else else
goto RETRY goto RETRY
@@ -461,13 +461,13 @@ if command == "install" then
local success, errorMessage = handle:write(trackingFile) local success, errorMessage = handle:write(trackingFile)
if not success then if not success then
handle:close() handle:close()
print(("\27[91mFailed to write to file '/ag2/pkg/%s.json': " .. errorMessage):format(package)) print(("\27[91mFailed to write to file '/ag2/pkg/%s.json': " .. errorMessage .. "\27[0m"):format(package))
local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"}) local answer = terminal.read({prefix = "Abort, Retry, Skip? [a/R/s]"})
if answer:lower() == "a" then if answer:lower() == "a" then
print("Exiting.") print("Exiting.")
return return
elseif answer:lower() == "s" then elseif answer:lower() == "s" then
print((" \27[93mSkipped file /ag2/pkg/%s.json."):format(package)) print((" \27[93mSkipped file /ag2/pkg/%s.json.\27[0m"):format(package))
goto SKIP goto SKIP
else else
goto RETRY goto RETRY
@@ -479,9 +479,9 @@ if command == "install" then
end end
elseif command == "remove" then elseif command == "remove" then
if dependencyCounter == 1 then if dependencyCounter == 1 then
print("\27[93m1 orphaned dependency will be removed.") print("\27[93m1 orphaned dependency will be removed.\27[0m")
elseif dependencyCounter >= 2 then elseif dependencyCounter >= 2 then
print(("\27[93m%d orphaned dependencies will be removed."):format(dependencyCounter)) print(("\27[93m%d orphaned dependencies will be removed.\27[0m"):format(dependencyCounter))
end end
print("Packages that will be removed:") print("Packages that will be removed:")
print(table.concat(packages, ", ")) print(table.concat(packages, ", "))
+30 -33
View File
@@ -9,7 +9,7 @@ if not command then
return return
end end
if not component.list("internet")() then if not component.list("internet")() then
print("\27[91mThis program requires an internet card to run.") print("\27[91mThis program requires an internet card to run.\27[0m")
return return
end end
local internet = component.internet local internet = component.internet
@@ -69,12 +69,12 @@ local function getAgConfig(package, source)
source = source or agReg[package] source = source or agReg[package]
local data, errorMessage = getFile(source .. "argentum.cfg") local data, errorMessage = getFile(source .. "argentum.cfg")
if not data or data == "" then if not data or data == "" then
print("\27[91mCould not fetch Ag config: " .. (errorMessage or "returned nil data")) print("\27[91mCould not fetch Ag config: " .. (errorMessage or "returned nil data") .. "\27[0m")
return false return false
end end
local func, errorMessage = load(data, "=argentum.cfg", "bt", {}) local func, errorMessage = load(data, "=argentum.cfg", "bt", {})
if not func then if not func then
print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.") print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.\27[0m")
return false return false
end end
local agcfg local agcfg
@@ -82,22 +82,22 @@ local function getAgConfig(package, source)
agcfg = func() agcfg = func()
end) end)
if not status then if not status then
print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.") print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.\27[0m")
return false return false
end 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 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.") local response = "\27[91mAg config of " .. package .. " is improperly configured.\nPlease contact the package owner.\27[0m"
end end
return agcfg return agcfg
end end
local function doChecks(package) local function doChecks(package)
if not agReg[package] and not source then if not agReg[package] and not source then
print("\27[91mPackage " .. package .. " does not exist.") print("\27[91mPackage " .. package .. " does not exist.\27[0m")
return false return false
end end
if fs.exists("/argentum/store/" .. package) then if fs.exists("/argentum/store/" .. package) then
print("\27[91mPackage " .. package .. " is already installed.") print("\27[91mPackage " .. package .. " is already installed.\27[0m")
return false return false
end end
agcfg = getAgConfig(package, source) agcfg = getAgConfig(package, source)
@@ -107,7 +107,7 @@ local function doChecks(package)
if agcfg[package].dependencies then if agcfg[package].dependencies then
for _, dependency in ipairs(agcfg[package].dependencies) do for _, dependency in ipairs(agcfg[package].dependencies) do
if not agReg[dependency] and not agcfg[dependency] then if not agReg[dependency] and not agcfg[dependency] then
local response = terminal.read({prefix = "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]"}) local response = terminal.read({prefix = "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]\27[0m"})
if response:lower() ~= "s" then if response:lower() ~= "s" then
fs.remove("/argentum/store/" .. package) fs.remove("/argentum/store/" .. package)
return false return false
@@ -132,24 +132,21 @@ local function lpad(str, len, char)
return string.rep(char, len - #str) .. str return string.rep(char, len - #str) .. str
end end
local gpu = component.gpu local width, height = terminal.getResolution()
local width,height = gpu.getResolution()
local function progress(package,progress)
local info = string.format("%s %s%%",package,lpad(math.floor(progress*100),2))
info=info..string.rep(" ",width-#info) local function progress(package, progress)
local progX = math.floor(progress*width) terminal.write("\x1b[s")
gpu.setBackground(0x00FF00) local info = string.format("%s %s%%", package, lpad(math.floor(progress * 100), 2))
gpu.setForeground(0x000000) info = info .. string.rep(" ", width - #info)
gpu.set(1,height,info:sub(1,progX)) local progX = math.floor(progress * width)
gpu.setBackground(0x000000) terminal.write("\x1b[42m\x1b[30m" .. info:sub(1, progX) .. "\x1b[40m\x1b[37m" .. info:sub(progX + 1) .. "\x1b[0m")
gpu.setForeground(0xFFFFFF) terminal.write("\x1b[u")
gpu.set(progX+1,height,info:sub(progX+1))
end end
local function clearProgress() local function clearProgress()
gpu.setBackground(0x000000) terminal.write("\x1b[s")
gpu.fill(1,height,width,1," ") terminal.write("\r\x1b[40m" .. string.rep(" ", width) .. "\x1b[0m\r")
terminal.write("\x1b[u")
end end
local function installPackage(package, overwriteFlag) local function installPackage(package, overwriteFlag)
@@ -166,7 +163,7 @@ local function installPackage(package, overwriteFlag)
if agcfg[package].dependencies then if agcfg[package].dependencies then
for _, dependency in ipairs(agcfg[package].dependencies) do for _, dependency in ipairs(agcfg[package].dependencies) do
if not agReg[dependency] and not agcfg[dependency] then if not agReg[dependency] and not agcfg[dependency] then
local response = terminal.read({prefix = "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]"}) local response = terminal.read({prefix = "\27[91mPackage " .. package .. " requires dependency " .. dependency .. " that does not exist.\n[A - Abort/s - Skip]\27[0m"})
if response:lower() ~= "s" then if response:lower() ~= "s" then
fs.remove("/argentum/store/" .. package) fs.remove("/argentum/store/" .. package)
return false return false
@@ -218,7 +215,7 @@ local function installPackage(package, overwriteFlag)
else else
packageStore = packageStore .. "\nA" .. file packageStore = packageStore .. "\nA" .. file
end end
local handle = fs.open(file, "w") local handle, err = fs.open(file, "w")
handle:write(data) handle:write(data)
handle:close() handle:close()
::skip:: ::skip::
@@ -234,7 +231,7 @@ end
local function removePackage(package) local function removePackage(package)
print("Removing " .. package .. "...") print("Removing " .. package .. "...")
if not fs.exists("/argentum/store/" .. package .. "/package.cfg") then if not fs.exists("/argentum/store/" .. package .. "/package.cfg") then
print("\27[91mLocal Ag config of " .. package .. " does not exist.") print("\27[91mLocal Ag config of " .. package .. " does not exist.\27[0m")
return false return false
end end
local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil local handle, data, tmpdata = fs.open("/argentum/store/" .. package .. "/package.cfg", "r"), "", nil
@@ -344,7 +341,7 @@ if command == "install" then
handle:write(newRegistry) handle:write(newRegistry)
handle:close() handle:close()
else else
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil") .. "\27[0m")
end end
agReg = require("/argentum/registry.cfg") agReg = require("/argentum/registry.cfg")
while true do while true do
@@ -402,19 +399,19 @@ elseif command == "remove" then
end end
while true do while true do
if not fs.exists("/argentum/store/" .. packages[i]) then if not fs.exists("/argentum/store/" .. packages[i]) then
print("\27[91mPackage " .. packages[i] .. " is not installed.") print("\27[91mPackage " .. packages[i] .. " is not installed.\27[0m")
table.insert(fails, packages[i]) table.insert(fails, packages[i])
table.remove(packageList, table.find(packageList, packages[i])) table.remove(packageList, table.find(packageList, packages[i]))
table.remove(packages, table.find(packages, packages[i])) table.remove(packages, table.find(packages, packages[i]))
i = i - 1 i = i - 1
elseif packages[i] == "halyde" then -- yes, this stuff is hard-coded. elseif packages[i] == "halyde" then -- yes, this stuff is hard-coded.
print("\27[91mFor obvious reasons, you can't uninstall Halyde.") print("\27[91mFor obvious reasons, you can't uninstall Halyde.\27[0m")
table.insert(fails, packages[i]) table.insert(fails, packages[i])
table.remove(packageList, table.find(packageList, packages[i])) table.remove(packageList, table.find(packageList, packages[i]))
table.remove(packages, table.find(packages, packages[i])) table.remove(packages, table.find(packages, packages[i]))
i = i - 1 i = i - 1
elseif packages[i] == "argentum" then elseif packages[i] == "argentum" then
print("\27[91mFor obvious reasons, you can't uninstall Argentum.") print("\27[91mFor obvious reasons, you can't uninstall Argentum.\27[0m")
table.insert(fails, packages[i]) table.insert(fails, packages[i])
table.remove(packageList, table.find(packageList, packages[i])) table.remove(packageList, table.find(packageList, packages[i]))
table.remove(packages, table.find(packages, packages[i])) table.remove(packages, table.find(packages, packages[i]))
@@ -495,7 +492,7 @@ elseif command == "update" then
handle:write(newRegistry) handle:write(newRegistry)
handle:close() handle:close()
else else
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil") .. "\27[0m")
end end
agReg = require("/argentum/registry.cfg") agReg = require("/argentum/registry.cfg")
if not packages[1] then if not packages[1] then
@@ -541,7 +538,7 @@ elseif command == "update" then
table.remove(packages, table.find(packages, packages[i])) table.remove(packages, table.find(packages, packages[i]))
i = i - 1 i = i - 1
else else
print(packages[i].." is out of date [\x1b[93m"..version.."\x1b[39m < \x1b[92m"..agcfg[packages[i]].version.."\x1b[39m]") print(packages[i].." is out of date [\x1b[93m"..version.."\x1b[0m < \x1b[92m"..agcfg[packages[i]].version.."\x1b[0m")
end end
end end
i = i + 1 i = i + 1
@@ -630,7 +627,7 @@ elseif command == "info" then
handle:write(newRegistry) handle:write(newRegistry)
handle:close() handle:close()
else else
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil") .. "\27[0m")
end end
agReg = require("/argentum/registry.cfg") agReg = require("/argentum/registry.cfg")
if not agReg[packages[1]] and not source then if not agReg[packages[1]] and not source then
@@ -677,7 +674,7 @@ elseif command == "list" then
handle:write(newRegistry) handle:write(newRegistry)
handle:close() handle:close()
else else
print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil")) print("\27[91mFailed to fetch Ag registry: " .. (errorMessage or "returned nil") .. "\27[0m")
end end
agReg = require("/argentum/registry.cfg") agReg = require("/argentum/registry.cfg")
local sortedPackages = {} local sortedPackages = {}
+1 -1
View File
@@ -9,7 +9,7 @@ cliparse.config({
}) })
local parsed, err = cliparse.parse(...) local parsed, err = cliparse.parse(...)
if not parsed then if not parsed then
return print("\x1b[91m" .. err) return print("\x1b[91m" .. err .. "\x1b[0m")
end end
local freq = local freq =
+5 -5
View File
@@ -34,25 +34,25 @@ if type(args[1])=="string" then
local compID,err = getComponentID(args[1]) local compID,err = getComponentID(args[1])
if not compID then if not compID then
print("\x1b[91mCould not get component ID from '"..args[1].."'.") print("\x1b[91mCould not get component ID from '"..args[1].."'.")
if type(err)=="string" then print("\x1b[91m"..err) end if type(err)=="string" then print("\x1b[91m"..err.."\x1b[0m") end
return return
end end
if not force then if not force then
if component.virtual.check(compID) then if component.virtual.check(compID) then
return print("\x1b[91mThis component is virtual and cannot be booted from directly.\nID: "..compID) return print("\x1b[91mThis component is virtual and cannot be booted from directly.\nID: "..compID.."\x1b[0m")
end end
local type = component.type(compID) local type = component.type(compID)
if type~="filesystem" and type~="drive" then if type~="filesystem" and type~="drive" then
return print("\x1b[91mThis component is not a storage medium.\nID: "..compID) return print("\x1b[91mThis component is not a storage medium.\nID: "..compID.."\x1b[0m")
end end
if type=="filesystem" and not fileExists(compID,"/init.lua") then if type=="filesystem" and not fileExists(compID,"/init.lua") then
return print("\x1b[91mThis storage medium doesn't have an \"init.lua\" file.\nID: "..compID) return print("\x1b[91mThis storage medium doesn't have an \"init.lua\" file.\nID: "..compID.."\x1b[0m")
end end
end end
computer.setBootAddress(compID) computer.setBootAddress(compID)
if computer.getBootAddress()~=compID then if computer.getBootAddress()~=compID then
return print("\x1b[91mFailed to set the boot address.") return print("\x1b[91mFailed to set the boot address.\x1b[0m")
end end
computer.shutdown(true) computer.shutdown(true)
else else
+20 -16
View File
@@ -1,21 +1,25 @@
local files = { ... }
local shell = require("shell")
local fs = require("filesystem") local fs = require("filesystem")
if not files or not files[1] then local shell = require("shell")
shell.run("help cat")
return local args = {...}
if not args[1] then
return shell.run("help cat")
end end
for _, file in ipairs(files) do
if file:sub(1, 1) ~= "/" then for _, file in pairs(args) do
file = fs.concat(shell.getWorkingDirectory(), file) file = shell.resolvePath(file)
end
if not fs.exists(file) then
print("\27[91mFile does not exist.")
end
local handle = fs.open(file, "r") local handle = fs.open(file, "r")
local data if handle == nil then
repeat terminal.write("\27[91mCan't open " .. file .. "\27[0m\n")
data = handle:read(math.huge or math.maxinteger) goto continue
end
while true do
local data = handle:read(math.huge or math.maxinteger)
if data == nil then break end
terminal.write(data) terminal.write(data)
until not data end
handle:close()
::continue::
end end
+20 -9
View File
@@ -1,15 +1,26 @@
local directory = ... local args = {...}
if args[2] then
terminal.write("\27[91mToo many arguments.\27[0m")
end
if not args[1] then
return
end
local fs = require("filesystem") local fs = require("filesystem")
local shell = require("shell") local shell = require("shell")
if not directory then local directory = shell.resolvePath(args[1])
if not fs.exists(directory) then
terminal.write("\27[91mError: " .. directory .. ": No such file or directory\27[0m\n")
return return
end end
if directory:sub(1, 1) ~= "/" then
directory = fs.concat(shell.getWorkingDirectory(), directory) if not fs.isDirectory(directory) then
end terminal.write("\27[91mError: " .. directory .. ": Not a directory\27[0m\n")
if fs.exists(directory) and fs.isDirectory(directory) then return
shell.setWorkingDirectory(fs.canonical(directory))
else
print("\27[91mNo such directory.")
end end
shell.setWorkingDirectory(fs.canonical(directory))
+1
View File
@@ -1,2 +1,3 @@
terminal.clear() terminal.clear()
-- truly so much going on here -- truly so much going on here
-- meow
+64 -21
View File
@@ -1,27 +1,70 @@
local fromFile, toFile = ...
local fs = require("filesystem") local fs = require("filesystem")
local shell = require("shell") local shell = require("shell")
if not fromFile or not toFile then local args = {...}
shell.run("help cp")
if not args[1] then
return shell.run("help cp")
end
if not args[2] then
terminal.write("\27[91mError: No destination\27[0m\n")
return return
end end
if fromFile:sub(1, 1) ~= "/" then
fromFile = fs.concat(shell.getWorkingDirectory(), fromFile) local dest = shell.resolvePath(args[#args])
if fs.isFile(dest) then
if #args ~= 2 then
terminal.write("\27[91mError: Destination is not a directory\27[0m\n")
return
end
local src = shell.resolvePath(args[1])
if not fs.exists(src) then
terminal.write("\27[91mError: " .. src .. ": No such file or directory\27[0m\n")
return
end
if fs.isDirectory(src) then
terminal.write("\27[91mError: Cannot write directory " .. src .. " to file " .. dest .. "\27[0m\n")
return
end
fs.copy(src, dest)
elseif fs.isDirectory(dest) then
for i = 1, #args - 1 do
local src = shell.resolvePath(args[i])
if src == dest then
terminal.write("\27[91mError: Source and destination are the same\27[0m\n")
goto continue
end
if not fs.exists(src) then
terminal.write("\27[91mError: " .. src .. ": No such file or directory\27[0m\n")
goto continue
end
fs.copy(src, fs.concat(dest, fs.basename(src)))
::continue::
end
elseif not fs.exists(dest) then
if #args ~= 2 then
terminal.write("\27[91mError: " .. dest .. ": No such file or directory\27[0m\n")
return
end
local src = shell.resolvePath(args[1])
if not fs.exists(src) then
terminal.write("\27[91mError: " .. src .. ": No such file or directory\27[0m\n")
return
end
local destp = fs.parent(dest)
if not fs.exists(destp) then
terminal.write("\27[91mError: " .. destp .. ": No such file or directory\27[0m\n")
return
end
if not fs.isDirectory(destp) then
terminal.write("\27[91mError: " .. destp .. ": Not a directory\27[0m\n")
return
end
fs.copy(src, dest)
else
terminal.write("\27[91mUnknown error\27[0m\n")
end end
if toFile:sub(1, 1) ~= "/" then
toFile = fs.concat(shell.getWorkingDirectory(), toFile)
end
if fromFile == toFile then
print("\27[91mSource and destination are the same.")
return
end
if not fs.exists(fromFile) then
print("\27[91mSource file does not exist.")
return
end
if fs.exists(toFile) and not (table.find({...}, "-o") or table.find({...}, "--overwrite")) then
print("\27[91mDestination file already exists. Run this command again with -o to overwrite it.")
return
end
fs.copy(fromFile, toFile)
+5 -5
View File
@@ -4,7 +4,7 @@ local component = require("component")
local fs = require("filesystem") local fs = require("filesystem")
if not component.list("internet")() then if not component.list("internet")() then
print("\27[91mThis program requires an internet card to run.") print("\27[91mThis program requires an internet card to run.\27[0m")
return return
end end
@@ -26,11 +26,11 @@ local status, errorMessage = pcall(function()
request:finishConnect() request:finishConnect()
end) end)
if not status then if not status then
print("\27[91mDownload failed: " .. errorMessage) print("\27[91mDownload failed: " .. errorMessage .. "\27[0m")
end end
local responseCode = request:response() local responseCode = request:response()
if responseCode and responseCode ~= 200 then if responseCode and responseCode ~= 200 then
print("\27[91mDownload failed: " .. tostring(responseCode)) print("\27[91mDownload failed: " .. tostring(responseCode) .. "\27[0m")
end end
repeat repeat
tmpdata = request.read(math.huge) tmpdata = request.read(math.huge)
@@ -41,9 +41,9 @@ local saveLocationOK = false
repeat repeat
saveLocation = terminal.read(nil, "File save location: ", fs.concat(require("shell").getWorkingDirectory(), url:match("/([^/]+)$"))) saveLocation = terminal.read(nil, "File save location: ", fs.concat(require("shell").getWorkingDirectory(), url:match("/([^/]+)$")))
if fs.isDirectory(saveLocation) then if fs.isDirectory(saveLocation) then
print("\27[91mThe specified location is a directory.") print("\27[91mThe specified location is a directory.\27[0m")
elseif fs.exists(saveLocation) then elseif fs.exists(saveLocation) then
local answer = terminal.read({prefix = "\27[91mThere is already a file at the specified directory. Overwrite it? [Y/n]"}) local answer = terminal.read({prefix = "\27[91mThere is already a file at the specified directory. Overwrite it? [Y/n]\27[0m"})
if answer:lower() ~= "n" then if answer:lower() ~= "n" then
saveLocationOK = true saveLocationOK = true
end end
+3 -4
View File
@@ -16,8 +16,7 @@ local tab = " "
--local ocelot = component.ocelot --local ocelot = component.ocelot
local function rawset(x, y, text) local function rawset(x, y, text)
terminal.setCursorPos(x,y) terminal.write("\x1b[".. tostring(y) .. ";" .. tostring(x) .. "H" .. text)
terminal.write(text, false)
end end
local filestring, filepath, handle, data, tmpdata local filestring, filepath, handle, data, tmpdata
@@ -261,7 +260,7 @@ local function save()
gpu.setBackground(0xFFFFFF) gpu.setBackground(0xFFFFFF)
gpu.setForeground(0) gpu.setForeground(0)
gpu.set(1, height - 1, string.rep(" ", width)) gpu.set(1, height - 1, string.rep(" ", width))
terminal.setCursorPos(1, height - 1) rawset(1, height - 1)
local savepath = terminal.read({prefix = "\27[107m\27[30mSave location: ", defaultText = filepath}) local savepath = terminal.read({prefix = "\27[107m\27[30mSave location: ", defaultText = filepath})
gpu.setBackground(0xFFFFFF) gpu.setBackground(0xFFFFFF)
gpu.setForeground(0) gpu.setForeground(0)
@@ -300,7 +299,7 @@ while true do
renderFlag, cursorRenderFlag, specialKey = processEvent(args) renderFlag, cursorRenderFlag, specialKey = processEvent(args)
if specialKey == "x" then if specialKey == "x" then
if changesMade then if changesMade then
terminal.setCursorPos(1, height - 1) rawset(1, height - 1)
local response = terminal.read({prefix = "\27[107m\27[30mWould you like to save changes? [Y/n] "}) local response = terminal.read({prefix = "\27[107m\27[30mWould you like to save changes? [Y/n] "})
if response:lower() ~= "n" then if response:lower() ~= "n" then
save() save()
+38 -55
View File
@@ -2,82 +2,65 @@ local component = require("component")
local computer = require("computer") local computer = require("computer")
local filesystem = require("filesystem") local filesystem = require("filesystem")
local function convert(value, fromUnit, toUnit)
local units = {B = 1, KiB = 1024, MiB = 1024^2, GiB = 1024^3}
return value * units[fromUnit] / units[toUnit]
end
local function printstat(text) local function printstat(text)
local cursorPosX, cursorPosY = terminal.getCursorPos() terminal.write("\27[35G" .. text .. "\n")
terminal.setCursorPos(35, cursorPosY)
terminal.write(text .. "\n", false)
end end
local logo = "" local logo = ""
local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil
repeat repeat
tmpdata = handle:read(math.inf or math.maxinteger) tmpdata = handle:read(math.huge)
logo = logo .. (tmpdata or "") logo = logo .. (tmpdata or "")
until not tmpdata until not tmpdata
handle:close()
terminal.write(logo)
terminal.write("\27[17A")
terminal.write(logo, false)
local cursorPosX, cursorPosY = terminal.getCursorPos()
terminal.setCursorPos(cursorPosX, cursorPosY - 17)
printstat("\27[92mOS\27[0m: " .. _OSVERSION) printstat("\27[92mOS\27[0m: " .. _OSVERSION)
printstat("\27[92mArchitecture\27[0m: " .. _VERSION) printstat("\27[92mArchitecture\27[0m: " .. _VERSION)
local componentCounter = 0 local componentCounter = 0
for _, _ in component.list() do for _ in component.list() do
componentCounter = componentCounter + 1 componentCounter = componentCounter + 1
end end
printstat("\27[92mComponents\27[0m: " .. tostring(componentCounter)) printstat("\27[92mComponents\27[0m: " .. tostring(componentCounter))
printstat("\27[92mCoroutines\27[0m: " .. tostring(#tsched.getTasks())) printstat("\27[92mCoroutines\27[0m: " .. tostring(#tsched.getTasks()))
printstat( printstat("\27[92mBattery\27[0m: " .. tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10) .. "%")
"\27[92mBattery\27[0m: " .. tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10) .. "%"
)
local totalMemory = computer.totalMemory() local totalMemory = computer.totalMemory()
local usedMemory = computer.totalMemory() - computer.freeMemory() local usedMemory = computer.totalMemory() - computer.freeMemory()
local totalMemoryString
if convert(totalMemory, "B", "GiB") >= 1 then local function formatBytes(bytes)
totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "GiB") * 100 + 0.5) / 100) .. " GiB" if convert(bytes, "B", "GiB") >= 1 then
elseif convert(totalMemory, "B", "MiB") >= 1 then return tostring(math.floor(convert(bytes, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "MiB") * 100 + 0.5) / 100) .. " MiB" elseif convert(bytes, "B", "MiB") >= 1 then
elseif convert(totalMemory, "B", "KiB") >= 1 then return tostring(math.floor(convert(bytes, "B", "MiB") * 100 + 0.5) / 100) .. " MiB"
totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "KiB") * 100 + 0.5) / 100) .. " KiB" elseif convert(bytes, "B", "KiB") >= 1 then
else return tostring(math.floor(convert(bytes, "B", "KiB") * 100 + 0.5) / 100) .. " KiB"
totalMemoryString = tostring(totalMemory) .. " B" else
return tostring(bytes) .. " B"
end
end end
local usedMemoryString
if convert(usedMemory, "B", "GiB") >= 1 then printstat("\27[92mMemory\27[0m: " .. formatBytes(usedMemory) .. " / " .. formatBytes(totalMemory))
usedMemoryString = tostring(math.floor(convert(usedMemory, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
elseif convert(usedMemory, "B", "MiB") >= 1 then
usedMemoryString = tostring(math.floor(convert(usedMemory, "B", "MiB") * 100 + 0.5) / 100) .. " MiB"
elseif convert(usedMemory, "B", "KiB") >= 1 then
usedMemoryString = tostring(math.floor(convert(usedMemory, "B", "KiB") * 100 + 0.5) / 100) .. " KiB"
else
usedMemoryString = tostring(usedMemory) .. " B"
end
printstat("\27[92mMemory\27[0m: " .. usedMemoryString .. " / " .. totalMemoryString)
local totalDisk = component.invoke(computer.getBootAddress(), "spaceTotal") local totalDisk = component.invoke(computer.getBootAddress(), "spaceTotal")
local usedDisk = component.invoke(computer.getBootAddress(), "spaceUsed") local usedDisk = component.invoke(computer.getBootAddress(), "spaceUsed")
local totalDiskString
if convert(totalDisk, "B", "GiB") >= 1 then printstat("\27[92mDisk\27[0m: " .. formatBytes(usedDisk) .. " / " .. formatBytes(totalDisk))
totalDiskString = tostring(math.floor(convert(totalDisk, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
elseif convert(totalDisk, "B", "MiB") >= 1 then local gpuComponent = component.list("gpu")()
totalDiskString = tostring(math.floor(convert(totalDisk, "B", "MiB") * 100 + 0.5) / 100) .. " MiB" local width, height = component.invoke(gpuComponent, "getResolution")
elseif convert(totalDisk, "B", "KiB") >= 1 then
totalDiskString = tostring(math.floor(convert(totalDisk, "B", "KiB") * 100 + 0.5) / 100) .. " KiB"
else
totalDiskString = tostring(totalDisk) .. " B"
end
local usedDiskString
if convert(usedDisk, "B", "GiB") >= 1 then
usedDiskString = tostring(math.floor(convert(usedDisk, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
elseif convert(usedDisk, "B", "MiB") >= 1 then
usedDiskString = tostring(math.floor(convert(usedDisk, "B", "MiB") * 100 + 0.5) / 100) .. " MiB"
elseif convert(usedDisk, "B", "KiB") >= 1 then
usedDiskString = tostring(math.floor(convert(usedDisk, "B", "KiB") * 100 + 0.5) / 100) .. " KiB"
else
usedDiskString = tostring(usedDisk) .. " B"
end
printstat("\27[92mDisk\27[0m: " .. usedDiskString .. " / " .. totalDiskString)
local width, height = component.invoke(component.list("gpu")(), "getResolution")
printstat("\27[92mResolution\27[0m: " .. tostring(width) .. "x" .. tostring(height) .. "\n") printstat("\27[92mResolution\27[0m: " .. tostring(width) .. "x" .. tostring(height) .. "\n")
printstat("\27[40m \27[41m \27[42m \27[43m \27[44m \27[45m \27[46m \27[47m ") printstat("\27[40m \27[41m \27[42m \27[43m \27[44m \27[45m \27[46m \27[47m ")
printstat("\27[100m \27[101m \27[102m \27[103m \27[104m \27[105m \27[106m \27[107m ") printstat("\27[100m \27[101m \27[102m \27[103m \27[104m \27[105m \27[106m \27[107m ")
local cursorPosX, cursorPosY = terminal.getCursorPos()
terminal.setCursorPos(cursorPosX, cursorPosY + 5) terminal.write("\27[5B\27[0m")
+261 -33
View File
@@ -1,40 +1,268 @@
local shell = require("shell")
local fs = require("filesystem") local fs = require("filesystem")
local args = {...} local shell = require("shell")
local command = args[1]
args = nil local arg = ... or "default"
if not command then local what = arg
local handle, data, tmpdata = fs.open("/halyde/apps/helpdb/default.txt", "r"), "", nil
repeat local aliases = shell.getAliases()
tmpdata = handle:read(math.huge or math.maxinteger) if aliases[what] then
data = data .. (tmpdata or "") what = aliases[what]
until not tmpdata end
print(data) local path = "/halyde/apps/helpdb/" .. what
if not fs.exists(path) then
print("Could not find help file for: " .. arg .. ".")
return return
end end
local aliases = shell.getAliases() if path == "/halyde/apps/helpdb/default" then
if aliases[command] then return shell.run("cat " .. path) -- smh
command = aliases[command]
end end
if fs.exists("/halyde/apps/helpdb/" .. command .. ".txt") then local handle = fs.open(path, "r")
local handle, data, tmpdata = fs.open("/halyde/apps/helpdb/" .. command .. ".txt", "r"), "", nil local data = {
repeat command = "",
tmpdata = handle:read(math.huge or math.maxinteger) usage = "",
data = data .. (tmpdata or "") description = "",
until not tmpdata args = {},
print(data) examples = {}
-- local aliases = table.copy(shell.aliases) }
if table.find(aliases, command) then
local aliasIndex = table.find(aliases, command) while true do
local aliasString = "Aliases:\n " .. aliasIndex local line = ""
aliases[aliasIndex] = nil while true do
while table.find(aliases, command) do local char = handle:read(1)
aliasIndex = table.find(aliases, command) if not char then
aliasString = aliasString .. ", " .. aliasIndex if line == "" then
aliases[aliasIndex] = nil line = nil
break
end
break
end end
print(aliasString) if char == "\n" then
break
end
if char == "\r" then
local next_char = handle:read(1)
if next_char and next_char == "\n" then
break
elseif next_char then
local pos = file:seek("cur")
if pos then
file:seek("set", pos - 1)
end
break
end
break
end
line = line .. char
end
if line == nil then
break
end
line = line:match("^%s*(.-)%s*$")
if line then
local key, value = line:match("^(%w+)%s+(.*)$")
if not key then goto continue end
if key:lower() == "command" then
data.command = value
end
if key:lower() == "usage" then
data.usage = value
end
if key:lower() == "description" then
data.description = value
end
if key:lower():match("^arg%d+$") then
local num = key:lower():match("^arg(%d+)$")
if not data.args[tonumber(num)] then data.args[tonumber(num)] = {} end
data.args[tonumber(num)].name = value
end
if key:lower():match("^arg%d+description$") then
local num = key:lower():match("^arg(%d+)description$")
if not data.args[tonumber(num)] then data.args[tonumber(num)] = {} end
data.args[tonumber(num)].description = value
end
if key:lower():match("^arg%d+sub%d+$") then
local main_num, sub_num = key:lower():match("^arg(%d+)sub(%d+)$")
if main_num and sub_num then
if not data.args[tonumber(main_num)] then data.args[tonumber(main_num)] = {} end
if not data.args[tonumber(main_num)].subflags then data.args[tonumber(main_num)].subflags = {} end
if not data.args[tonumber(main_num)].subflags[tonumber(sub_num)] then
data.args[tonumber(main_num)].subflags[tonumber(sub_num)] = {}
end
data.args[tonumber(main_num)].subflags[tonumber(sub_num)].name = value
end
end
if key:lower():match("^arg%d+sub%d+description$") then
local main_num, sub_num = key:lower():match("^arg(%d+)sub(%d+)description$")
if main_num and sub_num then
if not data.args[tonumber(main_num)] then data.args[tonumber(main_num)] = {} end
if not data.args[tonumber(main_num)].subflags then data.args[tonumber(main_num)].subflags = {} end
if not data.args[tonumber(main_num)].subflags[tonumber(sub_num)] then
data.args[tonumber(main_num)].subflags[tonumber(sub_num)] = {}
end
data.args[tonumber(main_num)].subflags[tonumber(sub_num)].description = value
end
end
if key:lower():match("^example%d+$") then
local num = key:lower():match("^example(%d+)$")
if not data.examples[tonumber(num)] then data.examples[tonumber(num)] = {} end
data.examples[tonumber(num)].name = value
end
if key:lower():match("^example%d+description$") then
local num = key:lower():match("^example(%d+)description$")
if not data.examples[tonumber(num)] then data.examples[tonumber(num)] = {} end
data.examples[tonumber(num)].description = value
end
::continue::
end end
else end
print("Could not find help file for: " .. command .. ".")
handle:close()
--print(require("serialize")(data, "\t"))
-- Halyde terminal doesn't support bold (CSI 1 m) but who cares
if data.command then
terminal.write("\27[1mUsage: \27[0m\n")
terminal.write(" \27[96m" .. data.command)
if data.usage then
terminal.write("\27[93m " .. data.usage)
end
terminal.write("\27[0m\n\n")
end
local width, height = terminal.getResolution()
local function wrap_text(text, indent)
if not text then return "" end
local words = {}
for word in text:gmatch("%S+") do
table.insert(words, word)
end
local lines = {}
local current_line = ""
for i, word in ipairs(words) do
if #current_line + #word + 1 <= width * 0.66 - indent then
if current_line == "" then
current_line = word
else
current_line = current_line .. " " .. word
end
else
table.insert(lines, current_line)
current_line = word
end
end
if current_line ~= "" then
table.insert(lines, current_line)
end
local result = {}
for i, line in ipairs(lines) do
if i == 1 then
table.insert(result, line)
else
table.insert(result, string.rep(" ", indent) .. line)
end
end
return table.concat(result, "\n")
end
if data.description then
terminal.write("\27[1mDescription:\27[0m\n")
terminal.write(" " .. wrap_text(data.description, 2))
terminal.write("\n\n")
end
if #data.args > 0 then
terminal.write("\27[1mArguments:\27[0m\n")
local max_len = 0
for _, flag in ipairs(data.args) do
if flag.name then
max_len = math.max(max_len, #flag.name)
end
for _, subf in ipairs(flag.subflags or {}) do
if subf.name then
max_len = math.max(max_len, #subf.name + 2)
end
end
end
for _, flag in ipairs(data.args) do
terminal.write(" \27[93m" .. (flag.name or "") .. "\27[0m" .. string.rep(" ", max_len - (flag.name and #flag.name or 0) + 2) .. wrap_text(flag.description, 4 + max_len) .. "\n")
for _, subf in ipairs(flag.subflags or {}) do
terminal.write(" \27[92m" .. (subf.name or "") .. "\27[0m" .. string.rep(" ", max_len - (subf.name and #subf.name or 0)) .. wrap_text(subf.description, 4 + max_len) .. "\n")
end
end
terminal.write("\n")
end
local function formatExampleName(name, utility)
if not name then return name end
local contains = false
if name:find(utility, 1, true) then
contains = true
else
for alias, cmd in pairs(aliases) do
if cmd == utility and name:find(alias, 1, true) then
contains = true
break
end
end
end
if not contains then
return "\27[92m" .. name
end
local formatted = name
formatted = formatted:gsub("(" .. utility .. ")", "\27[96m%1\27[92m")
for alias, cmd in pairs(aliases) do
if cmd == utility then
formatted = formatted:gsub("(" .. alias .. ")", "\27[96m%1\27[92m")
end
end
return formatted
end
if #data.examples > 0 then
terminal.write("\27[1mExamples:\27[0m\n")
local max_len = 0
for _, flag in ipairs(data.examples) do
max_len = math.max(max_len, #flag.name)
end
for _, flag in ipairs(data.examples) do
terminal.write(" " .. formatExampleName(flag.name, arg) .. "\27[0m" .. string.rep(" ", max_len - #flag.name + 2) .. wrap_text(flag.description, 4 + max_len) .. "\n")
end
terminal.write("\n")
end
local first = true
for k, v in pairs(aliases) do
if v == arg then
if first then
terminal.write("\27[1mAliases:\27[0m\n ")
end
terminal.write("\27[96m" .. k)
if not first then
terminal.write("\27[0m, ")
end
first = false
end
end
if not first then
terminal.writec(0xa)
end end
+47
View File
@@ -0,0 +1,47 @@
COMMAND ag2
USAGE [COMMAND] [PACKAGES] [FLAGS]
DESCRIPTION Uses the Argentum 2 package manager.
ARG1 COMMAND
ARG1SUB1 install
ARG1SUB2 remove
ARG1SUB3 update
ARG1SUB4 list
ARG1SUB5 repo-list
ARG1SUB6 repo-add
ARG1SUB7 repo-remove
ARG1SUB8 info
ARG2 PACKAGES
ARG3 FLAGS
ARG3SUB1 -x, --exclude-deps
ARG3SUB2 -u, --update-repos
ARG3SUB3 -f, --force
ARG3SUB4 -c, --clean
ARG3SUB5 -s, --source [URL]
ARG3SUB6 -C, --cascade
ARG1DESCRIPTION Specifies the operation for Argentum 2 to do.
ARG1SUB1DESCRIPTION Installs packages.
ARG1SUB2DESCRIPTION Removes packages.
ARG1SUB3DESCRIPTION Updates packages.
ARG1SUB4DESCRIPTION Lists all available packages.
ARG1SUB5DESCRIPTION Lists all installed repositories.
ARG1SUB6DESCRIPTION Adds a custom repository.
ARG1SUB7DESCRIPTION Removes a repository.
ARG1SUB8DESCRIPTION Shows a packages version, description and other relevant information.
ARG2DESCRIPTION Packages to apply operations to.
ARG3DESCRIPTION These flags are available and can be inserted anywhere
ARG3SUB1DESCRIPTION Ignore dependencies. WARNING: Using this can and will leave you with broken packages. Use it at your own risk and only when truly necessary.
ARG3SUB2DESCRIPTION Update the list of repositories.
ARG3SUB3DESCRIPTION Force the operation, even if there are conflicts or unresolvable dependencies. WARNING: Using this can and will leave you with broken packages. Use it at your own risk and only when truly necessary.
ARG3SUB4DESCRIPTION Clean up now-unnecessary packages (previous dependencies).
ARG3SUB5DESCRIPTION Use a custom source for the operation.
ARG3SUB6DESCRIPTION When removing a package that other packages depend on, remove those packages too instead of aborting.
EXAMPLE1 ag2 install halyde
EXAMPLE2 ag2 list
EXAMPLE3 ag2 info halyde
EXAMPLE4 ag2 remove -x edit
EXAMPLE5 ag2 remove -c hal-draw
EXAMPLE1DESCRIPTION Installs the halyde package.
EXAMPLE2DESCRIPTION Lists all packages.
EXAMPLE3DESCRIPTION Shows information about the halyde package.
EXAMPLE4DESCRIPTION Removes edit, but does not remove any packages that depend on it.
EXAMPLE5DESCRIPTION Removes hal-draw and any dependencies that are no longer needed.
-32
View File
@@ -1,32 +0,0 @@
Usage: ag2 [COMMAND] [PACKAGES]
Uses the Argentum 2 package manager.
COMMAND Specifies the operation for Argentum 2 to do.
install Installs packages.
remove Removes packages.
update Updates packages.
list Lists all available packages.
repo-list Lists all installed repositories.
repo-add Adds a custom repository.
repo-remove Removes a repository.
info Shows a packages version, description and other relevant information.
PACKAGES* Packages to work on.
These flags are also available and can be inserted anywhere:
-x, --exclude-deps Ignore dependencies.
WARNING: Using this can and will leave you with broken packages.
Use it at your own risk and only when truly necessary.
-u, --update-repos Update the list of repositories.
-f, --force Force the operation, even if there are conflicts or unresolvable dependencies.
WARNING: Using this can and will leave you with broken packages.
Use it at your own risk and only when truly necessary.
-c, --clean Clean up now-unnecessary packages (previous dependencies).
-s, --source [URL] Use a custom source for the operation.
-C, --cascade When removing a package that other packages depend on, remove those packages too instead of aborting.
Examples:
ag2 install halyde Installs the halyde package.
ag2 list Lists all packages.
ag2 info halyde Shows information about the halyde package.
ag2 remove -x edit Removes edit, but does not remove any packages that depend on it.
ag2 remove -c hal-draw Removes hal-draw and any dependencies that are no longer needed.
+29
View File
@@ -0,0 +1,29 @@
COMMAND argentum
USAGE [COMMAND] [PACKAGES]
DESCRIPTION Uses the Argentum package manager.
ARG1 COMMAND
ARG1SUB1 install
ARG1SUB2 remove
ARG1SUB3 update
ARG1SUB4 list
ARG1SUB5 search
ARG1SUB6 info
ARG2 PACKAGES
ARG1DESCRIPTION Specifies the operation for Ag to do.
ARG1SUB1DESCRIPTION Installs packages.
ARG1SUB2DESCRIPTION Removes packages.
ARG1SUB3DESCRIPTION Updates packages.
ARG1SUB4DESCRIPTION Lists all available packages.
ARG1SUB5DESCRIPTION Searches all available packages.
ARG1SUB6DESCRIPTION Shows information on a specific package.
ARG2DESCRIPTION Packages to apply operations to.
EXAMPLE1 ag install hal-draw
EXAMPLE2 ag list
EXAMPLE3 ag info hal-draw
EXAMPLE4 ag update hal-draw
EXAMPLE5 ag update hal-draw
EXAMPLE1DESCRIPTION Installs the hal-draw package.
EXAMPLE2DESCRIPTION Lists all packages.
EXAMPLE3DESCRIPTION Shows information about hal-draw.
EXAMPLE4DESCRIPTION Updates the hal-draw package if it's not at the newest version.
EXAMPLE5DESCRIPTION Updates all packages.
-18
View File
@@ -1,18 +0,0 @@
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.
+8
View File
@@ -0,0 +1,8 @@
COMMAND beep
USAGE [FLAGS]
DESCRIPTION Make the computer beep.
ARG1 FLAGS
ARG1SUB1 -f, --frequency
ARG1SUB2 -t, --time
ARG1SUB1DESCRIPTION Specifies the frequency, in Hz. Defaults to 440Hz.
ARG1SUB2DESCRIPTION Specifies how long, in seconds, the computer should beep. Defaults to 0.1s.
-6
View File
@@ -1,6 +0,0 @@
Usage: beep [FLAGS]
Make the computer beep.
FLAGS
-f, --frequency Specifies the frequency, in Hz. Defaults to 440Hz.
-t, --time Specifies how long, in seconds, the computer should beep. Defaults to 0.1s.
+23
View File
@@ -0,0 +1,23 @@
COMMAND boot
USAGE [ADDRESS] [FLAGS]
DESCRIPTION Restarts and automatically boots into any storage medium. Meant to be used for systems using a Lua BIOS EEPROM.
ARG1 ADDRESS
ARG1SUB1 hdd1
ARG1SUB2 hdd2
ARG1SUB3 floppy
ARG1SUB4
ARG2 FLAGS
ARG2SUB1 -f, --force
ARG1DESCRIPTION The storage medium to boot to.
ARG1SUB1DESCRIPTION The first hard drive inserted in the computer.
ARG1SUB2DESCRIPTION The second hard drive inserted in the computer.
ARG1SUB3DESCRIPTION The floppy disk that is inserted in the computer.
ARG1SUB4DESCRIPTION The ID of the component, abbreviated. Must have three or more characters.
ARG2DESCRIPTION Specifies extra options when executing the command.
ARG2SUB1DESCRIPTION Forces booting into the storage medium.
EXAMPLE1 boot hdd1
EXAMPLE2 boot hdd2
EXAMPLE3 boot floppy
EXAMPLE1DESCRIPTION Boot into the first hard drive inserted in the computer.
EXAMPLE2DESCRIPTION Boot into the second hard drive inserted in the computer.
EXAMPLE3DESCRIPTION Boot into the floppy disk inserted in the comuter.
-15
View File
@@ -1,15 +0,0 @@
Usage: boot [ADDRESS] [FLAGS]
Restarts and automatically boots into any storage medium. Meant to be used for systems using a Lua BIOS EEPROM.
ADDRESS The storage medium to boot to.
hdd1 The first hard drive inserted in the computer.
hdd2 The second hard drive inserted in the computer.
floppy The floppy disk that is inserted in the computer.
The ID of the component, abbreviated. Must have three or more characters.
FLAGS Specifies extra options when executing the command.
-f, --force Forces booting into the storage medium.
Examples:
boot hdd1 Boot into the first hard drive inserted in the computer.
boot hdd2 Boot into the second hard drive inserted in the computer.
boot floppy Boot into the floppy disk inserted in the comuter.
+9
View File
@@ -0,0 +1,9 @@
COMMAND cat
USAGE [FILES]...
DESCRIPTION Concatenates and prints a file.
ARG1 FILES
ARG1DESCRIPTION Specifies the paths to the files to print.
EXAMPLE1 cat /init.lua
EXAMPLE2 cat help.lua cat.lua
EXAMPLE1DESCRIPTION Concatenates and prints init.lua in the root directory.
EXAMPLE2DESCRIPTION Concatenates and prints help.lua and cat.lua in the current working directory.
-8
View File
@@ -1,8 +0,0 @@
Usage: cat [FILES]...
Concatenates and prints a file.
FILES Specifies the paths to the files to print.
Examples:
cat /init.lua Concatenates and prints init.lua in the root directory.
cat help.lua cat.lua Concatenates and prints help.lua and cat.lua in the current working directory.
+13
View File
@@ -0,0 +1,13 @@
COMMAND cd
USAGE [PATH]
DESCRIPTION Sets the shell working directory.
ARG1 PATH
ARG1DESCRIPTION Specifies the path to set the shell working directory to.
EXAMPLE1 cd /home/
EXAMPLE2 cd halyde
EXAMPLE3 cd ..
EXAMPLE4 ..
EXAMPLE1DESCRIPTION Sets the shell working directory to /home/.
EXAMPLE2DESCRIPTION Sets the shell working directory to a directory named "halyde" in the current working directory.
EXAMPLE3DESCRIPTION Sets the shell working directory back one directory.
EXAMPLE4DESCRIPTION Equivalent of "cd ..".
-10
View File
@@ -1,10 +0,0 @@
Usage: cd [PATH]
Sets the shell working directory.
PATH Specifies the path to set the shell working directory to.
Examples:
cd /home/ Sets the shell working directory to /home/.
cd halyde Sets the shell working directory to a directory named "halyde" in the current working directory.
cd .. Sets the shell working directory back one directory.
.. Equivalent of "cd ..".
+4
View File
@@ -0,0 +1,4 @@
COMMAND clear
DESCRIPTION Clears the screen.
EXAMPLE1 clear
EXAMPLE1DESCRIPTION Clears the screen.
-5
View File
@@ -1,5 +0,0 @@
Usage: clear
Clears the screen.
Examples:
clear Clears the screen.
+11
View File
@@ -0,0 +1,11 @@
COMMAND cp
USAGE [SOURCES]... [DESTINATION]
DESCRIPTION Copy files and directories.
ARG1 SOURCES
ARG2 DESTINATION
ARG1DESCRIPTION Specifies the files and directories to be copied.
ARG2DESCRIPTION Specifies the path or a directory to copy to.
EXAMPLE1 cp /home/a.txt /b.txt
EXAMPLE2 cp c.lua /halyde/apps .
EXAMPLE1DESCRIPTION Copies the file at /home/a.txt to /b.txt.
EXAMPLE2DESCRIPTION Copies c.lua and /halyde/apps to the shell working directory.
-11
View File
@@ -1,11 +0,0 @@
Usage: cp [FLAGS] [SOURCE] [DESTINATION]
Copies a file.
FLAGS Specifies extra options when executing the command.
-o, --overwrite Allows any file that might be at the destination to be overwritten.
SOURCE Specifies the file to be copied.
DESTINATION Specifies the path to copy the file to.
Examples:
cp /home/a.txt /b.txt Copies the file at /home/a.txt to /b.txt.
cp -o c.lua d.txt Copies the file c.lua to another file called d.txt in the shell working directory, overwriting any file that might be there.
+7
View File
@@ -0,0 +1,7 @@
COMMAND download
USAGE [URL]
DESCRIPTION Downloads a file from the internet.
ARG1 URL
ARG1DESCRIPTION Specifies the URL from which to download the file from.
EXAMPLE1 download https://github.com/
EXAMPLE1DESCRIPTION Downloads github.com.
-7
View File
@@ -1,7 +0,0 @@
Usage: download [URL]
Downloads a file from the internet.
URL Specifies the URL from which to download the file from.
Examples:
download https://github.com/ Downloads github.com.
+9
View File
@@ -0,0 +1,9 @@
COMMAND echo
USAGE [TEXT]...
DESCRIPTION Concatenates and prints text to the terminal.
ARG1 TEXT
ARG1DESCRIPTION Text to print.
EXAMPLE1 echo test
EXAMPLE2 echo Hello World!
EXAMPLE1DESCRIPTION Prints "test" to the terminal.
EXAMPLE2DESCRIPTION Prints "Hello World!" to the terminal.
-8
View File
@@ -1,8 +0,0 @@
Usage: echo [TEXT]...
Concatenates and prints text to the terminal.
TEXT Text to print.
Examples:
echo test Prints "test" to the terminal.
echo Hello World! Prints "Hello World!" to the terminal.
+9
View File
@@ -0,0 +1,9 @@
COMMAND edit
USAGE [PATH]
DESCRIPTION Opens a file with the text editor, or a new blank file if not specified.
ARG1 PATH
ARG1DESCRIPTION Specifies the file to be opened.
EXAMPLE1 edit
EXAMPLE2 edit /LICENSE
EXAMPLE1DESCRIPTION Opens a new blank file in the text editor.
EXAMPLE2DESCRIPTION Opens /LICENSE in the text editor.
-8
View File
@@ -1,8 +0,0 @@
Usage: edit [PATH]
Opens a file with the text editor, or a new blank file if not specified.
PATH* Specifies the file to be opened.
Examples:
edit Opens a new blank file in the text editor.
edit /LICENSE Opens /LICENSE in the text editor.
+4
View File
@@ -0,0 +1,4 @@
COMMAND fetch
DESCRIPTION Displays system information including OS version, Lua version, memory, etc.
EXAMPLE1 fetch
EXAMPLE1DESCRIPTION Displays system information.
-5
View File
@@ -1,5 +0,0 @@
Usage: fetch
Displays system information including OS version, Lua version, memory, etc.
Examples:
fetch Displays system information.
+9
View File
@@ -0,0 +1,9 @@
COMMAND help
USAGE [COMMAND]
DESCRIPTION Displays info on the command specified, or a list of commands if one is not specified.
ARG1 COMMAND
ARG1DESCRIPTION Command to display information on.
EXAMPLE1 help
EXAMPLE2 help cp
EXAMPLE1DESCRIPTION Displays a list of all default commands available.
EXAMPLE2DESCRIPTION Displays information about the cp command.
-8
View File
@@ -1,8 +0,0 @@
Usage: help [COMMAND]
Displays info on the command specified, or a list of commands if one is not specified.
COMMAND* Command to display information on.
Examples:
help Displays a list of all default commands available.
help cp Displays information about the cp command.
+24
View File
@@ -0,0 +1,24 @@
COMMAND label
USAGE [ADDRESS] [LABEL]
DESCRIPTION Get or set a label of a component that supports labelling.
ARG1 ADDRESS
ARG1SUB1 eeprom
ARG1SUB2 halyde
ARG1SUB3 slotN
ARG1SUB4 #N
ARG2 LABEL
ARG1DESCRIPTION The component to use for getting or setting the label.
ARG1SUB1DESCRIPTION The computer's EEPROM.
ARG1SUB2DESCRIPTION The drive where the Halyde installation resides in.
ARG1SUB3DESCRIPTION The slot number of the drive, in top-to-bottom order (range 7-9)
ARG1SUB4DESCRIPTION The slot number of the drive, in drive space (range 1-3)
ARG1SUB5DESCRIPTION The ID of the component, abbreviated. Must have three or more characters.
ARG2DESCRIPTION The label to set the component to. If not found, the current label will be printed out.
EXAMPLE1 label #3
EXAMPLE2 label eeprom
EXAMPLE3 label slot8 Storage
EXAMPLE4 label halyde Halyde
EXAMPLE1DESCRIPTION Get the label of the third drive in the computer.
EXAMPLE2DESCRIPTION Get the label of the EEPROM inserted in the computer.
EXAMPLE3DESCRIPTION Set the drive at slot 8 to have the label "Storage"
EXAMPLE4DESCRIPTION Set the label of the Halyde installation to "Halyde"
-16
View File
@@ -1,16 +0,0 @@
Usage: label [ADDRESS] [LABEL]
Get or set a label of a component that supports labelling.
ADDRESS The component to use for getting or setting the label.
eeprom The computer's EEPROM.
halyde The drive where the Halyde installation resides in.
slotN The slot number of the drive, in top-to-bottom order (range 7-9)
#N The slot number of the drive, in drive space (range 1-3)
The ID of the component, abbreviated. Must have three or more characters.
LABEL* The label to set the component to. If not found, the current label will be printed out.
Examples:
label #3 Get the label of the third drive in the computer.
label eeprom Get the label of the EEPROM inserted in the computer.
label slot8 Storage Set the drive at slot 8 to have the label "Storage"
label halyde Halyde Set the label of the Halyde installation to "Halyde"
+19
View File
@@ -0,0 +1,19 @@
COMMAND log
USAGE [OPERATION] [ARGS]
DESCRIPTION Tool to manage system logs.
ARG1 OPERATION
ARG1SUB1 view [LOG]
ARG1SUB2 list
ARG1SUB3 clear [LOG]
ARG1SUB4 info/warn/error [LOG] [TEXT]
ARG2 ARGS
ARG1DESCRIPTION Operation to do with the system logs.
ARG1SUB1DESCRIPTION View a log file.
ARG1SUB2DESCRIPTION List all logs.
ARG1SUB3DESCRIPTION Clear a log file, or all if none specified.
ARG1SUB4DESCRIPTION Create a log entry for the specified log at the specified log level.
ARG2DESCRIPTION Arguments (specified under OPERATION)
EXAMPLE1 log view example
EXAMPLE2 log list
EXAMPLE3 log clear example
EXAMPLE4 log info example This is an example.
-15
View File
@@ -1,15 +0,0 @@
Usage: log [OPERATION] [ARGS]
Tool to manage system logs.
OPERATION Operation to do with the system logs.
view [LOG] View a log file.
list List all logs.
clear [LOG*] Clear a log file, or all if none specified.
info/warn/error [LOG] [TEXT] Create a log entry for the specified log at the specified log level.
ARGS Arguments (specified under OPERATION)
Examples:
log view example
log list
log clear example
log info example This is an example.
+11
View File
@@ -0,0 +1,11 @@
COMMAND ls
USAGE [PATH]...
DESCRIPTION Lists all files and directories in the specified path, or in the shell working directory if the path isn't specified. Directories are shown in yellow, executable files are shown in green, and other files are shown in white.
ARG1 PATH
ARG1DESCRIPTION Path to the directories to list files and subdirectories from.
EXAMPLE1 ls
EXAMPLE2 ls /halyde
EXAMPLE3 ls apps
EXAMPLE1DESCRIPTION Lists all files and directories from the current shell working directory.
EXAMPLE2DESCRIPTION Lists all files and directories from /halyde.
EXAMPLE3DESCRIPTION Lists all files and directories from the apps directory in the shell working directory.
-10
View File
@@ -1,10 +0,0 @@
Usage: ls [PATH]
Lists all files and directories in the specified path, or in the shell working directory if the path isn't specified.
Directories are shown in yellow, executable files are shown in green, and other files are shown in white.
PATH* Path to the folder to list files and directories from.
Examples:
ls Lists all files and directories from the current shell working directory.
ls /halyde Lists all files and directories from /halyde.
ls apps Lists all files and directories from the apps directory in the shell working directory.
+4
View File
@@ -0,0 +1,4 @@
COMMAND lscor
DESCRIPTION Lists every active coroutine by ID and name.
EXAMPLE1 lscor
EXAMPLE1DESCRIPTION Lists every active coroutine by ID and name.
-5
View File
@@ -1,5 +0,0 @@
Usage: lscor
Lists every active coroutine by ID and name.
Examples:
lscor Lists every active coroutine by ID and name.
+37
View File
@@ -0,0 +1,37 @@
COMMAND lsdrv
USAGE [FLAGS]
DESCRIPTION Shows all drives that are inserted into the computer.
ARG1 FLAGS
ARG1SUB1 -a, --all
ARG1SUB2 -o, --output [COLS]
ARG1SUB3 -s, --show [EXPR]
ARG1SUB4 -S, --sort [EXPR]
ARG1SUB5 EXPR
ARG2 PACKAGES
ARG1DESCRIPTION Specifies extra options when executing the command.
ARG1SUB1DESCRIPTION Shows every column and every component. Acts the same as '-o all -s all'. Possible columns are: "slot", "capacity", "managed", "readOnly", "id", "mount", "bootable", and "label". If the list of columns start with a "+", the default columns will appear first. Default columns are slots, capacity, the entire ID, the mount point, and the drive label.
ARG1SUB2DESCRIPTION Specifies the columns to output in the output table.
ARG1SUB3DESCRIPTION Only list drives when the expression returns 'true'.
ARG1SUB4DESCRIPTION Sort the output by an expression that returns a number. The higher the number, the lower the drive is displayed, and vice-versa.
ARG1SUB5DESCRIPTION An expression in Lua, for filtering or sorting output. If this expression contains spaces, make sure to put quotation marks on them!
ARG1SUB6DESCRIPTION Built-in variables are: "component", "computer", "type", "id", "readonly", "capacity", "managed", "eeprom", "halyde", "tmp", "proxy", "slot", and "all" (true).
EXAMPLE1 lsdrv
EXAMPLE2 lsdrv -a
EXAMPLE3 lsdrv -o +bootable
EXAMPLE4 lsdrv -o slot,label -s halyde
EXAMPLE5 lsdrv -o mount,capacity,label -s "not halyde"
EXAMPLE6 lsdrv -s type=='filesystem'
EXAMPLE7 lsdrv -s slot==1
EXAMPLE8 lsdrv -S capacity
EXAMPLE9 lsdrv -S -capacity
EXAMPLE10 lsdrv -o +managed -S managed
EXAMPLE1DESCRIPTION Show regular drives, with the default columns.
EXAMPLE2DESCRIPTION Show all storage components, with every column.
EXAMPLE3DESCRIPTION Show drives, with an added "bootable" category.
EXAMPLE4DESCRIPTION Show the slot and the label of the drive where Halyde is installed.
EXAMPLE5DESCRIPTION Show the mount points, capacities and labels of all drives other than Halyde.
EXAMPLE6DESCRIPTION Only show managed drives.
EXAMPLE7DESCRIPTION Show all drives that aren't physical (Virtual components, tmpfs)
EXAMPLE8DESCRIPTION Sort the drives by capacity, in ascending order.
EXAMPLE9DESCRIPTION Sort the drives by capacity, in descending order.
EXAMPLE10DESCRIPTION Show managed drives first, then unmanaged drives second, with an extra "managed" column.
-27
View File
@@ -1,27 +0,0 @@
Usage: lsdrv [FLAGS]
Shows all drives that are inserted into the computer.
FLAGS Specifies extra options when executing the command.
-a, --all Shows every column and every component. Acts the same as '-o all -s all'.
-o, --output [COLS] Specifies the columns to output in the output table.
Possible columns are: "slot", "capacity", "managed", "readOnly", "id", "mount", "bootable", and "label".
If the list of columns start with a "+", the default columns will appear first.
Default columns are slots, capacity, the entire ID, the mount point, and the drive label.
-s, --show [EXPR] Only list drives when the expression returns 'true'.
-S, --sort [EXPR] Sort the output by an expression that returns a number.
The higher the number, the lower the drive is displayed, and vice-versa.
EXPR An expression in Lua, for filtering or sorting output.
If this expression contains spaces, make sure to put quotation marks on them!
Built-in variables are: "component", "computer", "type", "id", "readonly", "capacity", "managed", "eeprom", "halyde", "tmp", "proxy", "slot", and "all" (true).
Examples:
lsblk Show regular drives, with the default columns.
lsblk -a Show all storage components, with every column.
lsblk -o +bootable Show drives, with an added "bootable" category.
lsblk -o slot,label -s halyde Show the slot and the label of the drive where Halyde is installed.
lsblk -o mount,capacity,label -s "not halyde" Show the mount points, capacities and labels of all drives other than Halyde.
lsblk -s type=='filesystem' Only show managed drives.
lsblk -s slot==1 Show all drives that aren't physical (Virtual components, tmpfs)
lsblk -S capacity Sort the drives by capacity, in ascending order.
lsblk -S -capacity Sort the drives by capacity, in descending order.
lsblk -o +managed -S managed Show managed drives first, then unmanaged drives second, with an extra "managed" column.
+4
View File
@@ -0,0 +1,4 @@
COMMAND lua
DESCRIPTION Starts the Lua shell, where you can type commands to interpret them in real time.
EXAMPLE1 lua
EXAMPLE1DESCRIPTION Starts the Lua shell.
-5
View File
@@ -1,5 +0,0 @@
Usage: lua
Starts the Lua shell, where you can type commands to interpret them in real time.
Examples:
lua Starts the Lua shell.
+2
View File
@@ -0,0 +1,2 @@
COMMAND maindrv
DESCRIPTION Shows the entire ID of the drive where Halyde is installed to.
-2
View File
@@ -1,2 +0,0 @@
Usage: maindrv
Shows the entire ID of the drive where Halyde is installed to.
+7
View File
@@ -0,0 +1,7 @@
COMMAND mkdir
USAGE [PATH]...
DESCRIPTION Makes a directory.
ARG1 PATH
ARG1DESCRIPTION Specifies the path to create the directory in.
EXAMPLE1 mkdir a
EXAMPLE1DESCRIPTION Creates a directory named a in the current shell working directory.
-7
View File
@@ -1,7 +0,0 @@
Usage: mkdir [PATH]
Makes a directory.
PATH Specifies the path to create the directory in.
Examples:
mkdir a Creates a directory named a in the current shell working directory.
+11
View File
@@ -0,0 +1,11 @@
COMMAND mv
USAGE [SOURCE].. [DESTINATION]
DESCRIPTION Moves/renames a file.
ARG1 SOURCE
ARG2 DESTINATION
ARG1DESCRIPTION Specifies the files and directories to be moved.
ARG2DESCRIPTION Specifies the path or a directory to copy to.
EXAMPLE1 mv /home/a.txt /b.txt
EXAMPLE2 mv ../c.lua /halyde/apps .
EXAMPLE1DESCRIPTION Moves the file at /home/a.txt to /b.txt.
EXAMPLE2DESCRIPTION Moves c.lua from a subdirectory and /halyde/apps to the shell working directory.
-11
View File
@@ -1,11 +0,0 @@
Usage: mv [FLAGS] [SOURCE] [DESTINATION]
Moves/renames a file.
FLAGS Specifies extra options when executing the command.
-o, --overwrite Allows any file that might be at the destination to be overwritten.
SOURCE Specifies the file to be moved/renamed.
DESTINATION Specifies the path/filename to move/rename the file to.
Examples:
mv /home/a.txt /b.txt Moves the file at /home/a.txt to /b.txt.
mv -o c.lua d.txt Renames the file c.lua to another file called d.txt in the shell working directory, overwriting any file that might be there.
+4
View File
@@ -0,0 +1,4 @@
COMMAND reboot
DESCRIPTION Reboots the computer.
EXAMPLE1 reboot
EXAMPLE1DESCRIPTION Reboots the computer.
-5
View File
@@ -1,5 +0,0 @@
Usage: reboot
Reboots the computer.
Examples:
reboot Reboots the computer.
+11
View File
@@ -0,0 +1,11 @@
COMMAND res
USAGE [FLAGS]
DESCRIPTION Gets or sets the current resolution.
ARG1 FLAGS
ARG1SUB1 [no flags]
ARG1SUB2 -x [number]
ARG1SUB3 -y [number]
ARG1DESCRIPTION Specifies extra options when executing the command.
ARG1SUB1DESCRIPTION Displays the current and maximum resolution.
ARG1SUB2DESCRIPTION Displays the current and maximum resolution on the x-axis. A new x-axis resolution can be specified as a number.
ARG1SUB3DESCRIPTION Displays the current and maximum resolution on the y-axis. A new y-axis resolution can be specified as a number.
-9
View File
@@ -1,9 +0,0 @@
Usage: res [FLAGS]
Gets or sets the current resolution.
FLAGS* Specifies extra options when executing the command.
[no flags] Displays the current and maximum resolution.
-x [number*] Displays the current and maximum resolution on the x-axis.
A new x-axis resolution can be specified as a number.
-y [number*] Displays the current and maximum resolution on the y-axis.
A new y-axis resolution can be specified as a number.
+7
View File
@@ -0,0 +1,7 @@
COMMAND rm
USAGE [PATH]...
DESCRIPTION Removes files and directories.
ARG1 PATH
ARG1DESCRIPTION Specifies the files and directories to be moved/renamed.
EXAMPLE1 rm a.txt
EXAMPLE1DESCRIPTION Removes a.txt in the current shell working directory.
-7
View File
@@ -1,7 +0,0 @@
Usage: rm [PATH]
Removes files and directories.
PATH Specifies the file to be moved/renamed.
Examples:
rm a.txt Removes a.txt in the current shell working directory.
+4
View File
@@ -0,0 +1,4 @@
COMMAND shutdown
DESCRIPTION Shuts down the computer.
EXAMPLE1 shutdown
EXAMPLE1DESCRIPTION Shuts down the computer.
-5
View File
@@ -1,5 +0,0 @@
Usage: shutdown
Shuts down the computer.
Examples:
shutdown Shuts down the computer.
+5
View File
@@ -0,0 +1,5 @@
COMMAND touch
USAGE [FILE]...
DESCRIPTION Create an empty file.
ARG1 FILE
ARG1DESCRIPTION The path of the files to create.
-6
View File
@@ -1,6 +0,0 @@
Usage: touch [FLAGS] [FILE]
Creates a file with empty content.
FLAGS Specifies extra options when executing the command.
-o, --overwrite Allows emptying out a file if it already exists.
FILE The path of the file to create.²
+9 -9
View File
@@ -1,7 +1,7 @@
local component = require("component") local component = require("component")
local computer = require("computer") local computer = require("computer")
local args = {...} local args = {...}
if not args then return print("\x1b[91mCannot get arguments.") end if not args then return print("\x1b[91mCannot get arguments.\x1b[0m") end
if not args[1] then if not args[1] then
return require("shell").run("help label") return require("shell").run("help label")
end end
@@ -29,27 +29,27 @@ elseif inputID:sub(1,1)=="#" and tonumber(inputID:sub(2)) then
componentFromSlot(slotNum) componentFromSlot(slotNum)
elseif #inputID>=3 then elseif #inputID>=3 then
local fullID = component.get(inputID) local fullID = component.get(inputID)
if not fullID then return print("\x1b[91mCould not find entire component ID from \""..inputID.."\".") end if not fullID then return print("\x1b[91mCould not find entire component ID from \""..inputID.."\".\x1b[0m") end
comp = component.proxy(fullID) comp = component.proxy(fullID)
else else
print("\x1b[91mAddress must have atleast 3 characters") print("\x1b[91mAddress must have atleast 3 characters\x1b[0m")
return require("shell").run("help label") return require("shell").run("help label")
end end
if not comp then if not comp then
return print("\x1b[91mCould not find component from \""..inputID.."\".") return print("\x1b[91mCould not find component from \""..inputID.."\".\x1b[0m")
end end
local compID = comp.address local compID = comp.address
local function formatID(id) local function formatID(id)
return id:sub(1,8).."\x1b[37m"..id:sub(9).."\x1b[39m" return id:sub(1,8).."\x1b[37m"..id:sub(9).."\x1b[0m"
end end
local function unsupported(act) local function unsupported(act)
print("This \x1b[92m"..(comp.type or "unknown").."\x1b[39m component doesn't support "..act.." labels.\nID: "..formatID(compID)) print("This \x1b[92m"..(comp.type or "unknown").."\x1b[0m component doesn't support "..act.." labels.\nID: "..formatID(compID).."\x1b[0m")
end end
local function compError(act,reason) local function compError(act,reason)
print("\x1b[91mAn error occured while "..act.." the label of this component.\nComponent: "..(compID or "unknown id").." ("..((comp or {}).type or "unknown type")..")\n\n"..reason) print("\x1b[91mAn error occured while "..act.." the label of this component.\nComponent: "..(compID or "unknown id").." ("..((comp or {}).type or "unknown type")..")\n\n"..reason.."\x1b[0m")
end end
local function formatLabel(label) local function formatLabel(label)
@@ -67,7 +67,7 @@ if type(args[2])~="string" then
label = comp.getLabel() label = comp.getLabel()
end) end)
if success then if success then
print("Label of "..formatID(compID)..((comp.type and comp.type~="filesystem") and " ("..comp.type..")" or "")..":\n \x1b[92m"..formatLabel(label).."\x1b[39m") print("Label of "..formatID(compID)..((comp.type and comp.type~="filesystem") and " ("..comp.type..")" or "")..":\n \x1b[92m"..formatLabel(label).."\x1b[0m")
else else
compError("getting",reason) compError("getting",reason)
end end
@@ -85,7 +85,7 @@ else
label = comp.setLabel(newLabel) label = comp.setLabel(newLabel)
end) end)
if success then if success then
print("Successfully set label of "..formatID(compID)..(comp.type and " ("..comp.type..")" or "").." to:\n \x1b[92m"..formatLabel(label).."\x1b[39m") print("Successfully set label of "..formatID(compID)..(comp.type and " ("..comp.type..")" or "").." to:\n \x1b[92m"..formatLabel(label).."\x1b[0m")
else else
compError("setting",reason) compError("setting",reason)
end end
+4 -4
View File
@@ -27,9 +27,9 @@ local function viewlog(logname)
entry = string.sub(entry, 1, -1) entry = string.sub(entry, 1, -1)
end end
if entry:sub(1, 4) == "WARN" then if entry:sub(1, 4) == "WARN" then
print("\x1b[93m" .. entry) print("\x1b[93m" .. entry .. "\x1b[0m")
elseif entry:sub(1, 5) == "ERROR" then elseif entry:sub(1, 5) == "ERROR" then
print("\x1b[91m" .. entry) print("\x1b[91m" .. entry .. "\x1b[0m")
else else
print(entry) print(entry)
end end
@@ -58,9 +58,9 @@ local function listlogs2()
print("Found \x1b[93m" .. #logs .. "\x1b[0m logs.") print("Found \x1b[93m" .. #logs .. "\x1b[0m logs.")
for i in ipairs(logs) do for i in ipairs(logs) do
if i == #logs then if i == #logs then
print("\x1b[93m└ \x1b[0m" .. logs[i] .. "\x1b[90m.log") print("\x1b[93m└ \x1b[0m" .. logs[i] .. "\x1b[90m.log\x1b[0m")
else else
print("\x1b[93m├ \x1b[0m" .. logs[i] .. "\x1b[90m.log") print("\x1b[93m├ \x1b[0m" .. logs[i] .. "\x1b[90m.log\x1b[0m")
end end
end end
end end
+48 -61
View File
@@ -1,71 +1,58 @@
local args = {...}
local target = args[1]
args = nil
local fs = require("filesystem") local fs = require("filesystem")
local unicode = require("unicode") local shell = require("shell")
local maxLength = 0
local margin = 2 -- minimum space between filename and size
local dirTable = {}
local fileTable = {}
local workingDirectory = require("shell").getWorkingDirectory()
if target then local function formatSize(size, isDir)
if target:sub(1, 1) ~= "/" then if isDir then return "[DIR]" end
target = fs.concat(workingDirectory, target) if size >= 1024^3 then return string.format("%.1fGiB", size / 1024^3) end
end if size >= 1024^2 then return string.format("%.1fMiB", size / 1024^2) end
else if size >= 1024 then return string.format("%.1fKiB", size / 1024) end
target = workingDirectory return size.."B"
end end
local files = fs.list(target) local function getFileColor(name, isDir)
if isDir then return "\27[93m" end
if name:match("%.lua$") then return "\27[92m" end
return "\27[0m"
end
if files then local args = {...}
if not args[1] then
args = {require("shell").getWorkingDirectory()}
end
for _, path in pairs(args) do
path = shell.resolvePath(path)
local files = fs.list(path)
if not files then
terminal.write("\27[91mError: " .. path .. ": No such file or directory\27[0m\n")
goto continue
end
local fileList = {}
for _, file in pairs(files) do for _, file in pairs(files) do
if file:sub(-1, -1) == "/" then local isDir = file:sub(-1) == "/"
table.insert(dirTable, file) local name = isDir and file:sub(1, -2) or file
file = file:sub(1, -2) local size = isDir and 0 or fs.size(fs.concat(path, file))
else table.insert(fileList, {name = name, isDir = isDir, size = size})
table.insert(fileTable, file)
end
if unicode.wlen(file) > maxLength then
maxLength = unicode.wlen(file)
end
end end
table.sort(dirTable) -- directories first
table.sort(fileTable) -- then files
files = {} table.sort(fileList, function(a, b)
for _, v in ipairs(dirTable) do if a.isDir ~= b.isDir then return a.isDir end
table.insert(files, v) return a.name < b.name
end)
local maxSizeLen = 0
for _, item in ipairs(fileList) do
maxSizeLen = math.max(maxSizeLen, #formatSize(item.size, item.isDir))
end end
for _, v in ipairs(fileTable) do
table.insert(files, v) terminal.write(path.."\n")
end for _, item in ipairs(fileList) do
dirTable, fileTable = nil, nil local sizeStr = formatSize(item.size, item.isDir)
for _, file in ipairs(files) do sizeStr = string.rep(" ", maxSizeLen - #sizeStr) .. sizeStr
local dir = false local color = getFileColor(item.name, item.isDir)
local filetext terminal.write(string.format("%s %s%s\27[0m\n", sizeStr, color, item.name))
if file:sub(-1, -1) == "/" then
dir = true
filetext = "\27[93m"..file:sub(1, -2)
elseif file:find(".") and file:match("[^.]+$") == "lua" then
filetext = "\27[92m"..file
end
filetext = (filetext or file)..string.rep(" ", maxLength - unicode.wlen(file) + margin)
if dir then
print(filetext.." \27[0m[DIR]")
else
local size = fs.size(fs.concat(target, file))
local sizeString
if convert(size, "B", "GiB") >= 1 then
sizeString = tostring(math.floor(convert(size, "B", "GiB") * 100 + 0.5) / 100).." GiB"
elseif convert(size, "B", "MiB") >= 1 then
sizeString = tostring(math.floor(convert(size, "B", "MiB") * 100 + 0.5) / 100).." MiB"
elseif convert(size, "B", "KiB") >= 1 then
sizeString = tostring(math.floor(convert(size, "B", "KiB") * 100 + 0.5) / 100).." KiB"
else
sizeString = tostring(size).." B"
end
print(filetext.."\27[0m"..sizeString)
end
end end
::continue::
end end
+4 -4
View File
@@ -77,7 +77,7 @@ elseif outArgIdx then
if headers[word] then if headers[word] then
addHeader(word) addHeader(word)
else else
print("\x1b[93mCategory \""..word.."\" doesn't exist\x1b[39m") print("\x1b[93mCategory \""..word.."\" doesn't exist\x1b[0m")
end end
end end
end end
@@ -190,7 +190,7 @@ local function handleComponent(id,type)
if proxy.getLabel then if proxy.getLabel then
local clabel = proxy.getLabel() local clabel = proxy.getLabel()
label=clabel and serialize.string(clabel) or "None" label=clabel and serialize(clabel) or "None"
else else
label="Unsupported" label="Unsupported"
end end
@@ -266,7 +266,7 @@ if not showAll then
if func then if func then
filter(comps,func) filter(comps,func)
else else
return print("\x1b[91mInvalid component filter:\n\n"..tostring(err).."\x1b[39m") return print("\x1b[91mInvalid component filter:\n\n"..tostring(err).."\x1b[0m")
end end
else else
filter(comps,function(comp) filter(comps,function(comp)
@@ -286,7 +286,7 @@ if sortArgIdx then
return (boolToNum(func(a)) or 0)<(boolToNum(func(b)) or 0) return (boolToNum(func(a)) or 0)<(boolToNum(func(b)) or 0)
end) end)
else else
return print("\x1b[91mInvalid sort expression:\n\n"..tostring(err).."\x1b[39m") return print("\x1b[91mInvalid sort expression:\n\n"..tostring(err).."\x1b[0m")
end end
else else
table.sort(comps,function(a,b) table.sort(comps,function(a,b)
+11 -8
View File
@@ -12,15 +12,18 @@ for _, lib in pairs(libList) do
local name = lib:match("(.+)%.lua") local name = lib:match("(.+)%.lua")
_G[name] = require(name) _G[name] = require(name)
end end
end, debug.traceback) end, function(errMsg)
return errMsg .. "\n\n" .. debug.traceback()
end)
if not status then if not status then
local firstLine = tostring(err):match("^[^\n]*")
print( print(
string.format( string.format(
"\x1b[91mLibrary %s has failed loading:\n │ %s", "\x1b[91mLibrary %s has failed loading:\n │ %s\x1b[0m",
lib:match("(.+)%.lua"), lib:match("(.+)%.lua") or lib,
tostring(err or "unknown error"):match("^(.-)\n") firstLine or "unknown error"
) )
) -- TODO: only show first line of error )
log.lua.error( log.lua.error(
string.format( string.format(
'The library located at "%s" has failed loading:\n%s', 'The library located at "%s" has failed loading:\n%s',
@@ -35,7 +38,7 @@ end
if failed then if failed then
print( print(
string.format( string.format(
'\x1b[93mOne or more libraries failed to load. For more information, check the log entries located at "%s".', '\x1b[93mOne or more libraries failed to load. For more information, check the log entries located at "%s".\x1b[0m',
tostring(log.lua.logpath or "[unknown]") tostring(log.lua.logpath or "[unknown]")
) )
) )
@@ -59,7 +62,7 @@ while true do
returns = false returns = false
end end
if not func then if not func then
return print("\x1b[91msyntax error: " .. (err or "unknown error")) return print("\x1b[91msyntax error: " .. (err or "unknown error") .. "\x1b[0m")
end end
local res = { func() } local res = { func() }
if returns then if returns then
@@ -74,7 +77,7 @@ while true do
return errMsg .. "\n\n" .. debug.traceback() return errMsg .. "\n\n" .. debug.traceback()
end) end)
if not result then if not result then
print("\27[91m" .. reason) print("\27[91m" .. reason .. "\27[0m")
end end
end end
end end
+1 -1
View File
@@ -3,7 +3,7 @@
local computer = require("computer") local computer = require("computer")
if type(computer)~="table" then if type(computer)~="table" then
return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[39m") return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[0m")
end end
local address = computer.getBootAddress() local address = computer.getBootAddress()
+19 -10
View File
@@ -1,14 +1,23 @@
local directory = ...
local fs = require("filesystem") local fs = require("filesystem")
local shell = require("shell")
if not directory then local args = {...}
require("shell").run("help mkdir")
return if not args[1] then
return shell.run("help mkdir")
end end
if directory:sub(1, 1) ~= "/" then
directory = fs.concat(require("shell").getWorkingDirectory(), directory) for _, directory in pairs(args) do
directory = shell.resolvePath(directory)
if fs.exists(directory) then
terminal.write("\27[91mError: " .. directory ..": An object already exists\27[0m\n")
goto continue
end
local what, err = fs.makeDirectory(directory)
if err ~= nil then
terminal.write("\27[91mError: " .. err .. "\27[0m\n")
goto continue
end
::continue::
end end
if fs.exists(directory) then
print("\27[91mAn object already exists at the specified path.")
end
fs.makeDirectory(directory)
+65 -20
View File
@@ -1,25 +1,70 @@
local fromFile, toFile = ...
local shell = require("shell")
local fs = require("filesystem") local fs = require("filesystem")
local shell = require("shell")
if not fromFile or not toFile then local args = {...}
shell.run("help mv")
if not args[1] then
return shell.run("help mv")
end
if not args[2] then
terminal.write("\27[91mError: No destination\27[0m\n")
return return
end end
if fromFile:sub(1, 1) ~= "/" then
fromFile = fs.concat(shell.getWorkingDirectory(), fromFile) local dest = shell.resolvePath(args[#args])
if fs.isFile(dest) then
if #args ~= 2 then
terminal.write("\27[91mError: Destination is not a directory\27[0m\n")
return
end
local src = shell.resolvePath(args[1])
if not fs.exists(src) then
terminal.write("\27[91mError: " .. src .. ": No such file or directory\27[0m\n")
return
end
if fs.isDirectory(src) then
terminal.write("\27[91mError: Cannot write directory " .. src .. " to file " .. dest .. "\27[0m\n")
return
end
fs.rename(src, dest)
elseif fs.isDirectory(dest) then
for i = 1, #args - 1 do
local src = shell.resolvePath(args[i])
if src == dest then
terminal.write("\27[91mError: Source and destination are the same\27[0m\n")
goto continue
end
if not fs.exists(src) then
terminal.write("\27[91mError: " .. src .. ": No such file or directory\27[0m\n")
goto continue
end
fs.rename(src, fs.concat(dest, fs.basename(src)))
::continue::
end
elseif not fs.exists(dest) then
if #args ~= 2 then
terminal.write("\27[91mError: " .. dest .. ": No such file or directory\27[0m\n")
return
end
local src = shell.resolvePath(args[1])
if not fs.exists(src) then
terminal.write("\27[91mError: " .. src .. ": No such file or directory\27[0m\n")
return
end
local destp = fs.parent(dest)
if not fs.exists(destp) then
terminal.write("\27[91mError: " .. destp .. ": No such file or directory\27[0m\n")
return
end
if not fs.isDirectory(destp) then
terminal.write("\27[91mError: " .. destp .. ": Not a directory\27[0m\n")
return
end
fs.rename(src, dest)
else
terminal.write("\27[91mUnknown error\27[0m\n")
end end
if toFile:sub(1, 1) ~= "/" then
toFile = fs.concat(shell.getWorkingDirectory(), toFile)
end
if fromFile == toFile then
print("\27[91mSource and destination are the same.")
end
if not fs.exists(fromFile) then
print("\27[91mSource file does not exist.")
end
if fs.exists(toFile) and not (table.find({...}, "-o") or table.find({...}, "--overwrite")) then
print("\27[91mDestination file already exists. Run this command again with -o to overwrite it.")
return
end
fs.rename(fromFile, toFile)
+15 -15
View File
@@ -9,7 +9,7 @@ local curX, curY = gpu.getResolution()
local function setRes() local function setRes()
if not(args[1] == "-x" or args[1] == "-y") then if not(args[1] == "-x" or args[1] == "-y") then
print("\x1b[91mUnknown argument. \x1b[39mTry running \x1b[92m\"help res\"") print("\x1b[91mUnknown argument. \x1b[0mTry running \x1b[92m\"help res\"\x1b[0m")
return return
end end
@@ -21,7 +21,7 @@ local function setRes()
x = tonumber(args[i + 1]) x = tonumber(args[i + 1])
lastarg = "x" lastarg = "x"
else else
print("\x1b[91mValue \"x\" was set more than once. \x1b[39mTry running \x1b[92m\"help res\"") print("\x1b[91mValue \"x\" was set more than once. \x1b[0mTry running \x1b[92m\"help res\"\x1b[0m")
return return
end end
elseif args[i] == "-y" then elseif args[i] == "-y" then
@@ -29,7 +29,7 @@ local function setRes()
y = tonumber(args[i + 1]) y = tonumber(args[i + 1])
lastarg = "y" lastarg = "y"
else else
print("\x1b[91mValue \"y\" was set more than once. \x1b[39mTry running \x1b[92m\"help res\"") print("\x1b[91mValue \"y\" was set more than once. \x1b[0mTry running \x1b[92m\"help res\"\x1b[0m")
return return
end end
end end
@@ -37,42 +37,42 @@ local function setRes()
if x then if x then
if x > maxX then if x > maxX then
print("\x1b[91mGPU does not support x higher than " .. maxX) print("\x1b[91mGPU does not support x higher than " .. maxX .. "\x1b[0m.")
return return
end end
end end
if y then if y then
if y > maxY then if y > maxY then
print("\x1b[91mGPU does not support y higher than " .. maxY) print("\x1b[91mGPU does not support y higher than " .. maxY .. "\x1b[0m.")
return return
end end
end end
if x and not(y) then if x and not(y) then
gpu.setResolution(x, curY) gpu.setResolution(x, curY)
print("Successfully set X resolution from \x1b[93m" .. curX .. "\x1b[39m to \x1b[92m" .. x .. "\x1b[39m.") print("Successfully set X resolution from \x1b[93m" .. curX .. "\x1b[0m to \x1b[92m" .. x .. "\x1b[0m.")
return return
elseif not(x) and y then elseif not(x) and y then
gpu.setResolution(curX, y) gpu.setResolution(curX, y)
print("Successfully set Y resolution from \x1b[93m" .. curY .. "\x1b[39m to \x1b[92m" .. y .. "\x1b[39m.") print("Successfully set Y resolution from \x1b[93m" .. curY .. "\x1b[0m to \x1b[92m" .. y .. "\x1b[0m.")
return return
else else
gpu.setResolution(x, y) gpu.setResolution(x, y)
print("Successfully set resolution from \x1b[93m" .. curX .. "x" .. curY .. "\x1b[39m to \x1b[92m" .. x .. "x" .. y .. "\x1b[39m.") print("Successfully set resolution from \x1b[93m" .. curX .. "x" .. curY .. "\x1b[0m to \x1b[92m" .. x .. "x" .. y .. "\x1b[0m.")
return return
end end
end end
local function getRes(val) local function getRes(val)
if val == "x" then if val == "x" then
print("Current X resolution: \x1b[93m" .. curX) print("Current X resolution: \x1b[93m" .. curX .. "\x1b[0m")
print("Maximum supported X resolution: \x1b[92m" .. maxX) print("Maximum supported X resolution: \x1b[92m" .. maxX .. "\x1b[0m")
elseif val == "y" then elseif val == "y" then
print("Current Y resolution: \x1b[93m" .. curY) print("Current Y resolution: \x1b[93m" .. curY .. "\x1b[0m")
print("Maximum supported Y resolution: \x1b[92m" .. maxY) print("Maximum supported Y resolution: \x1b[92m" .. maxY .. "\x1b[0m")
else else
print("Current resolution: \x1b[93m" .. curX .. "x" .. curY) print("Current resolution: \x1b[93m" .. curX .. "x" .. curY .. "\x1b[0m")
print("Maximum supported resolution: \x1b[92m" .. maxX .. "x" .. maxY) print("Maximum supported resolution: \x1b[92m" .. maxX .. "x" .. maxY .. "\x1b[0m")
end end
end end
@@ -92,5 +92,5 @@ if axis == "-x" then
elseif axis == "-y" then elseif axis == "-y" then
getRes("y") getRes("y")
else else
print("\x1b[91mUnknown argument. \x1b[39mTry running \x1b[92m\"help res\"") print("\x1b[91mUnknown argument. \x1b[0mTry running \x1b[92m\"help res\"\x1b[0m")
end end
+13 -12
View File
@@ -1,16 +1,17 @@
local file = ...
local shell = require("shell")
local fs = require("filesystem") local fs = require("filesystem")
local shell = require("shell")
if not file then local args = {...}
shell.run("help rm")
return if not args[1] then
return shell.run("help rm")
end end
if file:sub(1, 1) ~= "/" then
file = fs.concat(shell.getWorkingDirectory(), file) for _, file in pairs(args) do
file = shell.resolvePath(file)
local result = fs.remove(file)
if result == false then
terminal.write("\27[91mError: cannot delete " .. file .. "\27[0m\n")
end
end end
if not fs.exists(file) then
print("\27[91mFile does not exist.")
return
end
fs.remove(file)
+1 -1
View File
@@ -88,4 +88,4 @@ end
end ]] end ]]
raster.free() raster.free()
terminal.setCursorPos(1,1) terminal.clear()
+12 -17
View File
@@ -1,28 +1,23 @@
-- TODO: Rename this to something else (while making an alias from the original command). -- TODO: Rename this to something else (while making an alias from the original command).
-- Touch seems kind of a silly name for a command to make a file. -- Touch seems kind of a silly name for a command to make a file.
-- Maybe something like mkfile would be better? -- Maybe something like mkfile would be better?
local cliparse = require("cliparse")
cliparse.config({
["o"] = 0,
["overwrite"] = 0,
})
local parsed = cliparse.parse(...)
local file = parsed.args[1]
local fs = require("filesystem") local fs = require("filesystem")
local shell = require("shell") local shell = require("shell")
if not file then local args = {...}
if not args[1] then
return shell.run("help touch") return shell.run("help touch")
end end
if file:sub(1, 1) ~= "/" then for _, file in pairs(args) do
file = fs.concat(shell.getWorkingDirectory(), file) file = shell.resolvePath(file)
end
if fs.exists(file) and not (parsed.flags.o or parsed.flags.overwrite) then local handle, err = fs.open(file, "a")
return print("\x1b[91mFile already exists.\n│ To empty file contents, use -o.") if err ~= nil then
terminal.write("\27[91mError: " .. err .. "\27[0m\n")
goto continue
end
handle:close()
::continue::
end end
local handle = fs.open(file, "w")
handle:write("") -- just in case
handle:close()
+407 -164
View File
@@ -1,3 +1,10 @@
--[[
TODO:
```bash
echo -e "\033[?25l" # hide
echo -e "\033[?25h" # show
```
]]
local module = {} local module = {}
function module.check() function module.check()
@@ -9,23 +16,11 @@ function module.init()
local unicode = require("unicode") local unicode = require("unicode")
local event = require("event") local event = require("event")
--local ocelot = component.proxy(component.list("ocelot")())
local component = require("component") local component = require("component")
local computer = require("computer") local computer = require("computer")
local gpu = component.gpu local gpu = component.gpu
_G._PUBLIC.terminal = {} _G._PUBLIC.terminal = {}
local cursorPosX = 1
local cursorPosY = 1
local width, height = gpu.getResolution()
function _PUBLIC.terminal.getCursorPos()
return cursorPosX,cursorPosY
end
function _PUBLIC.terminal.setCursorPos(x,y)
checkArg(1,x,"number","nil")
checkArg(2,y,"number","nil")
if type(x)~=nil then cursorPosX=math.min(math.max(x,1),width) end
if type(y)~=nil then cursorPosY=math.min(math.max(y,1),height) end
end
local readHistory = {} local readHistory = {}
function _PUBLIC.terminal.getHistory(id) function _PUBLIC.terminal.getHistory(id)
checkArg(1,id,"string") checkArg(1,id,"string")
@@ -46,6 +41,28 @@ function module.init()
end end
local ANSIColorPalette = { local ANSIColorPalette = {
["dark"] = {
[0] = 0x171421,
[1] = 0xc01c28,
[2] = 0x26a269,
[3] = 0xa2734c,
[4] = 0x12488b,
[5] = 0xa347ba,
[6] = 0x2aa1b3,
[7] = 0xd0cfcc
},
["bright"] = {
[0] = 0x5e5c64,
[1] = 0xf66151,
[2] = 0x33d17a,
[3] = 0xe9ad0c,
[4] = 0x2a7bde,
[5] = 0xc061cb,
[6] = 0x33c7de,
[7] = 0xffffff
}
}
--[[local ANSIColorPalette = {
["dark"] = { ["dark"] = {
[0] = 0x000000, [0] = 0x000000,
[1] = 0x800000, [1] = 0x800000,
@@ -66,172 +83,405 @@ function module.init()
[6] = 0x00FFFF, [6] = 0x00FFFF,
[7] = 0xFFFFFF [7] = 0xFFFFFF
} }
}]]
local expecting_unicode_bytes = 0
local unicode_bytes_left = 0
local unicode_codepoint = 0
local cursor = { x = 1, y = 1, X = nil, Y = nil } -- X and Y are managed by ESC s and ESC u
local printState = 0 -- 0:none 1:in ESC 2:in CSI
local color = {
FG = ANSIColorPalette["bright"][7], BG = ANSIColorPalette["dark"][0],
fg = nil, bg = nil, reverse = false
} }
color.fg = color.FG
color.bg = color.BG
local current_codepoint = 0
local bytes_remaining = 0
local seq = {}
defaultForegroundColor = ANSIColorPalette["bright"][7] local function update_gpu_colors()
defaultBackgroundColor = ANSIColorPalette["dark"][0] if color.reverse then
gpu.setForeground(color.bg)
gpu.setBackground(color.fg)
else
gpu.setForeground(color.fg)
gpu.setBackground(color.bg)
end
end
gpu.setForeground(defaultForegroundColor) local width, height = gpu.getResolution()
gpu.setBackground(defaultBackgroundColor)
local function scrollDown() function _G._PUBLIC.terminal.getResolution()
if gpu.copy(1,1,width,height,0,-1) then return width, height
local prevForeground = gpu.getForeground() end
local prevBackground = gpu.getBackground()
gpu.setForeground(defaultForegroundColor) gpu.setForeground(color.fg)
gpu.setBackground(defaultBackgroundColor) gpu.setBackground(color.bg)
local function scroll()
if gpu.copy(1, 2, width, height - 1, 0, -1) then
gpu.setForeground(color.FG)
gpu.setBackground(color.BG)
gpu.fill(1, height, width, 1, " ") gpu.fill(1, height, width, 1, " ")
gpu.setForeground(prevForeground) gpu.setForeground(color.fg)
gpu.setBackground(prevBackground) gpu.setBackground(color.bg)
cursorPosY=height cursor.y = height
end end
end end
local function newLine() local function check_wrap_and_scroll()
cursorPosX=1 if cursor.x > width then
cursorPosY = cursorPosY + 1 cursor.x = 1
if cursorPosY>height then cursor.y = cursor.y + 1
scrollDown() end
while cursor.y > height do
scroll()
end end
end end
local function parseCodeNumbers(code) local function exec_csi()
local o = {} local params = {}
for num in code:sub(3,-2):gmatch("[^;]+") do local op = 0
table.insert(o,tonumber(num)) local current_num = 0
end local have_num = false
return o
end
local function from8BitColor(num) for i = 1, #seq do
num=math.floor(num)&255 local byte = seq[i]
if num<16 then return 0x444444*((num>>3)&1)+(0xBB0000*((num>>2)&1)|0x00BB00*((num>>1)&1)|0x0000BB*(num&1)) end
if num>=232 then return 0x10101*(8+(num-232)*10) end
num=num-16
local palette = {0,95,135,175,215,255}
return (palette[(num//36)%6+1]<<16)|(palette[(num//6)%6+1]<<8)|palette[num%6+1]
end
local function from24BitColor(r,g,b) if 0x30 <= byte and byte <= 0x39 then
r,g,b=math.floor(r)&255,math.floor(g)&255,math.floor(b)&255 current_num = current_num * 10 + (byte - 0x30)
return (r<<16)|(g<<8)|b have_num = true
end elseif byte == 0x3b then
table.insert(params, have_num and current_num or 0)
local function findCodeEnd(text,i) current_num = 0
local function inRange(v,min,max) have_num = false
return v>=min and v<=max else
end if have_num then
i=i+2 table.insert(params, current_num)
while i<=#text and not inRange(text:byte(i),0x40,0x7F) do i=i+1 end end
return i if 0x40 <= byte and byte <= 0x7e then
end op = byte
end
function _PUBLIC.terminal.write(text, textWrap) break
-- you don't know how tiring this was just for ANSI escape code support end
if textWrap == nil then
textWrap = true
end end
if not text or not tostring(text) then local function get_param(idx, default)
if idx <= #params and params[idx] ~= nil then
return params[idx]
end
return default
end
if op == 0x48 or op == 0x66 then
local row = get_param(1, 1)
local col = get_param(2, 1)
cursor.y = row
cursor.x = col
if cursor.x < 1 then cursor.x = 1 end
if cursor.y < 1 then cursor.y = 1 end
if cursor.x > width then cursor.x = width end
if cursor.y > height then cursor.y = height end
return return
end end
if text:find("\a") then
computer.beep()
end
text = tostring(text)
text = "\27[0m" .. text:gsub("\t", " ")
local readBreak = 0
-- readBreak is for when, inside the for loop, there normally would have been an increase in the "i" variable because it has read more than one character.
-- unfortunately, changing the "i" variable would have unpredictable effects, so to not risk anything, this workaround was done.
local section = ""
local function printSection() if op == 0x41 then
if #section==0 then local n = get_param(1, 1)
cursor.y = cursor.y - n
if cursor.y < 1 then cursor.y = 1 end
return
end
if op == 0x42 then
local n = get_param(1, 1)
cursor.y = cursor.y + n
if cursor.y > height then cursor.y = height end
return
end
if op == 0x43 then
local n = get_param(1, 1)
cursor.x = cursor.x + n
if cursor.x > width then cursor.x = width end
return
end
if op == 0x44 then
local n = get_param(1, 1)
cursor.x = cursor.x - n
if cursor.x < 1 then cursor.x = 1 end
return
end
if op == 0x47 then
local col = get_param(1, 1)
cursor.x = col
if cursor.x < 1 then cursor.x = 1 end
if cursor.x > width then cursor.x = width end
return
end
if op == 0x4a then
local mode = get_param(1, 0)
if mode == 0 then
update_gpu_colors()
gpu.fill(cursor.x, cursor.y, width - cursor.x + 1, height - cursor.y + 1, " ")
elseif mode == 1 then
update_gpu_colors()
gpu.fill(1, 1, cursor.x, cursor.y, " ")
elseif mode == 2 then
update_gpu_colors()
gpu.fill(1, 1, width, height, " ")
cursor.x = 1
cursor.y = 1
end
return
end
if op == 0x4b then
local mode = get_param(1, 0)
if mode == 0 then
update_gpu_colors()
gpu.fill(cursor.x, cursor.y, width - cursor.x + 1, 1, " ")
elseif mode == 1 then
update_gpu_colors()
gpu.fill(1, cursor.y, cursor.x, 1, " ")
elseif mode == 2 then
update_gpu_colors()
gpu.fill(1, cursor.y, width, 1, " ")
end
return
end
if op == 0x60 then
local col = get_param(1, 1)
cursor.x = col
if cursor.x < 1 then cursor.x = 1 end
if cursor.x > width then cursor.x = width end
return
end
if op == 0x64 then
local row = get_param(1, 1)
cursor.y = row
if cursor.y < 1 then cursor.y = 1 end
if cursor.y > height then cursor.y = height end
return
end
if op == 0x6d then
local j = 1
local function parse_extended_color()
local mode = get_param(j + 1, -1)
if mode == 5 then
local idx = get_param(j + 2, 0)
j = j + 2
if idx < 8 then
return ANSIColorPalette["dark"][idx]
elseif idx < 16 then
return ANSIColorPalette["bright"][idx - 8]
elseif idx < 232 then
local i = idx - 16
local b = (i % 6) * 51
local g = ((i // 6) % 6) * 51
local r = (i // 36) * 51
return (r << 16) | (g << 8) | b
else
local v = (idx - 232) * 10 + 8
return (v << 16) | (v << 8) | v
end
elseif mode == 2 then
local r = get_param(j + 2, 0)
local g = get_param(j + 3, 0)
local b = get_param(j + 4, 0)
j = j + 4
return (r << 16) | (g << 8) | b
end
return nil
end
if #params == 0 then
color.reverse = false
color.fg = color.FG
color.bg = color.BG
update_gpu_colors()
return return
end end
while true do
gpu.set(cursorPosX,cursorPosY,section) while j <= #params do
if unicode.wlen(section) > width - cursorPosX + 1 and textWrap then local p = params[j] or 0
section = section:sub(width - cursorPosX + 2)
newLine() if p == 0 then
else color.reverse = false
cursorPosX = cursorPosX+unicode.wlen(section) color.fg = color.FG
break color.bg = color.BG
elseif p == 1 then
elseif p == 2 then
elseif p == 3 then
elseif p == 4 then
elseif p == 5 or p == 6 then
elseif p == 7 then
color.reverse = true
elseif p == 8 then
color.fg = color.bg
elseif p == 9 then
elseif p == 21 then
elseif p == 22 then
elseif p == 23 then
elseif p == 24 then
elseif p == 25 then
elseif p == 27 then
color.reverse = false
elseif p == 28 then
color.fg = color.FG
elseif p == 29 then
elseif 30 <= p and p <= 37 then
color.fg = ANSIColorPalette["dark"][p - 30]
elseif p == 38 then
local c = parse_extended_color()
if c then color.fg = c end
elseif p == 39 then
color.fg = color.FG
elseif 40 <= p and p <= 47 then
color.bg = ANSIColorPalette["dark"][p - 40]
elseif p == 48 then
local c = parse_extended_color()
if c then color.bg = c end
elseif p == 49 then
color.bg = color.BG
elseif p == 58 then
parse_extended_color()
elseif p == 59 then
elseif 90 <= p and p <= 97 then
color.fg = ANSIColorPalette["bright"][p - 90]
elseif 100 <= p and p <= 107 then
color.bg = ANSIColorPalette["bright"][p - 100]
end end
j = j + 1
end end
section = "" update_gpu_colors()
return
end end
for i=1,#text do if op == 0x73 then
if readBreak>0 then cursor.X = cursor.x
readBreak = readBreak - 1 cursor.Y = cursor.y
goto continue return
end end
if string.byte(text,i)==10 then if op == 0x75 then
printSection() if cursor.X and cursor.Y then
newLine() cursor.x = cursor.X
elseif string.byte(text,i)==13 then cursor.y = cursor.Y
printSection() if cursor.x < 1 then cursor.x = 1 end
cursorPosX=1 if cursor.y < 1 then cursor.y = 1 end
elseif string.byte(text,i)==0x1b and i<=#text-2 then if cursor.x > width then cursor.x = width end
printSection() if cursor.y > height then cursor.y = height end
--ocelot.log("0x1b char detected") end
local codeType = string.sub(text,i+1,i+1) return
if codeType=="[" then end
-- Control Sequence Introducer end
--ocelot.log("Control Sequence Introducer")
local codeEndIdx = findCodeEnd(text,i) function _G._PUBLIC.terminal.writec(byte)
-- codeEndIdx = string.find(text,"m",i) if byte == 0x1b then
local code = string.sub(text,i,codeEndIdx) printState = 1
--ocelot.log("Code: "..code.." ("..i..", "..codeEndIdx..")") seq = {}
readBreak = readBreak + #code - 1 return
local nums = parseCodeNumbers(code) end
local codeEnd = code:sub(-1)
--ocelot.log("Code end: "..codeEnd..", "..#codeEnd) if printState == 1 then
if codeEnd == "m" then if byte == 0x5b then
-- Select Graphic Rendition printState = 2
--ocelot.log("Select Graphic Rendition, ID "..nums[1])
if nums[1]>=30 and nums[1]<=37 then
gpu.setForeground(ANSIColorPalette["dark"][nums[1]%10])
end
if nums[1]==38 and nums[2]==5 then
gpu.setForeground(from8BitColor(nums[3]))
end
if nums[1]==38 and nums[2]==2 then
gpu.setForeground(from24BitColor(nums[3],nums[4],nums[5]))
end
if nums[1]==39 or nums[1]==0 then
gpu.setForeground(defaultForegroundColor)
end
if nums[1]>=40 and nums[1]<=47 then
gpu.setBackground(ANSIColorPalette["dark"][nums[1]%10])
end
if nums[1]==48 and nums[2]==5 then
gpu.setBackground(from8BitColor(nums[3]))
end
if nums[1]==48 and nums[2]==2 then
gpu.setBackground(from24BitColor(nums[3],nums[4],nums[5]))
end
if nums[1]==49 or nums[1]==0 then
gpu.setBackground(defaultBackgroundColor)
end
if nums[1]>=90 and nums[1]<=97 then
gpu.setForeground(ANSIColorPalette["bright"][nums[1]%10])
end
if nums[1]>=100 and nums[1]<=107 then
gpu.setBackground(ANSIColorPalette["bright"][nums[1]%10])
end
end
end
else else
--gpu.set(cursorPosX,cursorPosY,string.sub(text,i,i)) printState = 0
section = section..string.sub(text,i,i)
end end
::continue:: return
end end
printSection()
if printState == 2 then
table.insert(seq, byte)
if 0x40 <= byte and byte <= 0x7e then
exec_csi()
printState = 0
seq = {}
end
return
end
if byte == 0xa then
cursor.y = cursor.y + 1
cursor.x = 1
check_wrap_and_scroll()
return
end
if byte == 0xd then
cursor.x = 1
return
end
if byte == 0x8 then
if cursor.x > 1 then
cursor.x = cursor.x - 1
end
return
end
if byte == 0x9 then
cursor.x = ((cursor.x - 1) // 8) * 8 + 9
if cursor.x < 1 then cursor.x = 1 end
if cursor.x > width then cursor.x = width end
return
end
if byte >= 0x00 and byte <= 0x7F then
update_gpu_colors()
gpu.set(cursor.x, cursor.y, string.char(byte))
cursor.x = cursor.x + 1
check_wrap_and_scroll()
elseif byte >= 0xC2 and byte <= 0xDF then
current_codepoint = (byte & 0x1F)
bytes_remaining = 1
elseif byte >= 0xE0 and byte <= 0xEF then
current_codepoint = (byte & 0x0F)
bytes_remaining = 2
elseif byte >= 0xF0 and byte <= 0xF7 then
current_codepoint = (byte & 0x07)
bytes_remaining = 3
elseif byte >= 0x80 and byte <= 0xBF and bytes_remaining > 0 then
current_codepoint = (current_codepoint << 6) | (byte & 0x3F)
bytes_remaining = bytes_remaining - 1
if bytes_remaining == 0 then
local char = utf8.char(current_codepoint)
update_gpu_colors()
gpu.set(cursor.x, cursor.y, char)
cursor.x = cursor.x + 1
check_wrap_and_scroll()
current_codepoint = 0
end
else
current_codepoint = 0
bytes_remaining = 0
end
end
function _G._PUBLIC.terminal.write(text)
text = tostring(text)
for i = 1, #text do
_PUBLIC.terminal.writec(string.byte(text, i))
end
end
function _G._PUBLIC.terminal.clear()
update_gpu_colors()
gpu.fill(1, 1, width, height, " ")
cursor.x = 1
cursor.y = 1
end end
function _G.print(...) function _G.print(...)
@@ -239,19 +489,12 @@ function module.init()
local stringArgs = {} local stringArgs = {}
for _, arg in pairs(args) do for _, arg in pairs(args) do
if type(arg)=="table" then if type(arg)=="table" then
table.insert(stringArgs, serialize.table(arg,true)) table.insert(stringArgs, serialize(arg))
elseif tostring(arg) then elseif tostring(arg) then
table.insert(stringArgs, tostring(arg)) table.insert(stringArgs, tostring(arg))
end end
end end
_PUBLIC.terminal.write(table.concat(stringArgs, " ") .. "\n") _PUBLIC.terminal.write(table.concat(stringArgs, "\t") .. "\n")
end
function _G._PUBLIC.terminal.clear()
gpu.setForeground(defaultForegroundColor)
gpu.setBackground(defaultBackgroundColor)
gpu.fill(1,1,width,height," ")
cursorPosX, cursorPosY = 1, 1
end end
function _G._PUBLIC.terminal.read(options) function _G._PUBLIC.terminal.read(options)
@@ -289,7 +532,7 @@ function module.init()
local cur = unicode.len(text)+1 local cur = unicode.len(text)+1
if options.prefix then _PUBLIC.terminal.write(options.prefix) end if options.prefix then _PUBLIC.terminal.write(options.prefix) end
local startX, startY = cursorPosX, cursorPosY local startX, startY = cursor.x, cursor.y
local fg, bg = gpu.getForeground(), gpu.getBackground() local fg, bg = gpu.getForeground(), gpu.getBackground()
local cursorBlink = true local cursorBlink = true
local function checkScroll(y) local function checkScroll(y)
@@ -482,9 +725,9 @@ function module.init()
end end
end end
cursorPosX=1 cursor.x=1
cursorPosY=cursorPosY+math.ceil((unicode.wlen(text)+startX-1)/width) cursor.y=cursor.y+math.ceil((unicode.wlen(text)+startX-1)/width)
if cursorPosY>height then scrollDown() end if cursor.y>height then scroll() end
return text return text
end end
+1 -1
View File
@@ -42,7 +42,7 @@ function module.init()
if type(tsched.currentTask) == "table" and type(tsched.currentTask.id) == "number" then if type(tsched.currentTask) == "table" and type(tsched.currentTask.id) == "number" then
taskInfo.parent = tsched.currentTask.id taskInfo.parent = tsched.currentTask.id
else else
log.kernel.info("debug: tsched.currentTask is " .. require("serialize").table(tsched.currentTask)) log.kernel.info("debug: tsched.currentTask is " .. require("serialize")(tsched.currentTask))
end end
table.insert(tsched.tasks, taskInfo) table.insert(tsched.tasks, taskInfo)
if taskInfo.parent then if taskInfo.parent then
+5
View File
@@ -22,6 +22,11 @@ function _G.shell.getWorkingDirectory()
return workingDirectory return workingDirectory
end end
function _G.shell.resolvePath(path)
if path:sub(1, 1) == "/" then return path end
return fs.concat(workingDirectory, path)
end
function _G.shell.setWorkingDirectory(dir) function _G.shell.setWorkingDirectory(dir)
checkArg(1, dir, "string") checkArg(1, dir, "string")
workingDirectory = dir workingDirectory = dir
+22 -19
View File
@@ -32,6 +32,11 @@ function filesystem.canonical(path)
return "/" .. table.concat(segList, "/") return "/" .. table.concat(segList, "/")
end end
function filesystem.basename(path)
checkArg(1, path, "string")
return path:match("/([^/]+)/?$") or ""
end
function filesystem.concat(path1, path2) function filesystem.concat(path1, path2)
checkArg(1, path1, "string") checkArg(1, path1, "string")
checkArg(2, path2, "string") checkArg(2, path2, "string")
@@ -67,6 +72,13 @@ function filesystem.absolutePath(path) -- returns the address and absolute path
return address, path return address, path
end end
function filesystem.parent(path)
checkArg(1, path, "string")
local p = filesystem.canonical(path)
-- return "/" on "/"
return p == "/" and "/" or (p:match("^(.*)/[^/]+/?$") or "/")
end
function filesystem.exists(path) -- check if path exists function filesystem.exists(path) -- check if path exists
checkArg(1, path, "string") checkArg(1, path, "string")
local address, absPath = filesystem.absolutePath(path) local address, absPath = filesystem.absolutePath(path)
@@ -475,14 +487,12 @@ local function copyContent(fromHandle, toHandle)
if not (fromHandle and toHandle) then if not (fromHandle and toHandle) then
return return
end end
local memory = math.floor(computer.freeMemory() * 0.8)
local tmpdata
while true do while true do
tmpdata = fromHandle:read(memory) local tmpdata = fromHandle.read(2048)
if not tmpdata then if not tmpdata then
break break
end end
local status, reason = toHandle:write(tmpdata) local status, reason = toHandle.write(tmpdata)
if status ~= true then if status ~= true then
break break
end end
@@ -492,7 +502,6 @@ local function copyContent(fromHandle, toHandle)
end end
local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath) local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
-- TODO: make this use copyContent
if fromAbsPath:sub(-1) == "/" then if fromAbsPath:sub(-1) == "/" then
fromAbsPath = fromAbsPath:sub(1, -2) fromAbsPath = fromAbsPath:sub(1, -2)
end end
@@ -506,31 +515,21 @@ local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
end end
for i = 1, #fileList do for i = 1, #fileList do
local fromFile, toFile = fromAbsPath .. "/" .. fileList[i], toAbsPath .. "/" .. fileList[i] local fromFile, toFile = fromAbsPath .. "/" .. fileList[i], toAbsPath .. "/" .. fileList[i]
--[[ local handle = component.invoke(fromAddress, "open", fromFile, "r")
local data, tmpdata = "", nil
repeat
tmpdata = component.invoke(fromAddress, "read", handle, math.huge or math.maxinteger)
data = data .. (tmpdata or "")
until not tmpdata
tmpdata = component.invoke(fromAddress, "close", handle)
local handle = component.invoke(toAddress, "open", toFile, "w")
component.invoke(toAddress, "write", handle, data)
component.invoke(toAddress, "close", handle) ]]
local fromHandle = component.invoke(fromAddress, "open", fromFile, "r") local fromHandle = component.invoke(fromAddress, "open", fromFile, "r")
local toHandle = component.invoke(toAddress, "open", toFile, "w") local toHandle = component.invoke(toAddress, "open", toFile, "w")
copyContent({ copyContent({
["read"] = function(...) ["read"] = function(...)
return component.invoke(fromAddress, "read", handle, ...) return component.invoke(fromAddress, "read", fromHandle, ...)
end, end,
["close"] = function(...) ["close"] = function(...)
return component.invoke(fromAddress, "close", handle, ...) return component.invoke(fromAddress, "close", fromHandle, ...)
end, end,
}, { }, {
["write"] = function(...) ["write"] = function(...)
return component.invoke(fromAddress, "write", handle, ...) return component.invoke(toAddress, "write", toHandle, ...)
end, end,
["close"] = function(...) ["close"] = function(...)
return component.invoke(fromAddress, "close", handle, ...) return component.invoke(toAddress, "close", toHandle, ...)
end, end,
}) })
end end
@@ -545,6 +544,10 @@ function filesystem.isDirectory(path)
return component.invoke(address, "isDirectory", absPath) return component.invoke(address, "isDirectory", absPath)
end end
function filesystem.isFile(path)
return not filesystem.isDirectory(path) and filesystem.exists(path)
end
function filesystem.rename(fromPath, toPath) function filesystem.rename(fromPath, toPath)
checkArg(1, fromPath, "string") checkArg(1, fromPath, "string")
checkArg(2, toPath, "string") checkArg(2, toPath, "string")
+43 -122
View File
@@ -1,127 +1,48 @@
local serialize = {} local function _serialize(value, indent, level, visited)
local currentIndent = indent and string.rep(indent, level) or ""
function serialize.string(str) local nextIndent = indent and string.rep(indent, level + 1) or ""
return '"'..str:gsub("[%z\1-\31\34\92\127-\159]",function(c) local sep = indent and "\n" or " "
local byte = c:byte() local t = type(value)
if byte== 7 then return "\\a" end if t == "nil" then return "nil" end
if byte== 8 then return "\\b" end if t == "string" then return string.format("%q", value) end
if byte== 9 then return "\\t" end if t == "number" then
if byte==10 then return "\\n" end if value ~= value then return "0/0" end
if byte==11 then return "\\v" end if value == math.huge then return "math.huge" end
if byte==12 then return "\\f" end if value == -math.huge then return "-math.huge" end
if byte==13 then return "\\r" end return tostring(value)
if byte==34 then return "\\\"" end end
if byte==92 then return "\\\\" end if t == "boolean" then return tostring(value) end
return string.format("\\x%02x",byte) if t == "table" then
end)..'"' if visited[value] then return "..." end
visited[value] = true
local items = {}
local arrayCount = 0
for i = 1, #value do
if value[i] ~= nil then arrayCount = i else break end
end
for i = 1, arrayCount do
table.insert(items, nextIndent .. _serialize(value[i], indent, level + 1, visited))
end
for k, v in pairs(value) do
if type(k) ~= "number" or k < 1 or k > arrayCount then
local keyStr
if type(k) == "string" and k:match("^[%a_][%w_]*$") then
keyStr = k
else
keyStr = "[" .. _serialize(k, indent, level + 1, visited) .. "]"
end
table.insert(items, nextIndent .. keyStr .. " = " .. _serialize(v, indent, level + 1, visited))
end
end
visited[value] = nil
if #items == 0 then return "{}" end
return "{" .. sep .. table.concat(items, "," .. sep) .. sep .. currentIndent .. "}"
end
return tostring(value)
end end
function serialize.table(tbl,colors,stack) function serialize(value, indent)
stack = table.copy(stack or {}) return _serialize(value, indent, 0, {})
table.insert(stack,tbl)
local keyAmount = 0
local keyNumber = true
local out = ""
local first = true
for key,val in pairs(tbl) do
if not first then out=out..",\n" end
first=false
out=out.." "
if type(key)=="string" then
if key:match("^[%a_][%w_]*$") then
out=out..key.."="
else
out=out..'['..serialize.string(key)..']='
end
else
out=out.."["..tostring(key).."]="
end
if type(key)~="number" then
keyNumber=false
end
local success,reason = pcall(function()
local valStr = ""
if type(val)=="table" then
if #stack>4 or table.find(stack,val) then
valStr="..."
else
valStr=serialize.table(val,colors,stack)
end
elseif type(val)=="string" then
local lines = {}
for line in (val.."\n"):gmatch("([^\n]*)\n") do table.insert(lines,line) end
if #lines[#lines]==0 then
lines[#lines]=nil
lines[#lines]=lines[#lines].."\n"
end
for i=1,#lines do
if i<#lines then
lines[i]=serialize.string(lines[i].."\n")
else
lines[i]=serialize.string(lines[i])
end
end
valStr=table.concat(lines," ..\n ")
else
valStr=tostring(val)
end
local lines = {}
for line in (valStr.."\n"):gmatch("([^\n]*)\n") do table.insert(lines,line) end
out=out..table.concat(lines,"\n ")
lines = nil
keyAmount=keyAmount+1
end)
if not success then
if colors then out=out.."\x1b[91m" end
out=out.."["..tostring(reason).."]"
if colors then out=out.."\x1b[39m" end
end
coroutine.yield()
end
local metatbl = getmetatable(tbl)
local metakeys = {}
local metastring = ""
if type(metatbl)=="table" then
for i,v in pairs(metatbl) do
keyNumber=false
table.insert(metakeys,i)
end
end
if #metakeys>0 then
out=out.."\n "
if colors then metastring=metastring.."\x1b[92m" end
if table.find(metakeys,"__tostring") then
metastring=metastring.."tostring: "..serialize.string(tostring(tbl)).."\n "
table.remove(metakeys,table.find(metakeys,"__tostring"))
end
metastring=metastring..table.concat(metakeys,", ")
if colors then metastring=metastring.."\x1b[39m" end
out=out..metastring
end
if keyAmount==0 then return "{"..metastring.."}" end
if keyNumber then
-- fix strings not being serialised
local vals = {}
for _,v in pairs(tbl) do
if #vals>=5 and #stack>1 then
table.insert(vals,"...")
break
end
if type(v)=="table" then
table.insert(vals,serialize.table(v,colors,stack))
elseif type(v)=="string" then
table.insert(vals,serialize.string(v))
else
table.insert(vals,tostring(v))
end
end
return "{"..table.concat(vals,", ")..(#metakeys>0 and "\n "..metastring or "").."}"
end
return "{\n"..out.."\n}"
end end
return serialize return serialize
+1 -1
View File
@@ -236,7 +236,7 @@ local function startTransaction(dbpath)
function transaction.addInfo(name,info) function transaction.addInfo(name,info)
if not info.type then info.type="package" end if not info.type then info.type="package" end
packInfo[name]=info packInfo[name]=info
-- print(require("serialize").table(packInfo)) -- print(require("serialize")(packInfo))
end end
local function getPackInfo(pack) local function getPackInfo(pack)