guard 1.8.3 → 2.0.0.pre
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/CHANGELOG.md +68 -10
- data/README.md +54 -33
- data/lib/guard.rb +133 -483
- data/lib/guard/cli.rb +78 -82
- data/lib/guard/commander.rb +121 -0
- data/lib/guard/commands/all.rb +1 -1
- data/lib/guard/commands/reload.rb +1 -1
- data/lib/guard/deprecated_methods.rb +59 -0
- data/lib/guard/deprecator.rb +107 -0
- data/lib/guard/dsl.rb +143 -329
- data/lib/guard/dsl_describer.rb +101 -57
- data/lib/guard/group.rb +27 -8
- data/lib/guard/guard.rb +25 -150
- data/lib/guard/guardfile.rb +35 -85
- data/lib/guard/guardfile/evaluator.rb +245 -0
- data/lib/guard/guardfile/generator.rb +89 -0
- data/lib/guard/interactor.rb +147 -163
- data/lib/guard/notifier.rb +83 -137
- data/lib/guard/notifiers/base.rb +220 -0
- data/lib/guard/notifiers/emacs.rb +39 -37
- data/lib/guard/notifiers/file_notifier.rb +29 -25
- data/lib/guard/notifiers/gntp.rb +68 -75
- data/lib/guard/notifiers/growl.rb +49 -52
- data/lib/guard/notifiers/growl_notify.rb +51 -56
- data/lib/guard/notifiers/libnotify.rb +41 -48
- data/lib/guard/notifiers/notifysend.rb +58 -38
- data/lib/guard/notifiers/rb_notifu.rb +54 -54
- data/lib/guard/notifiers/terminal_notifier.rb +48 -36
- data/lib/guard/notifiers/terminal_title.rb +23 -19
- data/lib/guard/notifiers/tmux.rb +110 -93
- data/lib/guard/options.rb +21 -0
- data/lib/guard/plugin.rb +66 -0
- data/lib/guard/plugin/base.rb +178 -0
- data/lib/guard/plugin/hooker.rb +123 -0
- data/lib/guard/plugin_util.rb +158 -0
- data/lib/guard/rake_task.rb +47 -0
- data/lib/guard/runner.rb +62 -82
- data/lib/guard/setuper.rb +248 -0
- data/lib/guard/ui.rb +24 -80
- data/lib/guard/ui/colors.rb +60 -0
- data/lib/guard/version.rb +1 -2
- data/lib/guard/watcher.rb +30 -30
- data/man/guard.1 +4 -4
- data/man/guard.1.html +6 -4
- metadata +25 -11
- data/lib/guard/hook.rb +0 -120
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/tasklib'
|
5
|
+
|
6
|
+
require 'guard/cli'
|
7
|
+
|
8
|
+
module Guard
|
9
|
+
|
10
|
+
# Provides a method to define a Rake task that
|
11
|
+
# runs the Guard plugins.
|
12
|
+
#
|
13
|
+
class RakeTask < ::Rake::TaskLib
|
14
|
+
|
15
|
+
# Name of the main, top level task
|
16
|
+
attr_accessor :name
|
17
|
+
|
18
|
+
# CLI options
|
19
|
+
attr_accessor :options
|
20
|
+
|
21
|
+
# Initialize the Rake task
|
22
|
+
#
|
23
|
+
# @param [Symbol] name the name of the Rake task
|
24
|
+
# @param [String] options the CLI options
|
25
|
+
# @yield [Guard::RakeTask] the task
|
26
|
+
#
|
27
|
+
def initialize(name = :guard, options = '')
|
28
|
+
@name = name
|
29
|
+
@options = options
|
30
|
+
|
31
|
+
yield self if block_given?
|
32
|
+
|
33
|
+
desc "Starts Guard with options: '#{options}'"
|
34
|
+
task name => ["#{name}:start"]
|
35
|
+
|
36
|
+
namespace(name) do
|
37
|
+
|
38
|
+
desc "Starts Guard with options: '#{options}'"
|
39
|
+
task(:start) do
|
40
|
+
::Guard::CLI.start(options.split)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/lib/guard/runner.rb
CHANGED
@@ -1,56 +1,24 @@
|
|
1
|
+
require 'lumberjack'
|
2
|
+
|
3
|
+
require 'guard/ui'
|
4
|
+
require 'guard/watcher'
|
5
|
+
|
1
6
|
module Guard
|
2
7
|
|
3
|
-
# The runner is responsible for running all methods defined on each
|
8
|
+
# The runner is responsible for running all methods defined on each plugin.
|
4
9
|
#
|
5
10
|
class Runner
|
6
11
|
|
7
|
-
|
8
|
-
require 'guard/ui'
|
9
|
-
require 'guard/watcher'
|
10
|
-
|
11
|
-
require 'lumberjack'
|
12
|
-
|
13
|
-
# Deprecation message for the `run_on_change` method
|
14
|
-
RUN_ON_CHANGE_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
|
15
|
-
Starting with Guard v1.1 the use of the 'run_on_change' method in the '%s' guard is deprecated.
|
16
|
-
|
17
|
-
Please consider replacing that method-call with 'run_on_changes' if the type of change
|
18
|
-
is not important for your usecase or using either 'run_on_modifications' or 'run_on_additions'
|
19
|
-
based on the type of the changes you want to handle.
|
20
|
-
|
21
|
-
For more information on how to update existing guards, please head over to:
|
22
|
-
https://github.com/guard/guard/wiki/Upgrade-guide-for-existing-guards-to-Guard-v1.1
|
23
|
-
EOS
|
24
|
-
|
25
|
-
# Deprecation message for the `run_on_deletion` method
|
26
|
-
RUN_ON_DELETION_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
|
27
|
-
Starting with Guard v1.1 the use of the 'run_on_deletion' method in the '%s' guard is deprecated.
|
28
|
-
|
29
|
-
Please consider replacing that method-call with 'run_on_removals' for future proofing your code.
|
30
|
-
|
31
|
-
For more information on how to update existing guards, please head over to:
|
32
|
-
https://github.com/guard/guard/wiki/Upgrade-guide-for-existing-guards-to-Guard-v1.1
|
33
|
-
EOS
|
34
|
-
|
35
|
-
# Displays a warning for each deprecated-method used is any registered guard.
|
36
|
-
#
|
37
|
-
def deprecation_warning
|
38
|
-
::Guard.guards.each do |guard|
|
39
|
-
::Guard::UI.deprecation(RUN_ON_CHANGE_DEPRECATION % guard.class.name) if guard.respond_to?(:run_on_change)
|
40
|
-
::Guard::UI.deprecation(RUN_ON_DELETION_DEPRECATION % guard.class.name) if guard.respond_to?(:run_on_deletion)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Runs a Guard-task on all registered guards.
|
12
|
+
# Runs a Guard-task on all registered plugins.
|
45
13
|
#
|
46
14
|
# @param [Symbol] task the task to run
|
47
15
|
# @param [Hash] scopes either the Guard plugin or the group to run the task on
|
48
16
|
#
|
49
17
|
# @see self.run_supervised_task
|
50
18
|
#
|
51
|
-
def run(task,
|
19
|
+
def run(task, scope = {})
|
52
20
|
Lumberjack.unit_of_work do
|
53
|
-
|
21
|
+
_scoped_plugins(scope) do |guard|
|
54
22
|
run_supervised_task(guard, task) if guard.respond_to?(task)
|
55
23
|
end
|
56
24
|
end
|
@@ -60,7 +28,7 @@ module Guard
|
|
60
28
|
ADDITION_TASKS = [:run_on_additions, :run_on_changes, :run_on_change]
|
61
29
|
REMOVAL_TASKS = [:run_on_removals, :run_on_changes, :run_on_deletion]
|
62
30
|
|
63
|
-
# Runs the appropriate tasks on all registered
|
31
|
+
# Runs the appropriate tasks on all registered plugins
|
64
32
|
# based on the passed changes.
|
65
33
|
#
|
66
34
|
# @param [Array<String>] modified the modified paths.
|
@@ -69,16 +37,16 @@ module Guard
|
|
69
37
|
#
|
70
38
|
def run_on_changes(modified, added, removed)
|
71
39
|
::Guard::UI.clearable
|
72
|
-
|
40
|
+
_scoped_plugins do |guard|
|
73
41
|
modified_paths = ::Guard::Watcher.match_files(guard, modified)
|
74
42
|
added_paths = ::Guard::Watcher.match_files(guard, added)
|
75
43
|
removed_paths = ::Guard::Watcher.match_files(guard, removed)
|
76
44
|
|
77
|
-
::Guard::UI.clear if
|
45
|
+
::Guard::UI.clear if _clearable?(guard, modified_paths, added_paths, removed_paths)
|
78
46
|
|
79
|
-
|
80
|
-
|
81
|
-
|
47
|
+
_run_first_task_found(guard, MODIFICATION_TASKS, modified_paths) unless modified_paths.empty?
|
48
|
+
_run_first_task_found(guard, ADDITION_TASKS, added_paths) unless added_paths.empty?
|
49
|
+
_run_first_task_found(guard, REMOVAL_TASKS, removed_paths) unless removed_paths.empty?
|
82
50
|
end
|
83
51
|
end
|
84
52
|
|
@@ -87,14 +55,14 @@ module Guard
|
|
87
55
|
# When the Group has `:halt_on_fail` disabled, we've to catch `:task_has_failed`
|
88
56
|
# here in order to avoid an uncaught throw error.
|
89
57
|
#
|
90
|
-
# @param [Guard::
|
58
|
+
# @param [Guard::Plugin] guard the Guard to execute
|
91
59
|
# @param [Symbol] task the task to run
|
92
60
|
# @param [Array] args the arguments for the task
|
93
61
|
# @raise [:task_has_failed] when task has failed
|
94
62
|
#
|
95
63
|
def run_supervised_task(guard, task, *args)
|
96
64
|
begin
|
97
|
-
catch
|
65
|
+
catch self.class.stopping_symbol_for(guard) do
|
98
66
|
guard.hook("#{ task }_begin", *args)
|
99
67
|
result = guard.send(task, *args)
|
100
68
|
guard.hook("#{ task }_end", result)
|
@@ -105,7 +73,7 @@ module Guard
|
|
105
73
|
::Guard::UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
|
106
74
|
"\n#{ ex.class }: #{ ex.message }\n#{ ex.backtrace.join("\n") }")
|
107
75
|
|
108
|
-
::Guard.
|
76
|
+
::Guard.plugins.delete guard
|
109
77
|
::Guard::UI.info("\n#{ guard.class.name } has just been fired")
|
110
78
|
|
111
79
|
ex
|
@@ -117,28 +85,25 @@ module Guard
|
|
117
85
|
# @note If a Guard group is being run and it has the `:halt_on_fail`
|
118
86
|
# option set, this method returns :no_catch as it will be caught at the
|
119
87
|
# group level.
|
120
|
-
# @see .
|
88
|
+
# @see ._scoped_plugins
|
121
89
|
#
|
122
|
-
# @param [Guard::
|
90
|
+
# @param [Guard::Plugin] guard the Guard plugin to execute
|
123
91
|
# @return [Symbol] the symbol to catch
|
124
92
|
#
|
125
93
|
def self.stopping_symbol_for(guard)
|
126
|
-
|
127
|
-
|
128
|
-
group = ::Guard.groups(guard.group)
|
129
|
-
group.options.fetch(:halt_on_fail, false) ? :no_catch : :task_has_failed
|
94
|
+
guard.group.options[:halt_on_fail] ? :no_catch : :task_has_failed
|
130
95
|
end
|
131
96
|
|
132
|
-
|
97
|
+
private
|
133
98
|
|
134
99
|
# Tries to run the first implemented task by a given guard
|
135
100
|
# from a collection of tasks.
|
136
101
|
#
|
137
|
-
# @param [Guard::
|
102
|
+
# @param [Guard::Plugin] guard the Guard plugin to run the first found task on
|
138
103
|
# @param [Array<Symbol>] tasks the tasks to run the first among
|
139
104
|
# @param [Object] task_param the param to pass to each task
|
140
105
|
#
|
141
|
-
def
|
106
|
+
def _run_first_task_found(guard, tasks, task_param)
|
142
107
|
tasks.each do |task|
|
143
108
|
if guard.respond_to?(task)
|
144
109
|
run_supervised_task(guard, task, task_param)
|
@@ -161,16 +126,16 @@ module Guard
|
|
161
126
|
# @param [Hash] scopes hash with plugins or a groups scope
|
162
127
|
# @yield the task to run
|
163
128
|
#
|
164
|
-
def
|
165
|
-
if
|
166
|
-
|
129
|
+
def _scoped_plugins(scopes = {})
|
130
|
+
if plugins = _current_plugins_scope(scopes)
|
131
|
+
plugins.each do |guard|
|
167
132
|
yield(guard)
|
168
133
|
end
|
169
134
|
else
|
170
|
-
|
135
|
+
_current_groups_scope(scopes).each do |group|
|
171
136
|
current_plugin = nil
|
172
137
|
block_return = catch :task_has_failed do
|
173
|
-
::Guard.
|
138
|
+
::Guard.plugins(group: group.name).each do |guard|
|
174
139
|
current_plugin = guard
|
175
140
|
yield(guard)
|
176
141
|
end
|
@@ -186,12 +151,12 @@ module Guard
|
|
186
151
|
# Logic to know if the UI can be cleared or not in the run_on_changes method
|
187
152
|
# based on the guard and the changes.
|
188
153
|
#
|
189
|
-
# @param [Guard::
|
154
|
+
# @param [Guard::Plugin] guard the Guard plugin where run_on_changes is called
|
190
155
|
# @param [Array<String>] modified_paths the modified paths.
|
191
156
|
# @param [Array<String>] added_paths the added paths.
|
192
157
|
# @param [Array<String>] removed_paths the removed paths.
|
193
158
|
#
|
194
|
-
def
|
159
|
+
def _clearable?(guard, modified_paths, added_paths, removed_paths)
|
195
160
|
(MODIFICATION_TASKS.any? { |task| guard.respond_to?(task) } && !modified_paths.empty?) ||
|
196
161
|
(ADDITION_TASKS.any? { |task| guard.respond_to?(task) } && !added_paths.empty?) ||
|
197
162
|
(REMOVAL_TASKS.any? { |task| guard.respond_to?(task) } && !removed_paths.empty?)
|
@@ -202,15 +167,13 @@ module Guard
|
|
202
167
|
# If no plugins scope is found, then NO plugins are returned.
|
203
168
|
#
|
204
169
|
# @param [Hash] scopes hash with a local plugins or a groups scope
|
205
|
-
# @return [Array<Guard::
|
170
|
+
# @return [Array<Guard::Plugin>] the plugins to scope to
|
206
171
|
#
|
207
|
-
def
|
208
|
-
if
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
::Guard.scope[:plugins]
|
213
|
-
|
172
|
+
def _current_plugins_scope(scope)
|
173
|
+
if plugins = _find_non_empty_plugins_scope(scope)
|
174
|
+
Array(plugins).map do |plugin|
|
175
|
+
plugin.is_a?(Symbol) ? ::Guard.plugin(plugin) : plugin
|
176
|
+
end
|
214
177
|
else
|
215
178
|
nil
|
216
179
|
end
|
@@ -223,16 +186,33 @@ module Guard
|
|
223
186
|
# @param [Hash] scopes hash with a local plugins or a groups scope
|
224
187
|
# @return [Array<Guard::Group>] the groups to scope to
|
225
188
|
#
|
226
|
-
def
|
227
|
-
|
228
|
-
|
189
|
+
def _current_groups_scope(scope)
|
190
|
+
Array(_find_non_empty_groups_scope(scope)).map do |group|
|
191
|
+
group.is_a?(Symbol) ? ::Guard.group(group) : group
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Find the first non empty element in the given possibilities
|
196
|
+
#
|
197
|
+
def _find_non_empty_scope(type, local_scope, *additional_possibilities)
|
198
|
+
[
|
199
|
+
local_scope[:"#{type}s"],
|
200
|
+
local_scope[type.to_sym],
|
201
|
+
::Guard.scope[:"#{type}s"],
|
202
|
+
additional_possibilities.flatten
|
203
|
+
].compact.find { |a| !Array(a).empty? }
|
204
|
+
end
|
229
205
|
|
230
|
-
|
231
|
-
|
206
|
+
# Find the first non empty plugins scope
|
207
|
+
#
|
208
|
+
def _find_non_empty_plugins_scope(scope)
|
209
|
+
_find_non_empty_scope(:plugin, scope)
|
210
|
+
end
|
232
211
|
|
233
|
-
|
234
|
-
|
235
|
-
|
212
|
+
# Find the first non empty groups scope
|
213
|
+
#
|
214
|
+
def _find_non_empty_groups_scope(scope)
|
215
|
+
_find_non_empty_scope(:group, scope, ::Guard.groups)
|
236
216
|
end
|
237
217
|
end
|
238
218
|
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'listen'
|
3
|
+
require 'guard/options'
|
4
|
+
|
5
|
+
module Guard
|
6
|
+
|
7
|
+
module Setuper
|
8
|
+
|
9
|
+
DEFAULT_OPTIONS = {
|
10
|
+
clear: false,
|
11
|
+
notify: true,
|
12
|
+
debug: false,
|
13
|
+
group: [],
|
14
|
+
plugin: [],
|
15
|
+
watchdir: nil,
|
16
|
+
guardfile: nil,
|
17
|
+
no_interactions: false,
|
18
|
+
no_bundler_warning: false,
|
19
|
+
show_deprecations: false,
|
20
|
+
latency: nil,
|
21
|
+
force_polling: false
|
22
|
+
}
|
23
|
+
DEFAULT_GROUPS = [:default]
|
24
|
+
|
25
|
+
# Initializes the Guard singleton:
|
26
|
+
#
|
27
|
+
# * Initialize the internal Guard state;
|
28
|
+
# * Create the interactor when necessary for user interaction;
|
29
|
+
# * Select and initialize the file change listener.
|
30
|
+
#
|
31
|
+
# @option options [Boolean] clear if auto clear the UI should be done
|
32
|
+
# @option options [Boolean] notify if system notifications should be shown
|
33
|
+
# @option options [Boolean] debug if debug output should be shown
|
34
|
+
# @option options [Array<String>] group the list of groups to start
|
35
|
+
# @option options [Array<String>] watchdir the directories to watch
|
36
|
+
# @option options [String] guardfile the path to the Guardfile
|
37
|
+
#
|
38
|
+
# @return [Guard] the Guard singleton
|
39
|
+
#
|
40
|
+
def setup(opts = {})
|
41
|
+
@running = true
|
42
|
+
@lock = Mutex.new
|
43
|
+
@opts = opts
|
44
|
+
@watchdirs = [Dir.pwd]
|
45
|
+
@evaluator = ::Guard::Guardfile::Evaluator.new(opts)
|
46
|
+
@runner = ::Guard::Runner.new
|
47
|
+
|
48
|
+
if options.watchdir
|
49
|
+
# Ensure we have an array
|
50
|
+
@watchdirs = Array(options.watchdir).map { |dir| File.expand_path dir }
|
51
|
+
end
|
52
|
+
|
53
|
+
::Guard::UI.clear(force: true)
|
54
|
+
_setup_debug if options.debug
|
55
|
+
_setup_listener
|
56
|
+
_setup_signal_traps
|
57
|
+
|
58
|
+
reset_groups
|
59
|
+
reset_plugins
|
60
|
+
reset_scope
|
61
|
+
|
62
|
+
evaluate_guardfile
|
63
|
+
|
64
|
+
setup_scope(groups: options.group, plugins: options.plugin)
|
65
|
+
|
66
|
+
_setup_notifier
|
67
|
+
_setup_interactor
|
68
|
+
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
# Lazy initializer for Guard's options hash
|
73
|
+
#
|
74
|
+
def options
|
75
|
+
@options ||= ::Guard::Options.new(@opts || {}, DEFAULT_OPTIONS)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Clear Guard's options hash
|
79
|
+
#
|
80
|
+
def clear_options
|
81
|
+
@options = nil
|
82
|
+
end
|
83
|
+
|
84
|
+
# Initializes the groups array with the default group(s).
|
85
|
+
#
|
86
|
+
# @see DEFAULT_GROUPS
|
87
|
+
#
|
88
|
+
def reset_groups
|
89
|
+
@groups = DEFAULT_GROUPS.map { |name| Group.new(name) }
|
90
|
+
end
|
91
|
+
|
92
|
+
# Initializes the plugins array to an empty array.
|
93
|
+
#
|
94
|
+
# @see Guard.plugins
|
95
|
+
#
|
96
|
+
def reset_plugins
|
97
|
+
@plugins = []
|
98
|
+
end
|
99
|
+
|
100
|
+
# Initializes the scope hash to `{ groups: [], plugins: [] }`.
|
101
|
+
#
|
102
|
+
# @see Guard.setup_scope
|
103
|
+
#
|
104
|
+
def reset_scope
|
105
|
+
@scope = { groups: [], plugins: [] }
|
106
|
+
end
|
107
|
+
|
108
|
+
# Stores the scopes defined by the user via the `--group` / `-g` option (to run
|
109
|
+
# only a specific group) or the `--plugin` / `-P` option (to run only a
|
110
|
+
# specific plugin).
|
111
|
+
#
|
112
|
+
# @see CLI#start
|
113
|
+
# @see Dsl#scope
|
114
|
+
#
|
115
|
+
def setup_scope(new_scope)
|
116
|
+
if new_scope[:groups] && new_scope[:groups].any?
|
117
|
+
scope[:groups] = new_scope[:groups].map { |group| ::Guard.add_group(group) }
|
118
|
+
end
|
119
|
+
|
120
|
+
if new_scope[:plugins] && new_scope[:plugins].any?
|
121
|
+
scope[:plugins] = new_scope[:plugins].map { |plugin| ::Guard.plugin(plugin) }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Evaluates the Guardfile content. It displays an error message if no
|
126
|
+
# Guard plugins are instantiated after the Guardfile evaluation.
|
127
|
+
#
|
128
|
+
# @see Guard::Guardfile::Evaluator#evaluate_guardfile
|
129
|
+
#
|
130
|
+
def evaluate_guardfile
|
131
|
+
evaluator.evaluate_guardfile
|
132
|
+
::Guard::UI.error 'No plugins found in Guardfile, please add at least one.' if plugins.empty?
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
# Sets up various debug behaviors:
|
138
|
+
#
|
139
|
+
# * Abort threads on exception;
|
140
|
+
# * Set the logging level to `:debug`;
|
141
|
+
# * Modify the system and ` methods to log themselves before being executed
|
142
|
+
#
|
143
|
+
# @see #_debug_command_execution
|
144
|
+
#
|
145
|
+
def _setup_debug
|
146
|
+
Thread.abort_on_exception = true
|
147
|
+
::Guard::UI.options.level = :debug
|
148
|
+
_debug_command_execution
|
149
|
+
end
|
150
|
+
|
151
|
+
# Initializes the listener and registers a callback for changes.
|
152
|
+
#
|
153
|
+
def _setup_listener
|
154
|
+
listener_callback = lambda do |modified, added, removed|
|
155
|
+
# Convert to relative paths (respective to the watchdir it came from)
|
156
|
+
@watchdirs.each do |watchdir|
|
157
|
+
[modified, added, removed].each do |paths|
|
158
|
+
paths.map! do |path|
|
159
|
+
if path.start_with? watchdir
|
160
|
+
path.sub "#{watchdir}#{File::SEPARATOR}", ''
|
161
|
+
else
|
162
|
+
path
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
evaluator.reevaluate_guardfile if ::Guard::Watcher.match_guardfile?(modified)
|
168
|
+
|
169
|
+
within_preserved_state do
|
170
|
+
runner.run_on_changes(modified, added, removed)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
listener_options = {}
|
175
|
+
%w[latency force_polling].each do |option|
|
176
|
+
listener_options[option.to_sym] = options.send(option) if options.send(option)
|
177
|
+
end
|
178
|
+
|
179
|
+
listen_args = @watchdirs + [listener_options]
|
180
|
+
@listener = Listen.to(*listen_args).change(&listener_callback)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Sets up traps to catch signals used to control Guard.
|
184
|
+
#
|
185
|
+
# Currently two signals are caught:
|
186
|
+
# - `USR1` which pauses listening to changes.
|
187
|
+
# - `USR2` which resumes listening to changes.
|
188
|
+
# - 'INT' which is delegated to Pry if active, otherwise stops Guard.
|
189
|
+
#
|
190
|
+
def _setup_signal_traps
|
191
|
+
unless defined?(JRUBY_VERSION)
|
192
|
+
if Signal.list.keys.include?('USR1')
|
193
|
+
Signal.trap('USR1') { ::Guard.pause unless listener.paused? }
|
194
|
+
end
|
195
|
+
|
196
|
+
if Signal.list.keys.include?('USR2')
|
197
|
+
Signal.trap('USR2') { ::Guard.pause if listener.paused? }
|
198
|
+
end
|
199
|
+
|
200
|
+
if Signal.list.keys.include?('INT')
|
201
|
+
Signal.trap('INT') do
|
202
|
+
if interactor && interactor.thread
|
203
|
+
interactor.thread.raise(Interrupt)
|
204
|
+
else
|
205
|
+
::Guard.stop
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Enables or disables the notifier based on user's configurations.
|
213
|
+
#
|
214
|
+
def _setup_notifier
|
215
|
+
if options.notify && ENV['GUARD_NOTIFY'] != 'false'
|
216
|
+
::Guard::Notifier.turn_on
|
217
|
+
else
|
218
|
+
::Guard::Notifier.turn_off
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Initializes the interactor unless the user has specified not to.
|
223
|
+
#
|
224
|
+
def _setup_interactor
|
225
|
+
unless options.no_interactions || !::Guard::Interactor.enabled
|
226
|
+
@interactor = ::Guard::Interactor.new
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Adds a command logger in debug mode. This wraps common command
|
231
|
+
# execution functions and logs the executed command before execution.
|
232
|
+
#
|
233
|
+
def _debug_command_execution
|
234
|
+
Kernel.send(:alias_method, :original_system, :system)
|
235
|
+
Kernel.send(:define_method, :system) do |command, *args|
|
236
|
+
::Guard::UI.debug "Command execution: #{ command } #{ args.join(' ') }"
|
237
|
+
Kernel.send :original_system, command, *args
|
238
|
+
end
|
239
|
+
|
240
|
+
Kernel.send(:alias_method, :original_backtick, :'`')
|
241
|
+
Kernel.send(:define_method, :'`') do |command|
|
242
|
+
::Guard::UI.debug "Command execution: #{ command }"
|
243
|
+
Kernel.send :original_backtick, command
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|