Files
HyperionOS/Src/hysh/bin/ls

202 lines
6.2 KiB
Plaintext

--:Minify:--
local cloptions = {
a = false,
h = false,
l = false,
help = false,
}
local inpArgs = { ... }
local args = {}
local name = syscall.getTask(syscall.getpid()).name
for _, v in pairs(inpArgs) do
if v:sub(1, 2) == "--" then
local opt = v:sub(3)
if cloptions[opt] == nil then
print(name .. ": unrecognized option '" .. v .. "'.")
print("try '" .. name .. " --help' for more information.")
return
end
cloptions[opt] = true
elseif v:sub(1, 1) == "-" then
for i = 2, #v do
local opt = v:sub(i, i)
if cloptions[opt] == nil then
print(name .. ": invalid option '-" .. opt .. "'.")
print("try '" .. name .. " --help' for more information.")
return
end
cloptions[opt] = true
end
else
table.insert(args, v)
end
end
if cloptions.help then
print("Usage: " .. name .. " [OPTION]... [DIR]")
print("List all entries in the specified DIRectory, or cwd if not specified.")
print("")
print("Options:")
print(" -a do not ignore entries starting with .")
print(" -h with -l, print sizes in human readable format")
print(" -l use a long listing format")
print(" --help display this help and exit")
return
end
local fs = require("fs")
local dir = args[1] or ""
if dir:sub(1, 1) ~= "/" then
dir = syscall.getcwd() .. "/" .. dir
end
if dir:sub(-1) ~= "/" then dir = dir .. "/" end
if not fs.isDir(dir) then
print(name .. ": cannot access '" .. (args[1] or dir) .. "': no such directory")
return
end
local function permStr(perms, etype)
local function b(n) return math.floor(perms / (2^n)) % 2 == 1 end
local t
if etype == 0x01 then t = "l"
elseif etype == nil then t = "-"
else t = "-" end
local ur = b(5) and "r" or "-"
local uw = b(4) and "w" or "-"
local ux = b(9) and (b(6) and "s" or "x") or (b(6) and "S" or "-")
local gr = b(3) and "r" or "-"
local gw = b(2) and "w" or "-"
local gx = b(8) and "x" or "-"
local wr = b(1) and "r" or "-"
local ww = b(0) and "w" or "-"
local wx = b(7) and "x" or "-"
return t .. ur .. uw .. ux .. gr .. gw .. gx .. wr .. ww .. wx
end
local sizePrefixes = { "K", "M", "G", "T" }
local function humanSize(size)
local scale = 0
while size >= 1024 and scale < #sizePrefixes do
size = size / 1024
scale = scale + 1
end
if scale == 0 then return tostring(size).."B" end
if size < 10 then
return string.format("%.1f%s", size, sizePrefixes[scale])
end
return math.floor(size) .. sizePrefixes[scale]
end
local screenSizeStr = syscall.devctl(1, "size")
local sizeX = tonumber(screenSizeStr:match("^(%d+)")) or 80
local list = fs.list(dir)
if not cloptions.a then
for i = #list, 1, -1 do
if list[i]:sub(1, 1) == "." then table.remove(list, i) end
end
end
table.sort(list)
if #list == 0 then return end
if cloptions.l then
for _, v in ipairs(list) do
local fullPath = dir .. v
local stat = syscall.lstat and syscall.lstat(fullPath) or syscall.stat(fullPath)
local isDir = fs.isDir(fullPath)
local isSym = stat and stat.etype == 0x01
local isSock = stat and stat.etype == 0x02
local typeChar
if isSym then typeChar = "l"
elseif isDir then typeChar = "d"
elseif isSock then typeChar = "s"
else typeChar = "-" end
local pstr
if stat and stat.perms then
pstr = permStr(stat.perms, stat.etype)
else
pstr = typeChar .. "---------"
end
local size = (stat and stat.size) or 0
local sizeStr = cloptions.h and humanSize(size) or tostring(size)
local mtime = (stat and stat.modified) and math.floor(stat.modified / 1000) or 0
local owner = (stat and tostring(stat.owner)) or "0"
local group = (stat and tostring(stat.group)) or "0"
printInline(pstr .. " " .. owner .. " " .. group .. " ")
printInline(string.format("%6s", sizeStr) .. " ")
printInline(tostring(mtime) .. " ")
if isSym then
syscall.devctl(1, "sfgc", 0x00FFFF)
printInline(v)
syscall.devctl(1, "sfgc", 0xFFFFFF)
local ok, target = pcall(syscall.readlink, fullPath)
if ok then
printInline(" -> ")
local targetExists = pcall(syscall.stat, fullPath)
syscall.devctl(1, "sfgc", targetExists and 0x00FFFF or 0xFF0000)
printInline(target)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
elseif isDir then
syscall.devctl(1, "sfgc", 0x6D00FF)
printInline(v)
syscall.devctl(1, "sfgc", 0xFFFFFF)
elseif isSock then
syscall.devctl(1, "sfgc", 0xFF00FF)
printInline(v)
syscall.devctl(1, "sfgc", 0xFFFFFF)
else
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF)
printInline(v)
syscall.devctl(1, "sfgc", 0xFFFFFF)
end
print("")
end
return
end
local colWidth = 0
for _, v in ipairs(list) do
if #v + 2 > colWidth then colWidth = #v + 2 end
end
local numCols = math.max(1, math.floor(sizeX / colWidth))
for i, v in ipairs(list) do
local fullPath = dir .. v
local isDir = fs.isDir(fullPath)
local stat = syscall.lstat and syscall.lstat(fullPath) or syscall.stat(fullPath)
local isSym = stat and stat.etype == 0x01
if isSym then
syscall.devctl(1, "sfgc", 0x00FFFF)
elseif isDir then
syscall.devctl(1, "sfgc", 0x6D00FF)
elseif isSock then
syscall.devctl(1, "sfgc", 0xFF00FF)
else
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
syscall.devctl(1, "sfgc", isExec and 0x00FF00 or 0xFFFFFF)
end
printInline(v)
syscall.devctl(1, "sfgc", 0xFFFFFF)
printInline((" "):rep(colWidth - #v))
if i % numCols == 0 then print("") end
end
if #list % numCols ~= 0 then print("") end