1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
-- mod-version:4
local core = require "core"
local config = require "core.config"
local Doc = require "core.doc"
local Node = require "core.node"
local common = require "core.common"
local dirwatch = require "core.dirwatch"
config.plugins.autoreload = common.merge({
always_show_nagview = false,
config_spec = {
name = "Autoreload",
{
label = "Always Show Nagview",
description = "Alerts you if an opened file changes externally even if you haven't modified it.",
path = "always_show_nagview",
type = "toggle",
default = false
}
}
}, config.plugins.autoreload)
local watch = dirwatch.new()
local times = setmetatable({}, { __mode = "k" })
local visible = setmetatable({}, { __mode = "k" })
local function update_time(doc)
local info = system.get_file_info(doc.filename)
times[doc] = info and info.modified
end
local function reload_doc(doc)
doc:reload()
update_time(doc)
core.redraw = true
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?", {
{ 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
doc.deferred_reload = false
end)
end
end
local function doc_changes_visiblity(doc, visibility)
if doc and visible[doc] ~= visibility and doc.abs_filename then
visible[doc] = visibility
if visibility then check_prompt_reload(doc) end
watch:watch(doc.abs_filename, visibility)
end
end
local core_set_active_view = core.set_active_view
function core.set_active_view(view)
core_set_active_view(view)
doc_changes_visiblity(view.doc, true)
end
local node_set_active_view = Node.set_active_view
function Node:set_active_view(view)
if self.active_view then doc_changes_visiblity(self.active_view.doc, false) end
node_set_active_view(self, view)
doc_changes_visiblity(self.active_view.doc, true)
end
core.add_thread(function()
while true do
watch:check(function(file)
for i, doc in ipairs(core.docs) do
if doc.abs_filename == file then
local info = system.get_file_info(doc.filename or "")
if info and times[doc] ~= info.modified then
if not doc:is_dirty() and not config.plugins.autoreload.always_show_nagview then
reload_doc(doc)
else
doc.deferred_reload = true
if doc == core.active_view.doc then check_prompt_reload(doc) end
end
end
end
end
end)
coroutine.yield(0.05)
end
end)
-- patch `Doc.save|load` to store modified time
local load = Doc.load
local save = Doc.save
Doc.load = function(self, ...)
local res = load(self, ...)
update_time(self)
return res
end
Doc.save = function(self, ...)
local res = save(self, ...)
-- if starting with an unsaved document with a filename.
if not times[self] then watch:watch(self.abs_filename, true) end
update_time(self)
return res
end
|