diff options
| author | Guldoman <giulio.lettieri@gmail.com> | 2024-06-23 04:01:50 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-23 10:01:50 +0800 |
| commit | 74fcd19ac2b51c0e8b2a6cdc0e49f5d04e651db0 (patch) | |
| tree | 72568b505b1f2c8b00809fe354f54738b8ce0d33 /data | |
| parent | face6af0da1d9cd2ef56ebd65a94d13bc4730222 (diff) | |
| download | lite-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.lua | 33 |
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 |
