v2.5.0 - Added apps for drive actions (lsdrv/lsblk, label, maindrv)

This commit is contained in:
Ponali
2025-07-15 17:28:38 +02:00
parent 1776741114
commit c6aa57983a
10 changed files with 457 additions and 3 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
local agcfg = { local agcfg = {
["halyde"] = { ["halyde"] = {
["maindir"] = "", ["maindir"] = "",
["version"] = "2.4.1", ["version"] = "2.5.0",
["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.", ["description"] = "A universal, customizable and feature-packed operating system for OpenComputers.",
["directories"] = { ["directories"] = {
"halyde/apps", "halyde/apps",
+16
View File
@@ -0,0 +1,16 @@
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"
+27
View File
@@ -0,0 +1,27 @@
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.
+2
View File
@@ -0,0 +1,2 @@
Usage: maindrv
Shows the entire ID of the drive where Halyde is installed to.
+92
View File
@@ -0,0 +1,92 @@
local component = import("component")
local computer = import("computer")
local args = {...}
if not args then return print("\x1b[91mCannot get arguments.") end
if not args[1] then
return shell.run("help label")
end
local inputID = args[1]
local comp
local function componentFromSlot(slotNum)
if slotNum>=5 and slotNum<=8 then slotNum=slotNum-1 end
for i,v in component.list() do
if component.slot(i)==slotNum then
comp=component.proxy(i)
end
end
end
if inputID=="eeprom" then
comp = component.eeprom
elseif inputID=="halyde" then
comp = component.proxy(computer.getBootAddress())
elseif inputID:sub(1,4)=="slot" and tonumber(inputID:sub(5)) then
local slotNum = tonumber(inputID:sub(5))-1
componentFromSlot(slotNum)
elseif inputID:sub(1,1)=="#" and tonumber(inputID:sub(2)) then
local slotNum = tonumber(inputID:sub(2))+5
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
comp = component.proxy(fullID)
else
print("\x1b[91mAddress must have atleast 3 characters")
return shell.run("help label")
end
if not comp then
return print("\x1b[91mCould not find component from \""..inputID.."\".")
end
local compID = comp.address
local function formatID(id)
return id:sub(1,8).."\x1b[37m"..id:sub(9).."\x1b[39m"
end
local function unsupported(act)
print("This \x1b[92m"..(comp.type or "unknown").."\x1b[39m component doesn't support "..act.." labels.\nID: "..formatID(compID))
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)
end
local function formatLabel(label)
local res = "No label defined"
if label then res="\""..label.."\"" end
return res
end
if type(args[2])~="string" then
if not comp.getLabel then
return unsupported("getting")
end
local label
local success,reason = pcall(function()
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")
else
compError("getting",reason)
end
else
if not comp.setLabel then
return unsupported("setting")
end
local newLabel = ""
for i=2,#args do
newLabel=newLabel..tostring(args[i])
if i<#args then newLabel=newLabel.." " end
end
local label
local success,reason = pcall(function()
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")
else
compError("setting",reason)
end
end
+308
View File
@@ -0,0 +1,308 @@
local component = import("component")
local computer = import("computer")
local unicode = import("unicode")
local width,height = component.gpu.getResolution()
local args = {...}
local showAll = not not (table.find(args,"-a") or table.find(args,"--all"))
local tablePos = {}
local tableOut = {}
local headers = {
["slot"]="SLOT",
["capacity"]="CAPACITY",
["managed"]="MANAGED",
["readOnly"]="READ-ONLY",
["id"]="FULL COMPONENT ID",
["mount"]="MOUNT",
["bootable"]="BOOTABLE",
["label"]="LABEL"
}
local headerAlign = {
["slot"]=false,
["capacity"]=true,
["managed"]=false,
["readOnly"]=false,
["id"]=false,
["mount"]=false,
["bootable"]=false,
["label"]=false
}
local function addHeader(id)
table.insert(tableOut,{headerAlign[id],headers[id]})
tablePos[id]=#tableOut
end
for i,v in pairs(tablePos) do print(i,v) end
local function everyHeader()
addHeader("slot")
addHeader("capacity")
addHeader("managed")
addHeader("readOnly")
addHeader("id")
addHeader("mount")
addHeader("bootable")
addHeader("label")
end
local function defaultHeaders()
if width>100 then addHeader("slot") end
addHeader("capacity")
if width>80 then addHeader("id") end
addHeader("mount")
addHeader("label")
end
local outArgIdx = table.find(args,"-o") or table.find(args,"--output")
if showAll then
everyHeader()
elseif outArgIdx then
table.remove(args,outArgIdx)
local arg = table.remove(args,outArgIdx)
if not arg then return invalidArgSyntax("Argument -o must have a value") end
if arg=="all" then
everyHeader()
else
if arg:sub(1,1)=="+" then
defaultHeaders()
end
for word in string.gmatch(arg:sub(2),"([^,]+)") do
if headers[word] then
addHeader(word)
else
print("\x1b[93mCategory \""..word.."\" doesn't exist\x1b[39m")
end
end
end
else
defaultHeaders()
end
local function headerUsed(id)
return not not tablePos[id]
end
local bibytes = not (table.find(args,"-H") or table.find(args,"--si"))
local function formatSize(mem)
local units = bibytes and {"B","KiB","MiB","GiB"} or {"B","KB","MB","GB"}
local unit = 1
local unitStep = bibytes and 1024 or 1000
while mem > unitStep and units[unit] do
unit = unit + 1
mem = mem/unitStep
end
local memStr = tostring(mem):sub(1,5)
if unicode.sub(memStr,-2)==".0" then
memStr=unicode.sub(memStr,1,-3)
end
return memStr.." "..units[unit]
end
local function fileExists(proxy,path)
return proxy.exists(path) and not proxy.isDirectory(path)
end
local function getBootCode(proxy)
local sector1 = proxy.readSector(1)
for i = 1,#sector1 do
if sector1:sub(i,i)=="\0" then
sector1 = sector1:sub(1,i-1)
break
end
end
return sector1
end
local function isBootable(proxy,type)
if type=="drive" then
return not not load(getBootCode(proxy))
elseif type=="filesystem" then
return not not (fileExists(proxy,"/init.lua") or fileExists(proxy,"/OS.lua"))
end
end
local function formatBoolean(bool)
return ({[true]="Yes",[false]="No"})[bool]
end
local function handleComponent(id,type)
if not id then return end
local proxy = component.proxy(id)
if not proxy then return end
-- local out = {}
-- for i=1,#tableOut do table.insert(out,"unknown") end
local slot,capacity,managed,readOnly,mount,bootable,label
local cslot = component.slot(id)
if cslot==-1 then
slot="Virtual"
elseif cslot==9 then
slot="EEPROM"
else
slot="#"..(cslot+2)
end
managed="Yes"
readOnly="No"
if type=="drive" then
managed="No"
capacity=formatSize(proxy.getCapacity())
mount="/special/drive/"..id:sub(1,3)
elseif type=="filesystem" then
capacity=formatSize(proxy.spaceTotal())
if proxy.isReadOnly() then
readOnly="Yes"
end
mount="/mnt/"..id:sub(1,3)
if computer.getBootAddress()==id then mount="/" end
if computer.tmpAddress()==id then
mount="/tmp"
slot="Temporary"
end
elseif type=="eeprom" then
capacity=formatSize(proxy.getSize()+proxy.getDataSize())
mount="/special/eeprom/"
end
if headerUsed("bootable") then
bootable = formatBoolean(isBootable(proxy,type))
end
local clabel = proxy.getLabel()
label=clabel and "\""..clabel.."\"" or "None"
local function insertElement(i,v)
if not tablePos[i] then return end
table.insert(tableOut[tablePos[i]],v or "unknown")
end
insertElement("slot",slot)
insertElement("capacity",capacity)
insertElement("managed",managed)
insertElement("readOnly",readOnly)
insertElement("id",id)
insertElement("mount",mount)
insertElement("bootable",bootable)
insertElement("label",label)
end
local function filter(tbl,test)
local i=1
while i<=#tbl do
if not test(tbl[i]) then
table.remove(tbl,i)
i=i-1
end
i=i+1
end
end
local function luaExpr(arg)
local func,err = load("local component,computer,type,id,readonly,capacity=... local managed,eeprom,halyde,tmp,proxy,slot,all=type==\"drive\",type==\"eeprom\",id==\""..computer.getBootAddress().."\",id==\""..computer.tmpAddress().."\",component.proxy(id),component.slot(id)+2,true return "..arg)
if func then
return function(comp)
local readOnly,capacity=false,nil
if comp[2]=="filesystem" then
readOnly=component.invoke(comp[1],"isReadOnly")
capacity=component.invoke(comp[1],"spaceTotal")
elseif comp[2]=="drive" then
capacity=component.invoke(comp[1],"getCapacity")
elseif comp[2]=="eeprom" then
capacity=component.invoke(comp[1],"getSize")+component.invoke(comp[1],"getDataSize")
end
return func(component,computer,comp[2],comp[1],readOnly,capacity)
end
else
return nil,err
end
end
local function boolToNum(val)
if type(val)=="boolean" then
if val then
return 1
else
return 0
end
end
return val
end
local comps = {}
for i,v in component.list("filesystem") do table.insert(comps,{i,v}) end
for i,v in component.list("drive") do table.insert(comps,{i,v}) end
for i,v in component.list("eeprom") do table.insert(comps,{i,v}) end
if not showAll then
local showArgIdx = table.find(args,"-s") or table.find(args,"--show")
if showArgIdx then
table.remove(args,showArgIdx)
local arg = table.remove(args,showArgIdx)
local func,err = luaExpr(arg)
if func then
filter(comps,func)
else
return print("\x1b[91mInvalid component filter:\n\n"..tostring(err).."\x1b[39m")
end
else
filter(comps,function(comp)
return comp[2]~="eeprom" and comp[1]~=computer.tmpAddress()
end)
end
end
local sortArgIdx = table.find(args,"-S") or table.find(args,"--sort")
if sortArgIdx then
table.remove(args,sortArgIdx)
local arg = table.remove(args,sortArgIdx)
local func,err = luaExpr(arg)
if func then
table.sort(comps,function(a,b)
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")
end
else
table.sort(comps,function(a,b)
return a[1]<b[1]
end)
end
if #comps>0 then
for i,v in ipairs(comps) do handleComponent(v[1],v[2]) end
else
return print("Could not find storage components for this filter.")
end
local function renderTableOutput()
local lines = {}
for i=1,#tableOut[1]-1 do
table.insert(lines,"")
end
for i=1,#tableOut do
local length = 1
for j=1,#lines do
tableOut[i][j+1]=tableOut[i][j+1] or "[nil]"
length = math.max(length,unicode.wlen(tableOut[i][j+1]))
end
for j=1,#lines do
if tableOut[i][1] then
lines[j]=lines[j]..string.rep(" ",length-unicode.wlen(tableOut[i][j+1]))..tableOut[i][j+1]
elseif i<#tableOut then
lines[j]=lines[j]..tableOut[i][j+1]..string.rep(" ",length-unicode.wlen(tableOut[i][j+1]))
else
lines[j]=lines[j]..tableOut[i][j+1]
end
if i<#tableOut then lines[j]=lines[j].." " end
end
end
print(lines[1].."\n")
for i=2,#lines do
print(lines[i])
end
end
renderTableOutput()
+8
View File
@@ -0,0 +1,8 @@
local computer = import("computer")
if type(computer)~="table" then
return print("\x1b[91mComputer library returned '"..type(computer).."' type\x1b[39m")
end
local address = computer.getBootAddress()
print(address)
+1 -1
View File
@@ -1 +1 @@
{"prompt":"\u001b[92m%s > \u001b[0m","aliases":{"move":"mv","copy":"cp","ag":"argentum","rename":"mv","..":"cd ..","man":"help","del":"rm","delete":"rm","ren":"mv","remove":"rm","list":"ls","wget":"download","dir":"ls","ps":"lscor","poweroff":"shutdown","restart":"reboot"},"splashMessages":["Made by John Haly- I mean Cerulean Blue.","Welcome! Type \"help\" to get started.","Also try KOCOS!","Welcome back, Commander. We have no idea what we're doing.","99.9% bug-free. The remaining 0.1% are features.","0 days since last error.","Everything is fine. The fire is decorative.","Please don't feed the background processes.","Also has fetch!","Anything red is no man's land. Trust me.","Machine...","Abort, Retry, Fail?","What's the deal with /argentum/store?","So cutting-edge you can't hold it in your hand.","Americans are the reason you see colors on-screen. I'm talking about ANSI escape codes, not politics.","Shoutout to Ponali!"],"path":["/halyde/apps/"],"startupMessage":"\n │\n │ %s\n │ %s\n │\n ","defaultWorkingDirectory":"/home/"} {"prompt":"\u001b[92m%s > \u001b[0m","aliases":{"move":"mv","copy":"cp","ag":"argentum","rename":"mv","..":"cd ..","man":"help","del":"rm","delete":"rm","ren":"mv","remove":"rm","list":"ls","wget":"download","dir":"ls","ps":"lscor","poweroff":"shutdown","restart":"reboot","lsblk":"lsdrv"},"splashMessages":["Made by John Haly- I mean Cerulean Blue.","Welcome! Type \"help\" to get started.","Also try KOCOS!","Welcome back, Commander. We have no idea what we're doing.","99.9% bug-free. The remaining 0.1% are features.","0 days since last error.","Everything is fine. The fire is decorative.","Please don't feed the background processes.","Also has fetch!","Anything red is no man's land. Trust me.","Machine...","Abort, Retry, Fail?","What's the deal with /argentum/store?","So cutting-edge you can't hold it in your hand.","Americans are the reason you see colors on-screen. I'm talking about ANSI escape codes, not politics.","Shoutout to Ponali!"],"path":["/halyde/apps/"],"startupMessage":"\n │\n │ %s\n │ %s\n │\n ","defaultWorkingDirectory":"/home/"}
+1 -1
View File
@@ -1,7 +1,7 @@
local loadfile = ... local loadfile = ...
local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile) local filesystem = loadfile("/halyde/lib/filesystem.lua")(loadfile)
_G._OSVERSION = "Halyde 2.4.1" _G._OSVERSION = "Halyde 2.5.0"
_G._OSLOGO = "" _G._OSLOGO = ""
local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil local handle, tmpdata = filesystem.open("/halyde/config/oslogo.ans", "r"), nil
repeat repeat
+1
View File
@@ -18,6 +18,7 @@ function compLib.virtual.add(address, componentType, proxy)
checkArg(1, address, "string") checkArg(1, address, "string")
checkArg(2, componentType, "string") checkArg(2, componentType, "string")
checkArg(3, proxy, "table") checkArg(3, proxy, "table")
proxy["address"] = address
componentlib.additions[address] = {["componentType"] = componentType, ["proxy"] = proxy} componentlib.additions[address] = {["componentType"] = componentType, ["proxy"] = proxy}
if componentlib.removals[address] then if componentlib.removals[address] then
componentlib.removals[address] = nil componentlib.removals[address] = nil