Merge pull request #1010 from Guldoman/PR_improve_multiproject_treeview

`TreeView` improvements for multi-project
This commit is contained in:
Jefferson González 2022-06-07 18:24:54 -04:00 committed by GitHub
commit 2fc20330a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 144 additions and 47 deletions

View File

@ -140,9 +140,25 @@ function common.fuzzy_match_with_recents(haystack, recents, needle)
end end
function common.path_suggest(text) function common.path_suggest(text, root)
if root and root:sub(-1) ~= PATHSEP then
root = root .. PATHSEP
end
local path, name = text:match("^(.-)([^/\\]*)$") local path, name = text:match("^(.-)([^/\\]*)$")
local files = system.list_dir(path == "" and "." or path) or {} -- ignore root if path is absolute
local is_absolute = common.is_absolute_path(text)
if not is_absolute then
if path == "" then
path = root or "."
else
path = (root or "") .. path
end
end
local files = system.list_dir(path) or {}
if path:sub(-1) ~= PATHSEP then
path = path .. PATHSEP
end
local res = {} local res = {}
for _, file in ipairs(files) do for _, file in ipairs(files) do
file = path .. file file = path .. file
@ -151,6 +167,13 @@ function common.path_suggest(text)
if info.type == "dir" then if info.type == "dir" then
file = file .. PATHSEP file = file .. PATHSEP
end end
if root then
-- remove root part from file path
local s, e = file:find(root, nil, true)
if s == 1 then
file = file:sub(e + 1)
end
end
if file:lower():find(text:lower(), nil, true) == 1 then if file:lower():find(text:lower(), nil, true) == 1 then
table.insert(res, file) table.insert(res, file)
end end
@ -385,6 +408,11 @@ function common.normalize_path(filename)
end end
function common.is_absolute_path(path)
return path:sub(1, 1) == PATHSEP or path:match("^(%a):\\")
end
function common.path_belongs_to(filename, path) function common.path_belongs_to(filename, path)
return string.find(filename, path .. PATHSEP, 1, true) == 1 return string.find(filename, path .. PATHSEP, 1, true) == 1
end end

View File

@ -605,7 +605,7 @@ end
-- This function should get only filenames normalized using -- This function should get only filenames normalized using
-- common.normalize_path function. -- common.normalize_path function.
function core.project_absolute_path(filename) function core.project_absolute_path(filename)
if filename:match('^%a:\\') or filename:find('/', 1, true) == 1 then if common.is_absolute_path(filename) then
return common.normalize_path(filename) return common.normalize_path(filename)
elseif not core.project_dir then elseif not core.project_dir then
local cwd = system.absolute_path(".") local cwd = system.absolute_path(".")

View File

@ -389,6 +389,7 @@ function TreeView:draw()
end end
end end
function TreeView:get_parent(item) function TreeView:get_parent(item)
local parent_path = common.dirname(item.abs_filename) local parent_path = common.dirname(item.abs_filename)
if not parent_path then return end if not parent_path then return end
@ -399,6 +400,40 @@ function TreeView:get_parent(item)
end end
end end
function TreeView:get_item(item, where)
local last_item, last_x, last_y, last_w, last_h
local stop = false
for it, x, y, w, h in self:each_item() do
if not item and where >= 0 then
return it, x, y, w, h
end
if item == it then
if where < 0 and last_item then
break
elseif where == 0 or (where < 0 and not last_item) then
return it, x, y, w, h
end
stop = true
elseif stop then
item = it
return it, x, y, w, h
end
last_item, last_x, last_y, last_w, last_h = it, x, y, w, h
end
return last_item, last_x, last_y, last_w, last_h
end
function TreeView:get_next(item)
return self:get_item(item, 1)
end
function TreeView:get_previous(item)
return self:get_item(item, -1)
end
function TreeView:toggle_expand(toggle) function TreeView:toggle_expand(toggle)
local item = self.selected_item local item = self.selected_item
@ -483,6 +518,15 @@ function core.on_quit_project()
end end
local function is_project_folder(path) local function is_project_folder(path)
for _,dir in pairs(core.project_directories) do
if dir.name == path then
return true
end
end
return false
end
local function is_primary_project_folder(path)
return core.project_dir == path return core.project_dir == path
end end
@ -512,6 +556,17 @@ menu:register(
} }
) )
menu:register(
function()
return view.hovered_item
and not is_primary_project_folder(view.hovered_item.abs_filename)
and is_project_folder(view.hovered_item.abs_filename)
end,
{
{ text = "Remove directory", command = "treeview:remove-project-directory" },
}
)
local previous_view = nil local previous_view = nil
-- Register the TreeView commands and keymap -- Register the TreeView commands and keymap
@ -548,38 +603,13 @@ command.add(nil, {
command.add(TreeView, { command.add(TreeView, {
["treeview:next"] = function() ["treeview:next"] = function()
local item = view.selected_item local item, _, item_y = view:get_next(view.selected_item)
local item_y
local stop = false
for it, _, y in view:each_item() do
if item == it then
stop = true
elseif stop then
item = it
item_y = y
break
end
end
view:set_selection(item, item_y) view:set_selection(item, item_y)
end, end,
["treeview:previous"] = function() ["treeview:previous"] = function()
local last_item local item, _, item_y = view:get_previous(view.selected_item)
local last_item_y view:set_selection(item, item_y)
for it, _, y in view:each_item() do
if it == view.selected_item then
if not last_item then
last_item = it
last_item_y = y
end
break
end
last_item = it
last_item_y = y
end
view:set_selection(last_item, last_item_y)
end, end,
["treeview:open"] = function() ["treeview:open"] = function()
@ -627,7 +657,17 @@ command.add(TreeView, {
end, end,
["treeview:expand"] = function() ["treeview:expand"] = function()
view:toggle_expand(true) local item = view.selected_item
if not item or item.type ~= "dir" then return end
if item.expanded then
local next_item, _, next_y = view:get_next(item)
if next_item.depth > item.depth then
view:set_selection(next_item, next_y)
end
else
view:toggle_expand(true)
end
end, end,
}) })
@ -646,8 +686,13 @@ command.add(
) )
end, { end, {
["treeview:delete"] = function() ["treeview:delete"] = function()
local filename = treeitem().abs_filename local item = treeitem()
local relfilename = treeitem().filename local filename = item.abs_filename
local relfilename = item.filename
if item.dir_name ~= core.project_dir then
-- add secondary project dirs names to the file path to show
relfilename = common.basename(item.dir_name) .. PATHSEP .. relfilename
end
local file_info = system.get_file_info(filename) local file_info = system.get_file_info(filename)
local file_type = file_info.type == "dir" and "Directory" or "File" local file_type = file_info.type == "dir" and "Directory" or "File"
-- Ask before deleting -- Ask before deleting
@ -687,13 +732,16 @@ command.add(
command.add(function() return treeitem() ~= nil end, { command.add(function() return treeitem() ~= nil end, {
["treeview:rename"] = function() ["treeview:rename"] = function()
local old_filename = treeitem().filename local item = treeitem()
local old_abs_filename = treeitem().abs_filename local old_filename = item.filename
local old_abs_filename = item.abs_filename
core.command_view:set_text(old_filename) core.command_view:set_text(old_filename)
core.command_view:enter("Rename", { core.command_view:enter("Rename", {
submit = function(filename) submit = function(filename)
filename = core.normalize_to_project_dir(filename) local abs_filename = filename
local abs_filename = core.project_absolute_path(filename) if not common.is_absolute_path(filename) then
abs_filename = item.dir_name .. PATHSEP .. filename
end
local res, err = os.rename(old_abs_filename, abs_filename) local res, err = os.rename(old_abs_filename, abs_filename)
if res then -- successfully renamed if res then -- successfully renamed
for _, doc in ipairs(core.docs) do for _, doc in ipairs(core.docs) do
@ -708,38 +756,47 @@ command.add(function() return treeitem() ~= nil end, {
core.error("Error while renaming \"%s\" to \"%s\": %s", old_abs_filename, abs_filename, err) core.error("Error while renaming \"%s\" to \"%s\": %s", old_abs_filename, abs_filename, err)
end end
end, end,
suggest = common.path_suggest suggest = function(text)
return common.path_suggest(text, item.dir_name)
end
}) })
end, end,
["treeview:new-file"] = function() ["treeview:new-file"] = function()
if not is_project_folder(treeitem().abs_filename) then local item = treeitem()
core.command_view:set_text(treeitem().filename .. "/") if not is_project_folder(item.abs_filename) then
core.command_view:set_text(item.filename .. PATHSEP)
end end
core.command_view:enter("Filename", { core.command_view:enter("Filename", {
submit = function(filename) submit = function(filename)
local doc_filename = core.project_dir .. PATHSEP .. filename local doc_filename = item.dir_name .. PATHSEP .. filename
core.log(doc_filename)
local file = io.open(doc_filename, "a+") local file = io.open(doc_filename, "a+")
file:write("") file:write("")
file:close() file:close()
core.root_view:open_doc(core.open_doc(doc_filename)) core.root_view:open_doc(core.open_doc(doc_filename))
core.log("Created %s", doc_filename) core.log("Created %s", doc_filename)
end, end,
suggest = common.path_suggest suggest = function(text)
return common.path_suggest(text, item.dir_name)
end
}) })
end, end,
["treeview:new-folder"] = function() ["treeview:new-folder"] = function()
if not is_project_folder(treeitem().abs_filename) then local item = treeitem()
core.command_view:set_text(treeitem().filename .. "/") if not is_project_folder(item.abs_filename) then
core.command_view:set_text(item.filename .. "/")
end end
core.command_view:enter("Folder Name", { core.command_view:enter("Folder Name", {
submit = function(filename) submit = function(filename)
local dir_path = core.project_dir .. PATHSEP .. filename local dir_path = item.dir_name .. PATHSEP .. filename
common.mkdirp(dir_path) common.mkdirp(dir_path)
core.log("Created %s", dir_path) core.log("Created %s", dir_path)
end, end,
suggest = common.path_suggest suggest = function(text)
return common.path_suggest(text, item.dir_name)
end
}) })
end, end,
@ -756,6 +813,18 @@ command.add(function() return treeitem() ~= nil end, {
end end
}) })
command.add(function()
local item = treeitem()
return item
and not is_primary_project_folder(item.abs_filename)
and is_project_folder(item.abs_filename)
end, {
["treeview:remove-project-directory"] = function()
core.remove_project_directory(treeitem().dir_name)
end,
})
keymap.add { keymap.add {
["ctrl+\\"] = "treeview:toggle", ["ctrl+\\"] = "treeview:toggle",
["up"] = "treeview:previous", ["up"] = "treeview:previous",