Make shit less ass fuck shit fuck ass shit ass bruh what is this code
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
|
||||
local agregistry = {
|
||||
["halyde"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||
["edit"] = "https://raw.githubusercontent.com/Team-Cerulean-Blue/Halyde/refs/heads/main/",
|
||||
@@ -8,7 +9,10 @@ local agregistry = {
|
||||
["hextra"] = "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/",
|
||||
["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
|
||||
|
||||
+28
-28
@@ -106,15 +106,15 @@ do
|
||||
if parsed.flags.u or parsed.flags["update-registry"] then
|
||||
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")
|
||||
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")
|
||||
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)
|
||||
check(success, "\27[91mFailed to write to registry: " .. errorMessage)
|
||||
check(success, "\27[91mFailed to write to registry: " .. errorMessage .. "\27[0m")
|
||||
handle:close()
|
||||
else
|
||||
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
|
||||
|
||||
@@ -129,16 +129,16 @@ end
|
||||
local function getServersidePackageConfig(source, package)
|
||||
local success, data = getFile(fs.concat(source, "/ag2.json"))
|
||||
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
|
||||
local success, packageConfig = pcall(function()
|
||||
return json.decode(data)
|
||||
end)
|
||||
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
|
||||
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
|
||||
return packageConfig[package]
|
||||
end
|
||||
@@ -158,7 +158,7 @@ if command == "install" then
|
||||
table.remove(otherPackages, i)
|
||||
-- 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
|
||||
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)
|
||||
i = i - 1
|
||||
goto SKIP
|
||||
@@ -170,7 +170,7 @@ if command == "install" then
|
||||
source = registry[packages[i]]
|
||||
end
|
||||
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
|
||||
goto SKIP
|
||||
end
|
||||
@@ -212,7 +212,7 @@ if command == "install" then
|
||||
goto SKIP
|
||||
end
|
||||
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)
|
||||
i = i - 1
|
||||
goto SKIP
|
||||
@@ -248,7 +248,7 @@ elseif command == "remove" then
|
||||
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)
|
||||
i = i - 1
|
||||
::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.
|
||||
else
|
||||
-- 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
|
||||
end
|
||||
end
|
||||
@@ -324,9 +324,9 @@ end
|
||||
|
||||
if command == "install" then
|
||||
if dependencyCounter == 1 then
|
||||
print("\27[93m1 dependency pulled in.")
|
||||
print("\27[93m1 dependency pulled in.\27[0m")
|
||||
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
|
||||
print("Packages that will be installed:")
|
||||
print(table.concat(packages, ", "))
|
||||
@@ -359,13 +359,13 @@ if command == "install" then
|
||||
local success, data = getFile(fs.concat(source, file))
|
||||
|
||||
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]"})
|
||||
if answer:lower() == "a" then
|
||||
print("Exiting.")
|
||||
return
|
||||
elseif answer:lower() == "s" then
|
||||
print((" \27[93mSkipped file %s."):format(file))
|
||||
print((" \27[93mSkipped file %s.\27[0m"):format(file))
|
||||
goto SKIP
|
||||
else
|
||||
goto RETRY
|
||||
@@ -373,26 +373,26 @@ if command == "install" then
|
||||
end
|
||||
|
||||
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]"})
|
||||
if answer:lower() == "a" then
|
||||
print("Exiting.")
|
||||
return
|
||||
elseif answer:lower() == "s" then
|
||||
print((" \27[93mSkipped file %s."):format(file))
|
||||
print((" \27[93mSkipped file %s.\27[0m"):format(file))
|
||||
goto SKIP
|
||||
end
|
||||
end
|
||||
|
||||
local handle, errorMessage = fs.open(file, "w")
|
||||
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]"})
|
||||
if answer:lower() == "a" then
|
||||
print("Exiting.")
|
||||
return
|
||||
elseif answer:lower() == "s" then
|
||||
print((" \27[93mSkipped file %s."):format(file))
|
||||
print((" \27[93mSkipped file %s.\27[0m"):format(file))
|
||||
goto SKIP
|
||||
else
|
||||
goto RETRY
|
||||
@@ -402,13 +402,13 @@ if command == "install" then
|
||||
local success, errorMessage = handle:write(data)
|
||||
if not success then
|
||||
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]"})
|
||||
if answer:lower() == "a" then
|
||||
print("Exiting.")
|
||||
return
|
||||
elseif answer:lower() == "s" then
|
||||
print((" \27[93mSkipped file %s."):format(file))
|
||||
print((" \27[93mSkipped file %s.\27[0m"):format(file))
|
||||
goto SKIP
|
||||
else
|
||||
goto RETRY
|
||||
@@ -431,13 +431,13 @@ if command == "install" then
|
||||
::RETRY::
|
||||
local handle, errorMessage = fs.open(("/ag2/pkg/%s.json"):format(package), "w")
|
||||
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]"})
|
||||
if answer:lower() == "a" then
|
||||
print("Exiting.")
|
||||
return
|
||||
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
|
||||
else
|
||||
goto RETRY
|
||||
@@ -461,13 +461,13 @@ if command == "install" then
|
||||
local success, errorMessage = handle:write(trackingFile)
|
||||
if not success then
|
||||
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]"})
|
||||
if answer:lower() == "a" then
|
||||
print("Exiting.")
|
||||
return
|
||||
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
|
||||
else
|
||||
goto RETRY
|
||||
@@ -479,9 +479,9 @@ if command == "install" then
|
||||
end
|
||||
elseif command == "remove" 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
|
||||
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
|
||||
print("Packages that will be removed:")
|
||||
print(table.concat(packages, ", "))
|
||||
|
||||
+28
-31
@@ -9,7 +9,7 @@ if not command then
|
||||
return
|
||||
end
|
||||
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
|
||||
end
|
||||
local internet = component.internet
|
||||
@@ -69,12 +69,12 @@ local function getAgConfig(package, source)
|
||||
source = source or agReg[package]
|
||||
local data, errorMessage = getFile(source .. "argentum.cfg")
|
||||
if not data or data == "" then
|
||||
print("\27[91mCould not fetch Ag config: " .. (errorMessage or "returned nil data"))
|
||||
print("\27[91mCould not fetch Ag config: " .. (errorMessage or "returned nil data") .. "\27[0m")
|
||||
return false
|
||||
end
|
||||
local func, errorMessage = load(data, "=argentum.cfg", "bt", {})
|
||||
if not func then
|
||||
print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.")
|
||||
print("\27[91mCould not fetch Ag config: " .. errorMessage .. "\nPlease contact the package owner.\27[0m")
|
||||
return false
|
||||
end
|
||||
local agcfg
|
||||
@@ -82,22 +82,22 @@ local function getAgConfig(package, source)
|
||||
agcfg = func()
|
||||
end)
|
||||
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
|
||||
end
|
||||
if not agcfg[package] or not agcfg[package].maindir or not agcfg[package].directories or not agcfg[package].files or not agcfg[package].version then
|
||||
local response = ("\27[91mAg config of " .. package .. " is improperly configured.\nPlease contact the package owner.")
|
||||
local response = "\27[91mAg config of " .. package .. " is improperly configured.\nPlease contact the package owner.\27[0m"
|
||||
end
|
||||
return agcfg
|
||||
end
|
||||
|
||||
local function doChecks(package)
|
||||
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
|
||||
end
|
||||
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
|
||||
end
|
||||
agcfg = getAgConfig(package, source)
|
||||
@@ -107,7 +107,7 @@ local function doChecks(package)
|
||||
if agcfg[package].dependencies then
|
||||
for _, dependency in ipairs(agcfg[package].dependencies) do
|
||||
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
|
||||
fs.remove("/argentum/store/" .. package)
|
||||
return false
|
||||
@@ -132,24 +132,21 @@ local function lpad(str, len, char)
|
||||
return string.rep(char, len - #str) .. str
|
||||
end
|
||||
|
||||
local gpu = component.gpu
|
||||
local width,height = gpu.getResolution()
|
||||
local function progress(package,progress)
|
||||
local info = string.format("%s %s%%",package,lpad(math.floor(progress*100),2))
|
||||
local width, height = terminal.getResolution()
|
||||
|
||||
local function progress(package, progress)
|
||||
terminal.write("\x1b[s")
|
||||
local info = string.format("%s %s%%", package, lpad(math.floor(progress * 100), 2))
|
||||
info = info .. string.rep(" ", width - #info)
|
||||
local progX = math.floor(progress * width)
|
||||
gpu.setBackground(0x00FF00)
|
||||
gpu.setForeground(0x000000)
|
||||
gpu.set(1,height,info:sub(1,progX))
|
||||
gpu.setBackground(0x000000)
|
||||
gpu.setForeground(0xFFFFFF)
|
||||
gpu.set(progX+1,height,info:sub(progX+1))
|
||||
terminal.write("\x1b[42m\x1b[30m" .. info:sub(1, progX) .. "\x1b[40m\x1b[37m" .. info:sub(progX + 1) .. "\x1b[0m")
|
||||
terminal.write("\x1b[u")
|
||||
end
|
||||
|
||||
local function clearProgress()
|
||||
gpu.setBackground(0x000000)
|
||||
gpu.fill(1,height,width,1," ")
|
||||
terminal.write("\x1b[s")
|
||||
terminal.write("\r\x1b[40m" .. string.rep(" ", width) .. "\x1b[0m\r")
|
||||
terminal.write("\x1b[u")
|
||||
end
|
||||
|
||||
local function installPackage(package, overwriteFlag)
|
||||
@@ -166,7 +163,7 @@ local function installPackage(package, overwriteFlag)
|
||||
if agcfg[package].dependencies then
|
||||
for _, dependency in ipairs(agcfg[package].dependencies) do
|
||||
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
|
||||
fs.remove("/argentum/store/" .. package)
|
||||
return false
|
||||
@@ -218,7 +215,7 @@ local function installPackage(package, overwriteFlag)
|
||||
else
|
||||
packageStore = packageStore .. "\nA" .. file
|
||||
end
|
||||
local handle = fs.open(file, "w")
|
||||
local handle, err = fs.open(file, "w")
|
||||
handle:write(data)
|
||||
handle:close()
|
||||
::skip::
|
||||
@@ -234,7 +231,7 @@ end
|
||||
local function removePackage(package)
|
||||
print("Removing " .. package .. "...")
|
||||
if not fs.exists("/argentum/store/" .. package .. "/package.cfg") then
|
||||
print("\27[91mLocal Ag config of " .. package .. " does not exist.")
|
||||
print("\27[91mLocal Ag config of " .. package .. " does not exist.\27[0m")
|
||||
return false
|
||||
end
|
||||
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:close()
|
||||
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
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
while true do
|
||||
@@ -402,19 +399,19 @@ elseif command == "remove" then
|
||||
end
|
||||
while true do
|
||||
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.remove(packageList, table.find(packageList, packages[i]))
|
||||
table.remove(packages, table.find(packages, packages[i]))
|
||||
i = i - 1
|
||||
elseif packages[i] == "halyde" then -- yes, this stuff is hard-coded.
|
||||
print("\27[91mFor obvious reasons, you can't uninstall Halyde.")
|
||||
print("\27[91mFor obvious reasons, you can't uninstall Halyde.\27[0m")
|
||||
table.insert(fails, packages[i])
|
||||
table.remove(packageList, table.find(packageList, packages[i]))
|
||||
table.remove(packages, table.find(packages, packages[i]))
|
||||
i = i - 1
|
||||
elseif packages[i] == "argentum" then
|
||||
print("\27[91mFor obvious reasons, you can't uninstall Argentum.")
|
||||
print("\27[91mFor obvious reasons, you can't uninstall Argentum.\27[0m")
|
||||
table.insert(fails, packages[i])
|
||||
table.remove(packageList, table.find(packageList, packages[i]))
|
||||
table.remove(packages, table.find(packages, packages[i]))
|
||||
@@ -495,7 +492,7 @@ elseif command == "update" then
|
||||
handle:write(newRegistry)
|
||||
handle:close()
|
||||
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
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
if not packages[1] then
|
||||
@@ -541,7 +538,7 @@ elseif command == "update" then
|
||||
table.remove(packages, table.find(packages, packages[i]))
|
||||
i = i - 1
|
||||
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
|
||||
i = i + 1
|
||||
@@ -630,7 +627,7 @@ elseif command == "info" then
|
||||
handle:write(newRegistry)
|
||||
handle:close()
|
||||
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
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
if not agReg[packages[1]] and not source then
|
||||
@@ -677,7 +674,7 @@ elseif command == "list" then
|
||||
handle:write(newRegistry)
|
||||
handle:close()
|
||||
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
|
||||
agReg = require("/argentum/registry.cfg")
|
||||
local sortedPackages = {}
|
||||
|
||||
@@ -9,7 +9,7 @@ cliparse.config({
|
||||
})
|
||||
local parsed, err = cliparse.parse(...)
|
||||
if not parsed then
|
||||
return print("\x1b[91m" .. err)
|
||||
return print("\x1b[91m" .. err .. "\x1b[0m")
|
||||
end
|
||||
|
||||
local freq =
|
||||
|
||||
@@ -34,25 +34,25 @@ if type(args[1])=="string" then
|
||||
local compID,err = getComponentID(args[1])
|
||||
if not compID then
|
||||
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
|
||||
end
|
||||
if not force 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
|
||||
local type = component.type(compID)
|
||||
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
|
||||
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
|
||||
|
||||
computer.setBootAddress(compID)
|
||||
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
|
||||
computer.shutdown(true)
|
||||
else
|
||||
|
||||
+20
-16
@@ -1,21 +1,25 @@
|
||||
local files = { ... }
|
||||
local shell = require("shell")
|
||||
local fs = require("filesystem")
|
||||
if not files or not files[1] then
|
||||
shell.run("help cat")
|
||||
return
|
||||
end
|
||||
for _, file in ipairs(files) do
|
||||
if file:sub(1, 1) ~= "/" then
|
||||
file = fs.concat(shell.getWorkingDirectory(), file)
|
||||
end
|
||||
if not fs.exists(file) then
|
||||
print("\27[91mFile does not exist.")
|
||||
local shell = require("shell")
|
||||
|
||||
local args = {...}
|
||||
|
||||
if not args[1] then
|
||||
return shell.run("help cat")
|
||||
end
|
||||
|
||||
for _, file in pairs(args) do
|
||||
file = shell.resolvePath(file)
|
||||
|
||||
local handle = fs.open(file, "r")
|
||||
local data
|
||||
repeat
|
||||
data = handle:read(math.huge or math.maxinteger)
|
||||
if handle == nil then
|
||||
terminal.write("\27[91mCan't open " .. file .. "\27[0m\n")
|
||||
goto continue
|
||||
end
|
||||
while true do
|
||||
local data = handle:read(math.huge or math.maxinteger)
|
||||
if data == nil then break end
|
||||
terminal.write(data)
|
||||
until not data
|
||||
end
|
||||
handle:close()
|
||||
::continue::
|
||||
end
|
||||
|
||||
+19
-8
@@ -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 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
|
||||
end
|
||||
if directory:sub(1, 1) ~= "/" then
|
||||
directory = fs.concat(shell.getWorkingDirectory(), directory)
|
||||
|
||||
if not fs.isDirectory(directory) then
|
||||
terminal.write("\27[91mError: " .. directory .. ": Not a directory\27[0m\n")
|
||||
return
|
||||
end
|
||||
if fs.exists(directory) and fs.isDirectory(directory) then
|
||||
|
||||
shell.setWorkingDirectory(fs.canonical(directory))
|
||||
else
|
||||
print("\27[91mNo such directory.")
|
||||
end
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
terminal.clear()
|
||||
-- truly so much going on here
|
||||
-- meow
|
||||
|
||||
+59
-16
@@ -1,27 +1,70 @@
|
||||
local fromFile, toFile = ...
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
|
||||
if not fromFile or not toFile then
|
||||
shell.run("help cp")
|
||||
local args = {...}
|
||||
|
||||
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
|
||||
end
|
||||
if fromFile:sub(1, 1) ~= "/" then
|
||||
fromFile = fs.concat(shell.getWorkingDirectory(), fromFile)
|
||||
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.")
|
||||
|
||||
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
|
||||
if not fs.exists(fromFile) then
|
||||
print("\27[91mSource file does not exist.")
|
||||
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.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.")
|
||||
if fs.isDirectory(src) then
|
||||
terminal.write("\27[91mError: Cannot write directory " .. src .. " to file " .. dest .. "\27[0m\n")
|
||||
return
|
||||
end
|
||||
fs.copy(fromFile, toFile)
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@ local component = require("component")
|
||||
local fs = require("filesystem")
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
@@ -26,11 +26,11 @@ local status, errorMessage = pcall(function()
|
||||
request:finishConnect()
|
||||
end)
|
||||
if not status then
|
||||
print("\27[91mDownload failed: " .. errorMessage)
|
||||
print("\27[91mDownload failed: " .. errorMessage .. "\27[0m")
|
||||
end
|
||||
local responseCode = request:response()
|
||||
if responseCode and responseCode ~= 200 then
|
||||
print("\27[91mDownload failed: " .. tostring(responseCode))
|
||||
print("\27[91mDownload failed: " .. tostring(responseCode) .. "\27[0m")
|
||||
end
|
||||
repeat
|
||||
tmpdata = request.read(math.huge)
|
||||
@@ -41,9 +41,9 @@ local saveLocationOK = false
|
||||
repeat
|
||||
saveLocation = terminal.read(nil, "File save location: ", fs.concat(require("shell").getWorkingDirectory(), url:match("/([^/]+)$")))
|
||||
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
|
||||
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
|
||||
saveLocationOK = true
|
||||
end
|
||||
|
||||
@@ -16,8 +16,7 @@ local tab = " "
|
||||
--local ocelot = component.ocelot
|
||||
|
||||
local function rawset(x, y, text)
|
||||
terminal.setCursorPos(x,y)
|
||||
terminal.write(text, false)
|
||||
terminal.write("\x1b[".. tostring(y) .. ";" .. tostring(x) .. "H" .. text)
|
||||
end
|
||||
|
||||
local filestring, filepath, handle, data, tmpdata
|
||||
@@ -261,7 +260,7 @@ local function save()
|
||||
gpu.setBackground(0xFFFFFF)
|
||||
gpu.setForeground(0)
|
||||
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})
|
||||
gpu.setBackground(0xFFFFFF)
|
||||
gpu.setForeground(0)
|
||||
@@ -300,7 +299,7 @@ while true do
|
||||
renderFlag, cursorRenderFlag, specialKey = processEvent(args)
|
||||
if specialKey == "x" 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] "})
|
||||
if response:lower() ~= "n" then
|
||||
save()
|
||||
|
||||
+36
-53
@@ -2,82 +2,65 @@ local component = require("component")
|
||||
local computer = require("computer")
|
||||
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 cursorPosX, cursorPosY = terminal.getCursorPos()
|
||||
terminal.setCursorPos(35, cursorPosY)
|
||||
terminal.write(text .. "\n", false)
|
||||
terminal.write("\27[35G" .. text .. "\n")
|
||||
end
|
||||
|
||||
local logo = ""
|
||||
local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil
|
||||
repeat
|
||||
tmpdata = handle:read(math.inf or math.maxinteger)
|
||||
tmpdata = handle:read(math.huge)
|
||||
logo = logo .. (tmpdata or "")
|
||||
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[92mArchitecture\27[0m: " .. _VERSION)
|
||||
|
||||
local componentCounter = 0
|
||||
for _, _ in component.list() do
|
||||
for _ in component.list() do
|
||||
componentCounter = componentCounter + 1
|
||||
end
|
||||
printstat("\27[92mComponents\27[0m: " .. tostring(componentCounter))
|
||||
printstat("\27[92mCoroutines\27[0m: " .. tostring(#tsched.getTasks()))
|
||||
printstat(
|
||||
"\27[92mBattery\27[0m: " .. tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10) .. "%"
|
||||
)
|
||||
printstat("\27[92mBattery\27[0m: " .. tostring(math.floor(computer.energy() / computer.maxEnergy() * 1000 + 0.5) / 10) .. "%")
|
||||
|
||||
local totalMemory = computer.totalMemory()
|
||||
local usedMemory = computer.totalMemory() - computer.freeMemory()
|
||||
local totalMemoryString
|
||||
if convert(totalMemory, "B", "GiB") >= 1 then
|
||||
totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
|
||||
elseif convert(totalMemory, "B", "MiB") >= 1 then
|
||||
totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "MiB") * 100 + 0.5) / 100) .. " MiB"
|
||||
elseif convert(totalMemory, "B", "KiB") >= 1 then
|
||||
totalMemoryString = tostring(math.floor(convert(totalMemory, "B", "KiB") * 100 + 0.5) / 100) .. " KiB"
|
||||
|
||||
local function formatBytes(bytes)
|
||||
if convert(bytes, "B", "GiB") >= 1 then
|
||||
return tostring(math.floor(convert(bytes, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
|
||||
elseif convert(bytes, "B", "MiB") >= 1 then
|
||||
return tostring(math.floor(convert(bytes, "B", "MiB") * 100 + 0.5) / 100) .. " MiB"
|
||||
elseif convert(bytes, "B", "KiB") >= 1 then
|
||||
return tostring(math.floor(convert(bytes, "B", "KiB") * 100 + 0.5) / 100) .. " KiB"
|
||||
else
|
||||
totalMemoryString = tostring(totalMemory) .. " B"
|
||||
return tostring(bytes) .. " B"
|
||||
end
|
||||
local usedMemoryString
|
||||
if convert(usedMemory, "B", "GiB") >= 1 then
|
||||
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)
|
||||
|
||||
printstat("\27[92mMemory\27[0m: " .. formatBytes(usedMemory) .. " / " .. formatBytes(totalMemory))
|
||||
|
||||
local totalDisk = component.invoke(computer.getBootAddress(), "spaceTotal")
|
||||
local usedDisk = component.invoke(computer.getBootAddress(), "spaceUsed")
|
||||
local totalDiskString
|
||||
if convert(totalDisk, "B", "GiB") >= 1 then
|
||||
totalDiskString = tostring(math.floor(convert(totalDisk, "B", "GiB") * 100 + 0.5) / 100) .. " GiB"
|
||||
elseif convert(totalDisk, "B", "MiB") >= 1 then
|
||||
totalDiskString = tostring(math.floor(convert(totalDisk, "B", "MiB") * 100 + 0.5) / 100) .. " MiB"
|
||||
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[92mDisk\27[0m: " .. formatBytes(usedDisk) .. " / " .. formatBytes(totalDisk))
|
||||
|
||||
local gpuComponent = component.list("gpu")()
|
||||
local width, height = component.invoke(gpuComponent, "getResolution")
|
||||
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[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")
|
||||
|
||||
+260
-32
@@ -1,40 +1,268 @@
|
||||
local shell = require("shell")
|
||||
local fs = require("filesystem")
|
||||
local args = {...}
|
||||
local command = args[1]
|
||||
args = nil
|
||||
if not command then
|
||||
local handle, data, tmpdata = fs.open("/halyde/apps/helpdb/default.txt", "r"), "", nil
|
||||
repeat
|
||||
tmpdata = handle:read(math.huge or math.maxinteger)
|
||||
data = data .. (tmpdata or "")
|
||||
until not tmpdata
|
||||
print(data)
|
||||
local shell = require("shell")
|
||||
|
||||
local arg = ... or "default"
|
||||
local what = arg
|
||||
|
||||
local aliases = shell.getAliases()
|
||||
if aliases[what] then
|
||||
what = aliases[what]
|
||||
end
|
||||
local path = "/halyde/apps/helpdb/" .. what
|
||||
if not fs.exists(path) then
|
||||
print("Could not find help file for: " .. arg .. ".")
|
||||
return
|
||||
end
|
||||
local aliases = shell.getAliases()
|
||||
if aliases[command] then
|
||||
command = aliases[command]
|
||||
if path == "/halyde/apps/helpdb/default" then
|
||||
return shell.run("cat " .. path) -- smh
|
||||
end
|
||||
if fs.exists("/halyde/apps/helpdb/" .. command .. ".txt") then
|
||||
local handle, data, tmpdata = fs.open("/halyde/apps/helpdb/" .. command .. ".txt", "r"), "", nil
|
||||
repeat
|
||||
tmpdata = handle:read(math.huge or math.maxinteger)
|
||||
data = data .. (tmpdata or "")
|
||||
until not tmpdata
|
||||
print(data)
|
||||
-- local aliases = table.copy(shell.aliases)
|
||||
if table.find(aliases, command) then
|
||||
local aliasIndex = table.find(aliases, command)
|
||||
local aliasString = "Aliases:\n " .. aliasIndex
|
||||
aliases[aliasIndex] = nil
|
||||
while table.find(aliases, command) do
|
||||
aliasIndex = table.find(aliases, command)
|
||||
aliasString = aliasString .. ", " .. aliasIndex
|
||||
aliases[aliasIndex] = nil
|
||||
local handle = fs.open(path, "r")
|
||||
local data = {
|
||||
command = "",
|
||||
usage = "",
|
||||
description = "",
|
||||
args = {},
|
||||
examples = {}
|
||||
}
|
||||
|
||||
while true do
|
||||
local line = ""
|
||||
while true do
|
||||
local char = handle:read(1)
|
||||
if not char then
|
||||
if line == "" then
|
||||
line = nil
|
||||
break
|
||||
end
|
||||
print(aliasString)
|
||||
break
|
||||
end
|
||||
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
|
||||
|
||||
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
|
||||
print("Could not find help file for: " .. command .. ".")
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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 ..".
|
||||
@@ -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 ..".
|
||||
@@ -0,0 +1,4 @@
|
||||
COMMAND clear
|
||||
DESCRIPTION Clears the screen.
|
||||
EXAMPLE1 clear
|
||||
EXAMPLE1DESCRIPTION Clears the screen.
|
||||
@@ -1,5 +0,0 @@
|
||||
Usage: clear
|
||||
Clears the screen.
|
||||
|
||||
Examples:
|
||||
clear Clears the screen.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,4 @@
|
||||
COMMAND fetch
|
||||
DESCRIPTION Displays system information including OS version, Lua version, memory, etc.
|
||||
EXAMPLE1 fetch
|
||||
EXAMPLE1DESCRIPTION Displays system information.
|
||||
@@ -1,5 +0,0 @@
|
||||
Usage: fetch
|
||||
Displays system information including OS version, Lua version, memory, etc.
|
||||
|
||||
Examples:
|
||||
fetch Displays system information.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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 [93myellow[0m, executable files are shown in [92mgreen[0m, 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.
|
||||
@@ -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 [93myellow[0m, executable files are shown in [92mgreen[0m, 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.
|
||||
@@ -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.
|
||||
@@ -1,5 +0,0 @@
|
||||
Usage: lscor
|
||||
Lists every active coroutine by ID and name.
|
||||
|
||||
Examples:
|
||||
lscor Lists every active coroutine by ID and name.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
COMMAND maindrv
|
||||
DESCRIPTION Shows the entire ID of the drive where Halyde is installed to.
|
||||
@@ -1,2 +0,0 @@
|
||||
Usage: maindrv
|
||||
Shows the entire ID of the drive where Halyde is installed to.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,4 @@
|
||||
COMMAND reboot
|
||||
DESCRIPTION Reboots the computer.
|
||||
EXAMPLE1 reboot
|
||||
EXAMPLE1DESCRIPTION Reboots the computer.
|
||||
@@ -1,5 +0,0 @@
|
||||
Usage: reboot
|
||||
Reboots the computer.
|
||||
|
||||
Examples:
|
||||
reboot Reboots the computer.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,4 @@
|
||||
COMMAND shutdown
|
||||
DESCRIPTION Shuts down the computer.
|
||||
EXAMPLE1 shutdown
|
||||
EXAMPLE1DESCRIPTION Shuts down the computer.
|
||||
@@ -1,5 +0,0 @@
|
||||
Usage: shutdown
|
||||
Shuts down the computer.
|
||||
|
||||
Examples:
|
||||
shutdown Shuts down the computer.
|
||||
@@ -0,0 +1,5 @@
|
||||
COMMAND touch
|
||||
USAGE [FILE]...
|
||||
DESCRIPTION Create an empty file.
|
||||
ARG1 FILE
|
||||
ARG1DESCRIPTION The path of the files to create.
|
||||
@@ -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.²
|
||||
@@ -1,7 +1,7 @@
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
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
|
||||
return require("shell").run("help label")
|
||||
end
|
||||
@@ -29,27 +29,27 @@ elseif inputID:sub(1,1)=="#" and tonumber(inputID:sub(2)) then
|
||||
componentFromSlot(slotNum)
|
||||
elseif #inputID>=3 then
|
||||
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)
|
||||
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")
|
||||
end
|
||||
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
|
||||
local compID = comp.address
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
local function formatLabel(label)
|
||||
@@ -67,7 +67,7 @@ if type(args[2])~="string" then
|
||||
label = comp.getLabel()
|
||||
end)
|
||||
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
|
||||
compError("getting",reason)
|
||||
end
|
||||
@@ -85,7 +85,7 @@ else
|
||||
label = comp.setLabel(newLabel)
|
||||
end)
|
||||
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
|
||||
compError("setting",reason)
|
||||
end
|
||||
|
||||
+4
-4
@@ -27,9 +27,9 @@ local function viewlog(logname)
|
||||
entry = string.sub(entry, 1, -1)
|
||||
end
|
||||
if entry:sub(1, 4) == "WARN" then
|
||||
print("\x1b[93m" .. entry)
|
||||
print("\x1b[93m" .. entry .. "\x1b[0m")
|
||||
elseif entry:sub(1, 5) == "ERROR" then
|
||||
print("\x1b[91m" .. entry)
|
||||
print("\x1b[91m" .. entry .. "\x1b[0m")
|
||||
else
|
||||
print(entry)
|
||||
end
|
||||
@@ -58,9 +58,9 @@ local function listlogs2()
|
||||
print("Found \x1b[93m" .. #logs .. "\x1b[0m logs.")
|
||||
for i in ipairs(logs) do
|
||||
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
|
||||
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
|
||||
|
||||
+48
-61
@@ -1,71 +1,58 @@
|
||||
local args = {...}
|
||||
local target = args[1]
|
||||
args = nil
|
||||
local fs = require("filesystem")
|
||||
local unicode = require("unicode")
|
||||
local maxLength = 0
|
||||
local margin = 2 -- minimum space between filename and size
|
||||
local dirTable = {}
|
||||
local fileTable = {}
|
||||
local workingDirectory = require("shell").getWorkingDirectory()
|
||||
local shell = require("shell")
|
||||
|
||||
if target then
|
||||
if target:sub(1, 1) ~= "/" then
|
||||
target = fs.concat(workingDirectory, target)
|
||||
end
|
||||
else
|
||||
target = workingDirectory
|
||||
local function formatSize(size, isDir)
|
||||
if isDir then return "[DIR]" end
|
||||
if size >= 1024^3 then return string.format("%.1fGiB", size / 1024^3) end
|
||||
if size >= 1024^2 then return string.format("%.1fMiB", size / 1024^2) end
|
||||
if size >= 1024 then return string.format("%.1fKiB", size / 1024) end
|
||||
return size.."B"
|
||||
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
|
||||
if file:sub(-1, -1) == "/" then
|
||||
table.insert(dirTable, file)
|
||||
file = file:sub(1, -2)
|
||||
else
|
||||
table.insert(fileTable, file)
|
||||
local isDir = file:sub(-1) == "/"
|
||||
local name = isDir and file:sub(1, -2) or file
|
||||
local size = isDir and 0 or fs.size(fs.concat(path, file))
|
||||
table.insert(fileList, {name = name, isDir = isDir, size = size})
|
||||
end
|
||||
if unicode.wlen(file) > maxLength then
|
||||
maxLength = unicode.wlen(file)
|
||||
end
|
||||
end
|
||||
table.sort(dirTable)
|
||||
table.sort(fileTable)
|
||||
files = {}
|
||||
for _, v in ipairs(dirTable) do
|
||||
table.insert(files, v)
|
||||
end
|
||||
for _, v in ipairs(fileTable) do
|
||||
table.insert(files, v)
|
||||
end
|
||||
dirTable, fileTable = nil, nil
|
||||
for _, file in ipairs(files) do
|
||||
local dir = false
|
||||
local filetext
|
||||
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)
|
||||
-- directories first
|
||||
-- then files
|
||||
table.sort(fileList, function(a, b)
|
||||
if a.isDir ~= b.isDir then return a.isDir end
|
||||
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
|
||||
|
||||
terminal.write(path.."\n")
|
||||
for _, item in ipairs(fileList) do
|
||||
local sizeStr = formatSize(item.size, item.isDir)
|
||||
sizeStr = string.rep(" ", maxSizeLen - #sizeStr) .. sizeStr
|
||||
local color = getFileColor(item.name, item.isDir)
|
||||
terminal.write(string.format("%s %s%s\27[0m\n", sizeStr, color, item.name))
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
|
||||
@@ -77,7 +77,7 @@ elseif outArgIdx then
|
||||
if headers[word] then
|
||||
addHeader(word)
|
||||
else
|
||||
print("\x1b[93mCategory \""..word.."\" doesn't exist\x1b[39m")
|
||||
print("\x1b[93mCategory \""..word.."\" doesn't exist\x1b[0m")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -190,7 +190,7 @@ local function handleComponent(id,type)
|
||||
|
||||
if proxy.getLabel then
|
||||
local clabel = proxy.getLabel()
|
||||
label=clabel and serialize.string(clabel) or "None"
|
||||
label=clabel and serialize(clabel) or "None"
|
||||
else
|
||||
label="Unsupported"
|
||||
end
|
||||
@@ -266,7 +266,7 @@ if not showAll then
|
||||
if func then
|
||||
filter(comps,func)
|
||||
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
|
||||
else
|
||||
filter(comps,function(comp)
|
||||
@@ -286,7 +286,7 @@ if sortArgIdx then
|
||||
return (boolToNum(func(a)) or 0)<(boolToNum(func(b)) or 0)
|
||||
end)
|
||||
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
|
||||
else
|
||||
table.sort(comps,function(a,b)
|
||||
|
||||
+11
-8
@@ -12,15 +12,18 @@ for _, lib in pairs(libList) do
|
||||
local name = lib:match("(.+)%.lua")
|
||||
_G[name] = require(name)
|
||||
end
|
||||
end, debug.traceback)
|
||||
end, function(errMsg)
|
||||
return errMsg .. "\n\n" .. debug.traceback()
|
||||
end)
|
||||
if not status then
|
||||
local firstLine = tostring(err):match("^[^\n]*")
|
||||
print(
|
||||
string.format(
|
||||
"\x1b[91mLibrary %s has failed loading:\n │ %s",
|
||||
lib:match("(.+)%.lua"),
|
||||
tostring(err or "unknown error"):match("^(.-)\n")
|
||||
"\x1b[91mLibrary %s has failed loading:\n │ %s\x1b[0m",
|
||||
lib:match("(.+)%.lua") or lib,
|
||||
firstLine or "unknown error"
|
||||
)
|
||||
)
|
||||
) -- TODO: only show first line of error
|
||||
log.lua.error(
|
||||
string.format(
|
||||
'The library located at "%s" has failed loading:\n%s',
|
||||
@@ -35,7 +38,7 @@ end
|
||||
if failed then
|
||||
print(
|
||||
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]")
|
||||
)
|
||||
)
|
||||
@@ -59,7 +62,7 @@ while true do
|
||||
returns = false
|
||||
end
|
||||
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
|
||||
local res = { func() }
|
||||
if returns then
|
||||
@@ -74,7 +77,7 @@ while true do
|
||||
return errMsg .. "\n\n" .. debug.traceback()
|
||||
end)
|
||||
if not result then
|
||||
print("\27[91m" .. reason)
|
||||
print("\27[91m" .. reason .. "\27[0m")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
local computer = require("computer")
|
||||
|
||||
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
|
||||
|
||||
local address = computer.getBootAddress()
|
||||
|
||||
+18
-9
@@ -1,14 +1,23 @@
|
||||
local directory = ...
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
|
||||
if not directory then
|
||||
require("shell").run("help mkdir")
|
||||
return
|
||||
end
|
||||
if directory:sub(1, 1) ~= "/" then
|
||||
directory = fs.concat(require("shell").getWorkingDirectory(), directory)
|
||||
local args = {...}
|
||||
|
||||
if not args[1] then
|
||||
return shell.run("help mkdir")
|
||||
end
|
||||
|
||||
for _, directory in pairs(args) do
|
||||
directory = shell.resolvePath(directory)
|
||||
|
||||
if fs.exists(directory) then
|
||||
print("\27[91mAn object already exists at the specified path.")
|
||||
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
|
||||
fs.makeDirectory(directory)
|
||||
|
||||
+64
-19
@@ -1,25 +1,70 @@
|
||||
local fromFile, toFile = ...
|
||||
local shell = require("shell")
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
|
||||
if not fromFile or not toFile then
|
||||
shell.run("help mv")
|
||||
local args = {...}
|
||||
|
||||
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
|
||||
end
|
||||
if fromFile:sub(1, 1) ~= "/" then
|
||||
fromFile = fs.concat(shell.getWorkingDirectory(), fromFile)
|
||||
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.")
|
||||
|
||||
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
|
||||
fs.rename(fromFile, toFile)
|
||||
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
|
||||
|
||||
+15
-15
@@ -9,7 +9,7 @@ local curX, curY = gpu.getResolution()
|
||||
|
||||
local function setRes()
|
||||
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
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ local function setRes()
|
||||
x = tonumber(args[i + 1])
|
||||
lastarg = "x"
|
||||
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
|
||||
end
|
||||
elseif args[i] == "-y" then
|
||||
@@ -29,7 +29,7 @@ local function setRes()
|
||||
y = tonumber(args[i + 1])
|
||||
lastarg = "y"
|
||||
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
|
||||
end
|
||||
end
|
||||
@@ -37,42 +37,42 @@ local function setRes()
|
||||
|
||||
if x 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
|
||||
end
|
||||
end
|
||||
if y 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
|
||||
end
|
||||
end
|
||||
|
||||
if x and not(y) then
|
||||
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
|
||||
elseif not(x) and y then
|
||||
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
|
||||
else
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
local function getRes(val)
|
||||
if val == "x" then
|
||||
print("Current X resolution: \x1b[93m" .. curX)
|
||||
print("Maximum supported X resolution: \x1b[92m" .. maxX)
|
||||
print("Current X resolution: \x1b[93m" .. curX .. "\x1b[0m")
|
||||
print("Maximum supported X resolution: \x1b[92m" .. maxX .. "\x1b[0m")
|
||||
elseif val == "y" then
|
||||
print("Current Y resolution: \x1b[93m" .. curY)
|
||||
print("Maximum supported Y resolution: \x1b[92m" .. maxY)
|
||||
print("Current Y resolution: \x1b[93m" .. curY .. "\x1b[0m")
|
||||
print("Maximum supported Y resolution: \x1b[92m" .. maxY .. "\x1b[0m")
|
||||
else
|
||||
print("Current resolution: \x1b[93m" .. curX .. "x" .. curY)
|
||||
print("Maximum supported resolution: \x1b[92m" .. maxX .. "x" .. maxY)
|
||||
print("Current resolution: \x1b[93m" .. curX .. "x" .. curY .. "\x1b[0m")
|
||||
print("Maximum supported resolution: \x1b[92m" .. maxX .. "x" .. maxY .. "\x1b[0m")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -92,5 +92,5 @@ if axis == "-x" then
|
||||
elseif axis == "-y" then
|
||||
getRes("y")
|
||||
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
|
||||
+12
-11
@@ -1,16 +1,17 @@
|
||||
local file = ...
|
||||
local shell = require("shell")
|
||||
local fs = require("filesystem")
|
||||
local shell = require("shell")
|
||||
|
||||
if not file then
|
||||
shell.run("help rm")
|
||||
return
|
||||
local args = {...}
|
||||
|
||||
if not args[1] then
|
||||
return shell.run("help rm")
|
||||
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
|
||||
if not fs.exists(file) then
|
||||
print("\27[91mFile does not exist.")
|
||||
return
|
||||
end
|
||||
fs.remove(file)
|
||||
|
||||
@@ -88,4 +88,4 @@ end
|
||||
end ]]
|
||||
|
||||
raster.free()
|
||||
terminal.setCursorPos(1,1)
|
||||
terminal.clear()
|
||||
|
||||
+11
-16
@@ -1,28 +1,23 @@
|
||||
-- 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.
|
||||
-- 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 shell = require("shell")
|
||||
|
||||
if not file then
|
||||
local args = {...}
|
||||
|
||||
if not args[1] then
|
||||
return shell.run("help touch")
|
||||
end
|
||||
|
||||
if file:sub(1, 1) ~= "/" then
|
||||
file = fs.concat(shell.getWorkingDirectory(), file)
|
||||
end
|
||||
for _, file in pairs(args) do
|
||||
file = shell.resolvePath(file)
|
||||
|
||||
if fs.exists(file) and not (parsed.flags.o or parsed.flags.overwrite) then
|
||||
return print("\x1b[91mFile already exists.\n│ To empty file contents, use -o.")
|
||||
local handle, err = fs.open(file, "a")
|
||||
if err ~= nil then
|
||||
terminal.write("\27[91mError: " .. err .. "\27[0m\n")
|
||||
goto continue
|
||||
end
|
||||
|
||||
local handle = fs.open(file, "w")
|
||||
handle:write("") -- just in case
|
||||
handle:close()
|
||||
::continue::
|
||||
end
|
||||
|
||||
+410
-167
@@ -1,3 +1,10 @@
|
||||
--[[
|
||||
TODO:
|
||||
```bash
|
||||
echo -e "\033[?25l" # hide
|
||||
echo -e "\033[?25h" # show
|
||||
```
|
||||
]]
|
||||
local module = {}
|
||||
|
||||
function module.check()
|
||||
@@ -9,23 +16,11 @@ function module.init()
|
||||
local unicode = require("unicode")
|
||||
local event = require("event")
|
||||
|
||||
--local ocelot = component.proxy(component.list("ocelot")())
|
||||
local component = require("component")
|
||||
local computer = require("computer")
|
||||
local gpu = component.gpu
|
||||
_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 = {}
|
||||
function _PUBLIC.terminal.getHistory(id)
|
||||
checkArg(1,id,"string")
|
||||
@@ -46,6 +41,28 @@ function module.init()
|
||||
end
|
||||
|
||||
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"] = {
|
||||
[0] = 0x000000,
|
||||
[1] = 0x800000,
|
||||
@@ -66,172 +83,405 @@ function module.init()
|
||||
[6] = 0x00FFFF,
|
||||
[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]
|
||||
defaultBackgroundColor = ANSIColorPalette["dark"][0]
|
||||
|
||||
gpu.setForeground(defaultForegroundColor)
|
||||
gpu.setBackground(defaultBackgroundColor)
|
||||
|
||||
local function scrollDown()
|
||||
if gpu.copy(1,1,width,height,0,-1) then
|
||||
local prevForeground = gpu.getForeground()
|
||||
local prevBackground = gpu.getBackground()
|
||||
gpu.setForeground(defaultForegroundColor)
|
||||
gpu.setBackground(defaultBackgroundColor)
|
||||
gpu.fill(1, height, width, 1, " ")
|
||||
gpu.setForeground(prevForeground)
|
||||
gpu.setBackground(prevBackground)
|
||||
cursorPosY=height
|
||||
end
|
||||
end
|
||||
|
||||
local function newLine()
|
||||
cursorPosX=1
|
||||
cursorPosY = cursorPosY + 1
|
||||
if cursorPosY>height then
|
||||
scrollDown()
|
||||
end
|
||||
end
|
||||
|
||||
local function parseCodeNumbers(code)
|
||||
local o = {}
|
||||
for num in code:sub(3,-2):gmatch("[^;]+") do
|
||||
table.insert(o,tonumber(num))
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
local function from8BitColor(num)
|
||||
num=math.floor(num)&255
|
||||
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)
|
||||
r,g,b=math.floor(r)&255,math.floor(g)&255,math.floor(b)&255
|
||||
return (r<<16)|(g<<8)|b
|
||||
end
|
||||
|
||||
local function findCodeEnd(text,i)
|
||||
local function inRange(v,min,max)
|
||||
return v>=min and v<=max
|
||||
end
|
||||
i=i+2
|
||||
while i<=#text and not inRange(text:byte(i),0x40,0x7F) do i=i+1 end
|
||||
return i
|
||||
end
|
||||
|
||||
function _PUBLIC.terminal.write(text, textWrap)
|
||||
-- you don't know how tiring this was just for ANSI escape code support
|
||||
|
||||
if textWrap == nil then
|
||||
textWrap = true
|
||||
end
|
||||
|
||||
if not text or not tostring(text) then
|
||||
return
|
||||
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 #section==0 then
|
||||
return
|
||||
end
|
||||
while true do
|
||||
gpu.set(cursorPosX,cursorPosY,section)
|
||||
if unicode.wlen(section) > width - cursorPosX + 1 and textWrap then
|
||||
section = section:sub(width - cursorPosX + 2)
|
||||
newLine()
|
||||
local function update_gpu_colors()
|
||||
if color.reverse then
|
||||
gpu.setForeground(color.bg)
|
||||
gpu.setBackground(color.fg)
|
||||
else
|
||||
cursorPosX = cursorPosX+unicode.wlen(section)
|
||||
gpu.setForeground(color.fg)
|
||||
gpu.setBackground(color.bg)
|
||||
end
|
||||
end
|
||||
|
||||
local width, height = gpu.getResolution()
|
||||
|
||||
function _G._PUBLIC.terminal.getResolution()
|
||||
return width, height
|
||||
end
|
||||
|
||||
gpu.setForeground(color.fg)
|
||||
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.setForeground(color.fg)
|
||||
gpu.setBackground(color.bg)
|
||||
cursor.y = height
|
||||
end
|
||||
end
|
||||
|
||||
local function check_wrap_and_scroll()
|
||||
if cursor.x > width then
|
||||
cursor.x = 1
|
||||
cursor.y = cursor.y + 1
|
||||
end
|
||||
|
||||
while cursor.y > height do
|
||||
scroll()
|
||||
end
|
||||
end
|
||||
|
||||
local function exec_csi()
|
||||
local params = {}
|
||||
local op = 0
|
||||
local current_num = 0
|
||||
local have_num = false
|
||||
|
||||
for i = 1, #seq do
|
||||
local byte = seq[i]
|
||||
|
||||
if 0x30 <= byte and byte <= 0x39 then
|
||||
current_num = current_num * 10 + (byte - 0x30)
|
||||
have_num = true
|
||||
elseif byte == 0x3b then
|
||||
table.insert(params, have_num and current_num or 0)
|
||||
current_num = 0
|
||||
have_num = false
|
||||
else
|
||||
if have_num then
|
||||
table.insert(params, current_num)
|
||||
end
|
||||
if 0x40 <= byte and byte <= 0x7e then
|
||||
op = byte
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
section = ""
|
||||
|
||||
local function get_param(idx, default)
|
||||
if idx <= #params and params[idx] ~= nil then
|
||||
return params[idx]
|
||||
end
|
||||
return default
|
||||
end
|
||||
|
||||
for i=1,#text do
|
||||
if readBreak>0 then
|
||||
readBreak = readBreak - 1
|
||||
goto continue
|
||||
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
|
||||
end
|
||||
|
||||
if string.byte(text,i)==10 then
|
||||
printSection()
|
||||
newLine()
|
||||
elseif string.byte(text,i)==13 then
|
||||
printSection()
|
||||
cursorPosX=1
|
||||
elseif string.byte(text,i)==0x1b and i<=#text-2 then
|
||||
printSection()
|
||||
--ocelot.log("0x1b char detected")
|
||||
local codeType = string.sub(text,i+1,i+1)
|
||||
if codeType=="[" then
|
||||
-- Control Sequence Introducer
|
||||
--ocelot.log("Control Sequence Introducer")
|
||||
local codeEndIdx = findCodeEnd(text,i)
|
||||
-- codeEndIdx = string.find(text,"m",i)
|
||||
local code = string.sub(text,i,codeEndIdx)
|
||||
--ocelot.log("Code: "..code.." ("..i..", "..codeEndIdx..")")
|
||||
readBreak = readBreak + #code - 1
|
||||
local nums = parseCodeNumbers(code)
|
||||
local codeEnd = code:sub(-1)
|
||||
--ocelot.log("Code end: "..codeEnd..", "..#codeEnd)
|
||||
if codeEnd == "m" then
|
||||
-- Select Graphic Rendition
|
||||
--ocelot.log("Select Graphic Rendition, ID "..nums[1])
|
||||
if nums[1]>=30 and nums[1]<=37 then
|
||||
gpu.setForeground(ANSIColorPalette["dark"][nums[1]%10])
|
||||
if op == 0x41 then
|
||||
local n = get_param(1, 1)
|
||||
cursor.y = cursor.y - n
|
||||
if cursor.y < 1 then cursor.y = 1 end
|
||||
return
|
||||
end
|
||||
if nums[1]==38 and nums[2]==5 then
|
||||
gpu.setForeground(from8BitColor(nums[3]))
|
||||
|
||||
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 nums[1]==38 and nums[2]==2 then
|
||||
gpu.setForeground(from24BitColor(nums[3],nums[4],nums[5]))
|
||||
|
||||
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 nums[1]==39 or nums[1]==0 then
|
||||
gpu.setForeground(defaultForegroundColor)
|
||||
|
||||
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 nums[1]>=40 and nums[1]<=47 then
|
||||
gpu.setBackground(ANSIColorPalette["dark"][nums[1]%10])
|
||||
|
||||
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 nums[1]==48 and nums[2]==5 then
|
||||
gpu.setBackground(from8BitColor(nums[3]))
|
||||
|
||||
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
|
||||
if nums[1]==48 and nums[2]==2 then
|
||||
gpu.setBackground(from24BitColor(nums[3],nums[4],nums[5]))
|
||||
return
|
||||
end
|
||||
if nums[1]==49 or nums[1]==0 then
|
||||
gpu.setBackground(defaultBackgroundColor)
|
||||
|
||||
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
|
||||
if nums[1]>=90 and nums[1]<=97 then
|
||||
gpu.setForeground(ANSIColorPalette["bright"][nums[1]%10])
|
||||
return
|
||||
end
|
||||
if nums[1]>=100 and nums[1]<=107 then
|
||||
gpu.setBackground(ANSIColorPalette["bright"][nums[1]%10])
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
while j <= #params do
|
||||
local p = params[j] or 0
|
||||
|
||||
if p == 0 then
|
||||
color.reverse = false
|
||||
color.fg = color.FG
|
||||
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
|
||||
|
||||
j = j + 1
|
||||
end
|
||||
update_gpu_colors()
|
||||
return
|
||||
end
|
||||
|
||||
if op == 0x73 then
|
||||
cursor.X = cursor.x
|
||||
cursor.Y = cursor.y
|
||||
return
|
||||
end
|
||||
|
||||
if op == 0x75 then
|
||||
if cursor.X and cursor.Y then
|
||||
cursor.x = cursor.X
|
||||
cursor.y = cursor.Y
|
||||
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
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function _G._PUBLIC.terminal.writec(byte)
|
||||
if byte == 0x1b then
|
||||
printState = 1
|
||||
seq = {}
|
||||
return
|
||||
end
|
||||
|
||||
if printState == 1 then
|
||||
if byte == 0x5b then
|
||||
printState = 2
|
||||
else
|
||||
printState = 0
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
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
|
||||
--gpu.set(cursorPosX,cursorPosY,string.sub(text,i,i))
|
||||
section = section..string.sub(text,i,i)
|
||||
current_codepoint = 0
|
||||
bytes_remaining = 0
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
printSection()
|
||||
|
||||
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
|
||||
|
||||
function _G.print(...)
|
||||
@@ -239,19 +489,12 @@ function module.init()
|
||||
local stringArgs = {}
|
||||
for _, arg in pairs(args) do
|
||||
if type(arg)=="table" then
|
||||
table.insert(stringArgs, serialize.table(arg,true))
|
||||
table.insert(stringArgs, serialize(arg))
|
||||
elseif tostring(arg) then
|
||||
table.insert(stringArgs, tostring(arg))
|
||||
end
|
||||
end
|
||||
_PUBLIC.terminal.write(table.concat(stringArgs, " ") .. "\n")
|
||||
end
|
||||
|
||||
function _G._PUBLIC.terminal.clear()
|
||||
gpu.setForeground(defaultForegroundColor)
|
||||
gpu.setBackground(defaultBackgroundColor)
|
||||
gpu.fill(1,1,width,height," ")
|
||||
cursorPosX, cursorPosY = 1, 1
|
||||
_PUBLIC.terminal.write(table.concat(stringArgs, "\t") .. "\n")
|
||||
end
|
||||
|
||||
function _G._PUBLIC.terminal.read(options)
|
||||
@@ -289,7 +532,7 @@ function module.init()
|
||||
|
||||
local cur = unicode.len(text)+1
|
||||
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 cursorBlink = true
|
||||
local function checkScroll(y)
|
||||
@@ -482,9 +725,9 @@ function module.init()
|
||||
end
|
||||
end
|
||||
|
||||
cursorPosX=1
|
||||
cursorPosY=cursorPosY+math.ceil((unicode.wlen(text)+startX-1)/width)
|
||||
if cursorPosY>height then scrollDown() end
|
||||
cursor.x=1
|
||||
cursor.y=cursor.y+math.ceil((unicode.wlen(text)+startX-1)/width)
|
||||
if cursor.y>height then scroll() end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ function module.init()
|
||||
if type(tsched.currentTask) == "table" and type(tsched.currentTask.id) == "number" then
|
||||
taskInfo.parent = tsched.currentTask.id
|
||||
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
|
||||
table.insert(tsched.tasks, taskInfo)
|
||||
if taskInfo.parent then
|
||||
|
||||
@@ -22,6 +22,11 @@ function _G.shell.getWorkingDirectory()
|
||||
return workingDirectory
|
||||
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)
|
||||
checkArg(1, dir, "string")
|
||||
workingDirectory = dir
|
||||
|
||||
+22
-19
@@ -32,6 +32,11 @@ function filesystem.canonical(path)
|
||||
return "/" .. table.concat(segList, "/")
|
||||
end
|
||||
|
||||
function filesystem.basename(path)
|
||||
checkArg(1, path, "string")
|
||||
return path:match("/([^/]+)/?$") or ""
|
||||
end
|
||||
|
||||
function filesystem.concat(path1, path2)
|
||||
checkArg(1, path1, "string")
|
||||
checkArg(2, path2, "string")
|
||||
@@ -67,6 +72,13 @@ function filesystem.absolutePath(path) -- returns the address and absolute path
|
||||
return address, path
|
||||
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
|
||||
checkArg(1, path, "string")
|
||||
local address, absPath = filesystem.absolutePath(path)
|
||||
@@ -475,14 +487,12 @@ local function copyContent(fromHandle, toHandle)
|
||||
if not (fromHandle and toHandle) then
|
||||
return
|
||||
end
|
||||
local memory = math.floor(computer.freeMemory() * 0.8)
|
||||
local tmpdata
|
||||
while true do
|
||||
tmpdata = fromHandle:read(memory)
|
||||
local tmpdata = fromHandle.read(2048)
|
||||
if not tmpdata then
|
||||
break
|
||||
end
|
||||
local status, reason = toHandle:write(tmpdata)
|
||||
local status, reason = toHandle.write(tmpdata)
|
||||
if status ~= true then
|
||||
break
|
||||
end
|
||||
@@ -492,7 +502,6 @@ local function copyContent(fromHandle, toHandle)
|
||||
end
|
||||
|
||||
local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
|
||||
-- TODO: make this use copyContent
|
||||
if fromAbsPath:sub(-1) == "/" then
|
||||
fromAbsPath = fromAbsPath:sub(1, -2)
|
||||
end
|
||||
@@ -506,31 +515,21 @@ local function copyRecursive(fromAddress, fromAbsPath, toAddress, toAbsPath)
|
||||
end
|
||||
for i = 1, #fileList do
|
||||
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 toHandle = component.invoke(toAddress, "open", toFile, "w")
|
||||
copyContent({
|
||||
["read"] = function(...)
|
||||
return component.invoke(fromAddress, "read", handle, ...)
|
||||
return component.invoke(fromAddress, "read", fromHandle, ...)
|
||||
end,
|
||||
["close"] = function(...)
|
||||
return component.invoke(fromAddress, "close", handle, ...)
|
||||
return component.invoke(fromAddress, "close", fromHandle, ...)
|
||||
end,
|
||||
}, {
|
||||
["write"] = function(...)
|
||||
return component.invoke(fromAddress, "write", handle, ...)
|
||||
return component.invoke(toAddress, "write", toHandle, ...)
|
||||
end,
|
||||
["close"] = function(...)
|
||||
return component.invoke(fromAddress, "close", handle, ...)
|
||||
return component.invoke(toAddress, "close", toHandle, ...)
|
||||
end,
|
||||
})
|
||||
end
|
||||
@@ -545,6 +544,10 @@ function filesystem.isDirectory(path)
|
||||
return component.invoke(address, "isDirectory", absPath)
|
||||
end
|
||||
|
||||
function filesystem.isFile(path)
|
||||
return not filesystem.isDirectory(path) and filesystem.exists(path)
|
||||
end
|
||||
|
||||
function filesystem.rename(fromPath, toPath)
|
||||
checkArg(1, fromPath, "string")
|
||||
checkArg(2, toPath, "string")
|
||||
|
||||
+43
-122
@@ -1,127 +1,48 @@
|
||||
local serialize = {}
|
||||
|
||||
function serialize.string(str)
|
||||
return '"'..str:gsub("[%z\1-\31\34\92\127-\159]",function(c)
|
||||
local byte = c:byte()
|
||||
if byte== 7 then return "\\a" end
|
||||
if byte== 8 then return "\\b" end
|
||||
if byte== 9 then return "\\t" end
|
||||
if byte==10 then return "\\n" end
|
||||
if byte==11 then return "\\v" end
|
||||
if byte==12 then return "\\f" end
|
||||
if byte==13 then return "\\r" end
|
||||
if byte==34 then return "\\\"" end
|
||||
if byte==92 then return "\\\\" end
|
||||
return string.format("\\x%02x",byte)
|
||||
end)..'"'
|
||||
local function _serialize(value, indent, level, visited)
|
||||
local currentIndent = indent and string.rep(indent, level) or ""
|
||||
local nextIndent = indent and string.rep(indent, level + 1) or ""
|
||||
local sep = indent and "\n" or " "
|
||||
local t = type(value)
|
||||
if t == "nil" then return "nil" end
|
||||
if t == "string" then return string.format("%q", value) end
|
||||
if t == "number" then
|
||||
if value ~= value then return "0/0" end
|
||||
if value == math.huge then return "math.huge" end
|
||||
if value == -math.huge then return "-math.huge" end
|
||||
return tostring(value)
|
||||
end
|
||||
if t == "boolean" then return tostring(value) end
|
||||
if t == "table" then
|
||||
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
|
||||
|
||||
function serialize.table(tbl,colors,stack)
|
||||
stack = table.copy(stack or {})
|
||||
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}"
|
||||
function serialize(value, indent)
|
||||
return _serialize(value, indent, 0, {})
|
||||
end
|
||||
|
||||
return serialize
|
||||
|
||||
+1
-1
@@ -236,7 +236,7 @@ local function startTransaction(dbpath)
|
||||
function transaction.addInfo(name,info)
|
||||
if not info.type then info.type="package" end
|
||||
packInfo[name]=info
|
||||
-- print(require("serialize").table(packInfo))
|
||||
-- print(require("serialize")(packInfo))
|
||||
end
|
||||
|
||||
local function getPackInfo(pack)
|
||||
|
||||
Reference in New Issue
Block a user