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.
This commit is contained in:
parent
ac0dba18de
commit
803d6e0f8d
|
@ -87,8 +87,8 @@ command.add(nil, {
|
||||||
|
|
||||||
["core:open-file"] = function()
|
["core:open-file"] = function()
|
||||||
local view = core.active_view
|
local view = core.active_view
|
||||||
if view.doc and view.doc.abs_filename then
|
if view.doc and view.doc.filename then
|
||||||
core.command_view:set_text(common.home_encode(view.doc.abs_filename))
|
core.command_view:set_text(common.home_encode(view.doc.filename))
|
||||||
end
|
end
|
||||||
core.command_view:enter("Open File", function(text, item)
|
core.command_view:enter("Open File", function(text, item)
|
||||||
local filename = common.home_expand(item and item.text or text)
|
local filename = common.home_expand(item and item.text or text)
|
||||||
|
|
|
@ -68,12 +68,10 @@ end
|
||||||
|
|
||||||
|
|
||||||
local function save(filename)
|
local function save(filename)
|
||||||
local abs_filename
|
|
||||||
if filename then
|
if filename then
|
||||||
filename = core.normalize_to_project_dir(filename)
|
filename = core.normalize_to_working_dir(filename)
|
||||||
abs_filename = core.project_absolute_path(filename)
|
|
||||||
end
|
end
|
||||||
doc():save(filename, abs_filename)
|
doc():save(filename)
|
||||||
local saved_filename = doc().filename
|
local saved_filename = doc().filename
|
||||||
core.on_doc_save(saved_filename)
|
core.on_doc_save(saved_filename)
|
||||||
core.log("Saved \"%s\"", saved_filename)
|
core.log("Saved \"%s\"", saved_filename)
|
||||||
|
|
|
@ -36,11 +36,11 @@ local function splice(t, at, remove, insert)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:new(filename, abs_filename, new_file)
|
function Doc:new(filename, new_file)
|
||||||
self.new_file = new_file
|
self.new_file = new_file
|
||||||
self:reset()
|
self:reset()
|
||||||
if filename then
|
if filename then
|
||||||
self:set_filename(filename, abs_filename)
|
self.filename = filename
|
||||||
if not new_file then
|
if not new_file then
|
||||||
self:load(filename)
|
self:load(filename)
|
||||||
end
|
end
|
||||||
|
@ -69,12 +69,6 @@ function Doc:reset_syntax()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:set_filename(filename, abs_filename)
|
|
||||||
self.filename = filename
|
|
||||||
self.abs_filename = abs_filename
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function Doc:load(filename)
|
function Doc:load(filename)
|
||||||
local fp = assert( io.open(filename, "rb") )
|
local fp = assert( io.open(filename, "rb") )
|
||||||
self:reset()
|
self:reset()
|
||||||
|
@ -94,11 +88,10 @@ function Doc:load(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:save(filename, abs_filename)
|
function Doc:save(filename)
|
||||||
if not filename then
|
if not filename then
|
||||||
assert(self.filename, "no filename set to default to")
|
assert(self.filename, "no filename set to default to")
|
||||||
filename = self.filename
|
filename = self.filename
|
||||||
abs_filename = self.abs_filename
|
|
||||||
end
|
end
|
||||||
local fp = assert( io.open(filename, "wb") )
|
local fp = assert( io.open(filename, "wb") )
|
||||||
for _, line in ipairs(self.lines) do
|
for _, line in ipairs(self.lines) do
|
||||||
|
@ -106,7 +99,7 @@ function Doc:save(filename, abs_filename)
|
||||||
fp:write(line)
|
fp:write(line)
|
||||||
end
|
end
|
||||||
fp:close()
|
fp:close()
|
||||||
self:set_filename(filename, abs_filename)
|
self.filename = filename
|
||||||
self.new_file = false
|
self.new_file = false
|
||||||
self:reset_syntax()
|
self:reset_syntax()
|
||||||
self:clean()
|
self:clean()
|
||||||
|
|
|
@ -88,9 +88,9 @@ end
|
||||||
|
|
||||||
|
|
||||||
function DocView:get_filename()
|
function DocView:get_filename()
|
||||||
if self.doc.abs_filename then
|
if self.doc.filename then
|
||||||
local post = self.doc:is_dirty() and "*" or ""
|
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
|
end
|
||||||
return self:get_name()
|
return self:get_name()
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,13 +59,11 @@ end
|
||||||
|
|
||||||
|
|
||||||
function core.open_folder_project(dir_path_abs)
|
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.root_view:close_all_docviews()
|
||||||
core.project_entries = {}
|
core.project_entries = {}
|
||||||
-- FIXME: check stat info to verify is a directory
|
-- FIXME: check stat info to verify is a directory
|
||||||
core.add_project_directory(dir_path_abs)
|
core.add_project_directory(dir_path_abs)
|
||||||
update_recents_project("add", dir_path_abs)
|
update_recents_project("add", dir_path_abs)
|
||||||
-- core.on_enter_project(dir_path_abs)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -304,7 +302,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
function core.add_project_file(path)
|
function core.add_project_file(path)
|
||||||
path = normalize_path(path)
|
path = common.normalize_path(path)
|
||||||
table.insert(core.project_entries, {
|
table.insert(core.project_entries, {
|
||||||
-- type = 'file',
|
-- type = 'file',
|
||||||
name = path,
|
name = path,
|
||||||
|
@ -404,6 +402,7 @@ function core.init()
|
||||||
core.threads = setmetatable({}, { __mode = "k" })
|
core.threads = setmetatable({}, { __mode = "k" })
|
||||||
core.blink_start = system.get_time()
|
core.blink_start = system.get_time()
|
||||||
core.blink_timer = core.blink_start
|
core.blink_timer = core.blink_start
|
||||||
|
core.working_dir = system.absolute_path(".")
|
||||||
|
|
||||||
local project_dir_abs = system.absolute_path(project_dir)
|
local project_dir_abs = system.absolute_path(project_dir)
|
||||||
if project_dir_abs then
|
if project_dir_abs then
|
||||||
|
@ -411,7 +410,7 @@ function core.init()
|
||||||
update_recents_project("add", project_dir_abs)
|
update_recents_project("add", project_dir_abs)
|
||||||
end
|
end
|
||||||
-- FIXME: below, check if project_dir_abs is ok as a project directory
|
-- 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 set_project_ok then
|
||||||
if project_dir_explicit then
|
if project_dir_explicit then
|
||||||
update_recents_project("add", project_dir_abs)
|
update_recents_project("add", project_dir_abs)
|
||||||
|
@ -722,16 +721,7 @@ function core.pop_clip_rect()
|
||||||
renderer.set_clip_rect(x, y, w, h)
|
renderer.set_clip_rect(x, y, w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- FIXME: update comment
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
-- The function below works like system.absolute_path except it
|
-- The function below works like system.absolute_path except it
|
||||||
-- doesn't fail if the file does not exist. We consider that the
|
-- doesn't fail if the file does not exist. We consider that the
|
||||||
-- current dir is core.project_dir so relative filename are considered
|
-- current dir is core.project_dir so relative filename are considered
|
||||||
|
@ -739,31 +729,34 @@ end
|
||||||
-- Please note that .. or . in the filename are not taken into account.
|
-- Please note that .. or . in the filename are not taken into account.
|
||||||
-- 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.working_dir_absolute_path(filename)
|
||||||
if filename:match('^%a:\\') or filename:find('/', 1, true) then
|
if filename:match('^%a:\\') or filename:find('/', 1, true) then
|
||||||
return filename
|
return filename
|
||||||
else
|
else
|
||||||
return core.project_dir .. PATHSEP .. filename
|
return core.working_dir .. PATHSEP .. filename
|
||||||
end
|
end
|
||||||
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)
|
function core.open_doc(filename)
|
||||||
local new_file = not filename or not system.get_file_info(filename)
|
local new_file = not filename or not system.get_file_info(filename)
|
||||||
local abs_filename
|
|
||||||
if filename then
|
if filename then
|
||||||
-- normalize filename and set absolute filename then
|
-- normalize filename and set absolute filename then
|
||||||
-- try to find existing doc for filename
|
-- try to find existing doc for filename
|
||||||
filename = core.normalize_to_project_dir(filename)
|
filename = core.normalize_to_working_dir(filename)
|
||||||
abs_filename = core.project_absolute_path(filename)
|
|
||||||
for _, doc in ipairs(core.docs) do
|
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
|
return doc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- no existing doc for filename; create new
|
-- 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)
|
table.insert(core.docs, doc)
|
||||||
core.log_quiet(filename and "Opened doc \"%s\"" or "Opened new doc", filename)
|
core.log_quiet(filename and "Opened doc \"%s\"" or "Opened new doc", filename)
|
||||||
return doc
|
return doc
|
||||||
|
@ -1023,7 +1016,7 @@ end
|
||||||
|
|
||||||
core.add_save_hook(function(filename)
|
core.add_save_hook(function(filename)
|
||||||
local doc = core.active_view.doc
|
local doc = core.active_view.doc
|
||||||
if doc and doc:is(Doc) and doc.abs_filename == USERDIR .. PATHSEP .. "init.lua" then
|
if doc and doc:is(Doc) and doc.filename == USERDIR .. PATHSEP .. "init.lua" then
|
||||||
core.reload_module("core.style")
|
core.reload_module("core.style")
|
||||||
core.load_user_directory()
|
core.load_user_directory()
|
||||||
end
|
end
|
||||||
|
|
|
@ -238,7 +238,7 @@ function TreeView:on_mouse_pressed(button, x, y, clicks)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
core.try(function()
|
core.try(function()
|
||||||
local doc_filename = common.relative_path(core.project_dir, self.hovered_item.abs_filename)
|
local doc_filename = self.hovered_item.abs_filename
|
||||||
core.root_view:open_doc(core.open_doc(doc_filename))
|
core.root_view:open_doc(core.open_doc(doc_filename))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
-- mod-version:1 -- lite-xl 1.16
|
|
||||||
local core = require "core"
|
|
||||||
local common = require "core.common"
|
|
||||||
local DocView = require "core.docview"
|
|
||||||
|
|
||||||
|
|
||||||
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 load_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
|
|
||||||
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 ok, doc = pcall(core.open_doc, t.filename)
|
|
||||||
if not ok then
|
|
||||||
return DocView(core.open_doc())
|
|
||||||
end
|
|
||||||
local dv = DocView(doc)
|
|
||||||
if t.text then doc:insert(1, 1, t.text) end
|
|
||||||
doc:set_selection(table.unpack(t.selection))
|
|
||||||
dv.last_line, dv.last_col = 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
|
|
||||||
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
|
|
||||||
for _, v in ipairs(t.views) do
|
|
||||||
local view = load_view(v)
|
|
||||||
if v.active then res = view end
|
|
||||||
node:add_view(view)
|
|
||||||
end
|
|
||||||
if t.active_view then
|
|
||||||
node:set_active_view(node.views[t.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 = load_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
|
|
Loading…
Reference in New Issue