guard 2.8.2 → 2.9.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 (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