mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-16 15:38:05 +11:00
2ae3f9a93a
Currently eeprog pirate-speak language is unsupported, but... oh well.
234 lines
6.7 KiB
Lua
234 lines
6.7 KiB
Lua
-- The File Manager (manager of files).
|
|
-- Args:
|
|
local filetype, openmode, gpu = ...
|
|
local fileManager = nil
|
|
function fileManager(filetype, openmode)
|
|
-- Like policykit, this is a trusted gateway.
|
|
-- Note that The File Manager just returns a path {fs, path}.
|
|
-- The File Wrapper is given that path, and the open mode.
|
|
local title = nil
|
|
-- Valid open modes are:
|
|
-- nil: The File Wrapper should not be invoked -
|
|
-- likely a "file manager launcher" application.
|
|
if openmode == nil then title = "File Manager" end
|
|
-- "r": Open the file for reading. Binary mode is assumed.
|
|
if openmode == "r" then
|
|
title = "Read " .. filetype
|
|
end
|
|
if openmode == "w" then
|
|
title = "Write " .. filetype
|
|
end
|
|
-- "w": Open the file for truncate-writing, again binary assumed.
|
|
if not title then error("Bad openmode") end
|
|
|
|
local scrW, scrH = gpu.getResolution()
|
|
gpu.setBackground(0)
|
|
gpu.setForeground(0xFFFFFF)
|
|
local function cls()
|
|
gpu.fill(1, 1, scrW, scrH, " ")
|
|
end
|
|
local function menuKey(cursor, el, text, ka, kc, allowEntry)
|
|
if ka == 13 then
|
|
-- entry denied, so we hit here.
|
|
return cursor, text
|
|
end
|
|
if kc == 200 then
|
|
cursor = cursor - 1
|
|
if cursor < 1 then cursor = el end
|
|
return cursor, text, false, true
|
|
end
|
|
if kc == 208 then
|
|
cursor = cursor + 1
|
|
if cursor > el then cursor = 1 end
|
|
return cursor, text, false, true
|
|
end
|
|
if allowEntry then
|
|
if ka == 8 then
|
|
return cursor, unicode.sub(text, 1, unicode.len(text) - 1), true
|
|
end
|
|
if (ka ~= 0) and (ka ~= ("/"):byte()) and (ka ~= ("\\"):byte()) then
|
|
text = text .. unicode.char(ka)
|
|
return cursor, text, true
|
|
end
|
|
end
|
|
return cursor, text
|
|
end
|
|
local function menu(title, entries, allowEntry)
|
|
cls()
|
|
gpu.fill(1, 1, scrW, 1, "-")
|
|
gpu.set(1, 1, title)
|
|
local cursor = 1
|
|
local escrH = scrH
|
|
local entryText = ""
|
|
local cursorBlinky = false
|
|
if allowEntry then escrH = scrH - 1 end
|
|
while true do
|
|
for y = 2, escrH do
|
|
local o = cursor + (y - 8)
|
|
local s = tostring(entries[o])
|
|
if not entries[o] then s = "" end
|
|
if o == cursor then s = ">" .. s else s = " " .. s end
|
|
gpu.fill(1, y, scrW, 1, " ")
|
|
gpu.set(1, y, s)
|
|
end
|
|
cursorBlinky = not cursorBlinky
|
|
if allowEntry then
|
|
gpu.fill(1, scrH, scrW, 1, " ")
|
|
if cursorBlinky then
|
|
gpu.set(1, scrH, ":" .. entryText)
|
|
else
|
|
gpu.set(1, scrH, ":" .. entryText .. "_")
|
|
end
|
|
end
|
|
local t, p1, p2, p3, p4 = computer.pullSignal(1)
|
|
if t == "key_down" then
|
|
if p2 == 13 then
|
|
if allowEntry then
|
|
if entryText ~= "" then
|
|
return entryText
|
|
end
|
|
else
|
|
return entries[cursor]
|
|
end
|
|
end
|
|
cursor, entryText, search, lookup = menuKey(cursor, #entries, entryText, p2, p3, allowEntry)
|
|
if search then
|
|
for k, v in ipairs(entries) do
|
|
if v:sub(1, v:len()) == entryText then cursor = k end
|
|
end
|
|
end
|
|
if lookup then
|
|
entryText = entries[cursor]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local currentDir = nil
|
|
local currentDrive = nil
|
|
local function listDir(dv, dr)
|
|
if dv == nil then
|
|
local l = {}
|
|
local t = {}
|
|
for c in component.list("filesystem") do
|
|
l[c] = {c, "/"}
|
|
table.insert(t, c)
|
|
end
|
|
return l, t, "Filesystems"
|
|
end
|
|
local names = component.invoke(dv, "list", dr)
|
|
local l = {}
|
|
for k, v in ipairs(names) do
|
|
if component.invoke(dv, "isDirectory", dr .. v) then
|
|
l[v] = {dv, dr .. v}
|
|
end
|
|
end
|
|
return l, names, dv .. ":" .. dr
|
|
end
|
|
local function isDir(dv, dr)
|
|
if dv == nil then return true end
|
|
return component.invoke(dv, "isDirectory", dr)
|
|
end
|
|
|
|
local tagMkdir = "// Create Directory //"
|
|
local tagCancel = "// Cancel //"
|
|
local tagOpen = "// Open //"
|
|
local tagDelete = "// Delete //"
|
|
local tagRename = "// Rename //"
|
|
local tagCopy = "// Copy //"
|
|
local tagBack = ".."
|
|
|
|
local function textEntry(title)
|
|
local txt = menu(title, {tagCancel}, true)
|
|
if txt ~= tagCancel then return txt end
|
|
return nil
|
|
end
|
|
local function report(title)
|
|
menu(title, {"OK"}, false)
|
|
end
|
|
|
|
local history = {}
|
|
local function navigate(ndr, ndd)
|
|
table.insert(history, {currentDrive, currentDir})
|
|
currentDrive, currentDir = ndr, ndd
|
|
end
|
|
while true do
|
|
local map, sl, name = listDir(currentDrive, currentDir)
|
|
if #history ~= 0 then
|
|
table.insert(sl, tagBack)
|
|
end
|
|
table.insert(sl, tagCancel)
|
|
if currentDrive then
|
|
table.insert(sl, tagMkdir)
|
|
end
|
|
local str = menu(title .. " " .. name, sl, (openmode == "w") and currentDrive)
|
|
if str == tagBack then
|
|
local r = table.remove(history, #history)
|
|
currentDrive, currentDir = table.unpack(r)
|
|
else
|
|
if str == tagCancel then return nil end
|
|
if str == tagMkdir then
|
|
local nam = textEntry("Create Directory...")
|
|
if nam then
|
|
component.invoke(currentDrive, "makeDirectory", currentDir .. nam)
|
|
end
|
|
else
|
|
if map[str] then
|
|
if map[str][1] and currentDrive then
|
|
local act = menu(name .. ":" .. str, {tagOpen, tagRename, tagDelete, tagCancel})
|
|
if act == tagOpen then
|
|
navigate(table.unpack(map[str]))
|
|
end
|
|
if act == tagRename then
|
|
local s = textEntry("Rename " .. str)
|
|
if s then
|
|
component.invoke(map[str][1], "rename", map[str][2], currentDir .. s)
|
|
end
|
|
end
|
|
if act == tagDelete then
|
|
component.invoke(map[str][1], "remove", map[str][2])
|
|
end
|
|
else
|
|
navigate(table.unpack(map[str]))
|
|
end
|
|
else
|
|
if openmode == "w" then return {currentDrive, currentDir .. str} end
|
|
local r = currentDir .. str
|
|
local subTag = "Size: " .. math.ceil(component.invoke(currentDrive, "size", r) / 1024) .. "KiB"
|
|
if openmode == "r" then subTag = tagOpen end
|
|
local act = menu(name .. ":" .. str, {subTag, tagRename, tagCopy, tagDelete, tagCancel})
|
|
if act == tagOpen then return {currentDrive, currentDir .. str} end
|
|
if act == tagRename then
|
|
local s = textEntry("Rename " .. str)
|
|
component.invoke(currentDrive, "rename", currentDir .. str, currentDir .. s)
|
|
end
|
|
if act == tagCopy then
|
|
local f2 = fileManager("Copy " .. str, "w")
|
|
if f2 then
|
|
local h = component.invoke(currentDrive, "open", currentDir .. str, "rb")
|
|
if not h then
|
|
report("Couldn't open file!")
|
|
else
|
|
local h2 = component.invoke(f2[1], "open", f2[2], "wb")
|
|
if not h2 then
|
|
report("Couldn't open dest. file!")
|
|
else
|
|
local chk = component.invoke(currentDrive, "read", h, 128)
|
|
while chk do
|
|
component.invoke(f2[1], "write", h2, chk)
|
|
chk = component.invoke(currentDrive, "read", h, 128)
|
|
end
|
|
end
|
|
component.invoke(currentDrive, "close", h)
|
|
end
|
|
end
|
|
end
|
|
if act == tagDelete then
|
|
component.invoke(currentDrive, "remove", currentDir .. str)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return fileManager(filetype, openmode) |