@@ -27,6 +27,7 @@ local file_read_timer
27
27
local autocmd_id
28
28
local handles = {}
29
29
local fs_watching_stopped = false
30
+ local event_timestamps = {}
30
31
31
32
--- Uses libuv to start file system watchers
32
33
--- @param path string #The path to watch
@@ -78,55 +79,67 @@ local function init_fs_watcher(dir_to_watch, is_library_root)
78
79
local info_path
79
80
local do_unwatch = false
80
81
local do_update = true
81
- if is_library_root then
82
- log .debug (" Filesystem event in the library root directory" )
83
- entry_dir = Path (dir_to_watch , filename )
84
- info_path = entry_dir / info_name
85
- local entry_dir_str = tostring (entry_dir )
86
- local info_path_str = tostring (info_path )
87
- if entry_dir :exists () and entry_dir :is_dir () then
88
- log .debug (string.format (" Filesystem event: path '%s' added" , entry_dir_str ))
89
- init_fs_watcher (entry_dir_str )
90
- if info_path :exists () then
91
- mtime = fs_stat (info_path_str ).mtime .sec
82
+ local current_time = uv .hrtime () / 1e6 -- get current time in milliseconds
83
+ local last_event_time = event_timestamps [filename ]
84
+
85
+ if last_event_time and current_time - last_event_time < 200 then
86
+ log .debug (" Debouncing: skipping filesystem event" )
87
+ -- If the last event for this file was less than 200ms ago, discard this event
88
+ return
89
+ end
90
+
91
+ -- Update the timestamp for this file
92
+ event_timestamps [filename ] = current_time
93
+
94
+ vim .defer_fn (function ()
95
+ if is_library_root then
96
+ log .debug (" Filesystem event in the library root directory" )
97
+ entry_dir = Path (dir_to_watch , filename )
98
+ info_path = entry_dir / info_name
99
+ local entry_dir_str = tostring (entry_dir )
100
+ local info_path_str = tostring (info_path )
101
+ if entry_dir :exists () and entry_dir :is_dir () then
102
+ log .debug (string.format (" Filesystem event: path '%s' added" , entry_dir_str ))
103
+ init_fs_watcher (entry_dir_str )
104
+ if info_path :exists () then
105
+ mtime = fs_stat (info_path_str ).mtime .sec
106
+ end
107
+ elseif entry_dir :is_dir () then
108
+ log .debug (string.format (" Filesystem event: path '' removed" , entry_dir_str ))
109
+ -- don't update here, because we'll catch it below under entry events
110
+ do_update = false
111
+ else
112
+ -- it's a file (not a directory). ignore
113
+ do_update = false
92
114
end
93
- elseif entry_dir :is_dir () then
94
- log .debug (string.format (" Filesystem event: path '' removed" , entry_dir_str ))
95
- -- don't update here, because we'll catch it below under entry events
96
- do_update = false
97
115
else
98
- -- it's a file (not a directory). ignore
99
- do_update = false
100
- end
101
- else
102
- log .debug (" Filesystem event in entry directory" )
103
- entry_dir = Path (dir_to_watch )
104
- info_path = entry_dir / info_name
105
- local info_path_str = tostring (info_path )
106
- if info_path :exists () then
107
- -- info file exists, update with new info
108
- log .debug (string.format (" Filesystem event: '%s' changed" , info_path_str ))
109
- mtime = fs_stat (tostring (info_path )).mtime .sec
110
- elseif not entry_dir :exists () then
111
- -- info file and entry dir don't exist. delete entry (mtime = nil) and remove watcher
112
- log .debug (string.format (" Filesystem event: '%s' removed" , info_path_str ))
113
- do_unwatch = true
114
- else
115
- -- info file doesn't exist but entry dir does. delete entry but keep watcher
116
- log .debug (string.format (" Filesystem event: '%s' removed" , info_path_str ))
116
+ log .debug (" Filesystem event in entry directory" )
117
+ entry_dir = Path (dir_to_watch )
118
+ info_path = entry_dir / info_name
119
+ local info_path_str = tostring (info_path )
120
+ if info_path :exists () then
121
+ -- info file exists, update with new info
122
+ log .debug (string.format (" Filesystem event: '%s' changed" , info_path_str ))
123
+ mtime = fs_stat (tostring (info_path )).mtime .sec
124
+ elseif not entry_dir :exists () then
125
+ -- info file and entry dir don't exist. delete entry (mtime = nil) and remove watcher
126
+ log .debug (string.format (" Filesystem event: '%s' removed" , info_path_str ))
127
+ do_unwatch = true
128
+ else
129
+ -- info file doesn't exist but entry dir does. delete entry but keep watcher
130
+ log .debug (string.format (" Filesystem event: '%s' removed" , info_path_str ))
131
+ end
117
132
end
118
- end
119
- if do_update then
120
- local info_path_str = tostring (info_path )
121
- log .debug (" Update database for this fs event..." )
122
- log .debug (" Updating: " .. vim .inspect ({ path = info_path_str , mtime = mtime }))
123
- vim .defer_fn (function ()
133
+ if do_update then
134
+ local info_path_str = tostring (info_path )
135
+ log .debug (" Update database for this fs event..." )
136
+ log .debug (" Updating: " .. vim .inspect ({ path = info_path_str , mtime = mtime }))
124
137
data .update_db ({ path = info_path_str , mtime = mtime })
125
- end , 200 )
126
- elseif do_unwatch then
127
- log . debug ( " Removing watcher " )
128
- unwatch_cb ()
129
- end
138
+ elseif do_unwatch then
139
+ log . debug ( " Removing watcher " )
140
+ unwatch_cb ( )
141
+ end
142
+ end , 200 )
130
143
end
131
144
132
145
-- start the file watcher
0 commit comments