From 2aac1b817965e75e6edbb3dad4483871532260d6 Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Thu, 13 May 2021 12:07:56 +0200 Subject: [PATCH] Fix doc opening to use absolute filenames Now we store doc.filename only and removed doc.abs_filename. The former doc.filename is always the absolute filename. We use now the variable core.working_dir to transform relative path into absolute ones. --- data/core/commands/core.lua | 9 +- data/core/commands/doc.lua | 6 +- data/core/doc/init.lua | 15 +-- data/core/docview.lua | 4 +- data/core/init.lua | 41 +++--- data/plugins/treeview.lua | 8 +- data/plugins/workspace.lua | 240 ------------------------------------ 7 files changed, 31 insertions(+), 292 deletions(-) delete mode 100644 data/plugins/workspace.lua diff --git a/data/core/commands/core.lua b/data/core/commands/core.lua index 636f81a4..3c2bdb12 100644 --- a/data/core/commands/core.lua +++ b/data/core/commands/core.lua @@ -90,13 +90,8 @@ command.add(nil, { ["core:open-file"] = function() local view = core.active_view - if view.doc and view.doc.abs_filename then - local dirname, filename = view.doc.abs_filename:match("(.*)[/\\](.+)$") - if dirname then - dirname = core.normalize_to_project_dir(dirname) - local text = dirname == core.project_dir and "" or common.home_encode(dirname) .. PATHSEP - core.command_view:set_text(text) - end + if view.doc and view.doc.filename then + core.command_view:set_text(common.home_encode(view.doc.filename)) end core.command_view:enter("Open File", function(text, item) local filename = common.home_expand(item and item.text or text) diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index a9b4554e..592fc9fe 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -41,12 +41,10 @@ end local function save(filename) - local abs_filename if filename then - filename = core.normalize_to_project_dir(filename) - abs_filename = core.project_absolute_path(filename) + filename = core.normalize_to_working_dir(filename) end - doc():save(filename, abs_filename) + doc():save(filename) local saved_filename = doc().filename core.on_doc_save(saved_filename) core.log("Saved \"%s\"", saved_filename) diff --git a/data/core/doc/init.lua b/data/core/doc/init.lua index ca41cdad..ed561d23 100644 --- a/data/core/doc/init.lua +++ b/data/core/doc/init.lua @@ -36,11 +36,11 @@ local function splice(t, at, remove, insert) end -function Doc:new(filename, abs_filename, new_file) +function Doc:new(filename, new_file) self.new_file = new_file self:reset() if filename then - self:set_filename(filename, abs_filename) + self.filename = filename if not new_file then self:load(filename) end @@ -69,12 +69,6 @@ function Doc:reset_syntax() end -function Doc:set_filename(filename, abs_filename) - self.filename = filename - self.abs_filename = abs_filename -end - - function Doc:load(filename) local fp = assert( io.open(filename, "rb") ) self:reset() @@ -94,11 +88,10 @@ function Doc:load(filename) end -function Doc:save(filename, abs_filename) +function Doc:save(filename) if not filename then assert(self.filename, "no filename set to default to") filename = self.filename - abs_filename = self.abs_filename end local fp = assert( io.open(filename, "wb") ) for _, line in ipairs(self.lines) do @@ -106,7 +99,7 @@ function Doc:save(filename, abs_filename) fp:write(line) end fp:close() - self:set_filename(filename, abs_filename) + self.filename = filename self.new_file = false self:reset_syntax() self:clean() diff --git a/data/core/docview.lua b/data/core/docview.lua index 070ee0c4..6070a386 100644 --- a/data/core/docview.lua +++ b/data/core/docview.lua @@ -88,9 +88,9 @@ end function DocView:get_filename() - if self.doc.abs_filename then + if self.doc.filename then local post = self.doc:is_dirty() and "*" or "" - return common.home_encode(self.doc.abs_filename) .. post + return common.home_encode(self.doc.filename) .. post end return self:get_name() end diff --git a/data/core/init.lua b/data/core/init.lua index 17188762..b0155fc3 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -61,13 +61,11 @@ end function core.open_folder_project(dir_path_abs) - -- if core.set_project_dir(dir_path_abs, core.on_quit_project) then core.root_view:close_all_docviews() core.project_entries = {} -- FIXME: check stat info to verify is a directory core.add_project_directory(dir_path_abs) update_recents_project("add", dir_path_abs) - -- core.on_enter_project(dir_path_abs) end @@ -357,7 +355,7 @@ end function core.add_project_file(path) - path = normalize_path(path) + path = common.normalize_path(path) table.insert(core.project_entries, { -- type = 'file', name = path, @@ -406,9 +404,9 @@ local function reload_on_user_module_save() -- auto-realod style when user's module is saved by overriding Doc:Save() local doc_save = Doc.save local user_filename = system.absolute_path(USERDIR .. PATHSEP .. "init.lua") - function Doc:save(filename, abs_filename) - doc_save(self, filename, abs_filename) - if self.abs_filename == user_filename then + function Doc:save(filename) + doc_save(self, filename) + if self.filename == user_filename then core.reload_module("core.style") core.load_user_directory() end @@ -473,6 +471,7 @@ function core.init() core.threads = setmetatable({}, { __mode = "k" }) core.blink_start = system.get_time() core.blink_timer = core.blink_start + core.working_dir = system.absolute_path(".") local project_dir_abs = system.absolute_path(project_dir) if project_dir_abs then @@ -480,7 +479,7 @@ function core.init() update_recents_project("add", project_dir_abs) end -- FIXME: below, check if project_dir_abs is ok as a project directory - local set_project_ok = project_dir_abs --and core.open_folder_project(project_dir_abs) --core.set_project_dir(project_dir_abs) + local set_project_ok = project_dir_abs if set_project_ok then if project_dir_explicit then update_recents_project("add", project_dir_abs) @@ -799,16 +798,7 @@ function core.pop_clip_rect() renderer.set_clip_rect(x, y, w, h) end - -function core.normalize_to_project_dir(filename) - filename = common.normalize_path(filename) - if common.path_belongs_to(filename, core.project_dir) then - filename = common.relative_path(core.project_dir, filename) - end - return filename -end - - +-- FIXME: update comment -- The function below works like system.absolute_path except it -- doesn't fail if the file does not exist. We consider that the -- current dir is core.project_dir so relative filename are considered @@ -816,31 +806,34 @@ end -- Please note that .. or . in the filename are not taken into account. -- This function should get only filenames normalized using -- common.normalize_path function. -function core.project_absolute_path(filename) +function core.working_dir_absolute_path(filename) if filename:match('^%a:\\') or filename:find('/', 1, true) then return filename else - return core.project_dir .. PATHSEP .. filename + return core.working_dir .. PATHSEP .. filename end end +function core.normalize_to_working_dir(filename) + filename = common.normalize_path(filename) + return core.working_dir_absolute_path(filename) +end + function core.open_doc(filename) local new_file = not filename or not system.get_file_info(filename) - local abs_filename if filename then -- normalize filename and set absolute filename then -- try to find existing doc for filename - filename = core.normalize_to_project_dir(filename) - abs_filename = core.project_absolute_path(filename) + filename = core.normalize_to_working_dir(filename) for _, doc in ipairs(core.docs) do - if doc.abs_filename and abs_filename == doc.abs_filename then + if doc.filename and filename == doc.filename then return doc end end end -- no existing doc for filename; create new - local doc = Doc(filename, abs_filename, new_file) + local doc = Doc(filename, new_file) table.insert(core.docs, doc) core.log_quiet(filename and "Opened doc \"%s\"" or "Opened new doc", filename) return doc diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index f5b420bd..b5c855ab 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -193,13 +193,13 @@ end function TreeView:on_mouse_moved(px, py, ...) TreeView.super.on_mouse_moved(self, px, py, ...) if self.dragging_scrollbar then return end - + local item_changed, tooltip_changed for item, x,y,w,h in self:each_item() do if px > x and py > y and px <= x + w and py <= y + h then item_changed = true self.hovered_item = item - + x,y,w,h = self:get_text_bounding_box(item, x,y,w,h) if px > x and py > y and px <= x + w and py <= y + h then tooltip_changed = true @@ -251,7 +251,7 @@ function TreeView:on_mouse_pressed(button, x, y, clicks) end else core.try(function() - local doc_filename = common.relative_path(core.project_dir, hovered_item.abs_filename) + local doc_filename = self.hovered_item.abs_filename core.root_view:open_doc(core.open_doc(doc_filename)) end) end @@ -267,7 +267,7 @@ function TreeView:update() else self:move_towards(self.size, "x", dest) end - + local duration = system.get_time() - self.tooltip.begin if self.hovered_item and self.tooltip.x and duration > tooltip_delay then self:move_towards(self.tooltip, "alpha", tooltip_alpha, tooltip_alpha_rate) diff --git a/data/plugins/workspace.lua b/data/plugins/workspace.lua deleted file mode 100644 index 77efd7c9..00000000 --- a/data/plugins/workspace.lua +++ /dev/null @@ -1,240 +0,0 @@ --- mod-version:1 -- lite-xl 1.16 -local core = require "core" -local common = require "core.common" -local DocView = require "core.docview" -local LogView = require "core.logview" - - -local function workspace_files_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: %s", 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+)$")) - if id then - coroutine.yield(workspace_dir .. PATHSEP .. file, 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 workspace = load_f and load_f() - if workspace and workspace.path == project_dir then - os.remove(filename) - 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 - return has_no_locked_children(node.a) and has_no_locked_children(node.b) -end - - -local function get_unlocked_root(node) - if node.type == "leaf" then - return not node.locked and node - end - if has_no_locked_children(node) then - return node - end - return get_unlocked_root(node.a) or get_unlocked_root(node.b) -end - - -local function save_view(view) - local mt = getmetatable(view) - if mt == DocView then - return { - type = "doc", - active = (core.active_view == view), - filename = view.doc.filename, - selection = { view.doc:get_selection() }, - scroll = { x = view.scroll.to.x, y = view.scroll.to.y }, - text = not view.doc.filename and view.doc:get_text(1, 1, math.huge, math.huge) - } - end - if mt == LogView then return end - for name, mod in pairs(package.loaded) do - if mod == mt then - return { - type = "view", - active = (core.active_view == view), - module = name - } - end - end -end - - -local function load_view(t) - if t.type == "doc" then - local dv - if not t.filename then - -- document not associated to a file - dv = DocView(core.open_doc()) - if t.text then dv.doc:insert(1, 1, t.text) end - else - -- we have a filename, try to read the file - local ok, doc = pcall(core.open_doc, t.filename) - if ok then - dv = DocView(doc) - end - end - -- doc view "dv" can be nil here if the filename associated to the document - -- cannot be read. - if dv and dv.doc then - dv.doc:set_selection(table.unpack(t.selection)) - dv.last_line, dv.last_col = dv.doc:get_selection() - dv.scroll.x, dv.scroll.to.x = t.scroll.x, t.scroll.x - dv.scroll.y, dv.scroll.to.y = t.scroll.y, t.scroll.y - end - return dv - end - return require(t.module)() -end - - -local function save_node(node) - local res = {} - res.type = node.type - if node.type == "leaf" then - res.views = {} - for _, view in ipairs(node.views) do - local t = save_view(view) - if t then - table.insert(res.views, t) - if node.active_view == view then - res.active_view = #res.views - end - end - end - else - res.divider = node.divider - res.a = save_node(node.a) - res.b = save_node(node.b) - end - return res -end - - -local function load_node(node, t) - if t.type == "leaf" then - local res - local active_view - for i, v in ipairs(t.views) do - local view = load_view(v) - if view then - if v.active then res = view end - node:add_view(view) - if t.active_view == i then - active_view = view - end - end - end - if active_view then - node:set_active_view(active_view) - end - return res - else - node:split(t.type == "hsplit" and "right" or "down") - node.divider = t.divider - local res1 = load_node(node.a, t.a) - local res2 = load_node(node.b, t.b) - return res1 or res2 - end -end - - -local function save_directories() - local project_dir = core.project_dir - local dir_list = {} - for i = 2, #core.project_directories do - dir_list[#dir_list + 1] = common.relative_path(project_dir, core.project_directories[i].name) - end - return dir_list -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() - end -end - - -local function load_workspace() - local workspace = consume_workspace_file(core.project_dir) - if workspace then - local root = get_unlocked_root(core.root_view.root_node) - local active_view = load_node(root, workspace.documents) - if active_view then - core.set_active_view(active_view) - end - for i, dir_name in ipairs(workspace.directories) do - core.add_project_directory(system.absolute_path(dir_name)) - end - end -end - - -local run = core.run - -function core.run(...) - if #core.docs == 0 then - core.try(load_workspace) - - local on_quit_project = core.on_quit_project - function core.on_quit_project() - core.try(save_workspace) - 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) - end - end - - core.run = run - return core.run(...) -end