guard 2.10.0 → 2.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/guard.rb +11 -2
- data/lib/guard.rb.orig +57 -154
- data/lib/guard/dsl.rb +13 -8
- data/lib/guard/dsl.rb.orig +77 -23
- data/lib/guard/internals/session.rb +5 -0
- data/lib/guard/internals/session.rb.orig +15 -2
- data/lib/guard/notifier.rb +5 -6
- data/lib/guard/notifiers/tmux.rb +24 -24
- data/lib/guard/plugin.rb +2 -2
- data/lib/guard/ui.rb +1 -7
- data/lib/guard/version.rb +1 -1
- data/lib/guard/version.rb.orig +1 -1
- metadata +2 -12
- data/lib/guard/cli.rb.orig +0 -220
- data/lib/guard/deprecated/guard.rb.orig +0 -178
- data/lib/guard/dsl_describer.rb.orig +0 -188
- data/lib/guard/notifier.rb.orig +0 -247
- data/lib/guard/notifier/detected.rb.orig +0 -83
- data/lib/guard/plugin.rb.orig +0 -300
- data/lib/guard/reevaluator.rb.orig +0 -22
- data/lib/guard/templates/Guardfile.orig +0 -2
- data/lib/guard/ui.rb.orig +0 -274
- data/lib/guard/watcher.rb.orig +0 -122
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 100b160735c5c331821d9fa8119bb168ed5f907e
|
4
|
+
data.tar.gz: d677f7e1a7491ff72654d415d7c571f028fbef52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0dcad099ca8bd1dca2486e078233215366c4236b8a1b0b465336d020667e041bd16e75df106efeef75a6013fcdb9601fdd35bd28eac8130c4eb3a910694004a3
|
7
|
+
data.tar.gz: 835a20ae288b6c660d9cb058eeba5b2c25f999bc3790c0dfb0ccf48a7816eff2405fe82e26cc9884b2397f02a610ba73f848c63bf89eb478fd94aae632ff31f7
|
data/lib/guard.rb
CHANGED
@@ -60,8 +60,15 @@ module Guard
|
|
60
60
|
_evaluate(state.session.evaluator_options)
|
61
61
|
|
62
62
|
# NOTE: this should be *after* evaluate so :directories can work
|
63
|
+
# TODO: move listener setup to session?
|
63
64
|
@listener = Listen.send(*state.session.listener_args, &_listener_callback)
|
64
65
|
|
66
|
+
ignores = state.session.guardfile_ignore
|
67
|
+
@listener.ignore(ignores) unless ignores.empty?
|
68
|
+
|
69
|
+
ignores = state.session.guardfile_ignore_bang
|
70
|
+
@listener.ignore!(ignores) unless ignores.empty?
|
71
|
+
|
65
72
|
Notifier.connect(state.session.notify_options)
|
66
73
|
|
67
74
|
traps = Internals::Traps
|
@@ -86,9 +93,11 @@ module Guard
|
|
86
93
|
#
|
87
94
|
# Currently supported args:
|
88
95
|
#
|
89
|
-
#
|
96
|
+
# @example Old style hash:
|
97
|
+
# async_queue_add(modified: ['foo'], added: ['bar'], removed: [])
|
90
98
|
#
|
91
|
-
#
|
99
|
+
# @example New style signals with args:
|
100
|
+
# async_queue_add([:guard_pause, :unpaused ])
|
92
101
|
#
|
93
102
|
def async_queue_add(changes)
|
94
103
|
@queue << changes
|
data/lib/guard.rb.orig
CHANGED
@@ -8,11 +8,13 @@ require "guard/internals/debugging"
|
|
8
8
|
require "guard/internals/traps"
|
9
9
|
require "guard/internals/helpers"
|
10
10
|
|
11
|
-
require "guard/
|
12
|
-
require "guard/
|
11
|
+
require "guard/internals/queue"
|
12
|
+
require "guard/internals/state"
|
13
13
|
|
14
|
+
require "guard/options"
|
14
15
|
require "guard/commander"
|
15
16
|
require "guard/dsl"
|
17
|
+
require "guard/group"
|
16
18
|
require "guard/interactor"
|
17
19
|
require "guard/notifier"
|
18
20
|
require "guard/plugin_util"
|
@@ -20,6 +22,7 @@ require "guard/runner"
|
|
20
22
|
require "guard/sheller"
|
21
23
|
require "guard/ui"
|
22
24
|
require "guard/watcher"
|
25
|
+
require "guard/guardfile/evaluator"
|
23
26
|
|
24
27
|
# Guard is the main module for all Guard related modules and classes.
|
25
28
|
# Also Guard plugins should use this namespace.
|
@@ -30,6 +33,9 @@ module Guard
|
|
30
33
|
class << self
|
31
34
|
attr_reader :listener
|
32
35
|
|
36
|
+
# @private api
|
37
|
+
attr_reader :queue
|
38
|
+
|
33
39
|
include Internals::Helpers
|
34
40
|
|
35
41
|
# Initializes the Guard singleton:
|
@@ -46,103 +52,52 @@ module Guard
|
|
46
52
|
# @option options [String] guardfile the path to the Guardfile
|
47
53
|
#
|
48
54
|
# @return [Guard] the Guard singleton
|
49
|
-
|
55
|
+
def setup(cmdline_options = {})
|
56
|
+
init(cmdline_options)
|
50
57
|
|
51
|
-
|
52
|
-
# and some are mock and leak between tests,
|
53
|
-
# so ideally there should be a guard "instance"
|
54
|
-
# object that can be created anew between tests
|
55
|
-
def setup(opts = {})
|
56
|
-
# NOTE: must be set before anything calls Guard.options
|
57
|
-
reset_options(opts)
|
58
|
+
@queue = Internals::Queue.new(Guard)
|
58
59
|
|
59
|
-
|
60
|
-
::Guard::Internals::Debugging.start if options[:debug]
|
60
|
+
_evaluate(state.session.evaluator_options)
|
61
61
|
|
62
|
-
|
63
|
-
|
62
|
+
# NOTE: this should be *after* evaluate so :directories can work
|
63
|
+
# TODO: move listener setup to session?
|
64
|
+
@listener = Listen.send(*state.session.listener_args, &_listener_callback)
|
64
65
|
|
65
|
-
|
66
|
+
ignores = state.session.guardfile_ignore
|
67
|
+
@listener.ignore(ignores) unless ignores.empty?
|
66
68
|
|
67
|
-
|
69
|
+
ignores = state.session.guardfile_ignore_bang
|
70
|
+
@listener.ignore!(ignores) unless ignores.empty?
|
68
71
|
|
69
|
-
|
70
|
-
evaluate_guardfile
|
71
|
-
setup_scope
|
72
|
-
|
73
|
-
::Guard::Notifier.connect(notify: options[:notify])
|
72
|
+
Notifier.connect(state.session.notify_options)
|
74
73
|
|
75
74
|
traps = Internals::Traps
|
76
75
|
traps.handle("USR1") { async_queue_add([:guard_pause, :paused]) }
|
77
76
|
traps.handle("USR2") { async_queue_add([:guard_pause, :unpaused]) }
|
78
77
|
|
79
|
-
@interactor =
|
78
|
+
@interactor = Interactor.new(state.session.interactor_name == :sleep)
|
80
79
|
traps.handle("INT") { @interactor.handle_interrupt }
|
81
80
|
|
82
81
|
self
|
83
82
|
end
|
84
83
|
|
85
|
-
|
86
|
-
|
87
|
-
# Used only by tests (for all I know...)
|
88
|
-
def clear_options
|
89
|
-
@options = nil
|
90
|
-
end
|
91
|
-
|
92
|
-
# Initializes the groups array with the default group(s).
|
93
|
-
#
|
94
|
-
# @see DEFAULT_GROUPS
|
95
|
-
#
|
96
|
-
def reset_groups
|
97
|
-
@groups = DEFAULT_GROUPS.map { |name| Group.new(name) }
|
98
|
-
end
|
99
|
-
|
100
|
-
# Initializes the plugins array to an empty array.
|
101
|
-
#
|
102
|
-
# @see Guard.plugins
|
103
|
-
#
|
104
|
-
def reset_plugins
|
105
|
-
@plugins = []
|
84
|
+
def init(cmdline_options)
|
85
|
+
@state = Internals::State.new(cmdline_options)
|
106
86
|
end
|
107
87
|
|
108
|
-
attr_reader :
|
88
|
+
attr_reader :state
|
109
89
|
|
110
|
-
|
111
|
-
# run only a specific group) or the `--plugin` / `-P` option (to run only a
|
112
|
-
# specific plugin).
|
113
|
-
#
|
114
|
-
# @see CLI#start
|
115
|
-
# @see Dsl#scope
|
116
|
-
#
|
117
|
-
def setup_scope(scope = {})
|
118
|
-
# TODO: there should be a special Scope class instead
|
119
|
-
scope = _prepare_scope(scope)
|
120
|
-
|
121
|
-
::Guard.scope = {
|
122
|
-
groups: scope[:groups].map { |item| ::Guard.add_group(item) },
|
123
|
-
plugins: scope[:plugins].map { |item| ::Guard.plugin(item) },
|
124
|
-
}
|
125
|
-
end
|
126
|
-
|
127
|
-
# Evaluates the Guardfile content. It displays an error message if no
|
128
|
-
# Guard plugins are instantiated after the Guardfile evaluation.
|
129
|
-
#
|
130
|
-
# @see Guard::Guardfile::Evaluator#evaluate_guardfile
|
131
|
-
#
|
132
|
-
def evaluate_guardfile
|
133
|
-
evaluator = Guard::Guardfile::Evaluator.new(options)
|
134
|
-
evaluator.evaluate_guardfile
|
135
|
-
msg = "No plugins found in Guardfile, please add at least one."
|
136
|
-
::Guard::UI.error msg if _pluginless_guardfile?
|
137
|
-
end
|
90
|
+
attr_reader :interactor
|
138
91
|
|
139
92
|
# Asynchronously trigger changes
|
140
93
|
#
|
141
94
|
# Currently supported args:
|
142
95
|
#
|
143
|
-
#
|
96
|
+
# @example Old style hash:
|
97
|
+
# async_queue_add(modified: ['foo'], added: ['bar'], removed: [])
|
144
98
|
#
|
145
|
-
#
|
99
|
+
# @example New style signals with args:
|
100
|
+
# async_queue_add([:guard_pause, :unpaused ])
|
146
101
|
#
|
147
102
|
def async_queue_add(changes)
|
148
103
|
@queue << changes
|
@@ -152,60 +107,17 @@ module Guard
|
|
152
107
|
Thread.new { interactor.background }
|
153
108
|
end
|
154
109
|
|
155
|
-
def pending_changes?
|
156
|
-
! @queue.empty?
|
157
|
-
end
|
158
|
-
|
159
|
-
def watchdirs=(dirs)
|
160
|
-
dirs = [Dir.pwd] if dirs.empty?
|
161
|
-
@watchdirs = dirs.map { |dir| File.expand_path dir }
|
162
|
-
end
|
163
|
-
|
164
110
|
private
|
165
111
|
|
166
|
-
# Initializes the listener and registers a callback for changes.
|
167
|
-
#
|
168
|
-
def _setup_listener
|
169
|
-
if options[:listen_on]
|
170
|
-
Listen.on(options[:listen_on], &_listener_callback)
|
171
|
-
else
|
172
|
-
listener_options = {}
|
173
|
-
[:latency, :force_polling, :wait_for_delay].each do |option|
|
174
|
-
listener_options[option] = options[option] if options[option]
|
175
|
-
end
|
176
|
-
listen_args = watchdirs + [listener_options]
|
177
|
-
Listen.to(*listen_args, &_listener_callback)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
# Process the change queue, running tasks within the main Guard thread
|
182
|
-
def _process_queue
|
183
|
-
actions, changes = [], { modified: [], added: [], removed: [] }
|
184
|
-
|
185
|
-
while pending_changes?
|
186
|
-
if (item = @queue.pop).first.is_a?(Symbol)
|
187
|
-
actions << item
|
188
|
-
else
|
189
|
-
item.each { |key, value| changes[key] += value }
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
_run_actions(actions)
|
194
|
-
return if changes.values.all?(&:empty?)
|
195
|
-
Runner.new.run_on_changes(*changes.values)
|
196
|
-
end
|
197
|
-
|
198
|
-
# TODO: Guard::Watch or Guard::Scope should provide this
|
199
|
-
def _scoped_watchers
|
200
|
-
watchers = []
|
201
|
-
Runner.new.send(:_scoped_plugins) { |guard| watchers += guard.watchers }
|
202
|
-
watchers
|
203
|
-
end
|
204
|
-
|
205
112
|
# Check if any of the changes are actually watched for
|
113
|
+
# TODO: why iterate twice? reuse this info when running tasks
|
206
114
|
def _relevant_changes?(changes)
|
115
|
+
# TODO: no coverage!
|
207
116
|
files = changes.values.flatten(1)
|
208
|
-
|
117
|
+
scope = Guard.state.scope
|
118
|
+
watchers = scope.grouped_plugins.map do |_group, plugins|
|
119
|
+
plugins.map(&:watchers).flatten
|
120
|
+
end.flatten
|
209
121
|
watchers.any? { |watcher| files.any? { |file| watcher.match(file) } }
|
210
122
|
end
|
211
123
|
|
@@ -213,19 +125,6 @@ module Guard
|
|
213
125
|
paths.map { |path| _relative_pathname(path) }
|
214
126
|
end
|
215
127
|
|
216
|
-
def _run_actions(actions)
|
217
|
-
actions.each do |action_args|
|
218
|
-
args = action_args.dup
|
219
|
-
namespaced_action = args.shift
|
220
|
-
action = namespaced_action.to_s.sub(/^guard_/, "")
|
221
|
-
if ::Guard.respond_to?(action)
|
222
|
-
::Guard.send(action, *args)
|
223
|
-
else
|
224
|
-
fail "Unknown action: #{action.inspect}"
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
128
|
def _listener_callback
|
230
129
|
lambda do |modified, added, removed|
|
231
130
|
relative_paths = {
|
@@ -238,12 +137,7 @@ module Guard
|
|
238
137
|
end
|
239
138
|
end
|
240
139
|
|
241
|
-
|
242
|
-
reset_groups
|
243
|
-
reset_plugins
|
244
|
-
reset_scope
|
245
|
-
end
|
246
|
-
|
140
|
+
# TODO: obsoleted? (move to Dsl?)
|
247
141
|
def _pluginless_guardfile?
|
248
142
|
# no Reevaluator means there was no Guardfile configured that could be
|
249
143
|
# reevaluated, so we don't have a pluginless guardfile, because we don't
|
@@ -252,20 +146,29 @@ module Guard
|
|
252
146
|
# But, if we have a Guardfile, we'll at least have the built-in
|
253
147
|
# Reevaluator, so the following will work:
|
254
148
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
plugins.map(&:name) == ["reevaluator"]
|
149
|
+
plugins = state.session.plugins.all
|
150
|
+
plugins.empty? || plugins.map(&:name) == ["reevaluator"]
|
259
151
|
end
|
260
152
|
|
261
|
-
def
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
153
|
+
def _evaluate(options)
|
154
|
+
evaluator = Guardfile::Evaluator.new(options)
|
155
|
+
evaluator.evaluate
|
156
|
+
|
157
|
+
# TODO: remove this workaround when options are removed
|
158
|
+
state.session.clearing(state.session.options[:clear])
|
159
|
+
|
160
|
+
UI.reset_and_clear
|
161
|
+
|
162
|
+
msg = "No plugins found in Guardfile, please add at least one."
|
163
|
+
UI.error msg if _pluginless_guardfile?
|
164
|
+
|
165
|
+
if evaluator.inline?
|
166
|
+
UI.info("Using inline Guardfile.")
|
167
|
+
elsif evaluator.custom?
|
168
|
+
UI.info("Using Guardfile at #{ evaluator.path }.")
|
169
|
+
end
|
170
|
+
rescue Guardfile::Evaluator::NoPluginsError => e
|
171
|
+
UI.error(e.message)
|
269
172
|
end
|
270
173
|
end
|
271
174
|
end
|
data/lib/guard/dsl.rb
CHANGED
@@ -5,8 +5,6 @@ require "guard/ui"
|
|
5
5
|
require "guard/watcher"
|
6
6
|
|
7
7
|
require "guard/deprecated/dsl" unless Guard::Config.new.strict?
|
8
|
-
|
9
|
-
# TODO: only for listener
|
10
8
|
require "guard"
|
11
9
|
|
12
10
|
module Guard
|
@@ -75,6 +73,7 @@ module Guard
|
|
75
73
|
# @see Guard::Notifier for available notifier and its options.
|
76
74
|
#
|
77
75
|
def notification(notifier, options = {})
|
76
|
+
# TODO: remove dependency on Notifier (let session handle this)
|
78
77
|
Notifier.add(notifier.to_sym, options.merge(silent: false))
|
79
78
|
end
|
80
79
|
|
@@ -90,6 +89,7 @@ module Guard
|
|
90
89
|
# options
|
91
90
|
#
|
92
91
|
def interactor(options)
|
92
|
+
# TODO: remove dependency on Interactor (let session handle this)
|
93
93
|
case options
|
94
94
|
when :off
|
95
95
|
Interactor.enabled = false
|
@@ -132,6 +132,7 @@ module Guard
|
|
132
132
|
|
133
133
|
if block_given?
|
134
134
|
groups.each do |group|
|
135
|
+
# TODO: let groups be added *after* evaluation
|
135
136
|
Guard.state.session.groups.add(group, options)
|
136
137
|
end
|
137
138
|
|
@@ -181,6 +182,7 @@ module Guard
|
|
181
182
|
groups = @current_groups && @current_groups.last || [:default]
|
182
183
|
groups.each do |group|
|
183
184
|
opts = @plugin_options.merge(group: group)
|
185
|
+
# TODO: let plugins be added *after* evaluation
|
184
186
|
Guard.state.session.plugins.add(name, opts)
|
185
187
|
end
|
186
188
|
|
@@ -227,11 +229,10 @@ module Guard
|
|
227
229
|
# `run_on_additions`, `run_on_modifications` and `run_on_removals` plugin
|
228
230
|
# method.
|
229
231
|
#
|
230
|
-
# @example
|
232
|
+
# @example Add callback before the `reload` action.
|
231
233
|
# callback(:reload_begin) { puts "Let's reload!" }
|
232
234
|
#
|
233
|
-
# @example
|
234
|
-
# `stop` actions.
|
235
|
+
# @example Add callback before the `start` and `stop` actions.
|
235
236
|
#
|
236
237
|
# my_lambda = lambda do |plugin, event, *args|
|
237
238
|
# puts "Let's #{event} #{plugin} with #{args}!"
|
@@ -264,8 +265,8 @@ module Guard
|
|
264
265
|
# @param [Regexp] regexps a pattern (or list of patterns) for ignoring paths
|
265
266
|
#
|
266
267
|
def ignore(*regexps)
|
267
|
-
# TODO:
|
268
|
-
Guard.
|
268
|
+
# TODO: use guardfile results class
|
269
|
+
Guard.state.session.guardfile_ignore = regexps
|
269
270
|
end
|
270
271
|
|
271
272
|
# TODO: deprecate
|
@@ -281,8 +282,11 @@ module Guard
|
|
281
282
|
def ignore!(*regexps)
|
282
283
|
@ignore_regexps ||= []
|
283
284
|
@ignore_regexps << regexps
|
284
|
-
|
285
|
+
# TODO: use guardfile results class
|
286
|
+
Guard.state.session.guardfile_ignore_bang = @ignore_regexps
|
285
287
|
end
|
288
|
+
|
289
|
+
# TODO: deprecate
|
286
290
|
alias filter! ignore!
|
287
291
|
|
288
292
|
# Configures the Guard logger.
|
@@ -366,6 +370,7 @@ module Guard
|
|
366
370
|
# @param [Hash] scopes the scope for the groups and plugins
|
367
371
|
#
|
368
372
|
def scope(scope = {})
|
373
|
+
# TODO: use a Guardfile::Results class
|
369
374
|
Guard.state.session.guardfile_scope(scope)
|
370
375
|
end
|
371
376
|
|
data/lib/guard/dsl.rb.orig
CHANGED
@@ -26,10 +26,10 @@ module Guard
|
|
26
26
|
# {Notifier} for more information about the supported libraries.
|
27
27
|
#
|
28
28
|
# A more advanced DSL use is the {#callback} keyword that allows you to
|
29
|
-
# execute arbitrary code before or after any of the {Plugin
|
30
|
-
# {Plugin
|
31
|
-
# {Plugin
|
32
|
-
# {Plugin
|
29
|
+
# execute arbitrary code before or after any of the {Plugin#start},
|
30
|
+
# {Plugin#stop}, {Plugin#reload}, {Plugin#run_all},
|
31
|
+
# {Plugin#run_on_changes}, {Plugin#run_on_additions},
|
32
|
+
# {Plugin#run_on_modifications} and {Plugin#run_on_removals}
|
33
33
|
# Guard plugins method.
|
34
34
|
# You can even insert more hooks inside these methods. Please [checkout the
|
35
35
|
# Wiki page](https://github.com/guard/guard/wiki/Hooks-and-callbacks) for
|
@@ -50,6 +50,10 @@ module Guard
|
|
50
50
|
class Dsl
|
51
51
|
Deprecated::Dsl.add_deprecated(self) unless Config.new.strict?
|
52
52
|
|
53
|
+
# Wrap exceptions during parsing Guardfile
|
54
|
+
class Error < RuntimeError
|
55
|
+
end
|
56
|
+
|
53
57
|
WARN_INVALID_LOG_LEVEL = "Invalid log level `%s` ignored. "\
|
54
58
|
"Please use either :debug, :info, :warn or :error."
|
55
59
|
|
@@ -88,9 +92,9 @@ module Guard
|
|
88
92
|
def interactor(options)
|
89
93
|
case options
|
90
94
|
when :off
|
91
|
-
|
95
|
+
Interactor.enabled = false
|
92
96
|
when Hash
|
93
|
-
|
97
|
+
Interactor.options = options
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
@@ -128,7 +132,7 @@ module Guard
|
|
128
132
|
|
129
133
|
if block_given?
|
130
134
|
groups.each do |group|
|
131
|
-
|
135
|
+
Guard.state.session.groups.add(group, options)
|
132
136
|
end
|
133
137
|
|
134
138
|
@current_groups ||= []
|
@@ -138,7 +142,7 @@ module Guard
|
|
138
142
|
|
139
143
|
@current_groups.pop
|
140
144
|
else
|
141
|
-
|
145
|
+
UI.error \
|
142
146
|
"No Guard plugins found in the group '#{ groups.join(", ") }',"\
|
143
147
|
" please add at least one."
|
144
148
|
end
|
@@ -176,7 +180,8 @@ module Guard
|
|
176
180
|
@current_groups ||= []
|
177
181
|
groups = @current_groups && @current_groups.last || [:default]
|
178
182
|
groups.each do |group|
|
179
|
-
|
183
|
+
opts = @plugin_options.merge(group: group)
|
184
|
+
Guard.state.session.plugins.add(name, opts)
|
180
185
|
end
|
181
186
|
|
182
187
|
@plugin_options = nil
|
@@ -214,7 +219,7 @@ module Guard
|
|
214
219
|
@plugin_options ||= nil
|
215
220
|
return guard(:plugin) { watch(pattern, &action) } unless @plugin_options
|
216
221
|
|
217
|
-
@plugin_options[:watchers] <<
|
222
|
+
@plugin_options[:watchers] << Watcher.new(pattern, action)
|
218
223
|
end
|
219
224
|
|
220
225
|
# Defines a callback to execute arbitrary code before or after any of
|
@@ -222,11 +227,10 @@ module Guard
|
|
222
227
|
# `run_on_additions`, `run_on_modifications` and `run_on_removals` plugin
|
223
228
|
# method.
|
224
229
|
#
|
225
|
-
# @example
|
230
|
+
# @example Add callback before the `reload` action.
|
226
231
|
# callback(:reload_begin) { puts "Let's reload!" }
|
227
232
|
#
|
228
|
-
# @example
|
229
|
-
# `stop` actions.
|
233
|
+
# @example Add callback before the `start` and `stop` actions.
|
230
234
|
#
|
231
235
|
# my_lambda = lambda do |plugin, event, *args|
|
232
236
|
# puts "Let's #{event} #{plugin} with #{args}!"
|
@@ -237,8 +241,6 @@ module Guard
|
|
237
241
|
# @param [Array] args the callback arguments
|
238
242
|
# @yield a callback block
|
239
243
|
#
|
240
|
-
# @see Guard::Hooker
|
241
|
-
#
|
242
244
|
def callback(*args, &block)
|
243
245
|
@plugin_options ||= nil
|
244
246
|
fail "callback must be called within a guard block" unless @plugin_options
|
@@ -262,8 +264,10 @@ module Guard
|
|
262
264
|
#
|
263
265
|
def ignore(*regexps)
|
264
266
|
# TODO: instead, use Guard.reconfigure(ignore: regexps) or something
|
265
|
-
|
267
|
+
Guard.listener.ignore(regexps) if Guard.listener
|
266
268
|
end
|
269
|
+
|
270
|
+
# TODO: deprecate
|
267
271
|
alias filter ignore
|
268
272
|
|
269
273
|
# Replaces ignored paths globally
|
@@ -276,7 +280,7 @@ module Guard
|
|
276
280
|
def ignore!(*regexps)
|
277
281
|
@ignore_regexps ||= []
|
278
282
|
@ignore_regexps << regexps
|
279
|
-
|
283
|
+
Guard.listener.ignore!(@ignore_regexps) if Guard.listener
|
280
284
|
end
|
281
285
|
alias filter! ignore!
|
282
286
|
|
@@ -341,7 +345,7 @@ module Guard
|
|
341
345
|
options[name] = Regexp.new(list.join("|"), Regexp::IGNORECASE)
|
342
346
|
end
|
343
347
|
|
344
|
-
|
348
|
+
UI.options.merge!(options)
|
345
349
|
end
|
346
350
|
|
347
351
|
# Sets the default scope on startup
|
@@ -361,18 +365,68 @@ module Guard
|
|
361
365
|
# @param [Hash] scopes the scope for the groups and plugins
|
362
366
|
#
|
363
367
|
def scope(scope = {})
|
364
|
-
|
368
|
+
Guard.state.session.guardfile_scope(scope)
|
369
|
+
end
|
370
|
+
|
371
|
+
def evaluate(contents, filename, lineno) # :nodoc
|
372
|
+
instance_eval(contents, filename.to_s, lineno)
|
373
|
+
rescue StandardError, ScriptError => e
|
374
|
+
prefix = "\n\t(dsl)> "
|
375
|
+
cleaned_backtrace = _cleanup_backtrace(e.backtrace)
|
376
|
+
backtrace = "#{prefix}#{cleaned_backtrace.join(prefix)}"
|
377
|
+
msg = "Invalid Guardfile, original error is: \n\n%s, \nbacktrace: %s"
|
378
|
+
raise Error, format(msg, e, backtrace)
|
365
379
|
end
|
366
380
|
|
367
|
-
# Sets the directories to pass to Listen
|
381
|
+
# Sets the directories to pass to Listen
|
368
382
|
#
|
369
383
|
# @example watch only given directories
|
370
384
|
# directories %w(lib specs)
|
371
385
|
#
|
372
|
-
# @param [Array] directories to watch
|
386
|
+
# @param [Array] directories directories for Listen to watch
|
387
|
+
#
|
388
|
+
def directories(directories)
|
389
|
+
directories.each do |dir|
|
390
|
+
fail "Directory #{dir.inspect} does not exist!" unless Dir.exist?(dir)
|
391
|
+
end
|
392
|
+
Guard.state.session.watchdirs = directories
|
393
|
+
end
|
394
|
+
|
395
|
+
# Sets Guard to clear the screen before every task is run
|
396
|
+
#
|
397
|
+
# @example switching clearing the screen on
|
398
|
+
# clearing(:on)
|
373
399
|
#
|
374
|
-
|
375
|
-
|
400
|
+
# @param [Symbol] on ':on' to turn on, ':off' (default) to turn off
|
401
|
+
#
|
402
|
+
def clearing(on)
|
403
|
+
Guard.state.session.clearing(on == :on)
|
404
|
+
end
|
405
|
+
|
406
|
+
private
|
407
|
+
|
408
|
+
def _cleanup_backtrace(backtrace)
|
409
|
+
dirs = { File.realpath(Dir.pwd) => ".", }
|
410
|
+
|
411
|
+
gem_env = ENV["GEM_HOME"] || ""
|
412
|
+
dirs[gem_env] = "$GEM_HOME" unless gem_env.empty?
|
413
|
+
|
414
|
+
gem_paths = (ENV["GEM_PATH"] || "").split(File::PATH_SEPARATOR)
|
415
|
+
gem_paths.each_with_index do |path, index|
|
416
|
+
dirs[path] = "$GEM_PATH[#{index}]"
|
417
|
+
end
|
418
|
+
|
419
|
+
backtrace.dup.map do |raw_line|
|
420
|
+
path = nil
|
421
|
+
symlinked_path = raw_line.split(":").first
|
422
|
+
begin
|
423
|
+
path = raw_line.sub(symlinked_path, File.realpath(symlinked_path))
|
424
|
+
dirs.detect { |dir, name| path.sub!(File.realpath(dir), name) }
|
425
|
+
path
|
426
|
+
rescue Errno::ENOENT
|
427
|
+
path || symlinked_path
|
428
|
+
end
|
429
|
+
end
|
376
430
|
end
|
377
431
|
end
|
378
432
|
end
|