Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autoreload Nagview #942

Merged

Conversation

adamharrison
Copy link
Member

@adamharrison adamharrison commented Apr 22, 2022

In addition to changing the plugin from the special core hook to a normal overload for detecting file changes, I've also done the following, based on some suggestions on discord:

  1. If a file has changed, and we have it open, and clean, automatically reload it. (current behaviour)
  2. If a file has changed, and we have it open, and dirty, and is the active view, show nagbar to ask if you want to reload the file or not.
  3. If a file has changed, and we have it open, and dirty, and it's not the active view, flag the file, but don't show nagbar yet.
  4. When the active view is changed, check to see if the view we're changing to is flagged, and if so, activate nagbar to ask if a reload is desirable.

This covers most of the cases; and should get rid of the issue where autoreload.lua will just stomp on changes you have if you're actively editing the file.

This is not the end-behaviour; as there is some discussion about exactly how a file should be reloaded (should it go directly into the undo stack, so you can easily undo it?), but this is an incremental step in the right direction.

@StunxFS
Copy link

StunxFS commented Apr 22, 2022

Great! 😆

should it go directly into the undo stack, so you can easily undo it?

I would say yes, it would be helpful to be able to undo those changes

@adamharrison
Copy link
Member Author

So, @jgmdev mentioned that there seems to be an issue here that was introduced when dmon introduced; basically if you're on a project that's at the file limit, autoreload doesn't actually reload things, because it's listening for dmon/dirmonitor events, even though those only fire on 'open' directories inside a project, and don't fire outside a project.

Solution here is to add a thread in the cases where we're looking at an external file, and add poll the file. There's also strong consensus around putting reload under doc directly; as several people would like this, so I'll move that over there as well.

@adamharrison
Copy link
Member Author

OK; made those changes. Any thoughts? If none, I'll merge this as is on the 30th.

@Guldoman
Copy link
Member

Testing with a file from outside the project, it looks like refusing the changes doesn't work.

@jgmdev
Copy link
Member

jgmdev commented May 13, 2022

Testing with a file from outside the project, it looks like refusing the changes doesn't work.

This is fixable by moving check_prompt_reload():

local on_check = dirwatch.check
function dirwatch:check(change_callback, ...)
  on_check(self, function(dir)
    for _, doc in ipairs(core.docs) do
      if dir == common.dirname(doc.abs_filename) then
        check_if_modified(doc)
      end
    end
    change_callback(dir)
  end, ...)
  check_prompt_reload() -- <--------------- from here
end
local on_check = dirwatch.check
function dirwatch:check(change_callback, ...)
  on_check(self, function(dir)
    for _, doc in ipairs(core.docs) do
      if dir == common.dirname(doc.abs_filename) then
        check_if_modified(doc)
        check_prompt_reload() -- <--------------- to here
      end
    end
    change_callback(dir)
  end, ...)
end

also shouldn't this coroutine: (wrong assumption)

      core.add_thread(function()
        while core.active_view.doc == doc do
          check_if_modified(doc)
          coroutine.yield(0.25)
        end
      end)

use an if instead like:

      core.add_thread(function()
        if doc and core.active_view.doc == doc then
          check_if_modified(doc)
        end
      end)

because using that while would keep it running far more than we desire doesn't?

Second Edit: seems that check_prompt_reload() also needs a call to update_time at least for files external to project

local function check_prompt_reload()
  if core.active_view.doc and core.active_view.doc.deferred_reload then
    local doc = core.active_view.doc
    core.nag_view:show("File Changed", doc.filename .. " has changed. Reload this file?", {
      { font = style.font, text = "Yes", default_yes = true },
      { font = style.font, text = "No" , default_no = true }
    }, function(item)
      if item.text == "Yes" then 
        reload_doc(doc) 
      else 
        update_time(doc) -- <----------------------- here 
      end
      doc.deferred_reload = false
    end)
  end
end

@TorchedSammy
Copy link
Contributor

would be better to send that as a patch

@jgmdev
Copy link
Member

jgmdev commented May 14, 2022

would be better to send that as a patch

I did those checks on a rush and just posted what I found, here is a patch if it is right:

diff --git a/data/plugins/autoreload.lua b/data/plugins/autoreload.lua
index fba22a2..0882164 100644
--- a/data/plugins/autoreload.lua
+++ b/data/plugins/autoreload.lua
@@ -30,7 +30,11 @@ local function check_prompt_reload()
       { font = style.font, text = "Yes", default_yes = true },
       { font = style.font, text = "No" , default_no = true }
     }, function(item)
-      if item.text == "Yes" then reload_doc(doc) end
+      if item.text == "Yes" then
+        reload_doc(doc)
+      else
+        update_time(doc)
+      end
       doc.deferred_reload = false
     end)
   end
@@ -53,11 +57,11 @@ function dirwatch:check(change_callback, ...)
     for _, doc in ipairs(core.docs) do
       if dir == common.dirname(doc.abs_filename) then
         check_if_modified(doc)
+        check_prompt_reload()
       end
     end
     change_callback(dir)
   end, ...)
-  check_prompt_reload()
 end

…nagview to verify that fs changes don't stomp on our changes, unless you want them to.
…ead to check the document, in the cases where it wouldn't be covered by dirwatch.
…s when we load a non-existent file, and added some checks.
@adamharrison adamharrison force-pushed the change-dirty-and-dirwatch branch from 177e75d to 32ecf9a Compare May 15, 2022 18:31
@adamharrison adamharrison changed the base branch from master to master-2.1 May 15, 2022 18:31
@adamharrison
Copy link
Member Author

OK; I actually realised there was an easier way to just cover all bases here; now that dirwatch is a modular class; we can actually just use that to efficiently check individual files outside the project, so that they too also reload with inotify.

I'm also going to target this PR at 2.1, because autoreload is straight broken in 2.1 at present.

@adamharrison
Copy link
Member Author

OK, jgmdev tested this; seems to work. Squashing and merging.

@adamharrison adamharrison merged commit 36c4d5d into lite-xl:master-2.1 May 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants