guard 2.10.0 → 2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|