aboutsummaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
authorGuldoman <giulio.lettieri@gmail.com>2024-06-23 04:01:50 +0200
committerGitHub <noreply@github.com>2024-06-23 10:01:50 +0800
commit74fcd19ac2b51c0e8b2a6cdc0e49f5d04e651db0 (patch)
tree72568b505b1f2c8b00809fe354f54738b8ce0d33 /data
parentface6af0da1d9cd2ef56ebd65a94d13bc4730222 (diff)
downloadlite-xl-74fcd19ac2b51c0e8b2a6cdc0e49f5d04e651db0.tar.gz
lite-xl-74fcd19ac2b51c0e8b2a6cdc0e49f5d04e651db0.zip
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.
Diffstat (limited to 'data')
-rw-r--r--data/plugins/autoreload.lua33
1 files changed, 30 insertions, 3 deletions
diff --git a/data/plugins/autoreload.lua b/data/plugins/autoreload.lua
index f1ba6e0d..7086fb35 100644
--- a/data/plugins/autoreload.lua
+++ b/data/plugins/autoreload.lua
@@ -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