OC-KittenOS/code/libs/sys-filevfs.lua

221 lines
5.8 KiB
Lua

-- This is released into the public domain.
-- No warranty is provided, implied or otherwise.
-- Used by filedialog to provide a sane relative environment.
-- Essentially, the filedialog is just a 'thin' UI wrapper over this.
-- Returns the root node.
local function dialog(name, parent)
return {
name = name,
list = function () return {{"Back", function () return nil, parent end}} end,
unknownAvailable = false,
selectUnknown = function (text) end
}
end
local getFsNode, getRoot
local setupCopyNode
function setupCopyNode(parent, myRoot, op, complete)
local function handleResult(aRes, res)
if aRes then
return complete(res, true)
else
return nil, setupCopyNode(parent, res, op, complete)
end
end
return {
name = "(" .. op .. ") " .. myRoot.name,
list = function ()
local l = {}
table.insert(l, {"Cancel Operation: " .. op, function ()
complete(nil, false)
return false, parent
end})
for _, v in ipairs(myRoot.list()) do
table.insert(l, {v[1], function ()
return handleResult(v[2]())
end})
end
return l
end,
unknownAvailable = myRoot.unknownAvailable,
selectUnknown = function (tx)
return handleResult(myRoot.selectUnknown(tx))
end
}
end
local function setupCopyVirtualEnvironment(fs, parent, fwrap, impliedName)
if not fwrap then
return false, dialog("Could not open source", parent)
end
local myRoot = getRoot(fs, true, impliedName)
-- Setup wrapping node
return setupCopyNode(parent, myRoot, "Copy", function (fwrap2, intent)
if not fwrap2 then
fwrap.close()
if intent then
return false, dialog("Could not open dest.", parent)
end
return false, parent
end
local data = fwrap.read(neo.readBufSize)
while data do
fwrap2.write(data)
data = fwrap.read(neo.readBufSize)
end
fwrap.close()
fwrap2.close()
return false, dialog("Completed copy.", parent)
end)
end
function getFsNode(fs, parent, fsc, path, mode, impliedName)
local va = fsc.address:sub(1, 4)
local fscrw = not fsc.isReadOnly()
local dir = path:sub(#path, #path) == "/"
local confirmedDel = false
local t
local function selectUnknown(text)
-- Relies on text being nil if used in leaf node
local rt, re = require("sys-filewrap").create(fsc, path .. (text or ""), mode)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return true, rt
end
t = {
name = ((dir and "DIR: ") or "FILE: ") .. va .. path,
list = function ()
local n = {}
n[1] = {"..", function ()
return nil, parent
end}
if dir then
for k, v in ipairs(fsc.list(path)) do
local nm = "F: " .. v
local fp = path .. v
if fsc.isDirectory(fp) then
nm = "D: " .. v
end
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode, impliedName) end}
end
end
if fscrw then
if dir then
table.insert(n, {"Mk. Directory", function ()
return nil, {
name = "MKDIR...",
list = function () return {{
"Cancel", function ()
return false, t
end
}} end,
unknownAvailable = true,
selectUnknown = function (text)
fsc.makeDirectory(path .. text)
return nil, dialog("Done!", t)
end
}
end})
end
if path ~= "/" then
local delText = "Delete"
if confirmedDel then
delText = "Delete <ARMED>"
end
table.insert(n, {delText, function ()
if not confirmedDel then
confirmedDel = true
return nil, t
end
fsc.remove(path)
return nil, dialog("Done.", parent)
end})
else
table.insert(n, {"Relabel Disk", function ()
return nil, {
name = "Disk Relabel...",
list = function () return {{
fsc.getLabel() or "Cancel",
function ()
return false, t
end
}} end,
unknownAvailable = true,
selectUnknown = function (tx)
fsc.setLabel(tx)
return false, t
end
}
end})
end
end
if not dir then
table.insert(n, {"Copy", function ()
local rt, re = require("sys-filewrap").create(fsc, path, false)
if not rt then
return false, dialog("Open Error: " .. tostring(re), parent)
end
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
end})
if (fscrw or mode == false) and (mode ~= nil) then
local tx = "Open"
if mode == true then
tx = "Save (Overwrite)"
elseif mode == "append" then
tx = "Append"
end
if fscrw or mode == false then
table.insert(n, {tx, selectUnknown})
end
end
elseif impliedName then
table.insert(n, {"Implied: " .. impliedName, function ()
return selectUnknown(impliedName)
end})
end
return n
end,
unknownAvailable = dir and (mode ~= nil) and ((mode == false) or fscrw),
selectUnknown = selectUnknown
}
return t
end
function getRoot(fs, mode, defName)
local t
t = {
name = "DRVS:",
list = function ()
local l = {}
for fsi in fs.list() do
local id = fsi.getLabel()
if fsi == fs.primary then
id = "NEO" .. ((id and (":" .. id)) or " Disk")
elseif fsi == fs.temporary then
id = "RAM" .. ((id and (" " .. id)) or "Disk")
else
id = id or "Disk"
end
local used, total = fsi.spaceUsed(), fsi.spaceTotal()
local amount = string.format("%02i", math.ceil((used / total) * 100))
local mb = math.floor(total / (1024 * 1024))
if fsi.isReadOnly() then
id = "RO " .. amount .. "% " .. mb .. "M " .. id
else
id = "RW " .. amount .. "% " .. mb .. "M " .. id
end
table.insert(l, {fsi.address:sub(1, 4) .. " " .. id, function ()
return nil, getFsNode(fs, t, fsi, "/", mode, defName)
end})
end
return l
end,
unknownAvailable = false,
selectUnknown = function (text)
return false, dialog("Ow, that hurt...", t)
end
}
return t
end
return getRoot