guard 2.6.1 → 2.7.0

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +73 -58
  3. data/bin/guard +2 -2
  4. data/lib/guard.rb +64 -59
  5. data/lib/guard/cli.rb +66 -60
  6. data/lib/guard/cli.rb.orig +215 -0
  7. data/lib/guard/commander.rb +45 -69
  8. data/lib/guard/commands/all.rb +21 -19
  9. data/lib/guard/commands/change.rb +17 -22
  10. data/lib/guard/commands/notification.rb +15 -16
  11. data/lib/guard/commands/pause.rb +14 -15
  12. data/lib/guard/commands/reload.rb +19 -20
  13. data/lib/guard/commands/scope.rb +23 -19
  14. data/lib/guard/commands/show.rb +13 -16
  15. data/lib/guard/deprecated_methods.rb +6 -10
  16. data/lib/guard/deprecator.rb +52 -37
  17. data/lib/guard/dsl.rb +55 -33
  18. data/lib/guard/dsl_describer.rb +83 -31
  19. data/lib/guard/dsl_describer.rb.orig +184 -0
  20. data/lib/guard/group.rb +7 -6
  21. data/lib/guard/guard.rb +4 -4
  22. data/lib/guard/guard.rb.orig +42 -0
  23. data/lib/guard/guardfile.rb +12 -13
  24. data/lib/guard/guardfile/evaluator.rb +77 -55
  25. data/lib/guard/guardfile/evaluator.rb.orig +275 -0
  26. data/lib/guard/guardfile/generator.rb +25 -20
  27. data/lib/guard/interactor.rb +52 -293
  28. data/lib/guard/interactor.rb.orig +85 -0
  29. data/lib/guard/jobs/base.rb +21 -0
  30. data/lib/guard/jobs/pry_wrapper.rb +290 -0
  31. data/lib/guard/jobs/pry_wrapper.rb.orig +293 -0
  32. data/lib/guard/jobs/sleep.rb +25 -0
  33. data/lib/guard/notifier.rb +42 -39
  34. data/lib/guard/notifiers/base.rb +25 -24
  35. data/lib/guard/notifiers/emacs.rb +30 -24
  36. data/lib/guard/notifiers/file_notifier.rb +3 -7
  37. data/lib/guard/notifiers/gntp.rb +22 -22
  38. data/lib/guard/notifiers/growl.rb +16 -15
  39. data/lib/guard/notifiers/libnotify.rb +7 -10
  40. data/lib/guard/notifiers/notifysend.rb +15 -14
  41. data/lib/guard/notifiers/rb_notifu.rb +8 -10
  42. data/lib/guard/notifiers/terminal_notifier.rb +15 -11
  43. data/lib/guard/notifiers/terminal_title.rb +4 -8
  44. data/lib/guard/notifiers/tmux.rb +104 -71
  45. data/lib/guard/options.rb +1 -5
  46. data/lib/guard/plugin.rb +1 -3
  47. data/lib/guard/plugin/base.rb +12 -9
  48. data/lib/guard/plugin/hooker.rb +1 -5
  49. data/lib/guard/plugin_util.rb +46 -25
  50. data/lib/guard/plugin_util.rb.orig +178 -0
  51. data/lib/guard/rake_task.rb +4 -7
  52. data/lib/guard/reevaluator.rb +13 -0
  53. data/lib/guard/runner.rb +50 -78
  54. data/lib/guard/runner.rb.orig +200 -0
  55. data/lib/guard/setuper.rb +199 -130
  56. data/lib/guard/setuper.rb.orig +348 -0
  57. data/lib/guard/sheller.rb +107 -0
  58. data/lib/guard/tags +367 -0
  59. data/lib/guard/ui.rb +50 -38
  60. data/lib/guard/ui.rb.orig +254 -0
  61. data/lib/guard/ui/colors.rb +17 -21
  62. data/lib/guard/version.rb +1 -1
  63. data/lib/guard/version.rb.orig +3 -0
  64. data/lib/guard/watcher.rb +49 -62
  65. metadata +21 -4
  66. data/lib/guard/notifiers/growl_notify.rb +0 -93
@@ -1,7 +1,6 @@
1
- require 'guard/ui'
1
+ require "guard/ui"
2
2
 
3
3
  module Guard
4
-
5
4
  # This class contains useful methods to:
6
5
  #
7
6
  # * Fetch all the Guard plugins names;
@@ -10,6 +9,11 @@ module Guard
10
9
  # * Add its template to the Guardfile.
11
10
  #
12
11
  class PluginUtil
12
+ ERROR_NO_GUARD_OR_CLASS = "Could not load 'guard/%s' or'\
13
+ ' find class Guard::%s"
14
+
15
+ INFO_ADDED_GUARD_TO_GUARDFILE = "%s guard added to Guardfile,"\
16
+ " feel free to edit it"
13
17
 
14
18
  attr_accessor :name
15
19
 
@@ -18,18 +22,27 @@ module Guard
18
22
  # @return [Array<String>] a list of Guard plugin gem names
19
23
  #
20
24
  def self.plugin_names
21
- if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
25
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create("1.8.0")
22
26
  Gem::Specification.find_all.select do |x|
23
27
  if x.name =~ /^guard-/
24
28
  true
25
- elsif x.name != 'guard'
26
- guard_plugin_path = File.join(x.full_gem_path, "lib/guard/#{ x.name }.rb")
27
- File.exists?( guard_plugin_path )
29
+ elsif x.name != "guard"
30
+
31
+ guard_plugin_path = File.join(
32
+ x.full_gem_path,
33
+ "lib/guard/#{ x.name }.rb"
34
+ )
35
+
36
+ File.exist?(guard_plugin_path)
28
37
  end
29
38
  end
30
39
  else
40
+ ::Guard::UI.deprecation \
41
+ "Rubygems version prior to 1.8.0 are no longer supported"\
42
+ " and may not work"
43
+
31
44
  Gem.source_index.find_name(/^guard-/)
32
- end.map { |x| x.name.sub(/^guard-/, '') }.uniq
45
+ end.map { |x| x.name.sub(/^guard-/, "") }.uniq
33
46
  end
34
47
 
35
48
  # Initializes a new `Guard::PluginUtil` object.
@@ -37,7 +50,7 @@ module Guard
37
50
  # @param [String] name the name of the Guard plugin
38
51
  #
39
52
  def initialize(name)
40
- @name = name.to_s.sub(/^guard-/, '')
53
+ @name = name.to_s.sub(/^guard-/, "")
41
54
  end
42
55
 
43
56
  # Initializes a new `Guard::Plugin` with the given `options` hash. This
@@ -45,16 +58,18 @@ module Guard
45
58
  # class as well as plugins that inherit from `Guard::Plugin`.
46
59
  #
47
60
  # @see Guard::Plugin
48
- # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to upgrade for Guard 2.0
61
+ # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
62
+ # upgrade for Guard 2.0
49
63
  #
50
64
  # @return [Guard::Plugin] the initialized plugin
51
65
  # @return [Guard::Guard] the initialized plugin. This return type is
52
66
  # deprecated and the plugin's maintainer should update it to be
53
67
  # compatible with Guard 2.0. For more information on how to upgrade for
54
- # Guard 2.0, please head over to: https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
68
+ # Guard 2.0, please head over to:
69
+ # https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
55
70
  #
56
71
  def initialize_plugin(options)
57
- if plugin_class.superclass.to_s == 'Guard::Guard'
72
+ if plugin_class.superclass.to_s == "Guard::Guard"
58
73
  plugin_class.new(options.delete(:watchers), options)
59
74
  else
60
75
  plugin_class.new(options)
@@ -67,7 +82,7 @@ module Guard
67
82
  #
68
83
  def plugin_location
69
84
  @plugin_location ||= begin
70
- if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
85
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create("1.8.0")
71
86
  Gem::Specification.find_by_name("guard-#{ name }").full_gem_path
72
87
  else
73
88
  Gem.source_index.find_name("guard-#{ name }").last.full_gem_path
@@ -89,7 +104,9 @@ module Guard
89
104
  #
90
105
  # * `rspec` will find a class `Guard::RSpec`
91
106
  #
92
- # @option options [Boolean] fail_gracefully whether error messages should not be printed
107
+ # @option options [Boolean] fail_gracefully whether error messages should
108
+ # not be printed
109
+ #
93
110
  # @return [Class, nil] the loaded class
94
111
  #
95
112
  def plugin_class(options = {})
@@ -100,18 +117,18 @@ module Guard
100
117
  require "guard/#{ name.downcase }" if try_require
101
118
 
102
119
  @plugin_class ||= ::Guard.const_get(_plugin_constant)
103
- rescue TypeError => typeError
120
+ rescue TypeError => error
104
121
  if try_require
105
122
  ::Guard::UI.error "Could not find class Guard::#{ _constant_name }"
106
- ::Guard::UI.error typeError.backtrace.join("\n")
123
+ ::Guard::UI.error error.backtrace.join("\n")
107
124
  else
108
125
  try_require = true
109
126
  retry
110
127
  end
111
- rescue LoadError => loadError
128
+ rescue LoadError => error
112
129
  unless options[:fail_gracefully]
113
- ::Guard::UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ _constant_name }"
114
- ::Guard::UI.error loadError.backtrace.join("\n")
130
+ UI.error ERROR_NO_GUARD_OR_CLASS % [name.downcase, _constant_name]
131
+ UI.error error.backtrace.join("\n")
115
132
  end
116
133
  end
117
134
  end
@@ -119,17 +136,19 @@ module Guard
119
136
  # Adds a plugin's template to the Guardfile.
120
137
  #
121
138
  def add_to_guardfile
139
+ msg = "Guard.evaluator not initialized"
140
+ fail msg if ::Guard.evaluator.nil?
122
141
  if ::Guard.evaluator.guardfile_include?(name)
123
142
  ::Guard::UI.info "Guardfile already includes #{ name } guard"
124
143
  else
125
- content = File.read('Guardfile')
126
- File.open('Guardfile', 'wb') do |f|
144
+ content = File.read("Guardfile")
145
+ File.open("Guardfile", "wb") do |f|
127
146
  f.puts(content)
128
- f.puts('')
147
+ f.puts("")
129
148
  f.puts(plugin_class.template(plugin_location))
130
149
  end
131
150
 
132
- ::Guard::UI.info "#{ name } guard added to Guardfile, feel free to edit it"
151
+ UI.info INFO_ADDED_GUARD_TO_GUARDFILE % name
133
152
  end
134
153
  end
135
154
 
@@ -142,7 +161,9 @@ module Guard
142
161
  # => Guard::RSpec
143
162
  #
144
163
  def _plugin_constant
145
- @_plugin_constant ||= ::Guard.constants.find { |c| c.to_s.downcase == _constant_name.downcase }
164
+ @_plugin_constant ||= ::Guard.constants.detect do |c|
165
+ c.to_s.downcase == _constant_name.downcase
166
+ end
146
167
  end
147
168
 
148
169
  # Guesses the most probable name for the current plugin based on its name.
@@ -152,8 +173,8 @@ module Guard
152
173
  # => "Rspec"
153
174
  #
154
175
  def _constant_name
155
- @_constant_name ||= name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.gsub(/(?:^|[_-])(.)/) { $1.upcase }
176
+ @_constant_name ||= name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.
177
+ gsub(/(?:^|[_-])(.)/) { $1.upcase }
156
178
  end
157
-
158
179
  end
159
180
  end
@@ -0,0 +1,178 @@
1
+ require "guard/ui"
2
+
3
+ module Guard
4
+ # This class contains useful methods to:
5
+ #
6
+ # * Fetch all the Guard plugins names;
7
+ # * Initialize a plugin, get its location;
8
+ # * Return its class name;
9
+ # * Add its template to the Guardfile.
10
+ #
11
+ class PluginUtil
12
+ ERROR_NO_GUARD_OR_CLASS = "Could not load 'guard/%s' or'\
13
+ ' find class Guard::%s"
14
+
15
+ INFO_ADDED_GUARD_TO_GUARDFILE = "%s guard added to Guardfile,"\
16
+ " feel free to edit it"
17
+
18
+ attr_accessor :name
19
+
20
+ # Returns a list of Guard plugin Gem names installed locally.
21
+ #
22
+ # @return [Array<String>] a list of Guard plugin gem names
23
+ #
24
+ def self.plugin_names
25
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create("1.8.0")
26
+ Gem::Specification.find_all.select do |x|
27
+ if x.name =~ /^guard-/
28
+ true
29
+ elsif x.name != "guard"
30
+
31
+ guard_plugin_path = File.join(
32
+ x.full_gem_path,
33
+ "lib/guard/#{ x.name }.rb"
34
+ )
35
+
36
+ File.exist?(guard_plugin_path)
37
+ end
38
+ end
39
+ else
40
+ ::Guard::UI.deprecation \
41
+ "Rubygems version prior to 1.8.0 are no longer supported"\
42
+ " and may not work"
43
+
44
+ Gem.source_index.find_name(/^guard-/)
45
+ end.map { |x| x.name.sub(/^guard-/, "") }.uniq
46
+ end
47
+
48
+ # Initializes a new `Guard::PluginUtil` object.
49
+ #
50
+ # @param [String] name the name of the Guard plugin
51
+ #
52
+ def initialize(name)
53
+ @name = name.to_s.sub(/^guard-/, "")
54
+ end
55
+
56
+ # Initializes a new `Guard::Plugin` with the given `options` hash. This
57
+ # methods handles plugins that inherit from the deprecated `Guard::Guard`
58
+ # class as well as plugins that inherit from `Guard::Plugin`.
59
+ #
60
+ # @see Guard::Plugin
61
+ # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
62
+ # upgrade for Guard 2.0
63
+ #
64
+ # @return [Guard::Plugin] the initialized plugin
65
+ # @return [Guard::Guard] the initialized plugin. This return type is
66
+ # deprecated and the plugin's maintainer should update it to be
67
+ # compatible with Guard 2.0. For more information on how to upgrade for
68
+ # Guard 2.0, please head over to:
69
+ # https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
70
+ #
71
+ def initialize_plugin(options)
72
+ if plugin_class.superclass.to_s == "Guard::Guard"
73
+ plugin_class.new(options.delete(:watchers), options)
74
+ else
75
+ plugin_class.new(options)
76
+ end
77
+ end
78
+
79
+ # Locates a path to a Guard plugin gem.
80
+ #
81
+ # @return [String] the full path to the plugin gem
82
+ #
83
+ def plugin_location
84
+ @plugin_location ||= begin
85
+ if Gem::Version.create(Gem::VERSION) >= Gem::Version.create("1.8.0")
86
+ Gem::Specification.find_by_name("guard-#{ name }").full_gem_path
87
+ else
88
+ Gem.source_index.find_name("guard-#{ name }").last.full_gem_path
89
+ end
90
+ end
91
+ rescue
92
+ ::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
93
+ end
94
+
95
+ # Tries to load the Guard plugin main class. This transforms the supplied
96
+ # plugin name into a class name:
97
+ #
98
+ # * `guardname` will become `Guard::Guardname`
99
+ # * `dashed-guard-name` will become `Guard::DashedGuardName`
100
+ # * `underscore_guard_name` will become `Guard::UnderscoreGuardName`
101
+ #
102
+ # When no class is found with the strict case sensitive rules, another
103
+ # try is made to locate the class without matching case:
104
+ #
105
+ # * `rspec` will find a class `Guard::RSpec`
106
+ #
107
+ # @option options [Boolean] fail_gracefully whether error messages should
108
+ # not be printed
109
+ #
110
+ # @return [Class, nil] the loaded class
111
+ #
112
+ def plugin_class(options = {})
113
+ options = { fail_gracefully: false }.merge(options)
114
+
115
+ try_require = false
116
+ begin
117
+ require "guard/#{ name.downcase }" if try_require
118
+
119
+ @plugin_class ||= ::Guard.const_get(_plugin_constant)
120
+ rescue TypeError => error
121
+ if try_require
122
+ ::Guard::UI.error "Could not find class Guard::#{ _constant_name }"
123
+ ::Guard::UI.error error.backtrace.join("\n")
124
+ else
125
+ try_require = true
126
+ retry
127
+ end
128
+ rescue LoadError => error
129
+ unless options[:fail_gracefully]
130
+ UI.error ERROR_NO_GUARD_OR_CLASS % [name.downcase, _constant_name]
131
+ UI.error error.backtrace.join("\n")
132
+ end
133
+ end
134
+ end
135
+
136
+ # Adds a plugin's template to the Guardfile.
137
+ #
138
+ def add_to_guardfile
139
+ if ::Guard.evaluator.guardfile_include?(name)
140
+ ::Guard::UI.info "Guardfile already includes #{ name } guard"
141
+ else
142
+ content = File.read("Guardfile")
143
+ File.open("Guardfile", "wb") do |f|
144
+ f.puts(content)
145
+ f.puts("")
146
+ f.puts(plugin_class.template(plugin_location))
147
+ end
148
+
149
+ UI.info INFO_ADDED_GUARD_TO_GUARDFILE % name
150
+ end
151
+ end
152
+
153
+ private
154
+
155
+ # Returns the constant for the current plugin.
156
+ #
157
+ # @example Returns the constant for a plugin
158
+ # > Guard::PluginUtil.new('rspec').send(:_plugin_constant)
159
+ # => Guard::RSpec
160
+ #
161
+ def _plugin_constant
162
+ @_plugin_constant ||= ::Guard.constants.detect do |c|
163
+ c.to_s.downcase == _constant_name.downcase
164
+ end
165
+ end
166
+
167
+ # Guesses the most probable name for the current plugin based on its name.
168
+ #
169
+ # @example Returns the most probable name for a plugin
170
+ # > Guard::PluginUtil.new('rspec').send(:_constant_name)
171
+ # => "Rspec"
172
+ #
173
+ def _constant_name
174
+ @_constant_name ||= name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.
175
+ gsub(/(?:^|[_-])(.)/) { $1.upcase }
176
+ end
177
+ end
178
+ end
@@ -1,17 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rake'
4
- require 'rake/tasklib'
3
+ require "rake"
4
+ require "rake/tasklib"
5
5
 
6
- require 'guard/cli'
6
+ require "guard/cli"
7
7
 
8
8
  module Guard
9
-
10
9
  # Provides a method to define a Rake task that
11
10
  # runs the Guard plugins.
12
11
  #
13
12
  class RakeTask < ::Rake::TaskLib
14
-
15
13
  # Name of the main, top level task
16
14
  attr_accessor :name
17
15
 
@@ -24,7 +22,7 @@ module Guard
24
22
  # @param [String] options the CLI options
25
23
  # @yield [Guard::RakeTask] the task
26
24
  #
27
- def initialize(name = :guard, options = '')
25
+ def initialize(name = :guard, options = "")
28
26
  @name = name
29
27
  @options = options
30
28
 
@@ -42,6 +40,5 @@ module Guard
42
40
 
43
41
  end
44
42
  end
45
-
46
43
  end
47
44
  end
@@ -0,0 +1,13 @@
1
+ require "guard"
2
+ require "guard/plugin"
3
+
4
+ module Guard
5
+ class Reevaluator < Guard::Plugin
6
+ def run_on_modifications(files)
7
+ return unless ::Guard::Watcher.match_guardfile?(files)
8
+ ::Guard.save_scope
9
+ ::Guard.evaluator.reevaluate_guardfile
10
+ ::Guard.restore_scope
11
+ end
12
+ end
13
+ end
data/lib/guard/runner.rb CHANGED
@@ -1,18 +1,18 @@
1
- require 'lumberjack'
1
+ require "lumberjack"
2
2
 
3
- require 'guard/ui'
4
- require 'guard/watcher'
3
+ require "guard/ui"
4
+ require "guard/watcher"
5
5
 
6
6
  module Guard
7
-
8
7
  # The runner is responsible for running all methods defined on each plugin.
9
8
  #
10
9
  class Runner
11
-
12
10
  # Runs a Guard-task on all registered plugins.
13
11
  #
14
12
  # @param [Symbol] task the task to run
15
- # @param [Hash] scopes either the Guard plugin or the group to run the task on
13
+ #
14
+ # @param [Hash] scopes either the Guard plugin or the group to run the task
15
+ # on
16
16
  #
17
17
  # @see self.run_supervised_task
18
18
  #
@@ -24,7 +24,10 @@ module Guard
24
24
  end
25
25
  end
26
26
 
27
- MODIFICATION_TASKS = [:run_on_modifications, :run_on_changes, :run_on_change]
27
+ MODIFICATION_TASKS = [
28
+ :run_on_modifications, :run_on_changes, :run_on_change
29
+ ]
30
+
28
31
  ADDITION_TASKS = [:run_on_additions, :run_on_changes, :run_on_change]
29
32
  REMOVAL_TASKS = [:run_on_removals, :run_on_changes, :run_on_deletion]
30
33
 
@@ -36,30 +39,32 @@ module Guard
36
39
  # @param [Array<String>] removed the removed paths.
37
40
  #
38
41
  def run_on_changes(modified, added, removed)
39
- ::Guard::UI.clearable
42
+ types = {
43
+ MODIFICATION_TASKS => modified,
44
+ ADDITION_TASKS => added,
45
+ REMOVAL_TASKS => removed
46
+ }
40
47
 
41
- #TODO: this should be handled like every other plugin
42
- if ::Guard::Watcher.match_guardfile?(modified)
43
- ::Guard.evaluator.reevaluate_guardfile
44
- end
48
+ ::Guard::UI.clearable
45
49
 
46
50
  _scoped_plugins do |guard|
47
- modified_paths = ::Guard::Watcher.match_files(guard, modified)
48
- added_paths = ::Guard::Watcher.match_files(guard, added)
49
- removed_paths = ::Guard::Watcher.match_files(guard, removed)
51
+ ::Guard::UI.clear
50
52
 
51
- ::Guard::UI.clear if _clearable?(guard, modified_paths, added_paths, removed_paths)
53
+ types.each do |tasks, unmatched_paths|
54
+ paths = ::Guard::Watcher.match_files(guard, unmatched_paths)
55
+ next if paths.empty?
52
56
 
53
- _run_first_task_found(guard, MODIFICATION_TASKS, modified_paths) unless modified_paths.empty?
54
- _run_first_task_found(guard, ADDITION_TASKS, added_paths) unless added_paths.empty?
55
- _run_first_task_found(guard, REMOVAL_TASKS, removed_paths) unless removed_paths.empty?
57
+ next unless (task = tasks.detect { |meth| guard.respond_to?(meth) })
58
+ run_supervised_task(guard, task, paths)
59
+ end
56
60
  end
57
61
  end
58
62
 
59
- # Run a Guard plugin task, but remove the Guard plugin when his work leads to a system failure.
63
+ # Run a Guard plugin task, but remove the Guard plugin when his work leads
64
+ # to a system failure.
60
65
  #
61
- # When the Group has `:halt_on_fail` disabled, we've to catch `:task_has_failed`
62
- # here in order to avoid an uncaught throw error.
66
+ # When the Group has `:halt_on_fail` disabled, we've to catch
67
+ # `:task_has_failed` here in order to avoid an uncaught throw error.
63
68
  #
64
69
  # @param [Guard::Plugin] guard the Guard to execute
65
70
  # @param [Symbol] task the task to run
@@ -67,27 +72,24 @@ module Guard
67
72
  # @raise [:task_has_failed] when task has failed
68
73
  #
69
74
  def run_supervised_task(guard, task, *args)
70
- begin
71
- catch self.class.stopping_symbol_for(guard) do
72
- guard.hook("#{ task }_begin", *args)
73
- begin
74
- result = guard.send(task, *args)
75
- rescue Interrupt
76
- throw(:task_has_failed)
77
- end
78
- guard.hook("#{ task }_end", result)
79
- result
75
+ catch self.class.stopping_symbol_for(guard) do
76
+ guard.hook("#{ task }_begin", *args)
77
+ begin
78
+ result = guard.send(task, *args)
79
+ rescue Interrupt
80
+ throw(:task_has_failed)
80
81
  end
81
-
82
- rescue Exception => ex
83
- ::Guard::UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
84
- "\n#{ ex.class }: #{ ex.message }\n#{ ex.backtrace.join("\n") }")
85
-
86
- ::Guard.plugins.delete guard
87
- ::Guard::UI.info("\n#{ guard.class.name } has just been fired")
88
-
89
- ex
82
+ guard.hook("#{ task }_end", result)
83
+ result
90
84
  end
85
+ rescue ScriptError, StandardError, RuntimeError
86
+ ::Guard::UI.error("#{ guard.class.name } failed to achieve its"\
87
+ " <#{ task }>, exception was:" \
88
+ "\n#{ $!.class }: #{ $!.message }" \
89
+ "\n#{ $!.backtrace.join("\n") }")
90
+ ::Guard.plugins.delete guard
91
+ ::Guard::UI.info("\n#{ guard.class.name } has just been fired")
92
+ $!
91
93
  end
92
94
 
93
95
  # Returns the symbol that has to be caught when running a supervised task.
@@ -106,24 +108,6 @@ module Guard
106
108
 
107
109
  private
108
110
 
109
- # Tries to run the first implemented task by a given guard
110
- # from a collection of tasks.
111
- #
112
- # @param [Guard::Plugin] guard the Guard plugin to run the first found task on
113
- # @param [Array<Symbol>] tasks the tasks to run the first among
114
- # @param [Object] task_param the param to pass to each task
115
- #
116
- def _run_first_task_found(guard, tasks, task_param)
117
- tasks.each do |task|
118
- if guard.respond_to?(task)
119
- run_supervised_task(guard, task, task_param)
120
- break
121
- else
122
- ::Guard::UI.debug "Trying to run #{ guard.class.name }##{ task.to_s } with #{ task_param.inspect }"
123
- end
124
- end
125
- end
126
-
127
111
  # Loop through all groups and run the given task for each Guard plugin.
128
112
  #
129
113
  # If no scope is supplied, the global Guard scope is taken into account.
@@ -151,27 +135,14 @@ module Guard
151
135
  end
152
136
  end
153
137
 
154
- if block_return.nil?
155
- ::Guard::UI.info "#{ current_plugin.class.name } has failed, other group's plugins execution has been halted."
156
- end
138
+ next unless block_return.nil?
139
+
140
+ ::Guard::UI.info "#{ current_plugin.class.name } has failed,"\
141
+ " other group's plugins execution has been halted."
157
142
  end
158
143
  end
159
144
  end
160
145
 
161
- # Logic to know if the UI can be cleared or not in the run_on_changes method
162
- # based on the guard and the changes.
163
- #
164
- # @param [Guard::Plugin] guard the Guard plugin where run_on_changes is called
165
- # @param [Array<String>] modified_paths the modified paths.
166
- # @param [Array<String>] added_paths the added paths.
167
- # @param [Array<String>] removed_paths the removed paths.
168
- #
169
- def _clearable?(guard, modified_paths, added_paths, removed_paths)
170
- (MODIFICATION_TASKS.any? { |task| guard.respond_to?(task) } && !modified_paths.empty?) ||
171
- (ADDITION_TASKS.any? { |task| guard.respond_to?(task) } && !added_paths.empty?) ||
172
- (REMOVAL_TASKS.any? { |task| guard.respond_to?(task) } && !removed_paths.empty?)
173
- end
174
-
175
146
  # Returns the current plugins scope.
176
147
  # Local plugins scope wins over global plugins scope.
177
148
  # If no plugins scope is found, then NO plugins are returned.
@@ -205,12 +176,13 @@ module Guard
205
176
  # Find the first non empty element in the given possibilities
206
177
  #
207
178
  def _find_non_empty_scope(type, local_scope, *additional_possibilities)
208
- [
179
+ found = [
209
180
  local_scope[:"#{type}s"],
210
181
  local_scope[type.to_sym],
211
182
  ::Guard.scope[:"#{type}s"],
212
183
  additional_possibilities.flatten
213
- ].compact.find { |a| !Array(a).empty? }
184
+ ].compact.detect { |a| !Array(a).empty? }
185
+ found ? [::Guard.group(:common)] + Array(found) : found
214
186
  end
215
187
 
216
188
  # Find the first non empty plugins scope