Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstracted out Workplace's storage system for other plugins. #1738

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Abstracted out the storage system of the workspace plugin so other pl…
…ugins can use it.
  • Loading branch information
adamharrison committed Sep 16, 2024
commit 9a50aab275078b4cafc5b54f310fa1312b4fe8bc
51 changes: 51 additions & 0 deletions data/core/storage.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-- Provides persistent storage between restarts of the application.
local common = require "core.common"
local storage = {}

local function module_key_to_path(module, key)
return USERDIR .. PATHSEP .. "storage" .. (module and (PATHSEP .. module .. (key and (PATHSEP .. key:gsub("[\\/]", "-")) or "")) or "")
end

function storage.load(module, key)
local path = module_key_to_path(module, key)
if system.get_file_info(path) then
local func, err = loadfile(path)
if func then
return func()
else
core.error("error loading storage file for %s[%s]: %s", module, key, err)
end
end
return nil
end

function storage.save(module, key, t)
local path = module_key_to_path(module, key)
local dir = common.dirname(path)
if not system.get_file_info(dir) then
local status, err = common.mkdirp(dir)
if not status then
core.error("error creating storage directory for %s at %s: %s", module, dir, err)
end
end
local f, err = io.open(path, "wb")
if f then
f:write("return " .. common.serialize(t))
f:flush()
else
core.error("error opening storage file %s for writing: %s", path, err)
end
end

function storage.keys(module)
return system.list_dir(module_key_to_path(module))
end

function storage.clear(module, key)
local path = module_key_to_path(module, key)
if system.get_file_info(path) then
common.rm(path, true)
end
end

return storage
69 changes: 26 additions & 43 deletions data/plugins/workspace.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,37 @@ local core = require "core"
local common = require "core.common"
local DocView = require "core.docview"
local LogView = require "core.logview"
local storage = require "core.storage"

local STORAGE_MODULE = "ws"

local function workspace_files_for(project_dir)
local function workspace_keys_for(project_dir)
local basename = common.basename(project_dir)
local workspace_dir = USERDIR .. PATHSEP .. "ws"
local info_wsdir = system.get_file_info(workspace_dir)
if not info_wsdir then
local ok, err = system.mkdir(workspace_dir)
if not ok then
error("cannot create workspace directory: \"" .. err .. "\"")
end
end
return coroutine.wrap(function()
local files = system.list_dir(workspace_dir) or {}
local n = #basename
for _, file in ipairs(files) do
if file:sub(1, n) == basename then
local id = tonumber(file:sub(n + 1):match("^-(%d+)$"))
for _, key in ipairs(storage.keys(STORAGE_MODULE) or {}) do
if key:sub(1, #basename) == basename then
local id = tonumber(key:sub(#basename + 1):match("^-(%d+)$"))
if id then
coroutine.yield(workspace_dir .. PATHSEP .. file, id)
coroutine.yield(key, id)
end
end
end
end)
end


local function consume_workspace_file(project_dir)
for filename, id in workspace_files_for(project_dir) do
local load_f = loadfile(filename)
local function consume_workspace(project_dir)
for key, id in workspace_keys_for(project_dir) do
local load_f = load(storage.load(STORAGE_MODULE, key))
local workspace = load_f and load_f()
if workspace and workspace.path == project_dir then
os.remove(filename)
storage.clear(STORAGE_MODULE, key)
return workspace
end
end
end


local function get_workspace_filename(project_dir)
local id_list = {}
for filename, id in workspace_files_for(project_dir) do
id_list[id] = true
end
local id = 1
while id_list[id] do
id = id + 1
end
local basename = common.basename(project_dir)
return USERDIR .. PATHSEP .. "ws" .. PATHSEP .. basename .. "-" .. tostring(id)
end


local function has_no_locked_children(node)
if node.locked then return false end
if node.type == "leaf" then return true end
Expand Down Expand Up @@ -166,7 +144,7 @@ local function load_node(node, t)
active_view = view
end
if not view:is(DocView) then
view.scroll = v.scroll
view.scroll = v.scroll
end
end
end
Expand Down Expand Up @@ -195,20 +173,25 @@ end


local function save_workspace()
local root = get_unlocked_root(core.root_view.root_node)
local workspace_filename = get_workspace_filename(core.project_dir)
local fp = io.open(workspace_filename, "w")
if fp then
local node_text = common.serialize(save_node(root))
local dir_text = common.serialize(save_directories())
fp:write(string.format("return { path = %q, documents = %s, directories = %s }\n", core.project_dir, node_text, dir_text))
fp:close()
local project_dir = common.basename(core.project_dir)
local id_list = {}
for filename, id in workspace_keys_for(project_dir) do
id_list[id] = true
end
local id = 1
while id_list[id] do
id = id + 1
end
local root = get_unlocked_root(core.root_view.root_node)
local node_text = common.serialize(save_node(root))
local dir_text = common.serialize(save_directories())

storage.save(STORAGE_MODULE, project_dir .. "-" .. id, string.format("return { path = %q, documents = %s, directories = %s }\n", core.project_dir, node_text, dir_text))
end


local function load_workspace()
local workspace = consume_workspace_file(core.project_dir)
local workspace = consume_workspace(core.project_dir)
if workspace then
local root = get_unlocked_root(core.root_view.root_node)
local active_view = load_node(root, workspace.documents)
Expand Down