diff --git a/data/core/fsutils.lua b/data/core/fsutils.lua new file mode 100644 index 0000000..746c978 --- /dev/null +++ b/data/core/fsutils.lua @@ -0,0 +1,167 @@ +local core = require "core" +local common = require "core.common" +local command = require "core.command" + +local fsutils = {} + +function fsutils.iterdir(dir) + local stack = { dir } + return function() + local path = table.remove(stack) + if not path then return end + + for _, file in ipairs(system.list_dir(path) or {}) do + stack[#stack + 1] = path .. PATHSEP .. file + end + + return path, system.get_file_info(path) + end +end + +function fsutils.delete(dir, yield) + local dirs = {} + local n = 0 + for filename, stat in fsutils.iterdir(dir) do + if stat.type == "dir" then + -- this will later allow us to delete the dirs in correct sequence + table.insert(dirs, filename) + else + os.remove(filename) + if yield then + n = n + 1 + coroutine.yield(n) + end + end + end + for i = #dirs, 1, -1 do + os.remove(dirs[i]) + if yield then + n = n + 1 + coroutine.yield(n) + end + end +end + +function fsutils.move(oldname, newname) + os.rename(oldname, newname) +end + +function fsutils.split(path) + local segments = {} + local pos = 1 + while true do + local s, e = string.find(path, "[/\\]+", pos) + if not s then break end + table.insert(segments, string.sub(path, pos, s - 1)) + pos = e + 1 + end + table.insert(list, string.sub(path, pos)) + + if segments[#segments] == '' then + table.remove(segments) + end + + return segments +end + +function fsutils.normalize(path) + return table.concat(fsutils.split(path), PATHSEP) +end + +function fsutils.normalize_posix(path) + return table.concat(fsutils.split(path), '/') +end + +function fsutils.mkdir(path) + local segments = fsutils.split(path) + if system.mkdir then + local p = "" + for i = 1, #segments do + p = table.concat(segments, PATHSEP, 1, i) + end + + if p == "" then + return nil, "path empty", p + end + + local stat = system.get_file_info(p) + if stat and stat.type == "file" then + return nil, "path exists as a file", p + end + local ok, err = system.mkdir(p) + if not ok then + return nil, err, p + end + else + -- just wing it lol + system.exec("mkdir -p %q", fsutils.normalize(path))) + end +end + +local function async_exec(f, cb) + cb = cb or function() end + local co = coroutine.create(f) + local function resolve(...) + local ok, exec_body = coroutine.resume(co, ...) + if not ok then + error(debug.traceback(co, exec_body)) + end + if coroutine.status(co) ~= "dead" then + exec_body(resolve) + end + end + resolve(cb) +end + +local function prompt(text, suggest) + return coroutine.yield(function(resolve) + core.command_view:enter(text, resolve, suggest) + end) +end + +command.add(nil, { + ["files:delete"] = function() + async_exec(function() + local path = prompt("Delete", common.path_suggest) + + core.add_thread(function() + -- we use a wrapping coroutine to get status + local function delete() + return coroutine.wrap(function() fsutils.delete(path, true) end) + end + + for n in delete() do + if n % 100 == 0 then + core.log("Deleted %d items...", n) + coroutine.yield() + end + end + core.log("%q deleted.", path) + end) + end) + end, + ["files:move"] = function() + async_exec(function() + local oldname = prompt("Move", common.path_suggest) + local newname = prompt("To", common.path_suggest) + + fsutils.move(oldname, newname) + core.log("Moved %q to %q", oldname, newname) + end) + end +}) + +if not command.map["files:create-directory"] then + command.add(nil, { + ["files:create-directory"] = function() + async_exec(function() + local path = prompt("Name", common.path_suggest) + fsutils.mkdir(path) + core.log("%q created.", path) + end) + end + }) +end + +return fsutils + diff --git a/data/core/init.lua b/data/core/init.lua index 1fa17f3..d400713 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -2,6 +2,7 @@ require "core.strict" local common = require "core.common" local config = require "core.config" local style = require "core.style" +local fs = require "core.fsutils" local command local keymap local RootView @@ -125,6 +126,11 @@ function core.init() end -- write project dir to log file + -- create userdir first + local us = fs.mkdir(USERDIR) + if !us then + error("Error creating user directory\n") + end local d = io.open(USERDIR .. '/last_dir', "w") d:write(tostring(system.absolute_path(project_dir))) d:close()