Create new document if file doesn't exist
If a non-existing file is specified with the command "core:open-file" a new document is opened with the given filename provided the directory already exists. The flag new_file is set to true in the Doc instance. The file will be actually created only when the "save" command is used. The document will be marked with the "*" event when no changes are done to mean that it is a new file and is not yet saved. The function common.normalize_path now process the .. and . in the filename. Before was not needed because system.absolute_path already get rid of them but now we need to have the absolute path of files that not yet exists so we cannot use system.absolute_path.
This commit is contained in:
parent
0d48f9e8b5
commit
527b11029e
|
@ -104,11 +104,20 @@ command.add(nil, {
|
||||||
end, function (text)
|
end, function (text)
|
||||||
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
|
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
|
||||||
end, nil, function(text)
|
end, nil, function(text)
|
||||||
local path_stat, err = system.get_file_info(common.home_expand(text))
|
local filename = common.home_expand(text)
|
||||||
|
local path_stat, err = system.get_file_info(filename)
|
||||||
if err then
|
if err then
|
||||||
core.error("Cannot open file %q: %q", text, err)
|
if err:find("No such file", 1, true) then
|
||||||
|
-- check if the containing directory exists
|
||||||
|
local dirname = common.dirname(filename)
|
||||||
|
local dir_stat = dirname and system.get_file_info(dirname)
|
||||||
|
if not dirname or (dir_stat and dir_stat.type == 'dir') then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
core.error("Cannot open file %s: %s", text, err)
|
||||||
elseif path_stat.type == 'dir' then
|
elseif path_stat.type == 'dir' then
|
||||||
core.error("Cannot open %q, is a folder", text)
|
core.error("Cannot open %s, is a folder", text)
|
||||||
else
|
else
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,7 +41,12 @@ end
|
||||||
|
|
||||||
|
|
||||||
local function save(filename)
|
local function save(filename)
|
||||||
doc():save(filename and core.normalize_to_project_dir(filename))
|
local abs_filename
|
||||||
|
if filename then
|
||||||
|
filename = core.normalize_to_project_dir(filename)
|
||||||
|
abs_filename = core.project_absolute_path(filename)
|
||||||
|
end
|
||||||
|
doc():save(filename, abs_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)
|
||||||
|
@ -356,12 +361,14 @@ local commands = {
|
||||||
end
|
end
|
||||||
core.command_view:set_text(old_filename)
|
core.command_view:set_text(old_filename)
|
||||||
core.command_view:enter("Rename", function(filename)
|
core.command_view:enter("Rename", function(filename)
|
||||||
doc():save(filename)
|
save(common.home_expand(filename))
|
||||||
core.log("Renamed \"%s\" to \"%s\"", old_filename, filename)
|
core.log("Renamed \"%s\" to \"%s\"", old_filename, filename)
|
||||||
if filename ~= old_filename then
|
if filename ~= old_filename then
|
||||||
os.remove(old_filename)
|
os.remove(old_filename)
|
||||||
end
|
end
|
||||||
end, common.path_suggest)
|
end, function (text)
|
||||||
|
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
|
||||||
|
end)
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,12 @@ function common.basename(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- can return nil if there is no directory part in the path
|
||||||
|
function common.dirname(path)
|
||||||
|
return path:match("(.+)[\\/][^\\/]+$")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function common.home_encode(text)
|
function common.home_encode(text)
|
||||||
if HOME and string.find(text, HOME, 1, true) == 1 then
|
if HOME and string.find(text, HOME, 1, true) == 1 then
|
||||||
local dir_pos = #HOME + 1
|
local dir_pos = #HOME + 1
|
||||||
|
@ -230,16 +236,6 @@ function common.home_expand(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function common.normalize_path(filename)
|
|
||||||
if PATHSEP == '\\' then
|
|
||||||
filename = filename:gsub('[/\\]', '\\')
|
|
||||||
local drive, rem = filename:match('^([a-zA-Z])(:.*)')
|
|
||||||
return drive and drive:upper() .. rem or filename
|
|
||||||
end
|
|
||||||
return filename
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function split_on_slash(s, sep_pattern)
|
local function split_on_slash(s, sep_pattern)
|
||||||
local t = {}
|
local t = {}
|
||||||
for fragment in string.gmatch(s, "([^/\\]+)") do
|
for fragment in string.gmatch(s, "([^/\\]+)") do
|
||||||
|
@ -249,8 +245,27 @@ local function split_on_slash(s, sep_pattern)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function common.normalize_path(filename)
|
||||||
|
if PATHSEP == '\\' then
|
||||||
|
filename = filename:gsub('[/\\]', '\\')
|
||||||
|
local drive, rem = filename:match('^([a-zA-Z])(:.*)')
|
||||||
|
filename = drive and drive:upper() .. rem or filename
|
||||||
|
end
|
||||||
|
local parts = split_on_slash(filename, PATHSEP)
|
||||||
|
local accu = {}
|
||||||
|
for _, part in ipairs(parts) do
|
||||||
|
if part == '..' then
|
||||||
|
table.remove(accu)
|
||||||
|
elseif part ~= '.' then
|
||||||
|
table.insert(accu, part)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(accu, PATHSEP)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function common.path_belongs_to(filename, path)
|
function common.path_belongs_to(filename, path)
|
||||||
return filename and string.find(filename, path .. PATHSEP, 1, true) == 1
|
return string.find(filename, path .. PATHSEP, 1, true) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,16 @@ local function splice(t, at, remove, insert)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:new(filename)
|
function Doc:new(filename, abs_filename, new_file)
|
||||||
|
self.new_file = new_file
|
||||||
self:reset()
|
self:reset()
|
||||||
if filename then
|
if filename then
|
||||||
|
self:set_filename(filename, abs_filename)
|
||||||
|
if not new_file then
|
||||||
self:load(filename)
|
self:load(filename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:reset()
|
function Doc:reset()
|
||||||
|
@ -65,16 +69,15 @@ function Doc:reset_syntax()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:set_filename(filename)
|
function Doc:set_filename(filename, abs_filename)
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.abs_filename = system.absolute_path(filename)
|
self.abs_filename = abs_filename
|
||||||
end
|
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()
|
||||||
self:set_filename(filename)
|
|
||||||
self.lines = {}
|
self.lines = {}
|
||||||
for line in fp:lines() do
|
for line in fp:lines() do
|
||||||
if line:byte(-1) == 13 then
|
if line:byte(-1) == 13 then
|
||||||
|
@ -91,17 +94,20 @@ function Doc:load(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Doc:save(filename)
|
function Doc:save(filename, abs_filename)
|
||||||
filename = filename or assert(self.filename, "no filename set to default to")
|
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") )
|
local fp = assert( io.open(filename, "wb") )
|
||||||
for _, line in ipairs(self.lines) do
|
for _, line in ipairs(self.lines) do
|
||||||
if self.crlf then line = line:gsub("\n", "\r\n") end
|
if self.crlf then line = line:gsub("\n", "\r\n") end
|
||||||
fp:write(line)
|
fp:write(line)
|
||||||
end
|
end
|
||||||
fp:close()
|
fp:close()
|
||||||
if filename then
|
self:set_filename(filename, abs_filename)
|
||||||
self:set_filename(filename)
|
self.new_file = false
|
||||||
end
|
|
||||||
self:reset_syntax()
|
self:reset_syntax()
|
||||||
self:clean()
|
self:clean()
|
||||||
end
|
end
|
||||||
|
@ -113,7 +119,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
function Doc:is_dirty()
|
function Doc:is_dirty()
|
||||||
return self.clean_change_id ~= self:get_change_id()
|
return self.clean_change_id ~= self:get_change_id() or self.new_file
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -812,10 +812,30 @@ function core.normalize_to_project_dir(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
-- to be in core.project_dir.
|
||||||
|
-- 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)
|
||||||
|
if filename:match('^%a:\\') or filename:find('/', 1, true) then
|
||||||
|
return filename
|
||||||
|
else
|
||||||
|
return core.project_dir .. PATHSEP .. filename
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function core.open_doc(filename)
|
function core.open_doc(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
|
||||||
-- try to find existing doc for filename
|
-- try to find existing doc for filename
|
||||||
local abs_filename = system.absolute_path(filename)
|
filename = core.normalize_to_project_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.abs_filename and abs_filename == doc.abs_filename then
|
||||||
return doc
|
return doc
|
||||||
|
@ -823,8 +843,7 @@ function core.open_doc(filename)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- no existing doc for filename; create new
|
-- no existing doc for filename; create new
|
||||||
filename = filename and core.normalize_to_project_dir(filename)
|
local doc = Doc(filename, abs_filename, new_file)
|
||||||
local doc = Doc(filename)
|
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue