listen 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,203 +1,203 @@
1
- require 'pathname'
2
-
3
- module Listen
4
- class Listener
5
- attr_reader :directory, :directory_record, :adapter
6
-
7
- # The default value for using relative paths in the callback.
8
- DEFAULT_TO_RELATIVE_PATHS = false
9
-
10
- # Initializes the directory listener.
11
- #
12
- # @param [String] directory the directory to listen to
13
- # @param [Hash] options the listen options
14
- # @option options [Regexp] ignore a pattern for ignoring paths
15
- # @option options [Regexp] filter a pattern for filtering paths
16
- # @option options [Float] latency the delay between checking for changes in seconds
17
- # @option options [Boolean] relative_paths whether or not to use relative-paths in the callback
18
- # @option options [Boolean] force_polling whether to force the polling adapter or not
19
- # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
20
- #
21
- # @yield [modified, added, removed] the changed files
22
- # @yieldparam [Array<String>] modified the list of modified files
23
- # @yieldparam [Array<String>] added the list of added files
24
- # @yieldparam [Array<String>] removed the list of removed files
25
- #
26
- def initialize(directory, options = {}, &block)
27
- @block = block
28
- @directory = Pathname.new(directory).realpath.to_s
29
- @directory_record = DirectoryRecord.new(@directory)
30
- @use_relative_paths = DEFAULT_TO_RELATIVE_PATHS
31
-
32
- @use_relative_paths = options.delete(:relative_paths) if options[:relative_paths]
33
- @directory_record.ignore(*options.delete(:ignore)) if options[:ignore]
34
- @directory_record.filter(*options.delete(:filter)) if options[:filter]
35
-
36
- @adapter_options = options
37
- end
38
-
39
- # Starts the listener by initializing the adapter and building
40
- # the directory record concurrently, then it starts the adapter to watch
41
- # for changes.
42
- #
43
- # @param [Boolean] blocking whether or not to block the current thread after starting
44
- #
45
- def start(blocking = true)
46
- t = Thread.new { @directory_record.build }
47
- @adapter = initialize_adapter
48
- t.join
49
- @adapter.start(blocking)
50
- end
51
-
52
- # Stops the listener.
53
- #
54
- def stop
55
- @adapter.stop
56
- end
57
-
58
- # Pauses the listener.
59
- #
60
- # @return [Listen::Listener] the listener
61
- #
62
- def pause
63
- @adapter.paused = true
64
- self
65
- end
66
-
67
- # Unpauses the listener.
68
- #
69
- # @return [Listen::Listener] the listener
70
- #
71
- def unpause
72
- @directory_record.build
73
- @adapter.paused = false
74
- self
75
- end
76
-
77
- # Returns whether the listener is paused or not.
78
- #
79
- # @return [Boolean] adapter paused status
80
- #
81
- def paused?
82
- !!@adapter && @adapter.paused == true
83
- end
84
-
85
- # Adds ignoring patterns to the listener.
86
- #
87
- # @param (see Listen::DirectoryRecord#ignore)
88
- #
89
- # @return [Listen::Listener] the listener
90
- #
91
- def ignore(*regexps)
92
- @directory_record.ignore(*regexps)
93
- self
94
- end
95
-
96
- # Adds filtering patterns to the listener.
97
- #
98
- # @param (see Listen::DirectoryRecord#filter)
99
- #
100
- # @return [Listen::Listener] the listener
101
- #
102
- def filter(*regexps)
103
- @directory_record.filter(*regexps)
104
- self
105
- end
106
-
107
- # Sets the latency for the adapter. This is a helper method
108
- # to simplify changing the latency directly from the listener.
109
- #
110
- # @example Wait 0.5 seconds each time before checking changes
111
- # latency 0.5
112
- #
113
- # @param [Float] seconds the amount of delay, in seconds
114
- #
115
- # @return [Listen::Listener] the listener
116
- #
117
- def latency(seconds)
118
- @adapter_options[:latency] = seconds
119
- self
120
- end
121
-
122
- # Sets whether the use of the polling adapter
123
- # should be forced or not.
124
- #
125
- # @example Forcing the use of the polling adapter
126
- # force_polling true
127
- #
128
- # @param [Boolean] value whether to force the polling adapter or not
129
- #
130
- # @return [Listen::Listener] the listener
131
- #
132
- def force_polling(value)
133
- @adapter_options[:force_polling] = value
134
- self
135
- end
136
-
137
- # Sets whether the paths in the callback should be
138
- # relative or absolute.
139
- #
140
- # @example Enabling relative paths in the callback
141
- # relative_paths true
142
- #
143
- # @param [Boolean] value whether to enable relative paths in the callback or not
144
- #
145
- # @return [Listen::Listener] the listener
146
- #
147
- def relative_paths(value)
148
- @use_relative_paths = value
149
- self
150
- end
151
-
152
- # Defines a custom polling fallback message of disable it.
153
- #
154
- # @example Disabling the polling fallback message
155
- # polling_fallback_message false
156
- #
157
- # @param [String, Boolean] value to change polling fallback message or remove it
158
- #
159
- # @return [Listen::Listener] the listener
160
- #
161
- def polling_fallback_message(value)
162
- @adapter_options[:polling_fallback_message] = value
163
- self
164
- end
165
-
166
- # Sets the callback that gets called on changes.
167
- #
168
- # @example Assign a callback to be called on changes
169
- # callback = lambda { |modified, added, removed| ... }
170
- # change &callback
171
- #
172
- # @param [Proc] block the callback proc
173
- #
174
- # @return [Listen::Listener] the listener
175
- #
176
- def change(&block) # modified, added, removed
177
- @block = block
178
- self
179
- end
180
-
181
- # Runs the callback passing it the changes if there are any.
182
- #
183
- # @param (see Listen::DirectoryRecord#fetch_changes)
184
- #
185
- def on_change(directories, options = {})
186
- changes = @directory_record.fetch_changes(directories, options.merge(
187
- :relative_paths => @use_relative_paths
188
- ))
189
- unless changes.values.all? { |paths| paths.empty? }
190
- @block.call(changes[:modified],changes[:added],changes[:removed])
191
- end
192
- end
193
-
194
- private
195
-
196
- # Initializes an adapter passing it the callback and adapters' options.
197
- #
198
- def initialize_adapter
199
- callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
200
- Adapter.select_and_initialize(@directory, @adapter_options, &callback)
201
- end
202
- end
203
- end
1
+ require 'pathname'
2
+
3
+ module Listen
4
+ class Listener
5
+ attr_reader :directory, :directory_record, :adapter
6
+
7
+ # The default value for using relative paths in the callback.
8
+ DEFAULT_TO_RELATIVE_PATHS = false
9
+
10
+ # Initializes the directory listener.
11
+ #
12
+ # @param [String] directory the directory to listen to
13
+ # @param [Hash] options the listen options
14
+ # @option options [Regexp] ignore a pattern for ignoring paths
15
+ # @option options [Regexp] filter a pattern for filtering paths
16
+ # @option options [Float] latency the delay between checking for changes in seconds
17
+ # @option options [Boolean] relative_paths whether or not to use relative-paths in the callback
18
+ # @option options [Boolean] force_polling whether to force the polling adapter or not
19
+ # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
20
+ #
21
+ # @yield [modified, added, removed] the changed files
22
+ # @yieldparam [Array<String>] modified the list of modified files
23
+ # @yieldparam [Array<String>] added the list of added files
24
+ # @yieldparam [Array<String>] removed the list of removed files
25
+ #
26
+ def initialize(directory, options = {}, &block)
27
+ @block = block
28
+ @directory = Pathname.new(directory).realpath.to_s
29
+ @directory_record = DirectoryRecord.new(@directory)
30
+ @use_relative_paths = DEFAULT_TO_RELATIVE_PATHS
31
+
32
+ @use_relative_paths = options.delete(:relative_paths) if options[:relative_paths]
33
+ @directory_record.ignore(*options.delete(:ignore)) if options[:ignore]
34
+ @directory_record.filter(*options.delete(:filter)) if options[:filter]
35
+
36
+ @adapter_options = options
37
+ end
38
+
39
+ # Starts the listener by initializing the adapter and building
40
+ # the directory record concurrently, then it starts the adapter to watch
41
+ # for changes.
42
+ #
43
+ # @param [Boolean] blocking whether or not to block the current thread after starting
44
+ #
45
+ def start(blocking = true)
46
+ t = Thread.new { @directory_record.build }
47
+ @adapter = initialize_adapter
48
+ t.join
49
+ @adapter.start(blocking)
50
+ end
51
+
52
+ # Stops the listener.
53
+ #
54
+ def stop
55
+ @adapter.stop
56
+ end
57
+
58
+ # Pauses the listener.
59
+ #
60
+ # @return [Listen::Listener] the listener
61
+ #
62
+ def pause
63
+ @adapter.paused = true
64
+ self
65
+ end
66
+
67
+ # Unpauses the listener.
68
+ #
69
+ # @return [Listen::Listener] the listener
70
+ #
71
+ def unpause
72
+ @directory_record.build
73
+ @adapter.paused = false
74
+ self
75
+ end
76
+
77
+ # Returns whether the listener is paused or not.
78
+ #
79
+ # @return [Boolean] adapter paused status
80
+ #
81
+ def paused?
82
+ !!@adapter && @adapter.paused == true
83
+ end
84
+
85
+ # Adds ignoring patterns to the listener.
86
+ #
87
+ # @param (see Listen::DirectoryRecord#ignore)
88
+ #
89
+ # @return [Listen::Listener] the listener
90
+ #
91
+ def ignore(*regexps)
92
+ @directory_record.ignore(*regexps)
93
+ self
94
+ end
95
+
96
+ # Adds filtering patterns to the listener.
97
+ #
98
+ # @param (see Listen::DirectoryRecord#filter)
99
+ #
100
+ # @return [Listen::Listener] the listener
101
+ #
102
+ def filter(*regexps)
103
+ @directory_record.filter(*regexps)
104
+ self
105
+ end
106
+
107
+ # Sets the latency for the adapter. This is a helper method
108
+ # to simplify changing the latency directly from the listener.
109
+ #
110
+ # @example Wait 0.5 seconds each time before checking changes
111
+ # latency 0.5
112
+ #
113
+ # @param [Float] seconds the amount of delay, in seconds
114
+ #
115
+ # @return [Listen::Listener] the listener
116
+ #
117
+ def latency(seconds)
118
+ @adapter_options[:latency] = seconds
119
+ self
120
+ end
121
+
122
+ # Sets whether the use of the polling adapter
123
+ # should be forced or not.
124
+ #
125
+ # @example Forcing the use of the polling adapter
126
+ # force_polling true
127
+ #
128
+ # @param [Boolean] value whether to force the polling adapter or not
129
+ #
130
+ # @return [Listen::Listener] the listener
131
+ #
132
+ def force_polling(value)
133
+ @adapter_options[:force_polling] = value
134
+ self
135
+ end
136
+
137
+ # Sets whether the paths in the callback should be
138
+ # relative or absolute.
139
+ #
140
+ # @example Enabling relative paths in the callback
141
+ # relative_paths true
142
+ #
143
+ # @param [Boolean] value whether to enable relative paths in the callback or not
144
+ #
145
+ # @return [Listen::Listener] the listener
146
+ #
147
+ def relative_paths(value)
148
+ @use_relative_paths = value
149
+ self
150
+ end
151
+
152
+ # Defines a custom polling fallback message of disable it.
153
+ #
154
+ # @example Disabling the polling fallback message
155
+ # polling_fallback_message false
156
+ #
157
+ # @param [String, Boolean] value to change polling fallback message or remove it
158
+ #
159
+ # @return [Listen::Listener] the listener
160
+ #
161
+ def polling_fallback_message(value)
162
+ @adapter_options[:polling_fallback_message] = value
163
+ self
164
+ end
165
+
166
+ # Sets the callback that gets called on changes.
167
+ #
168
+ # @example Assign a callback to be called on changes
169
+ # callback = lambda { |modified, added, removed| ... }
170
+ # change &callback
171
+ #
172
+ # @param [Proc] block the callback proc
173
+ #
174
+ # @return [Listen::Listener] the listener
175
+ #
176
+ def change(&block) # modified, added, removed
177
+ @block = block
178
+ self
179
+ end
180
+
181
+ # Runs the callback passing it the changes if there are any.
182
+ #
183
+ # @param (see Listen::DirectoryRecord#fetch_changes)
184
+ #
185
+ def on_change(directories, options = {})
186
+ changes = @directory_record.fetch_changes(directories, options.merge(
187
+ :relative_paths => @use_relative_paths
188
+ ))
189
+ unless changes.values.all? { |paths| paths.empty? }
190
+ @block.call(changes[:modified],changes[:added],changes[:removed])
191
+ end
192
+ end
193
+
194
+ private
195
+
196
+ # Initializes an adapter passing it the callback and adapters' options.
197
+ #
198
+ def initialize_adapter
199
+ callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
200
+ Adapter.select_and_initialize(@directory, @adapter_options, &callback)
201
+ end
202
+ end
203
+ end
@@ -1,121 +1,121 @@
1
- module Listen
2
- class MultiListener < Listener
3
- attr_reader :directories, :directories_records, :adapter
4
-
5
- # Initializes the multiple directories listener.
6
- #
7
- # @param [String] directories the directories to listen to
8
- # @param [Hash] options the listen options
9
- # @option options [Regexp] ignore a pattern for ignoring paths
10
- # @option options [Regexp] filter a pattern for filtering paths
11
- # @option options [Float] latency the delay between checking for changes in seconds
12
- # @option options [Boolean] force_polling whether to force the polling adapter or not
13
- # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
14
- #
15
- # @yield [modified, added, removed] the changed files
16
- # @yieldparam [Array<String>] modified the list of modified files
17
- # @yieldparam [Array<String>] added the list of added files
18
- # @yieldparam [Array<String>] removed the list of removed files
19
- #
20
- def initialize(*args, &block)
21
- options = args.last.is_a?(Hash) ? args.pop : {}
22
- directories = args
23
-
24
- @block = block
25
- @directories = directories.map { |d| Pathname.new(d).realpath.to_s }
26
- @directories_records = @directories.map { |d| DirectoryRecord.new(d) }
27
-
28
- ignore(*options.delete(:ignore)) if options[:ignore]
29
- filter(*options.delete(:filter)) if options[:filter]
30
-
31
- @adapter_options = options
32
- end
33
-
34
- # Starts the listener by initializing the adapter and building
35
- # the directory record concurrently, then it starts the adapter to watch
36
- # for changes.
37
- #
38
- # @param [Boolean] blocking whether or not to block the current thread after starting
39
- #
40
- def start(blocking = true)
41
- t = Thread.new { @directories_records.each { |r| r.build } }
42
- @adapter = initialize_adapter
43
- t.join
44
- @adapter.start(blocking)
45
- end
46
-
47
- # Unpauses the listener.
48
- #
49
- # @return [Listen::Listener] the listener
50
- #
51
- def unpause
52
- @directories_records.each { |r| r.build }
53
- @adapter.paused = false
54
- self
55
- end
56
-
57
- # Adds ignored paths to the listener.
58
- #
59
- # @param (see Listen::DirectoryRecord#ignore)
60
- #
61
- # @return [Listen::Listener] the listener
62
- #
63
- def ignore(*paths)
64
- @directories_records.each { |r| r.ignore(*paths) }
65
- self
66
- end
67
-
68
- # Adds file filters to the listener.
69
- #
70
- # @param (see Listen::DirectoryRecord#filter)
71
- #
72
- # @return [Listen::Listener] the listener
73
- #
74
- def filter(*regexps)
75
- @directories_records.each { |r| r.filter(*regexps) }
76
- self
77
- end
78
-
79
- # Runs the callback passing it the changes if there are any.
80
- #
81
- # @param (see Listen::DirectoryRecord#fetch_changes)
82
- #
83
- def on_change(directories_to_search, options = {})
84
- changes = fetch_records_changes(directories_to_search, options)
85
- unless changes.values.all? { |paths| paths.empty? }
86
- @block.call(changes[:modified],changes[:added],changes[:removed])
87
- end
88
- end
89
-
90
- private
91
-
92
- # Initializes an adapter passing it the callback and adapters' options.
93
- #
94
- def initialize_adapter
95
- callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
96
- Adapter.select_and_initialize(@directories, @adapter_options, &callback)
97
- end
98
-
99
- # Returns the sum of all the changes to the directories records
100
- #
101
- # @param (see Listen::DirectoryRecord#fetch_changes)
102
- #
103
- # @return [Hash] the changes
104
- #
105
- def fetch_records_changes(directories_to_search, options)
106
- @directories_records.inject({}) do |h, r|
107
- # directory records skips paths outside their range, so passing the
108
- # whole `directories` array is not a problem.
109
- record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => DEFAULT_TO_RELATIVE_PATHS))
110
-
111
- if h.empty?
112
- h.merge!(record_changes)
113
- else
114
- h.each { |k, v| h[k] += record_changes[k] }
115
- end
116
-
117
- h
118
- end
119
- end
120
- end
121
- end
1
+ module Listen
2
+ class MultiListener < Listener
3
+ attr_reader :directories, :directories_records, :adapter
4
+
5
+ # Initializes the multiple directories listener.
6
+ #
7
+ # @param [String] directories the directories to listen to
8
+ # @param [Hash] options the listen options
9
+ # @option options [Regexp] ignore a pattern for ignoring paths
10
+ # @option options [Regexp] filter a pattern for filtering paths
11
+ # @option options [Float] latency the delay between checking for changes in seconds
12
+ # @option options [Boolean] force_polling whether to force the polling adapter or not
13
+ # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it
14
+ #
15
+ # @yield [modified, added, removed] the changed files
16
+ # @yieldparam [Array<String>] modified the list of modified files
17
+ # @yieldparam [Array<String>] added the list of added files
18
+ # @yieldparam [Array<String>] removed the list of removed files
19
+ #
20
+ def initialize(*args, &block)
21
+ options = args.last.is_a?(Hash) ? args.pop : {}
22
+ directories = args
23
+
24
+ @block = block
25
+ @directories = directories.map { |d| Pathname.new(d).realpath.to_s }
26
+ @directories_records = @directories.map { |d| DirectoryRecord.new(d) }
27
+
28
+ ignore(*options.delete(:ignore)) if options[:ignore]
29
+ filter(*options.delete(:filter)) if options[:filter]
30
+
31
+ @adapter_options = options
32
+ end
33
+
34
+ # Starts the listener by initializing the adapter and building
35
+ # the directory record concurrently, then it starts the adapter to watch
36
+ # for changes.
37
+ #
38
+ # @param [Boolean] blocking whether or not to block the current thread after starting
39
+ #
40
+ def start(blocking = true)
41
+ t = Thread.new { @directories_records.each { |r| r.build } }
42
+ @adapter = initialize_adapter
43
+ t.join
44
+ @adapter.start(blocking)
45
+ end
46
+
47
+ # Unpauses the listener.
48
+ #
49
+ # @return [Listen::Listener] the listener
50
+ #
51
+ def unpause
52
+ @directories_records.each { |r| r.build }
53
+ @adapter.paused = false
54
+ self
55
+ end
56
+
57
+ # Adds ignored paths to the listener.
58
+ #
59
+ # @param (see Listen::DirectoryRecord#ignore)
60
+ #
61
+ # @return [Listen::Listener] the listener
62
+ #
63
+ def ignore(*paths)
64
+ @directories_records.each { |r| r.ignore(*paths) }
65
+ self
66
+ end
67
+
68
+ # Adds file filters to the listener.
69
+ #
70
+ # @param (see Listen::DirectoryRecord#filter)
71
+ #
72
+ # @return [Listen::Listener] the listener
73
+ #
74
+ def filter(*regexps)
75
+ @directories_records.each { |r| r.filter(*regexps) }
76
+ self
77
+ end
78
+
79
+ # Runs the callback passing it the changes if there are any.
80
+ #
81
+ # @param (see Listen::DirectoryRecord#fetch_changes)
82
+ #
83
+ def on_change(directories_to_search, options = {})
84
+ changes = fetch_records_changes(directories_to_search, options)
85
+ unless changes.values.all? { |paths| paths.empty? }
86
+ @block.call(changes[:modified],changes[:added],changes[:removed])
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ # Initializes an adapter passing it the callback and adapters' options.
93
+ #
94
+ def initialize_adapter
95
+ callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) }
96
+ Adapter.select_and_initialize(@directories, @adapter_options, &callback)
97
+ end
98
+
99
+ # Returns the sum of all the changes to the directories records
100
+ #
101
+ # @param (see Listen::DirectoryRecord#fetch_changes)
102
+ #
103
+ # @return [Hash] the changes
104
+ #
105
+ def fetch_records_changes(directories_to_search, options)
106
+ @directories_records.inject({}) do |h, r|
107
+ # directory records skips paths outside their range, so passing the
108
+ # whole `directories` array is not a problem.
109
+ record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => DEFAULT_TO_RELATIVE_PATHS))
110
+
111
+ if h.empty?
112
+ h.merge!(record_changes)
113
+ else
114
+ h.each { |k, v| h[k] += record_changes[k] }
115
+ end
116
+
117
+ h
118
+ end
119
+ end
120
+ end
121
+ end