guard 2.10.2 → 2.10.3

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,93 +0,0 @@
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
@@ -1,148 +0,0 @@
1
- require "guard/internals/plugins"
2
- require "guard/internals/groups"
3
-
4
- require "guard/options"
5
-
6
- module Guard
7
- # @private api
8
- module Internals
9
- # TODO: split into a commandline class and session (plugins, groups)
10
- # TODO: swap session and metadata
11
- # This class contains variables set during
12
- # evaluation of the guardfile (and are reset
13
- # before reevaluation)
14
- class Session
15
- attr_reader :options
16
- attr_reader :plugins
17
- attr_reader :groups
18
-
19
- DEFAULT_OPTIONS = {
20
- clear: false,
21
- debug: false,
22
- no_bundler_warning: false,
23
-
24
- # User defined scopes
25
- group: [],
26
- plugin: [],
27
-
28
- # Notifier
29
- notify: true,
30
-
31
- # Interactor
32
- no_interactions: false,
33
-
34
- # Guardfile options:
35
- # guardfile_contents
36
- guardfile: nil,
37
-
38
- # Listener options
39
- # TODO: rename to watchdirs?
40
- watchdir: Dir.pwd,
41
- latency: nil,
42
- force_polling: false,
43
- wait_for_delay: nil,
44
- listen_on: nil
45
- }
46
-
47
- def cmdline_groups
48
- @cmdline_groups.dup.freeze
49
- end
50
-
51
- def cmdline_plugins
52
- @cmdline_plugins.dup.freeze
53
- end
54
-
55
- def initialize(new_options)
56
- @options = Options.new(new_options, DEFAULT_OPTIONS)
57
-
58
- @plugins = Internals::Plugins.new
59
- @groups = Internals::Groups.new
60
-
61
- @cmdline_groups = @options[:group]
62
- @cmdline_plugins = @options[:plugin]
63
-
64
- @clear = @options[:clear]
65
- @debug = @options[:debug]
66
- @watchdirs = Array(@options[:watchdir])
67
- @notify = @options[:notify]
68
- @interactor_name = @options[:no_interactions] ? :sleep : :pry_wrapper
69
-
70
- @guardfile_plugin_scope = []
71
- @guardfile_group_scope = []
72
- end
73
-
74
- def guardfile_scope(scope)
75
- opts = scope.dup
76
- @guardfile_plugin_scope = Array(opts.delete(:plugins))
77
- @guardfile_group_scope = Array(opts.delete(:groups))
78
- fail "Unknown options: #{opts.inspect}" unless opts.empty?
79
- end
80
-
81
- attr_reader :guardfile_group_scope
82
- attr_reader :guardfile_plugin_scope
83
-
84
- def guardfile_ignore
85
- fail NotImplementedError
86
- end
87
-
88
- def guardfile_ignore_bang
89
- fail NotImplementedError
90
- end
91
-
92
- def clearing(on)
93
- @clear = on
94
- end
95
-
96
- def clearing?
97
- @clear
98
- end
99
-
100
- alias :clear? :clearing?
101
-
102
- def debug?
103
- @debug
104
- end
105
-
106
- def watchdirs
107
- @watchdirs_from_guardfile ||= nil
108
- @watchdirs_from_guardfile || @watchdirs
109
- end
110
-
111
- # set by Dsl with :directories() command
112
- def watchdirs=(dirs)
113
- dirs = [Dir.pwd] if dirs.empty?
114
- @watchdirs_from_guardfile = dirs.map { |dir| File.expand_path dir }
115
- end
116
-
117
- def listener_args
118
- if options[:listen_on]
119
- [:on, options[:listen_on]]
120
- else
121
- listener_options = {}
122
- [:latency, :force_polling, :wait_for_delay].each do |option|
123
- listener_options[option] = options[option] if options[option]
124
- end
125
- expanded_watchdirs = watchdirs.map { |dir| File.expand_path dir }
126
- [:to, *expanded_watchdirs, listener_options]
127
- end
128
- end
129
-
130
- def evaluator_options
131
- opts = { guardfile: options[:guardfile] }
132
- # TODO: deprecate :guardfile_contents
133
- if options[:guardfile_contents]
134
- opts[:contents] = options[:guardfile_contents]
135
- end
136
- opts
137
- end
138
-
139
- def notify_options
140
- { notify: @options[:notify] }
141
- end
142
-
143
- def interactor_name
144
- @interactor_name
145
- end
146
- end
147
- end
148
- end
@@ -1,182 +0,0 @@
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
- valid = Gem::Specification.find_all.select do |gem|
26
- _gem_valid?(gem)
27
- end
28
-
29
- valid.map { |x| x.name.sub(/^guard-/, "") }.uniq
30
- end
31
-
32
- # Initializes a new `Guard::PluginUtil` object.
33
- #
34
- # @param [String] name the name of the Guard plugin
35
- #
36
- def initialize(name)
37
- @name = name.to_s.sub(/^guard-/, "")
38
- end
39
-
40
- # Initializes a new `Guard::Plugin` with the given `options` hash. This
41
- # methods handles plugins that inherit from the deprecated `Guard::Guard`
42
- # class as well as plugins that inherit from `Guard::Plugin`.
43
- #
44
- # @see Guard::Plugin
45
- # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
46
- # upgrade for Guard 2.0
47
- #
48
- # @return [Guard::Plugin] the initialized plugin
49
- # @return [Guard::Guard] the initialized plugin. This return type is
50
- # deprecated and the plugin's maintainer should update it to be
51
- # compatible with Guard 2.0. For more information on how to upgrade for
52
- # Guard 2.0, please head over to:
53
- # https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
54
- #
55
- def initialize_plugin(options)
56
- klass = plugin_class
57
- fail "Could not load class: #{_constant_name.inspect}" unless klass
58
- if klass.superclass.to_s == "Guard::Guard"
59
- klass.new(options.delete(:watchers), options)
60
- else
61
- begin
62
- klass.new(options)
63
- rescue ArgumentError => e
64
- fail "Failed to call #{klass}.new(options): #{e}"
65
- end
66
- end
67
- end
68
-
69
- # Locates a path to a Guard plugin gem.
70
- #
71
- # @return [String] the full path to the plugin gem
72
- #
73
- def plugin_location
74
- @plugin_location ||= _full_gem_path("guard-#{name}")
75
- rescue Gem::LoadError
76
- ::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
77
- end
78
-
79
- # Tries to load the Guard plugin main class. This transforms the supplied
80
- # plugin name into a class name:
81
- #
82
- # * `guardname` will become `Guard::Guardname`
83
- # * `dashed-guard-name` will become `Guard::DashedGuardName`
84
- # * `underscore_guard_name` will become `Guard::UnderscoreGuardName`
85
- #
86
- # When no class is found with the strict case sensitive rules, another
87
- # try is made to locate the class without matching case:
88
- #
89
- # * `rspec` will find a class `Guard::RSpec`
90
- #
91
- # @option options [Boolean] fail_gracefully whether error messages should
92
- # not be printed
93
- #
94
- # @return [Class, nil] the loaded class
95
- #
96
- def plugin_class(options = {})
97
- options = { fail_gracefully: false }.merge(options)
98
-
99
- const = _plugin_constant
100
- fail TypeError, "no constant: #{_constant_name}" unless const
101
- @plugin_class ||= Guard.const_get(const)
102
-
103
- rescue TypeError
104
- begin
105
- require "guard/#{ name.downcase }"
106
- const = _plugin_constant
107
- @plugin_class ||= Guard.const_get(const)
108
-
109
- rescue TypeError => error
110
- UI.error "Could not find class Guard::#{ _constant_name }"
111
- UI.error error.backtrace.join("\n")
112
- rescue LoadError => error
113
- unless options[:fail_gracefully]
114
- UI.error ERROR_NO_GUARD_OR_CLASS % [name.downcase, _constant_name]
115
- UI.error "Error is: #{error}"
116
- UI.error error.backtrace.join("\n")
117
- end
118
- end
119
- end
120
-
121
- # Adds a plugin's template to the Guardfile.
122
- #
123
- def add_to_guardfile
124
- klass = plugin_class # call here to avoid failing later
125
-
126
- require "guard/guardfile/evaluator"
127
- # TODO: move this to Generator?
128
- options = Guard.state.session.evaluator_options
129
- evaluator = Guardfile::Evaluator.new(options)
130
- evaluator.evaluate
131
- if evaluator.guardfile_include?(name)
132
- UI.info "Guardfile already includes #{ name } guard"
133
- else
134
- content = File.read("Guardfile")
135
- File.open("Guardfile", "wb") do |f|
136
- f.puts(content)
137
- f.puts("")
138
- f.puts(klass.template(plugin_location))
139
- end
140
-
141
- UI.info INFO_ADDED_GUARD_TO_GUARDFILE % name
142
- end
143
- end
144
-
145
- private
146
-
147
- # Returns the constant for the current plugin.
148
- #
149
- # @example Returns the constant for a plugin
150
- # > Guard::PluginUtil.new('rspec').send(:_plugin_constant)
151
- # => Guard::RSpec
152
- #
153
- def _plugin_constant
154
- @_plugin_constant ||= Guard.constants.detect do |c|
155
- c.to_s.downcase == _constant_name.downcase
156
- end
157
- end
158
-
159
- # Guesses the most probable name for the current plugin based on its name.
160
- #
161
- # @example Returns the most probable name for a plugin
162
- # > Guard::PluginUtil.new('rspec').send(:_constant_name)
163
- # => "Rspec"
164
- #
165
- def _constant_name
166
- @_constant_name ||= name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.
167
- gsub(/(?:^|[_-])(.)/) { $1.upcase }
168
- end
169
-
170
- def self._gem_valid?(gem)
171
- return false if gem.name == 'guard-compat'
172
- return true if gem.name =~ /^guard-/
173
- full_path = gem.full_gem_path
174
- file = File.join(full_path, "lib", "guard", "#{gem.name}.rb")
175
- File.exist?(file)
176
- end
177
-
178
- def _full_gem_path(name)
179
- Gem::Specification.find_by_name(name).full_gem_path
180
- end
181
- end
182
- end
@@ -1,61 +0,0 @@
1
- require "guard/plugin"
2
- require "guard/guardfile/evaluator"
3
- require "guard/runner"
4
- require "guard/internals/helpers"
5
-
6
- module Guard
7
- class Reevaluator < Plugin
8
- include Internals::Helpers
9
-
10
- def run_on_modifications(files)
11
- # TODO: this is messed up, because reevaluator adds itself
12
- # anyway, so it know what the path is
13
- evaluator = _evaluator
14
- path = evaluator.path
15
- return unless files.any? { |file| path == Pathname(file) }
16
- reevaluate
17
- rescue Dsl::Error, Guardfile::Evaluator::Error => e
18
- UI.warning("Failed to reevaluate file: #{e}")
19
- _add_self_to_plugins
20
- throw :task_has_failed
21
- end
22
-
23
- def reevaluate
24
- evaluator = _evaluator
25
- return if evaluator.inline?
26
-
27
- Runner.new.run(:stop)
28
-
29
- Guard.state.reset_session
30
-
31
- Notifier.disconnect
32
- evaluator.evaluate
33
- Notifier.connect(Guard.state.session.notify_options)
34
-
35
- if Guard.send(:_pluginless_guardfile?)
36
- Notifier.notify(
37
- "No plugins found in Guardfile, please add at least one.",
38
- title: "Guard re-evaluate",
39
- image: :failed)
40
- else
41
- msg = "Guardfile has been re-evaluated."
42
- UI.info(msg)
43
- Notifier.notify(msg, title: "Guard re-evaluate")
44
- Runner.new.run(:start)
45
- end
46
- end
47
-
48
- private
49
-
50
- def _evaluator
51
- Guardfile::Evaluator.new(Guard.state.session.evaluator_options)
52
- end
53
-
54
- def _add_self_to_plugins
55
- # TODO: do this on reload as well
56
- pattern = _relative_pathname(_evaluator.path).to_s
57
- options = { watchers: [Watcher.new(pattern)], group: :common }
58
- Guard.state.session.plugins.add(:reevaluator, options)
59
- end
60
- end
61
- end