guard 2.6.1 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
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