guard 2.9.0 → 2.9.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.
@@ -1,7 +1,6 @@
1
1
  # required for async_queue_add
2
2
  require "pry"
3
3
 
4
- # TODO: remove this dependency
5
4
  require "guard/interactor"
6
5
  require "guard"
7
6
 
@@ -23,7 +22,7 @@ module Guard
23
22
  BANNER
24
23
 
25
24
  def process(*entries)
26
- scopes, unknown = ::Guard::Interactor.convert_scope(entries)
25
+ scopes, unknown = Interactor.convert_scope(entries)
27
26
 
28
27
  unless unknown.empty?
29
28
  output.puts "Unknown scopes: #{ unknown.join(", ") }"
@@ -1,6 +1,5 @@
1
1
  require "pry"
2
2
 
3
- # TODO: remove
4
3
  require "guard"
5
4
 
6
5
  module Guard
@@ -23,7 +22,7 @@ module Guard
23
22
  return
24
23
  end
25
24
 
26
- ::Guard.async_queue_add(modified: files, added: [], removed: [])
25
+ Guard.async_queue_add(modified: files, added: [], removed: [])
27
26
  end
28
27
  end
29
28
  end
@@ -1,6 +1,5 @@
1
1
  require "pry"
2
2
 
3
- # TODO: should not be necessary!
4
3
  require "guard/interactor"
5
4
  require "guard"
6
5
 
@@ -22,7 +21,7 @@ module Guard
22
21
  BANNER
23
22
 
24
23
  def process(*entries)
25
- scopes, unknown = ::Guard::Interactor.convert_scope(entries)
24
+ scopes, unknown = Interactor.convert_scope(entries)
26
25
 
27
26
  unless unknown.empty?
28
27
  output.puts "Unknown scopes: #{ unknown.join(", ") }"
@@ -29,8 +29,7 @@ module Guard
29
29
  return
30
30
  end
31
31
 
32
- # TODO: provide a way for guard to know this was called from Pry
33
- ::Guard.setup_scope(scope)
32
+ Guard.state.scope.from_interactor(scope)
34
33
  end
35
34
  end
36
35
  end
@@ -0,0 +1,34 @@
1
+ require "guard/config"
2
+ fail "Deprecations disabled (strict mode)" if Guard::Config.new.strict?
3
+
4
+ require "guard/ui"
5
+
6
+ module Guard
7
+ module Deprecated
8
+ module Evaluator
9
+ def self.add_deprecated(klass)
10
+ klass.send(:include, self)
11
+ end
12
+
13
+ EVALUATE_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
14
+ Starting with Guard 2.8.3 'Guard::Evaluator#evaluate_guardfile' is
15
+ deprecated in favor of '#evaluate'.
16
+ EOS
17
+
18
+ REEVALUATE_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
19
+ Starting with Guard 2.8.3 'Guard::Evaluator#reevaluate_guardfile' is
20
+ deprecated in favor of '#reevaluate'.
21
+ EOS
22
+
23
+ def evaluate_guardfile
24
+ UI.deprecation(EVALUATE_GUARDFILE)
25
+ evaluate
26
+ end
27
+
28
+ def reevaluate_guardfile
29
+ UI.deprecation(REEVALUATE_GUARDFILE)
30
+ ::Guard::Reevaluator.new.reevaluate
31
+ end
32
+ end
33
+ end
34
+ end
@@ -138,10 +138,9 @@ module Guard
138
138
  EOS
139
139
 
140
140
  def evaluator
141
- # TODO: probably deprecate once it isn't used internally
142
- # TODO: this will be changed to the following when scope is reworked
143
141
  UI.deprecation(EVALUATOR)
144
- ::Guard::Guardfile::Evaluator.new(::Guard.options)
142
+ options = ::Guard.state.session.evaluator_options
143
+ ::Guard::Guardfile::Evaluator.new(options)
145
144
  end
146
145
 
147
146
  RESET_EVALUATOR = <<-EOS.gsub(/^\s*/, "")
@@ -160,6 +159,19 @@ module Guard
160
159
  UI.deprecation(RUNNER)
161
160
  ::Guard::Runner.new
162
161
  end
162
+
163
+ EVALUATE_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
164
+ Starting with Guard 2.8.2 this method shouldn't be used
165
+ EOS
166
+
167
+ def evaluate_guardfile
168
+ UI.deprecation(EVALUATE_GUARDFILE)
169
+ options = ::Guard.state.session.evaluator_options
170
+ evaluator = ::Guard::Guardfile::Evaluator.new(options)
171
+ evaluator.evaluate
172
+ msg = "No plugins found in Guardfile, please add at least one."
173
+ ::Guard::UI.error msg if _pluginless_guardfile?
174
+ end
163
175
  end
164
176
  end
165
177
  end
@@ -0,0 +1,27 @@
1
+ require "guard/config"
2
+ fail "Deprecations disabled (strict mode)" if Guard::Config.new.strict?
3
+
4
+ module Guard
5
+ module Deprecated
6
+ module Watcher
7
+ def self.add_deprecated(dsl_klass)
8
+ dsl_klass.send(:extend, ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ MATCH_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
13
+ Starting with Guard 2.8.3 this method is deprecated.
14
+ EOS
15
+
16
+ def match_guardfile?(files)
17
+ require "guard/guardfile/evaluator"
18
+ UI.deprecation(MATCH_GUARDFILE)
19
+ options = ::Guard.state.session.evaluator_options
20
+ evaluator = ::Guard::Guardfile::Evaluator.new(options)
21
+ path = evaluator.guardfile_path
22
+ files.any? { |file| File.expand_path(file) == path }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -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::Base#start},
30
- # {Plugin::Base#stop}, {Plugin::Base#reload}, {Plugin::Base#run_all},
31
- # {Plugin::Base#run_on_changes}, {Plugin::Base#run_on_additions},
32
- # {Plugin::Base#run_on_modifications} and {Plugin::Base#run_on_removals}
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
- ::Guard::Interactor.enabled = false
95
+ Interactor.enabled = false
92
96
  when Hash
93
- ::Guard::Interactor.options = options
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
- ::Guard.add_group(group, options)
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
- ::Guard::UI.error \
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
- ::Guard.add_plugin(name, @plugin_options.merge(group: group))
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] << ::Guard::Watcher.new(pattern, action)
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
@@ -237,8 +242,6 @@ module Guard
237
242
  # @param [Array] args the callback arguments
238
243
  # @yield a callback block
239
244
  #
240
- # @see Guard::Hooker
241
- #
242
245
  def callback(*args, &block)
243
246
  @plugin_options ||= nil
244
247
  fail "callback must be called within a guard block" unless @plugin_options
@@ -262,8 +265,10 @@ module Guard
262
265
  #
263
266
  def ignore(*regexps)
264
267
  # TODO: instead, use Guard.reconfigure(ignore: regexps) or something
265
- ::Guard.listener.ignore(regexps) if ::Guard.listener
268
+ Guard.listener.ignore(regexps) if Guard.listener
266
269
  end
270
+
271
+ # TODO: deprecate
267
272
  alias filter ignore
268
273
 
269
274
  # Replaces ignored paths globally
@@ -276,7 +281,7 @@ module Guard
276
281
  def ignore!(*regexps)
277
282
  @ignore_regexps ||= []
278
283
  @ignore_regexps << regexps
279
- ::Guard.listener.ignore!(@ignore_regexps) if ::Guard.listener
284
+ Guard.listener.ignore!(@ignore_regexps) if Guard.listener
280
285
  end
281
286
  alias filter! ignore!
282
287
 
@@ -341,7 +346,7 @@ module Guard
341
346
  options[name] = Regexp.new(list.join("|"), Regexp::IGNORECASE)
342
347
  end
343
348
 
344
- ::Guard::UI.options.merge!(options)
349
+ UI.options.merge!(options)
345
350
  end
346
351
 
347
352
  # Sets the default scope on startup
@@ -361,7 +366,43 @@ module Guard
361
366
  # @param [Hash] scopes the scope for the groups and plugins
362
367
  #
363
368
  def scope(scope = {})
364
- ::Guard.setup_scope(scope)
369
+ Guard.state.session.guardfile_scope(scope)
370
+ end
371
+
372
+ def evaluate(contents, filename, lineno) # :nodoc
373
+ instance_eval(contents, filename.to_s, lineno)
374
+ rescue StandardError, ScriptError => e
375
+ prefix = "\n\t(dsl)> "
376
+ cleaned_backtrace = _cleanup_backtrace(e.backtrace)
377
+ backtrace = "#{prefix}#{cleaned_backtrace.join(prefix)}"
378
+ msg = "Invalid Guardfile, original error is: \n\n%s, \nbacktrace: %s"
379
+ raise Error, format(msg, e, backtrace)
380
+ end
381
+
382
+ private
383
+
384
+ def _cleanup_backtrace(backtrace)
385
+ dirs = { File.realpath(Dir.pwd) => ".", }
386
+
387
+ gem_env = ENV["GEM_HOME"] || ""
388
+ dirs[gem_env] = "$GEM_HOME" unless gem_env.empty?
389
+
390
+ gem_paths = (ENV["GEM_PATH"] || "").split(File::PATH_SEPARATOR)
391
+ gem_paths.each_with_index do |path, index|
392
+ dirs[path] = "$GEM_PATH[#{index}]"
393
+ end
394
+
395
+ backtrace.dup.map do |raw_line|
396
+ path = nil
397
+ symlinked_path = raw_line.split(":").first
398
+ begin
399
+ path = raw_line.sub(symlinked_path, File.realpath(symlinked_path))
400
+ dirs.detect { |dir, name| path.sub!(File.realpath(dir), name) }
401
+ path
402
+ rescue Errno::ENOENT
403
+ path || symlinked_path
404
+ end
405
+ end
365
406
  end
366
407
 
367
408
  # Sets the directories to pass to Listen
@@ -375,7 +416,7 @@ module Guard
375
416
  directories.each do |dir|
376
417
  fail "Directory #{dir.inspect} does not exist!" unless Dir.exist?(dir)
377
418
  end
378
- ::Guard.watchdirs = directories
419
+ Guard.state.session.watchdirs = directories
379
420
  end
380
421
  end
381
422
  end
@@ -1,9 +1,11 @@
1
1
  # encoding: utf-8
2
2
  require "formatador"
3
3
 
4
- require "guard/guardfile/evaluator"
5
4
  require "guard/ui"
6
- require "guard/metadata"
5
+ require "guard/notifier"
6
+
7
+ require "set"
8
+ require "ostruct"
7
9
 
8
10
  module Guard
9
11
  # The DslDescriber evaluates the Guardfile and creates an internal structure
@@ -14,20 +16,8 @@ module Guard
14
16
  # @see Guard::CLI
15
17
  #
16
18
  class DslDescriber
17
- # Initializes a new DslDescriber object.
18
- #
19
- # @option options [String] guardfile the path to a valid Guardfile
20
- #
21
- # @option options [String] guardfile_contents a string representing the
22
- # content of a valid Guardfile
23
- #
24
- # @see Guard::Guardfile::Evaluator#initialize
25
- #
26
- def initialize(options = {})
27
- ::Guard.reset_groups
28
- ::Guard.reset_plugins
29
- ::Guard.reset_scope
30
- ::Guard.reset_options(options)
19
+ def initialize(options = nil)
20
+ fail "options passed to DslDescriber are ignored!" unless options.nil?
31
21
  end
32
22
 
33
23
  # List the Guard plugins that are available for use in your system and marks
@@ -36,17 +26,21 @@ module Guard
36
26
  # @see CLI#list
37
27
  #
38
28
  def list
39
- _evaluate_guardfile
40
- names = ::Guard::PluginUtil.plugin_names.sort.uniq
41
- final_rows = names.inject([]) do |rows, name|
42
- used = ::Guard.plugins(name).any?
43
- rows << {
44
- Plugin: name.capitalize,
45
- Guardfile: used ? "✔" : "✘"
46
- }
29
+ # collect metadata
30
+ data = PluginUtil.plugin_names.sort.inject({}) do |hash, name|
31
+ hash[name.capitalize] = Guard.state.session.plugins.all(name).any?
32
+ hash
33
+ end
34
+
35
+ # presentation
36
+ header = [:Plugin, :Guardfile]
37
+ final_rows = []
38
+ data.each do |name, used|
39
+ final_rows << { Plugin: name, Guardfile: used ? "✔" : "✘" }
47
40
  end
48
41
 
49
- Formatador.display_compact_table(final_rows, [:Plugin, :Guardfile])
42
+ # render
43
+ Formatador.display_compact_table(final_rows, header)
50
44
  end
51
45
 
52
46
  # Shows all Guard plugins and their options that are defined in
@@ -55,53 +49,52 @@ module Guard
55
49
  # @see CLI#show
56
50
  #
57
51
  def show
58
- _evaluate_guardfile
59
- groups = ::Guard.groups
52
+ # collect metadata
53
+ groups = Guard.state.session.groups.all
60
54
 
61
- final_rows = groups.each_with_object([]) do |group, rows|
55
+ objects = []
62
56
 
63
- plugins = Array(::Guard.plugins(group: group.name))
57
+ empty_plugin = OpenStruct.new
58
+ empty_plugin.options = [["", nil]]
64
59
 
60
+ groups.each do |group|
61
+ plugins = Array(Guard.state.session.plugins.all(group: group.name))
62
+ plugins = [empty_plugin] if plugins.empty?
65
63
  plugins.each do |plugin|
66
- options = plugin.options.inject({}) do |o, (k, v)|
67
- o.tap { |option| option[k.to_s] = v }
68
- end.sort
69
-
70
- if options.empty?
71
- rows << :split
72
- rows << {
73
- Group: group.title,
74
- Plugin: plugin.title,
75
- Option: "",
76
- Value: ""
77
- }
78
- else
79
- options.each_with_index do |(option, value), index|
80
- if index == 0
81
- rows << :split
82
- rows << {
83
- Group: group.title,
84
- Plugin: plugin.title,
85
- Option: option.to_s,
86
- Value: value.inspect
87
- }
88
- else
89
- rows << {
90
- Group: "",
91
- Plugin: "",
92
- Option: option.to_s,
93
- Value: value.inspect
94
- }
95
- end
96
- end
64
+ options = plugin.options
65
+ options = [["", nil]] if options.empty?
66
+ options.each do |option, raw_value|
67
+ value = raw_value.nil? ? "" : raw_value.inspect
68
+ objects << [group.title, plugin.title, option.to_s, value]
97
69
  end
98
70
  end
71
+ end
99
72
 
100
- rows
73
+ # presentation
74
+ rows = []
75
+ prev_group = prev_plugin = prev_option = prev_value = nil
76
+ objects.each do |group, plugin, option, value|
77
+ group_changed = prev_group != group
78
+ plugin_changed = (prev_plugin != plugin || group_changed)
79
+
80
+ rows << :split if group_changed || plugin_changed
81
+
82
+ rows << {
83
+ Group: group_changed ? group : "",
84
+ Plugin: plugin_changed ? plugin : "",
85
+ Option: option,
86
+ Value: value
87
+ }
88
+
89
+ prev_group = group
90
+ prev_plugin = plugin
91
+ prev_option = option
92
+ prev_value = value
101
93
  end
102
94
 
95
+ # render
103
96
  Formatador.display_compact_table(
104
- final_rows.drop(1),
97
+ rows.drop(1),
105
98
  [:Group, :Plugin, :Option, :Value]
106
99
  )
107
100
  end
@@ -112,8 +105,6 @@ module Guard
112
105
  # @see CLI#show
113
106
  #
114
107
  def notifiers
115
- _evaluate_guardfile
116
-
117
108
  supported = ::Guard::Notifier::SUPPORTED
118
109
  Notifier.connect(notify: false)
119
110
  detected = Notifier.notifiers
@@ -156,15 +147,6 @@ module Guard
156
147
 
157
148
  private
158
149
 
159
- # Evaluates the `Guardfile` by delegating to
160
- # {Guard::Guardfile::Evaluator#evaluate_guardfile}.
161
- #
162
- def _evaluate_guardfile
163
- ::Guard.save_scope
164
- ::Guard::Guardfile::Evaluator.new(::Guard.options).evaluate_guardfile
165
- ::Guard.restore_scope
166
- end
167
-
168
150
  def _merge_options(klass, notifier)
169
151
  notify_options = notifier ? notifier[:options] : {}
170
152