WIP: implement new project commands

Implement commands to load a project from a directory and integrate
the project module within the core modules replacing the workspace
plugin.

Needs polishing but the basic functionalities are there.
This commit is contained in:
Francesco Abbate 2021-05-18 17:20:40 +02:00
parent 9e29b90318
commit 52325d20dd
3 changed files with 98 additions and 75 deletions

View File

@ -94,13 +94,15 @@ command.add(nil, {
core.command_view:set_text(common.home_encode(view.doc.filename)) core.command_view:set_text(common.home_encode(view.doc.filename))
end end
core.command_view:enter("Open File", function(text) core.command_view:enter("Open File", function(text)
local filename = core.working_dir_absolute_path(common.home_expand(text)) local filename = common.normalize_path(core.working_dir_absolute_path(common.home_expand(text)))
local info = system.get_file_info(filename) local info = system.get_file_info(filename)
if info and info.type == "dir" then if info and info.type == "dir" then
core.add_project_directory(filename) core.add_project_directory(filename)
core.set_recent_open("dir", filename)
core.reschedule_project_scan() core.reschedule_project_scan()
else else
core.add_project_file(filename) core.add_project_file(filename)
core.set_recent_open("file", filename)
core.root_view:open_doc(core.open_doc(filename)) core.root_view:open_doc(core.open_doc(filename))
end end
end, function (text) end, function (text)
@ -146,7 +148,7 @@ command.add(nil, {
end end
end, end,
["core:change-project-folder"] = function() --[[ ["core:change-project-folder"] = function()
core.command_view:enter("Change Project Folder", function(text, item) core.command_view:enter("Change Project Folder", function(text, item)
text = system.absolute_path(common.home_expand(item and item.text or text)) text = system.absolute_path(common.home_expand(item and item.text or text))
if text == core.working_dir then return end if text == core.working_dir then return end
@ -169,7 +171,7 @@ command.add(nil, {
end end
system.exec(string.format("%q %q", EXEFILE, text)) system.exec(string.format("%q %q", EXEFILE, text))
end, suggest_directory) end, suggest_directory)
end, end,]]
["core:add-directory"] = function() ["core:add-directory"] = function()
core.command_view:enter("Add Directory", function(text, item) core.command_view:enter("Add Directory", function(text, item)

View File

@ -4,6 +4,7 @@ local common = require "core.common"
local config = require "core.config" local config = require "core.config"
local style = require "core.style" local style = require "core.style"
local command local command
local project
local keymap local keymap
local RootView local RootView
local StatusView local StatusView
@ -20,40 +21,51 @@ local function load_session()
if ok then if ok then
return t.recents, t.window, t.window_mode return t.recents, t.window, t.window_mode
end end
return {} return {}, {dir={}, file={}}
end end
local function save_session() local function save_session()
local fp = io.open(USERDIR .. "/session.lua", "w") local fp = io.open(USERDIR .. "/session.lua", "w")
if fp then if fp then
fp:write("return {recents=", common.serialize(core.recent_projects), fp:write(string.format(
", window=", common.serialize(table.pack(system.get_window_size())), "return { recent_projects= %s, recents_open= %s, window= %s, window_mode= %s}\n",
", window_mode=", common.serialize(system.get_window_mode()), common.serialize(core.recent_projects),
"}\n") common.serialize(core.recents_open),
common.serialize(table.pack(system.get_window_size())),
common.serialize(system.get_window_mode())
))
fp:close() fp:close()
end end
end end
local function update_recents_project(action, dir_path_abs) local function update_recents(recents, action, name)
local dirname = common.normalize_path(dir_path_abs)
if not dirname then return end
local recents = core.recent_projects
local n = #recents local n = #recents
for i = 1, n do for i = 1, n do
if dirname == recents[i] then if name == recents[i] then
table.remove(recents, i) table.remove(recents, i)
break break
end end
end end
if action == "add" then if action == "add" then
table.insert(recents, 1, dirname) table.insert(recents, 1, name)
end end
end end
local function cleanup_recent_projects() function core.set_recent_project(name)
update_recents(core.recent_projects, "add", name)
end
function core.set_recent_open(type, filename)
update_recents(core.recents_open[type], "add", filename)
end
-- FIXME: remove or adapt
--[[ local function cleanup_recent_projects()
local recents = core.recent_projects local recents = core.recent_projects
local i = 1 local i = 1
while i <= #recents do while i <= #recents do
@ -64,7 +76,7 @@ local function cleanup_recent_projects()
i = i + 1 i = i + 1
end end
end end
end end ]]
function core.reschedule_project_scan() function core.reschedule_project_scan()
@ -74,11 +86,14 @@ function core.reschedule_project_scan()
end end
function core.open_folder_project(dir_path_abs) function core.new_project_from_directory(dir_path_abs)
core.root_view:close_all_docviews() core.root_view:close_all_docviews()
core.project_entries = {} core.project_entries = {}
core.add_project_directory(dir_path_abs) core.add_project_directory(dir_path_abs)
update_recents_project("add", dir_path_abs) system.chdir(dir_path_abs)
core.working_dir = dir_path_abs
core.set_recent_open("dir", dir_path_abs)
core.reschedule_project_scan()
end end
@ -451,6 +466,7 @@ end
function core.init() function core.init()
command = require "core.command" command = require "core.command"
keymap = require "core.keymap" keymap = require "core.keymap"
project = require "core.project"
RootView = require "core.rootview" RootView = require "core.rootview"
StatusView = require "core.statusview" StatusView = require "core.statusview"
TitleView = require "core.titleview" TitleView = require "core.titleview"
@ -466,19 +482,21 @@ function core.init()
end end
do do
local recent_projects, window_position, window_mode = load_session() -- FIXME: change the name for "recents_open"
local window_position
core.recent_projects, core.recents_open, window_position, window_mode = load_session()
if window_mode == "normal" then if window_mode == "normal" then
system.set_window_size(table.unpack(window_position)) system.set_window_size(table.unpack(window_position))
elseif window_mode == "maximized" then elseif window_mode == "maximized" then
system.set_window_mode("maximized") system.set_window_mode("maximized")
end end
core.recent_projects = recent_projects
end end
cleanup_recent_projects() -- cleanup_recent_projects()
core.log_items = {} core.log_items = {}
core.docs = {} core.docs = {}
core.project_entries = {} core.project_entries = {}
core.project_name = ""
local init_files = {} local init_files = {}
local delayed_errors = {} local delayed_errors = {}
@ -495,7 +513,8 @@ function core.init()
filename = system.absolute_path(filename) filename = system.absolute_path(filename)
if filename then if filename then
core.add_project_directory(filename) core.add_project_directory(filename)
update_recents_project("add", filename) -- FIXME
-- update_recents(core.recents_open.dir, "add", filename)
end end
else else
local error_msg = string.format("error: invalid file or directory \"%s\"", ARGS[i]) local error_msg = string.format("error: invalid file or directory \"%s\"", ARGS[i])
@ -503,16 +522,6 @@ function core.init()
end end
end end
local init_message
if #core.project_entries == 0 then
if #core.recent_projects > 0 then
init_message = string.format("Opening project from directory \"%s\"", core.recent_projects[1])
core.add_project_directory(core.recent_projects[1])
else
init_message = string.format("Empty project: use the \"Core: Open File\" command to open a file or a directory.")
end
end
core.threads = setmetatable({}, { __mode = "k" }) core.threads = setmetatable({}, { __mode = "k" })
core.frame_start = 0 core.frame_start = 0
core.clip_rect_stack = {{ 0,0,0,0 }} core.clip_rect_stack = {{ 0,0,0,0 }}
@ -554,10 +563,6 @@ function core.init()
core.working_dir = system.absolute_path(".") core.working_dir = system.absolute_path(".")
end end
if init_message then
core.log(init_message)
end
local got_user_error = not core.load_user_directory() local got_user_error = not core.load_user_directory()
local plugins_success, plugins_refuse_list = core.load_plugins() local plugins_success, plugins_refuse_list = core.load_plugins()
local got_project_error = not core.load_project_module() local got_project_error = not core.load_project_module()
@ -651,12 +656,16 @@ function core.temp_filename(ext)
.. string.format("%06x", temp_file_counter) .. (ext or "") .. string.format("%06x", temp_file_counter) .. (ext or "")
end end
-- override to perform an operation before quitting or entering the
-- current project function core.on_quit_project()
do local filename = USERDIR .. PATHSEP .. "workspace.lua"
local do_nothing = function() end core.try(project.save_workspace, filename)
core.on_quit_project = do_nothing end
core.on_enter_project = do_nothing
function core.on_enter_project(new_dir)
-- FIXME: check the logic
-- core.try(project.load_workspace, USERDIR .. PATHSEP .. "workspace.lua")
end end

View File

@ -1,9 +1,9 @@
-- mod-version:1 -- lite-xl 1.16
local core = require "core" local core = require "core"
local command = require "core.command" local command = require "core.command"
local common = require "core.common" local common = require "core.common"
local DocView = require "core.docview" local DocView = require "core.docview"
local project = {}
local function has_no_locked_children(node) local function has_no_locked_children(node)
if node.locked then return false end if node.locked then return false end
@ -110,7 +110,7 @@ local function load_node(node, t)
end end
local function save_workspace(filename) function project.save_workspace(filename)
local root = get_unlocked_root(core.root_view.root_node) local root = get_unlocked_root(core.root_view.root_node)
local fp = io.open(filename, "w") local fp = io.open(filename, "w")
if fp then if fp then
@ -122,21 +122,35 @@ local function save_workspace(filename)
end end
end end
local project_entries_text = common.serialize(topdir_entries) local project_entries_text = common.serialize(topdir_entries)
fp:write(string.format("return { working_dir = %q, documents = %s, project_entries = %s }\n", core.working_dir, node_text, project_entries_text)) fp:write(string.format(
"return { project_name = %q, working_dir = %q, documents = %s, project_entries = %s }\n",
core.project_name, core.working_dir, node_text, project_entries_text))
fp:close() fp:close()
end end
end end
local function load_workspace(filename) function project.load(name)
core.project_name = name
local filename = common.path_join(USERDIR, "projects", name .. ".lua")
project.load_workspace(filename)
core.log("Loaded project %s.", core.project_name)
core.reschedule_project_scan()
end
function project.load_workspace(filename)
local load = loadfile(filename) local load = loadfile(filename)
local workspace = load and load() local workspace = load and load()
-- FIXME: decide, error or return a success code
if not workspace then error("Cannot load workspace") end
if workspace then if workspace then
local root = get_unlocked_root(core.root_view.root_node) local root = get_unlocked_root(core.root_view.root_node)
local active_view = load_node(root, workspace.documents) local active_view = load_node(root, workspace.documents)
if active_view then if active_view then
core.set_active_view(active_view) core.set_active_view(active_view)
end end
core.project_name = workspace.project_name
core.project_entries = {} core.project_entries = {}
for _, entry in ipairs(workspace.project_entries) do for _, entry in ipairs(workspace.project_entries) do
if entry.type == "dir" then if entry.type == "dir" then
@ -149,29 +163,9 @@ local function load_workspace(filename)
end end
end end
local function suggest_directory(text)
local run = core.run text = common.home_expand(text)
return common.home_encode_list(text == "" and core.recents_open.dir or common.dir_path_suggest(text))
function core.run(...)
if #core.docs == 0 then
core.try(load_workspace, USERDIR .. PATHSEP .. "workspace.lua")
local on_quit_project = core.on_quit_project
function core.on_quit_project()
local filename = USERDIR .. PATHSEP .. "workspace.lua"
core.try(save_workspace, filename)
on_quit_project()
end
local on_enter_project = core.on_enter_project
function core.on_enter_project(new_dir)
on_enter_project(new_dir)
core.try(load_workspace, USERDIR .. PATHSEP .. "workspace.lua")
end
end
core.run = run
return core.run(...)
end end
command.add(nil, { command.add(nil, {
@ -188,20 +182,38 @@ command.add(nil, {
core.log("Saved project %s.", core.project_name) core.log("Saved project %s.", core.project_name)
end) end)
end, end,
["project:save"] = function() ["project:save"] = function()
if core.project_name == "" then
core.command_view:enter("Save Project As", function(text)
core.project_name = text
end)
end
local filename = common.path_join(USERDIR, "projects", core.project_name .. ".lua") local filename = common.path_join(USERDIR, "projects", core.project_name .. ".lua")
save_workspace(filename) save_workspace(filename)
core.set_recent_project(core.project_name)
core.log("Saved project %s.", core.project_name) core.log("Saved project %s.", core.project_name)
end, end,
["project:load"] = function() ["project:load"] = function()
core.command_view:enter("Load Project", function(text) core.command_view:enter("Load Project", function(text)
-- FIXME: add sanity check of project name. project.load(text)
core.project_name = text core.set_recent_project(core.project_name)
local filename = common.path_join(USERDIR, "projects", text .. ".lua")
load_workspace(filename)
core.log("Loaded project %s.", core.project_name)
core.reschedule_project_scan()
end) end)
end, end,
["project:open-directory"] = function()
core.command_view:enter("Open Directory", function(text, item)
text = system.absolute_path(common.home_expand(item and item.text or text))
if text == core.working_dir then return end
local path_stat = system.get_file_info(text)
if not path_stat or path_stat.type ~= 'dir' then
core.error("Cannot open folder %q", text)
return
end
core.confirm_close_all(core.new_project_from_directory, text)
end, suggest_directory)
end,
}) })
return project