-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.coffee
92 lines (81 loc) · 3 KB
/
main.coffee
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
fs = require 'fs'
np = require 'path'
# watches a directory recursively for file changes
# will call the listener once for each matching file
# immediately and then whenever
# files are changed, deleted or created
exports.watchDirectory = (dirname, options, listener) ->
if not listener?
listener = options
options = {}
options.persistent ?= true
options.interval ?= 100
options.recursive ?= true
# change message for initial pass. Use false for no initial pass.
options.initial ?= 'initial'
options.exclude ?=
node_modules: true
# options.filter = string extension or RegExp or function
matches = (name, filter, defaultValue) ->
if not filter?
defaultValue
else if typeof filter is 'string'
ext = filter
name.indexOf(ext, name.length - ext.length) isnt -1
else if filter.constructor is RegExp
filter.test name
else if typeof filter is 'function'
filter name
else
filter[name] is true
filter = (name) ->
if matches name, options.exclude, false
false
else
matches name, options.include, true
watchedFiles = {} # filename => bound listener
notifyListener = (filename, curr, prev, change) ->
if filter filename
listener filename, curr, prev, change
fsListener = (filename, depth, curr, prev) ->
change =
if curr.nlink is 0
'deleted'
else if prev.nlink is 0
'created'
else
'modified'
notifyListener filename, curr, prev, change
# we call watchFile again in case children were added
if change isnt 'deleted'
watchFile filename, depth, curr
else
unwatchFile filename
unwatchFile = (filename) ->
fs.unwatchFile filename, watchedFiles[filename]
delete watchedFiles[filename]
watchFile = (filename, depth=0, stats) ->
stats ?= fs.statSync filename
if stats.nlink > 0
if stats.isDirectory()
# also watch all children
# exclude directories in exclude list
if not matches filename, options.exclude, false
if depth is 0 or options.recursive
for child in fs.readdirSync filename
child = np.join filename, child
watchFile child, depth + 1
if not watchedFiles[filename]?
boundListener = fsListener.bind @, filename, depth
watchedFiles[filename] = boundListener
fs.watchFile filename, options, boundListener
if initial
notifyListener filename, stats, stats, initial
return
initial = options.initial
watchFile dirname
initial = 'created'
# return a function that will unwatch all watched files
->
for key of watchedFiles
unwatchFile key