guard 2.8.2 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -7
  3. data/lib/guard.rb +220 -152
  4. data/lib/guard.rb.orig +213 -155
  5. data/lib/guard/aruba_adapter.rb +2 -2
  6. data/lib/guard/cli.rb +8 -13
  7. data/lib/guard/cli.rb.orig +12 -10
  8. data/lib/guard/commander.rb +15 -7
  9. data/lib/guard/commands/all.rb +3 -0
  10. data/lib/guard/commands/change.rb +3 -0
  11. data/lib/guard/commands/pause.rb +2 -0
  12. data/lib/guard/commands/reload.rb +4 -0
  13. data/lib/guard/commands/scope.rb +3 -0
  14. data/lib/guard/config.rb +24 -0
  15. data/lib/guard/deprecated/dsl.rb +45 -0
  16. data/lib/guard/deprecated/guard.rb +166 -0
  17. data/lib/guard/deprecated/guardfile.rb +84 -0
  18. data/lib/guard/dsl.rb +24 -13
  19. data/lib/guard/dsl.rb.orig +378 -0
  20. data/lib/guard/dsl_describer.rb +8 -2
  21. data/lib/guard/dsl_describer.rb.orig +11 -3
  22. data/lib/guard/guardfile.rb +32 -44
  23. data/lib/guard/guardfile/evaluator.rb +13 -6
  24. data/lib/guard/guardfile/generator.rb +4 -3
  25. data/lib/guard/interactor.rb +7 -3
  26. data/lib/guard/internals/debugging.rb +1 -0
  27. data/lib/guard/internals/environment.rb +93 -0
  28. data/lib/guard/internals/helpers.rb +13 -0
  29. data/lib/guard/internals/traps.rb +10 -0
  30. data/lib/guard/jobs/pry_wrapper.rb +4 -3
  31. data/lib/guard/jobs/sleep.rb +2 -0
  32. data/lib/guard/metadata.rb +190 -0
  33. data/lib/guard/notifier.rb +124 -99
  34. data/lib/guard/notifier.rb.orig +124 -99
  35. data/lib/guard/notifier/detected.rb +83 -0
  36. data/lib/guard/notifiers/emacs.rb +2 -1
  37. data/lib/guard/notifiers/tmux.rb +173 -177
  38. data/lib/guard/plugin/base.rb +2 -0
  39. data/lib/guard/plugin_util.rb +26 -32
  40. data/lib/guard/reevaluator.rb +3 -3
  41. data/lib/guard/reevaluator.rb.orig +22 -0
  42. data/lib/guard/runner.rb +1 -0
  43. data/lib/guard/session.rb +5 -0
  44. data/lib/guard/sheller.rb +2 -2
  45. data/lib/guard/templates/Guardfile +4 -0
  46. data/lib/guard/templates/Guardfile.orig +2 -0
  47. data/lib/guard/terminal.rb +1 -0
  48. data/lib/guard/ui.rb +4 -1
  49. data/lib/guard/version.rb +1 -1
  50. data/lib/guard/version.rb.orig +1 -1
  51. data/lib/guard/watcher.rb +3 -1
  52. data/lib/guard/watcher.rb.orig +122 -0
  53. data/man/guard.1 +1 -4
  54. data/man/guard.1.html +1 -4
  55. metadata +17 -25
  56. data/lib/guard/commander.rb.orig +0 -103
  57. data/lib/guard/commands/all.rb.orig +0 -36
  58. data/lib/guard/commands/reload.rb.orig +0 -34
  59. data/lib/guard/commands/scope.rb.orig +0 -36
  60. data/lib/guard/deprecated_methods.rb +0 -72
  61. data/lib/guard/deprecated_methods.rb.orig +0 -71
  62. data/lib/guard/deprecator.rb +0 -133
  63. data/lib/guard/deprecator.rb.orig +0 -206
  64. data/lib/guard/guard.rb +0 -100
  65. data/lib/guard/guard.rb.orig +0 -42
  66. data/lib/guard/guardfile.rb.orig +0 -43
  67. data/lib/guard/guardfile/evaluator.rb.orig +0 -275
  68. data/lib/guard/internals/debugging.rb.orig +0 -0
  69. data/lib/guard/internals/environment.rb.orig +0 -0
  70. data/lib/guard/internals/tracing.rb.orig +0 -0
  71. data/lib/guard/notifiers/base.rb.orig +0 -221
  72. data/lib/guard/notifiers/tmux.rb.orig +0 -339
  73. data/lib/guard/plugin_util.rb.orig +0 -186
  74. data/lib/guard/runner.rb.orig +0 -210
  75. data/lib/guard/setuper.rb +0 -359
  76. data/lib/guard/setuper.rb.orig +0 -395
  77. data/lib/guard/ui.rb.orig +0 -278
@@ -3,6 +3,7 @@ require "formatador"
3
3
 
4
4
  require "guard/guardfile/evaluator"
5
5
  require "guard/ui"
6
+ require "guard/metadata"
6
7
 
7
8
  module Guard
8
9
  # The DslDescriber evaluates the Guardfile and creates an internal structure
@@ -113,13 +114,18 @@ module Guard
113
114
  def notifiers
114
115
  _evaluate_guardfile
115
116
 
116
- merged_notifiers = ::Guard::Notifier::NOTIFIERS.inject(:merge)
117
+ supported = ::Guard::Notifier::SUPPORTED
118
+ Notifier.connect(notify: false)
119
+ detected = Notifier.notifiers
120
+ Notifier.disconnect
121
+
122
+ merged_notifiers = supported.inject(:merge)
117
123
  final_rows = merged_notifiers.each_with_object([]) do |definition, rows|
118
124
 
119
125
  name = definition[0]
120
126
  clazz = definition[1]
121
127
  available = clazz.available?(silent: true) ? "✔" : "✘"
122
- notifier = ::Guard::Notifier.notifiers.detect { |n| n[:name] == name }
128
+ notifier = detected.detect { |n| n[:name] == name }
123
129
  used = notifier ? "✔" : "✘"
124
130
 
125
131
  options = _merge_options(clazz, notifier)
@@ -3,6 +3,7 @@ require "formatador"
3
3
 
4
4
  require "guard/guardfile/evaluator"
5
5
  require "guard/ui"
6
+ require "guard/metadata"
6
7
 
7
8
  module Guard
8
9
  # The DslDescriber evaluates the Guardfile and creates an internal structure
@@ -35,11 +36,13 @@ module Guard
35
36
  # @see CLI#list
36
37
  #
37
38
  def list
39
+ _evaluate_guardfile
38
40
  names = ::Guard::PluginUtil.plugin_names.sort.uniq
39
41
  final_rows = names.inject([]) do |rows, name|
42
+ used = ::Guard.plugins(name).any?
40
43
  rows << {
41
44
  Plugin: name.capitalize,
42
- Guardfile: ::Guard.plugins(name) ? "✔" : "✘"
45
+ Guardfile: used ? "✔" : "✘"
43
46
  }
44
47
  end
45
48
 
@@ -111,13 +114,18 @@ module Guard
111
114
  def notifiers
112
115
  _evaluate_guardfile
113
116
 
114
- merged_notifiers = ::Guard::Notifier::NOTIFIERS.inject(:merge)
117
+ supported = ::Guard::Notifier::SUPPORTED
118
+ Notifier.connect
119
+ detected = Notifier.notifiers
120
+ Notifier.disconnect
121
+
122
+ merged_notifiers = supported.inject(:merge)
115
123
  final_rows = merged_notifiers.each_with_object([]) do |definition, rows|
116
124
 
117
125
  name = definition[0]
118
126
  clazz = definition[1]
119
127
  available = clazz.available?(silent: true) ? "✔" : "✘"
120
- notifier = ::Guard::Notifier.notifiers.detect { |n| n[:name] == name }
128
+ notifier = detected.detect { |n| n[:name] == name }
121
129
  used = notifier ? "✔" : "✘"
122
130
 
123
131
  options = _merge_options(clazz, notifier)
@@ -1,49 +1,37 @@
1
- require "guard/guardfile/evaluator"
2
- require "guard/guardfile/generator"
3
- require "guard/ui"
4
-
5
- module Guard
6
- # @deprecated Use instance methods of {Guardfile::Evaluator} and
7
- # {Guardfile::Generator} instead.
8
- #
9
- # @see Guardfile::Evaluator
10
- # @see Guardfile::Generator
11
- #
12
- module Guardfile
13
- # @deprecated Use {Guardfile::Generator#create_guardfile} instead.
14
- #
15
- # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
16
- # upgrade for Guard 2.0
17
- #
18
- def self.create_guardfile(options = {})
19
- # FIXME: used internally by Guard
20
- # TODO: reenable after majore refactoring is finished
21
- # UI.deprecation(Deprecator::CREATE_GUARDFILE_DEPRECATION)
22
- Generator.new(options).create_guardfile
23
- end
1
+ require "guard/config"
24
2
 
25
- # @deprecated Use {Guardfile::Generator#initialize_template} instead.
26
- #
27
- # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
28
- # upgrade for Guard 2.0
29
- #
30
- def self.initialize_template(plugin_name)
31
- # FIXME: used internally by Guard
32
- # TODO: reenable after majore refactoring is finished
33
- # UI.deprecation(Deprecator::INITIALIZE_TEMPLATE_DEPRECATION)
34
- Generator.new.initialize_template(plugin_name)
35
- end
3
+ if Guard::Config.new.strict?
4
+ abort "Error: Deprecated file #{__FILE__} is being used"
5
+ else
6
+ require "guard/deprecated/guardfile"
7
+
8
+ # TODO: deprecate this whole file
9
+
10
+ module Guard
11
+ unless Guard::Config.new.silence_deprecations?
12
+ UPGRADE_WIKI_URL =
13
+ "https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0"
14
+
15
+ STDERR.puts <<-EOS
16
+ (guard/guardfile.rb message)
17
+
18
+ You are including "guard/guardfile.rb", which has been deprecated
19
+ since 2013 ... and will be removed.
36
20
 
37
- # @deprecated Use {Guardfile::Generator#initialize_all_templates} instead.
38
- #
39
- # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
40
- # upgrade for Guard 2.0
41
- #
42
- def self.initialize_all_templates
43
- # FIXME: used internally by Guard
44
- # TODO: reenable after majore refactoring is finished
45
- # UI.deprecation(Deprecator::INITIALIZE_ALL_TEMPLATES_DEPRECATION)
46
- Generator.new.initialize_all_templates
21
+ Migration is easy, see: #{UPGRADE_WIKI_URL}
22
+
23
+ This file was included from:
24
+ #{caller[0..10] * "\n >"}
25
+
26
+ Sorry for the inconvenience and have a nice day!
27
+
28
+ (end of guard/guardfile.rb message)
29
+
30
+
31
+ EOS
32
+ end
33
+ module Guardfile
34
+ extend Deprecated::Guardfile::ClassMethods
47
35
  end
48
36
  end
49
37
  end
@@ -1,6 +1,13 @@
1
+ require "guard/config"
1
2
  require "guard/options"
2
3
  require "guard/plugin"
3
4
 
5
+ # TODO: this class shouldn't use notify directly
6
+ require "guard/notifier"
7
+
8
+ require "guard/dsl"
9
+ require "guard/metadata"
10
+
4
11
  module Guard
5
12
  module Guardfile
6
13
  # This class is responsible for evaluating the Guardfile. It delegates to
@@ -52,7 +59,7 @@ module Guard
52
59
  def evaluate_guardfile
53
60
  _fetch_guardfile_contents
54
61
  _instance_eval_guardfile(guardfile_contents)
55
- ::Guard.add_builtin_plugins(guardfile_path)
62
+ Guard.add_builtin_plugins(guardfile_path)
56
63
  end
57
64
 
58
65
  # Re-evaluates the `Guardfile` to update
@@ -211,20 +218,20 @@ module Guard
211
218
  # before the Guardfile will be re-evaluated.
212
219
  #
213
220
  def _before_reevaluate_guardfile
214
- ::Guard.runner.run(:stop)
221
+ Guard::Runner.new.run(:stop)
215
222
  ::Guard.reset_groups
216
223
  ::Guard.reset_plugins
217
224
  ::Guard.reset_scope
218
- ::Guard::Notifier.clear_notifiers
225
+ ::Guard::Notifier.disconnect
219
226
  end
220
227
 
221
228
  # Starts Guard and notification and show a message
222
229
  # after the Guardfile has been re-evaluated.
223
230
  #
224
231
  def _after_reevaluate_guardfile
225
- ::Guard::Notifier.turn_on if ::Guard::Notifier.enabled?
232
+ ::Guard::Notifier.connect(::Guard.options)
226
233
 
227
- if !::Guard.send(:_pluginless_guardfile?)
234
+ if ::Guard.send(:_pluginless_guardfile?)
228
235
  ::Guard::Notifier.notify(
229
236
  "No plugins found in Guardfile, please add at least one.",
230
237
  title: "Guard re-evaluate",
@@ -235,7 +242,7 @@ module Guard
235
242
  ::Guard::Notifier.notify(msg, title: "Guard re-evaluate")
236
243
 
237
244
  ::Guard.setup_scope
238
- ::Guard.runner.run(:start)
245
+ Guard::Runner.new.run(:start)
239
246
  end
240
247
  end
241
248
 
@@ -1,3 +1,6 @@
1
+ require "guard/ui"
2
+ require "guard/plugin_util"
3
+
1
4
  module Guard
2
5
  module Guardfile
3
6
  # This class is responsible for generating the Guardfile and adding Guard'
@@ -6,9 +9,6 @@ module Guard
6
9
  # @see Guard::CLI
7
10
  #
8
11
  class Generator
9
- require "guard"
10
- require "guard/ui"
11
-
12
12
  attr_reader :options
13
13
 
14
14
  # The Guardfile template for `guard init`
@@ -59,6 +59,7 @@ module Guard
59
59
  #
60
60
  def initialize_template(plugin_name)
61
61
  plugin_util = ::Guard::PluginUtil.new(plugin_name)
62
+ # TODO: change to "plugin_class?" method
62
63
  if plugin_util.plugin_class(fail_gracefully: true)
63
64
  plugin_util.add_to_guardfile
64
65
 
@@ -1,8 +1,5 @@
1
1
  require "guard/ui"
2
2
 
3
- require "guard/jobs/sleep"
4
- require "guard/jobs/pry_wrapper"
5
-
6
3
  module Guard
7
4
  class Interactor
8
5
  # Initializes the interactor. This configures
@@ -12,6 +9,10 @@ module Guard
12
9
  def initialize(no_interaction = false)
13
10
  @interactive = !no_interaction && self.class.enabled?
14
11
 
12
+ # TODO: only require the one used
13
+ require "guard/jobs/sleep"
14
+ require "guard/jobs/pry_wrapper"
15
+
15
16
  job_klass = interactive? ? Jobs::PryWrapper : Jobs::Sleep
16
17
  @idle_job = job_klass.new(self.class.options)
17
18
  end
@@ -34,6 +35,9 @@ module Guard
34
35
  idle_job.handle_interrupt
35
36
  end
36
37
 
38
+ # TODO: everything below is just so the DSL can set options
39
+ # before setup() is called, which makes it useless for when
40
+ # Guardfile is reevaluated
37
41
  class << self
38
42
  def options
39
43
  @options ||= {}
@@ -1,5 +1,6 @@
1
1
  # Because it's used by Sheller
2
2
  require "open3"
3
+ require "logger"
3
4
 
4
5
  require "guard/ui"
5
6
 
@@ -0,0 +1,93 @@
1
+ module Guard
2
+ # @private api
3
+ module Internals
4
+ class Environment
5
+ class Error < ArgumentError
6
+ end
7
+
8
+ class MethodError < Error
9
+ def initialize(meth)
10
+ @meth = meth
11
+ end
12
+ end
13
+
14
+ class NoMethodError < MethodError
15
+ def message
16
+ format("No such method %s", @meth.inspect)
17
+ end
18
+ end
19
+
20
+ class AlreadyExistsError < MethodError
21
+ def message
22
+ format("Method %s already exists", @meth.inspect)
23
+ end
24
+ end
25
+
26
+ class Loader
27
+ def initialize(meth)
28
+ @bool = meth.to_s.end_with?("?")
29
+ end
30
+
31
+ def load(raw_value, &callback)
32
+ return callback.call(raw_value) if callback
33
+ @bool ? _to_bool(raw_value) : raw_value
34
+ end
35
+
36
+ private
37
+
38
+ def _to_bool(raw_value)
39
+ case raw_value
40
+ when nil
41
+ nil
42
+ when ""
43
+ fail ArgumentError, "Can't convert empty string into Bool"
44
+ when "0", "false"
45
+ false
46
+ else
47
+ true
48
+ end
49
+ end
50
+ end
51
+
52
+ class Dumper
53
+ def initialize
54
+ end
55
+
56
+ def dump(raw_value, &callback)
57
+ return callback.call(raw_value) if callback
58
+ raw_value.nil? ? nil : raw_value.to_s
59
+ end
60
+ end
61
+
62
+ def initialize(namespace)
63
+ @namespace = namespace
64
+ @methods = {}
65
+ end
66
+
67
+ def create_method(meth, &block)
68
+ fail AlreadyExistsError, meth if @methods.key?(meth)
69
+ @methods[meth] = block
70
+ end
71
+
72
+ def method_missing(*args)
73
+ meth, raw_value = *args
74
+ fail NoMethodError, meth unless @methods.key?(meth)
75
+
76
+ callback = @methods[meth]
77
+ env_name = format("%s_%s", @namespace, _sanitize(meth))
78
+
79
+ if args.size == 2
80
+ ENV[env_name] = Dumper.new.dump(raw_value, &callback)
81
+ else
82
+ Loader.new(meth).load(ENV[env_name], &callback)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def _sanitize(meth)
89
+ meth[/^([^=?]*)[=?]?$/, 1].upcase
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,13 @@
1
+ module Guard
2
+ # @private api
3
+ module Internals
4
+ module Helpers
5
+ def _relative_pathname(path)
6
+ full_path = Pathname(path)
7
+ full_path.relative_path_from(Pathname.pwd)
8
+ rescue ArgumentError
9
+ full_path
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module Guard
2
+ module Internals
3
+ module Traps
4
+ def self.handle(signal, &block)
5
+ return unless Signal.list.key?(signal)
6
+ Signal.trap(signal, &block)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -5,6 +5,7 @@ require "guard/commands/pause"
5
5
  require "guard/commands/reload"
6
6
  require "guard/commands/scope"
7
7
  require "guard/commands/show"
8
+ require "guard/sheller"
8
9
 
9
10
  require "guard/jobs/base"
10
11
 
@@ -18,17 +19,17 @@ module Guard
18
19
 
19
20
  def restore
20
21
  return unless configurable? && @settings
21
- ::Guard::Sheller.run("stty #{ @setting } 2>#{ DEV_NULL }")
22
+ ::Guard::Sheller.run("stty #{ @setting } 2>#{IO::NULL}")
22
23
  end
23
24
 
24
25
  def save
25
26
  return unless configurable?
26
- @settings = ::Guard::Sheller.stdout("stty -g 2>#{ DEV_NULL }").chomp
27
+ @settings = ::Guard::Sheller.stdout("stty -g 2>#{IO::NULL}").chomp
27
28
  end
28
29
 
29
30
  def echo
30
31
  return unless configurable?
31
- ::Guard::Sheller.run("stty echo 2>#{ DEV_NULL }")
32
+ ::Guard::Sheller.run("stty echo 2>#{IO::NULL}")
32
33
  end
33
34
 
34
35
  def configurable?
@@ -1,9 +1,11 @@
1
1
  require "guard/jobs/base"
2
+ require "guard/ui"
2
3
 
3
4
  module Guard
4
5
  module Jobs
5
6
  class Sleep < Base
6
7
  def foreground
8
+ # TODO: cleanup the namespace
7
9
  ::Guard::UI.debug "Guards jobs done. Sleeping..."
8
10
  sleep
9
11
  ::Guard::UI.debug "Sleep interrupted by events."
@@ -0,0 +1,190 @@
1
+ require "guard/group"
2
+
3
+ require "guard/plugin_util"
4
+
5
+ # TODO: should not be necessary
6
+ require "guard/internals/helpers"
7
+
8
+ module Guard
9
+ extend Internals::Helpers
10
+
11
+ # TODO: change to a normal class
12
+ class << self
13
+ DEFAULT_GROUPS = [:common, :default]
14
+
15
+ DEFAULT_OPTIONS = {
16
+ clear: false,
17
+ notify: true,
18
+ debug: false,
19
+ group: [],
20
+ plugin: [],
21
+ watchdir: nil,
22
+ guardfile: nil,
23
+ no_interactions: false,
24
+ no_bundler_warning: false,
25
+ latency: nil,
26
+ force_polling: false,
27
+ wait_for_delay: nil,
28
+ listen_on: nil
29
+ }
30
+
31
+ def add_group(name, options = {})
32
+ unless (group = group(name))
33
+ group = Group.new(name, options)
34
+ @groups << group
35
+ end
36
+
37
+ group
38
+ end
39
+
40
+ def group(filter)
41
+ groups(filter).first
42
+ end
43
+
44
+ def groups(filter = nil)
45
+ @groups ||= []
46
+
47
+ return @groups if filter.nil?
48
+
49
+ case filter
50
+ when String, Symbol
51
+ @groups.select { |group| group.name == filter.to_sym }
52
+ when Regexp
53
+ @groups.select { |group| group.name.to_s =~ filter }
54
+ else
55
+ fail "Invalid filter: #{filter.inspect}"
56
+ end
57
+ end
58
+
59
+ # TODO: remove
60
+ def _reset_for_tests
61
+ @options = nil
62
+ @queue = nil
63
+ @watchdirs = nil
64
+ @watchdirs = nil
65
+ @listener = nil
66
+ @interactor = nil
67
+ @scope = nil
68
+ end
69
+
70
+ # TODO: remove
71
+ def clear_options
72
+ @options = nil
73
+ end
74
+
75
+ # TODO: remove
76
+ def reset_groups
77
+ @groups = DEFAULT_GROUPS.map { |name| Group.new(name) }
78
+ end
79
+
80
+ # TODO: remove
81
+ def reset_plugins
82
+ @plugins = []
83
+ end
84
+
85
+ def plugins(filter = nil)
86
+ @plugins ||= []
87
+
88
+ return @plugins if filter.nil?
89
+
90
+ filtered_plugins = case filter
91
+ when String, Symbol
92
+ @plugins.select do |plugin|
93
+ plugin.name == filter.to_s.downcase.gsub("-", "")
94
+ end
95
+ when Regexp
96
+ @plugins.select do |plugin|
97
+ plugin.name =~ filter
98
+ end
99
+ when Hash
100
+ @plugins.select do |plugin|
101
+ filter.all? do |k, v|
102
+ case k
103
+ when :name
104
+ plugin.name == v.to_s.downcase.gsub("-", "")
105
+ when :group
106
+ plugin.group.name == v.to_sym
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ filtered_plugins
113
+ end
114
+
115
+ def scope
116
+ fail "::Guard.setup() not called" if @scope.nil?
117
+ @scope.dup.freeze
118
+ end
119
+
120
+ def plugin(filter)
121
+ plugins(filter).first
122
+ end
123
+
124
+ # Used by runner to remove a failed plugin
125
+ def remove_plugin(plugin)
126
+ # TODO: coverage/aruba
127
+ @plugins.delete(plugin)
128
+ end
129
+
130
+ # TODO: move elsewhere
131
+ def add_builtin_plugins(guardfile)
132
+ return unless guardfile
133
+
134
+ pattern = _relative_pathname(guardfile).to_s
135
+ watcher = ::Guard::Watcher.new(pattern)
136
+ ::Guard.add_plugin(:reevaluator, watchers: [watcher], group: :common)
137
+ end
138
+
139
+ def add_plugin(name, options = {})
140
+ instance = ::Guard::PluginUtil.new(name).initialize_plugin(options)
141
+ @plugins << instance
142
+ instance
143
+ end
144
+
145
+ def reset_scope
146
+ # calls Guard.scope=() to set the instance variable directly, as opposed
147
+ # to Guard.scope()
148
+ ::Guard.scope = { groups: [], plugins: [] }
149
+ end
150
+
151
+ # Called by Pry scope command
152
+
153
+ def scope=(new_scope)
154
+ @scope = new_scope
155
+ @scope.dup.freeze
156
+ end
157
+
158
+ # Used to merge CLI options with Setuper defaults
159
+ def reset_options(new_options)
160
+ @options = ::Guard::Options.new(new_options, DEFAULT_OPTIONS)
161
+ end
162
+
163
+ def save_scope
164
+ # This actually replaces scope from command line,
165
+ # so scope set by 'scope' Pry command will be reset
166
+ @saved_scope = _prepare_scope(::Guard.scope)
167
+ end
168
+
169
+ def restore_scope
170
+ ::Guard.setup_scope(@saved_scope || {})
171
+ end
172
+
173
+ private
174
+
175
+ def _prepare_scope(new_scope)
176
+ fail "Guard::setup() not called!" if options.nil?
177
+ {
178
+ plugins: _scope_names(new_scope, :plugin),
179
+ groups: _scope_names(new_scope, :group)
180
+ }
181
+ end
182
+
183
+ def _scope_names(new_scope, name)
184
+ items = Array(options[name])
185
+ items = Array(new_scope[:"#{name}s"] || new_scope[name]) if items.empty?
186
+ # Convert objects to names
187
+ items.map { |p| p.respond_to?(:name) ? p.name : p }
188
+ end
189
+ end
190
+ end