@@ -3,10 +3,16 @@ local uv = vim.loop
3
3
local log = require " nvim-tree.log"
4
4
local utils = require " nvim-tree.utils"
5
5
6
- local M = {
6
+ local M = {}
7
+
8
+ local Event = {
9
+ _events = {},
10
+ }
11
+ Event .__index = Event
12
+
13
+ local Watcher = {
7
14
_watchers = {},
8
15
}
9
- local Watcher = {}
10
16
Watcher .__index = Watcher
11
17
12
18
local FS_EVENT_FLAGS = {
@@ -16,87 +22,129 @@ local FS_EVENT_FLAGS = {
16
22
recursive = false ,
17
23
}
18
24
19
- function Watcher .new (opts )
20
- for _ , existing in ipairs (M ._watchers ) do
21
- if existing ._opts .absolute_path == opts .absolute_path then
22
- log .line (" watcher" , " Watcher:new using existing '%s'" , opts .absolute_path )
23
- return existing
24
- end
25
- end
26
-
27
- log .line (" watcher" , " Watcher:new '%s'" , opts .absolute_path )
25
+ function Event :new (path )
26
+ log .line (" watcher" , " Event:new '%s'" , path )
28
27
29
- local watcher = setmetatable ({
30
- _opts = opts ,
31
- }, Watcher )
28
+ local e = setmetatable ({
29
+ _path = path ,
30
+ _fs_event = nil ,
31
+ _listeners = {},
32
+ }, Event )
32
33
33
- watcher = watcher :start ()
34
-
35
- table.insert (M ._watchers , watcher )
36
-
37
- return watcher
34
+ if e :start () then
35
+ Event ._events [path ] = e
36
+ return e
37
+ else
38
+ return nil
39
+ end
38
40
end
39
41
40
- function Watcher :start ()
41
- log .line (" watcher" , " Watcher :start '%s'" , self ._opts . absolute_path )
42
+ function Event :start ()
43
+ log .line (" watcher" , " Event :start '%s'" , self ._path )
42
44
43
45
local rc , _ , name
44
46
45
- self ._e , _ , name = uv .new_fs_event ()
46
- if not self ._e then
47
- self ._e = nil
48
- utils .notify .warn (
49
- string.format (" Could not initialize an fs_event watcher for path %s : %s" , self ._opts .absolute_path , name )
50
- )
51
- return nil
47
+ self ._fs_event , _ , name = uv .new_fs_event ()
48
+ if not self ._fs_event then
49
+ self ._fs_event = nil
50
+ utils .notify .warn (string.format (" Could not initialize an fs_event watcher for path %s : %s" , self ._path , name ))
51
+ return false
52
52
end
53
53
54
- local event_cb = vim .schedule_wrap (function (err , filename , events )
54
+ local event_cb = vim .schedule_wrap (function (err , filename )
55
55
if err then
56
- log .line (" watcher" , " event_cb for %s fail : %s" , self ._opts . absolute_path , err )
56
+ log .line (" watcher" , " event_cb for %s fail : %s" , self ._path , err )
57
57
else
58
- log .line (" watcher" , " event_cb '%s' '%s' %s" , self ._opts .absolute_path , filename , vim .inspect (events ))
59
- self ._opts .on_event (self ._opts )
58
+ log .line (" watcher" , " event_cb '%s' '%s'" , self ._path , filename )
59
+ for _ , listener in ipairs (self ._listeners ) do
60
+ listener ()
61
+ end
60
62
end
61
63
end )
62
64
63
- rc , _ , name = self ._e :start (self ._opts . absolute_path , FS_EVENT_FLAGS , event_cb )
65
+ rc , _ , name = self ._fs_event :start (self ._path , FS_EVENT_FLAGS , event_cb )
64
66
if rc ~= 0 then
65
- utils .notify .warn (
66
- string.format (" Could not start the fs_event watcher for path %s : %s" , self ._opts .absolute_path , name )
67
- )
68
- return nil
67
+ utils .notify .warn (string.format (" Could not start the fs_event watcher for path %s : %s" , self ._path , name ))
68
+ return false
69
69
end
70
70
71
- return self
71
+ return true
72
72
end
73
73
74
- function Watcher :destroy ()
75
- log .line (" watcher" , " Watcher:destroy '%s'" , self ._opts .absolute_path )
76
- if self ._e then
77
- local rc , _ , name = self ._e :stop ()
74
+ function Event :add (listener )
75
+ table.insert (self ._listeners , listener )
76
+ end
77
+
78
+ function Event :remove (listener )
79
+ utils .array_remove (self ._listeners , listener )
80
+ if # self ._listeners == 0 then
81
+ self :destroy ()
82
+ end
83
+ end
84
+
85
+ function Event :destroy ()
86
+ log .line (" watcher" , " Event:destroy '%s'" , self ._path )
87
+
88
+ if self ._fs_event then
89
+ local rc , _ , name = self ._fs_event :stop ()
78
90
if rc ~= 0 then
79
- utils .notify .warn (
80
- string.format (" Could not stop the fs_event watcher for path %s : %s" , self ._opts .absolute_path , name )
81
- )
91
+ utils .notify .warn (string.format (" Could not stop the fs_event watcher for path %s : %s" , self ._path , name ))
82
92
end
83
- self ._e = nil
93
+ self ._fs_event = nil
84
94
end
85
- for i , w in ipairs (M ._watchers ) do
86
- if w == self then
87
- table.remove (M ._watchers , i )
88
- break
89
- end
95
+
96
+ Event ._events [self ._path ] = nil
97
+ end
98
+
99
+ function Watcher :new (path , callback , data )
100
+ log .line (" watcher" , " Watcher:new '%s'" , path )
101
+
102
+ local w = setmetatable (data , Watcher )
103
+
104
+ w ._event = Event ._events [path ] or Event :new (path )
105
+ w ._listener = nil
106
+ w ._path = path
107
+ w ._callback = callback
108
+
109
+ if not w ._event then
110
+ return nil
111
+ end
112
+
113
+ w :start ()
114
+
115
+ table.insert (Watcher ._watchers , w )
116
+
117
+ return w
118
+ end
119
+
120
+ function Watcher :start ()
121
+ self ._listener = function ()
122
+ self ._callback (self )
90
123
end
124
+
125
+ self ._event :add (self ._listener )
126
+ end
127
+
128
+ function Watcher :destroy ()
129
+ log .line (" watcher" , " Watcher:destroy '%s'" , self ._path )
130
+
131
+ self ._event :remove (self ._listener )
132
+
133
+ utils .array_remove (Watcher ._watchers , self )
91
134
end
92
135
93
136
M .Watcher = Watcher
94
137
95
138
function M .purge_watchers ()
96
- for _ , watcher in pairs (M ._watchers ) do
97
- watcher :destroy ()
139
+ log .line (" watcher" , " purge_watchers" )
140
+
141
+ for _ , w in ipairs (utils .array_shallow_clone (Watcher ._watchers )) do
142
+ w :destroy ()
143
+ end
144
+
145
+ for _ , e in pairs (Event ._events ) do
146
+ e :destroy ()
98
147
end
99
- M ._watchers = {}
100
148
end
101
149
102
150
return M
0 commit comments