From 9a428648a9bf3506713108aec95b9631f1cf9407 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 1 Jun 2022 03:48:47 +0200 Subject: [PATCH 1/4] Add `common.is_absolute_path` --- data/core/common.lua | 5 +++++ data/core/init.lua | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/data/core/common.lua b/data/core/common.lua index 1aa2b86e..7ed87456 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -385,6 +385,11 @@ function common.normalize_path(filename) 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) return string.find(filename, path .. PATHSEP, 1, true) == 1 end diff --git a/data/core/init.lua b/data/core/init.lua index 59b293c5..4ed83716 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -605,7 +605,7 @@ end -- This function should get only filenames normalized using -- common.normalize_path function. 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) elseif not core.project_dir then local cwd = system.absolute_path(".") From 295e6b7e5ac19348fa4052beec376bf2573122f1 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 1 Jun 2022 03:51:29 +0200 Subject: [PATCH 2/4] Allow `common.path_suggest` to specify a root directory This will make relative paths start from `root`. --- data/core/common.lua | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/data/core/common.lua b/data/core/common.lua index 7ed87456..c123bb4b 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -140,9 +140,25 @@ function common.fuzzy_match_with_recents(haystack, recents, needle) 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 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 = {} for _, file in ipairs(files) do file = path .. file @@ -151,6 +167,13 @@ function common.path_suggest(text) if info.type == "dir" then file = file .. PATHSEP 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 table.insert(res, file) end From e94c996a26f76aba6b1200412071f291e06ea14a Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 1 Jun 2022 03:55:55 +0200 Subject: [PATCH 3/4] Add `TreeView` helper functions to get previous/next item --- data/plugins/treeview.lua | 66 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index ecb3a76d..a0dc4a4f 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -389,6 +389,7 @@ function TreeView:draw() end end + function TreeView:get_parent(item) local parent_path = common.dirname(item.abs_filename) if not parent_path then return end @@ -399,6 +400,40 @@ function TreeView:get_parent(item) 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) local item = self.selected_item @@ -548,38 +583,13 @@ command.add(nil, { command.add(TreeView, { ["treeview:next"] = function() - local item = 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 - + local item, _, item_y = view:get_next(view.selected_item) view:set_selection(item, item_y) end, ["treeview:previous"] = function() - local last_item - local last_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) + local item, _, item_y = view:get_previous(view.selected_item) + view:set_selection(item, item_y) end, ["treeview:open"] = function() From 730ea0c91bf42b71f7be2ce641af521ca226ba81 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Wed, 1 Jun 2022 03:57:14 +0200 Subject: [PATCH 4/4] Make `TreeView` more multi-project-dir aware --- data/plugins/treeview.lua | 93 ++++++++++++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index a0dc4a4f..0f818e0c 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -404,7 +404,7 @@ 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 @@ -518,6 +518,15 @@ function core.on_quit_project() end 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 end @@ -547,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 -- Register the TreeView commands and keymap @@ -637,7 +657,17 @@ command.add(TreeView, { end, ["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, }) @@ -656,8 +686,13 @@ command.add( ) end, { ["treeview:delete"] = function() - local filename = treeitem().abs_filename - local relfilename = treeitem().filename + local item = treeitem() + 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_type = file_info.type == "dir" and "Directory" or "File" -- Ask before deleting @@ -697,13 +732,16 @@ command.add( command.add(function() return treeitem() ~= nil end, { ["treeview:rename"] = function() - local old_filename = treeitem().filename - local old_abs_filename = treeitem().abs_filename + local item = treeitem() + local old_filename = item.filename + local old_abs_filename = item.abs_filename core.command_view:set_text(old_filename) core.command_view:enter("Rename", { submit = function(filename) - filename = core.normalize_to_project_dir(filename) - local abs_filename = core.project_absolute_path(filename) + local abs_filename = 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) if res then -- successfully renamed for _, doc in ipairs(core.docs) do @@ -718,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) end end, - suggest = common.path_suggest + suggest = function(text) + return common.path_suggest(text, item.dir_name) + end }) end, ["treeview:new-file"] = function() - if not is_project_folder(treeitem().abs_filename) then - core.command_view:set_text(treeitem().filename .. "/") + local item = treeitem() + if not is_project_folder(item.abs_filename) then + core.command_view:set_text(item.filename .. PATHSEP) end core.command_view:enter("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+") file:write("") file:close() core.root_view:open_doc(core.open_doc(doc_filename)) core.log("Created %s", doc_filename) end, - suggest = common.path_suggest + suggest = function(text) + return common.path_suggest(text, item.dir_name) + end }) end, ["treeview:new-folder"] = function() - if not is_project_folder(treeitem().abs_filename) then - core.command_view:set_text(treeitem().filename .. "/") + local item = treeitem() + if not is_project_folder(item.abs_filename) then + core.command_view:set_text(item.filename .. "/") end core.command_view:enter("Folder Name", { submit = function(filename) - local dir_path = core.project_dir .. PATHSEP .. filename + local dir_path = item.dir_name .. PATHSEP .. filename common.mkdirp(dir_path) core.log("Created %s", dir_path) end, - suggest = common.path_suggest + suggest = function(text) + return common.path_suggest(text, item.dir_name) + end }) end, @@ -766,6 +813,18 @@ command.add(function() return treeitem() ~= nil 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 { ["ctrl+\\"] = "treeview:toggle", ["up"] = "treeview:previous",