fix(autoreload): wait a second before automatically reloading a file (#1823)
This is needed because we use `mtime` to determine if a file has actually changed, but on most systems this has a resolution of 1 second (and we truncate it to an integer anyways). Without this wait, we would skip reloading a file that has been changed multiple times in the same `mtime` second, thus losing some data.
This commit is contained in:
parent
face6af0da
commit
74fcd19ac2
|
@ -1,7 +1,6 @@
|
|||
-- mod-version:3
|
||||
local core = require "core"
|
||||
local config = require "core.config"
|
||||
local style = require "core.style"
|
||||
local Doc = require "core.doc"
|
||||
local Node = require "core.node"
|
||||
local common = require "core.common"
|
||||
|
@ -26,7 +25,7 @@ local times = setmetatable({}, { __mode = "k" })
|
|||
local visible = setmetatable({}, { __mode = "k" })
|
||||
|
||||
local function get_project_doc_watch(doc)
|
||||
for i, v in ipairs(core.project_directories) do
|
||||
for _, v in ipairs(core.project_directories) do
|
||||
if doc.abs_filename:find(v.name, 1, true) == 1 then return v.watch end
|
||||
end
|
||||
return watch
|
||||
|
@ -43,6 +42,34 @@ local function reload_doc(doc)
|
|||
core.log_quiet("Auto-reloaded doc \"%s\"", doc.filename)
|
||||
end
|
||||
|
||||
|
||||
local timers = setmetatable({}, { __mode = "k" })
|
||||
|
||||
local function delayed_reload(doc, mtime)
|
||||
if timers[doc] then
|
||||
-- If mtime remains the same, there's no need to restart the timer
|
||||
-- as we're waiting a full second anyways.
|
||||
if not mtime or timers[doc].mtime ~= mtime then
|
||||
timers[doc] = { last_trigger = system.get_time(), mtime = mtime }
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
timers[doc] = { last_trigger = system.get_time(), mtime = mtime }
|
||||
core.add_thread(function()
|
||||
local diff = system.get_time() - timers[doc].last_trigger
|
||||
-- Wait a second before triggering a reload because we're using mtime
|
||||
-- to determine if a file has changed, and on many systems it has a
|
||||
-- resolution of 1 second.
|
||||
while diff < 1 do
|
||||
coroutine.yield(diff)
|
||||
diff = system.get_time() - timers[doc].last_trigger
|
||||
end
|
||||
timers[doc] = nil
|
||||
reload_doc(doc)
|
||||
end)
|
||||
end
|
||||
|
||||
local function check_prompt_reload(doc)
|
||||
if doc and doc.deferred_reload then
|
||||
core.nag_view:show("File Changed", doc.filename .. " has changed. Reload this file?", {
|
||||
|
@ -71,7 +98,7 @@ function dirwatch:check(change_callback, ...)
|
|||
local info = system.get_file_info(doc.filename or "")
|
||||
if info and info.type == "file" and times[doc] ~= info.modified then
|
||||
if not doc:is_dirty() and not config.plugins.autoreload.always_show_nagview then
|
||||
reload_doc(doc)
|
||||
delayed_reload(doc, info.modified)
|
||||
else
|
||||
doc.deferred_reload = true
|
||||
if doc == core.active_view.doc then check_prompt_reload(doc) end
|
||||
|
|
Loading…
Reference in New Issue