@@ -2,21 +2,7 @@ local notify = require("nvim-tree.notify")
2
2
local log = require (" nvim-tree.log" )
3
3
local utils = require (" nvim-tree.utils" )
4
4
5
- local M = {
6
- config = {},
7
- }
8
-
9
- --- @class Event
10
- local Event = {
11
- _events = {},
12
- }
13
- Event .__index = Event
14
-
15
- --- @class Watcher
16
- local Watcher = {
17
- _watchers = {},
18
- }
19
- Watcher .__index = Watcher
5
+ local Class = require (" nvim-tree.class" )
20
6
21
7
local FS_EVENT_FLAGS = {
22
8
-- inotify or equivalent will be used; fallback to stat has not yet been implemented
@@ -25,42 +11,62 @@ local FS_EVENT_FLAGS = {
25
11
recursive = false ,
26
12
}
27
13
14
+ local M = {
15
+ config = {},
16
+ }
17
+
18
+ --- @class (exact ) Event : Class
19
+ --- @field destroyed boolean
20
+ --- @field private path string
21
+ --- @field private fs_event uv.uv_fs_event_t ?
22
+ --- @field private listeners function[]
23
+ local Event = Class :new ()
24
+
25
+ --- Registry of all events
26
+ --- @type Event[]
27
+ local events = {}
28
+
29
+ --- Static factory method
30
+ --- Creates and starts an Event
28
31
--- @param path string
29
32
--- @return Event | nil
30
- function Event :new (path )
31
- log .line (" watcher" , " Event:new '%s'" , path )
32
-
33
- local e = setmetatable ({
34
- _path = path ,
35
- _fs_event = nil ,
36
- _listeners = {},
37
- }, Event )
38
-
39
- if e :start () then
40
- Event ._events [path ] = e
41
- return e
33
+ function Event :create (path )
34
+ log .line (" watcher" , " Event:create '%s'" , path )
35
+
36
+ --- @type Event
37
+ local o = {
38
+ destroyed = false ,
39
+ path = path ,
40
+ fs_event = nil ,
41
+ listeners = {},
42
+ }
43
+ o = self :new (o ) --[[ @as Event]]
44
+
45
+ if o :start () then
46
+ events [path ] = o
47
+ return o
42
48
else
43
49
return nil
44
50
end
45
51
end
46
52
47
53
--- @return boolean
48
54
function Event :start ()
49
- log .line (" watcher" , " Event:start '%s'" , self ._path )
55
+ log .line (" watcher" , " Event:start '%s'" , self .path )
50
56
51
57
local rc , _ , name
52
58
53
- self ._fs_event , _ , name = vim .loop .new_fs_event ()
54
- if not self ._fs_event then
55
- self ._fs_event = nil
56
- notify .warn (string.format (" Could not initialize an fs_event watcher for path %s : %s" , self ._path , name ))
59
+ self .fs_event , _ , name = vim .loop .new_fs_event ()
60
+ if not self .fs_event then
61
+ self .fs_event = nil
62
+ notify .warn (string.format (" Could not initialize an fs_event watcher for path %s : %s" , self .path , name ))
57
63
return false
58
64
end
59
65
60
66
local event_cb = vim .schedule_wrap (function (err , filename )
61
67
if err then
62
- log .line (" watcher" , " event_cb '%s' '%s' FAIL : %s" , self ._path , filename , err )
63
- local message = string.format (" File system watcher failed (%s) for path %s, halting watcher." , err , self ._path )
68
+ log .line (" watcher" , " event_cb '%s' '%s' FAIL : %s" , self .path , filename , err )
69
+ local message = string.format (" File system watcher failed (%s) for path %s, halting watcher." , err , self .path )
64
70
if err == " EPERM" and (utils .is_windows or utils .is_wsl ) then
65
71
-- on directory removal windows will cascade the filesystem events out of order
66
72
log .line (" watcher" , message )
@@ -69,19 +75,19 @@ function Event:start()
69
75
self :destroy (message )
70
76
end
71
77
else
72
- log .line (" watcher" , " event_cb '%s' '%s'" , self ._path , filename )
73
- for _ , listener in ipairs (self ._listeners ) do
78
+ log .line (" watcher" , " event_cb '%s' '%s'" , self .path , filename )
79
+ for _ , listener in ipairs (self .listeners ) do
74
80
listener (filename )
75
81
end
76
82
end
77
83
end )
78
84
79
- rc , _ , name = self ._fs_event :start (self ._path , FS_EVENT_FLAGS , event_cb )
85
+ rc , _ , name = self .fs_event :start (self .path , FS_EVENT_FLAGS , event_cb )
80
86
if rc ~= 0 then
81
87
if name == " EMFILE" then
82
88
M .disable_watchers (" fs.inotify.max_user_watches exceeded, see https://github.com/nvim-tree/nvim-tree.lua/wiki/Troubleshooting" )
83
89
else
84
- notify .warn (string.format (" Could not start the fs_event watcher for path %s : %s" , self ._path , name ))
90
+ notify .warn (string.format (" Could not start the fs_event watcher for path %s : %s" , self .path , name ))
85
91
end
86
92
return false
87
93
end
91
97
92
98
--- @param listener function
93
99
function Event :add (listener )
94
- table.insert (self ._listeners , listener )
100
+ table.insert (self .listeners , listener )
95
101
end
96
102
97
103
--- @param listener function
98
104
function Event :remove (listener )
99
- utils .array_remove (self ._listeners , listener )
100
- if # self ._listeners == 0 then
105
+ utils .array_remove (self .listeners , listener )
106
+ if # self .listeners == 0 then
101
107
self :destroy ()
102
108
end
103
109
end
104
110
105
111
--- @param message string | nil
106
112
function Event :destroy (message )
107
- log .line (" watcher" , " Event:destroy '%s'" , self ._path )
113
+ log .line (" watcher" , " Event:destroy '%s'" , self .path )
108
114
109
- if self ._fs_event then
115
+ if self .fs_event then
110
116
if message then
111
117
notify .warn (message )
112
118
end
113
119
114
- local rc , _ , name = self ._fs_event :stop ()
120
+ local rc , _ , name = self .fs_event :stop ()
115
121
if rc ~= 0 then
116
- notify .warn (string.format (" Could not stop the fs_event watcher for path %s : %s" , self ._path , name ))
122
+ notify .warn (string.format (" Could not stop the fs_event watcher for path %s : %s" , self .path , name ))
117
123
end
118
- self ._fs_event = nil
124
+ self .fs_event = nil
119
125
end
120
126
121
- Event ._events [self ._path ] = nil
122
-
123
127
self .destroyed = true
128
+ events [self .path ] = nil
124
129
end
125
130
131
+ --- Static factory method
132
+ --- Creates and starts a Watcher
133
+ --- @class (exact ) Watcher : Class
134
+ --- @field data table user data
135
+ --- @field destroyed boolean
136
+ --- @field private path string
137
+ --- @field private callback fun (watcher : Watcher )
138
+ --- @field private files string[] ?
139
+ --- @field private listener fun (filename : string )?
140
+ --- @field private event Event
141
+ local Watcher = Class :new ()
142
+
143
+ --- Registry of all watchers
144
+ --- @type Watcher[]
145
+ local watchers = {}
146
+
147
+ --- Static factory method
126
148
--- @param path string
127
149
--- @param files string[] | nil
128
- --- @param callback function
129
- --- @param data table
150
+ --- @param callback fun ( watcher : Watcher )
151
+ --- @param data table user data
130
152
--- @return Watcher | nil
131
- function Watcher :new (path , files , callback , data )
132
- log .line (" watcher" , " Watcher:new '%s' %s" , path , vim .inspect (files ))
133
-
134
- local w = setmetatable (data , Watcher )
153
+ function Watcher :create (path , files , callback , data )
154
+ log .line (" watcher" , " Watcher:create '%s' %s" , path , vim .inspect (files ))
135
155
136
- w ._event = Event ._events [path ] or Event :new (path )
137
- w ._listener = nil
138
- w ._path = path
139
- w ._files = files
140
- w ._callback = callback
141
-
142
- if not w ._event then
156
+ local event = events [path ] or Event :create (path )
157
+ if not event then
143
158
return nil
144
159
end
145
160
146
- w :start ()
161
+ --- @type Watcher
162
+ local o = {
163
+ data = data ,
164
+ destroyed = false ,
165
+ path = path ,
166
+ callback = callback ,
167
+ files = files ,
168
+ listener = nil ,
169
+ event = event ,
170
+ }
171
+ o = self :new (o ) --[[ @as Watcher]]
172
+
173
+ o :start ()
147
174
148
- table.insert (Watcher . _watchers , w )
175
+ table.insert (watchers , o )
149
176
150
- return w
177
+ return o
151
178
end
152
179
153
180
function Watcher :start ()
154
- self ._listener = function (filename )
155
- if not self ._files or vim .tbl_contains (self ._files , filename ) then
156
- self ._callback (self )
181
+ self .listener = function (filename )
182
+ if not self .files or vim .tbl_contains (self .files , filename ) then
183
+ self .callback (self )
157
184
end
158
185
end
159
186
160
- self ._event :add (self ._listener )
187
+ self .event :add (self .listener )
161
188
end
162
189
163
190
function Watcher :destroy ()
164
- log .line (" watcher" , " Watcher:destroy '%s'" , self ._path )
191
+ log .line (" watcher" , " Watcher:destroy '%s'" , self .path )
165
192
166
- self ._event :remove (self ._listener )
193
+ self .event :remove (self .listener )
167
194
168
- utils .array_remove (Watcher . _watchers , self )
195
+ utils .array_remove (watchers , self )
169
196
170
197
self .destroyed = true
171
198
end
@@ -183,11 +210,11 @@ end
183
210
function M .purge_watchers ()
184
211
log .line (" watcher" , " purge_watchers" )
185
212
186
- for _ , w in ipairs (utils .array_shallow_clone (Watcher . _watchers )) do
213
+ for _ , w in ipairs (utils .array_shallow_clone (watchers )) do
187
214
w :destroy ()
188
215
end
189
216
190
- for _ , e in pairs (Event . _events ) do
217
+ for _ , e in pairs (events ) do
191
218
e :destroy ()
192
219
end
193
220
end
0 commit comments