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.
- checksums.yaml +4 -4
- data/lib/guard.rb +29 -29
- data/lib/guard/cli.rb +11 -78
- data/lib/guard/cli/environments/bundler.rb +22 -0
- data/lib/guard/cli/environments/evaluate_only.rb +35 -0
- data/lib/guard/cli/environments/valid.rb +59 -0
- data/lib/guard/commander.rb +7 -9
- data/lib/guard/commands/all.rb +1 -2
- data/lib/guard/commands/reload.rb +1 -2
- data/lib/guard/commands/scope.rb +1 -1
- data/lib/guard/config.rb +10 -16
- data/lib/guard/deprecated/evaluator.rb +4 -1
- data/lib/guard/deprecated/guard.rb +92 -2
- data/lib/guard/dsl_describer.rb +2 -0
- data/lib/guard/guardfile/evaluator.rb +1 -2
- data/lib/guard/interactor.rb +0 -29
- data/lib/guard/internals/plugins.rb +2 -0
- data/lib/guard/internals/scope.rb +5 -1
- data/lib/guard/internals/session.rb +25 -6
- data/lib/guard/internals/state.rb +9 -4
- data/lib/guard/notifier.rb +10 -12
- data/lib/guard/notifier/detected.rb +9 -5
- data/lib/guard/plugin.rb +3 -0
- data/lib/guard/templates/Guardfile +23 -1
- data/lib/guard/ui.rb +0 -7
- data/lib/guard/version.rb +1 -1
- data/lib/guard/watcher.rb +2 -2
- metadata +19 -11
- data/lib/guard.rb.orig +0 -174
- data/lib/guard/compat/test/helper.rb.orig +0 -0
- data/lib/guard/dsl.rb.orig +0 -432
- data/lib/guard/internals/environment.rb +0 -93
- data/lib/guard/internals/session.rb.orig +0 -148
- data/lib/guard/plugin_util.rb.orig +0 -182
- data/lib/guard/reevaluator.rb +0 -61
- data/lib/guard/ui.rb.orig +0 -268
- data/lib/guard/version.rb.orig +0 -3
data/lib/guard/plugin.rb
CHANGED
@@ -2,7 +2,29 @@
|
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
3
3
|
|
4
4
|
## Uncomment and set this to only include directories you want to watch
|
5
|
-
# directories %(app lib config test spec feature)
|
5
|
+
# directories %w(app lib config test spec feature)
|
6
6
|
|
7
7
|
## Uncomment to clear the screen before every task
|
8
8
|
# clearing :on
|
9
|
+
|
10
|
+
## Make Guard exit when config is changed so it can be restarted
|
11
|
+
#
|
12
|
+
## Note: if you want Guard to automatically start up again, run guard in a
|
13
|
+
## shell loop, e.g.:
|
14
|
+
#
|
15
|
+
# $ while bundle exec guard; do echo "Restarting Guard..."; done
|
16
|
+
#
|
17
|
+
## Note: if you are using the `directories` clause above and you are not
|
18
|
+
## watching the project directory ('.'), the you will want to move the Guardfile
|
19
|
+
## to a watched dir and symlink it back, e.g.
|
20
|
+
#
|
21
|
+
# $ mkdir config
|
22
|
+
# $ mv Guardfile config/
|
23
|
+
# $ ln -s config/Guardfile .
|
24
|
+
#
|
25
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
26
|
+
#
|
27
|
+
watch ("Guardfile") do
|
28
|
+
UI.info "Exiting because Guard must be restarted for changes to take effect"
|
29
|
+
exit 0
|
30
|
+
end
|
data/lib/guard/ui.rb
CHANGED
data/lib/guard/version.rb
CHANGED
data/lib/guard/watcher.rb
CHANGED
@@ -106,8 +106,8 @@ module Guard
|
|
106
106
|
def call_action(matches)
|
107
107
|
@action.arity > 0 ? @action.call(matches) : @action.call
|
108
108
|
rescue => ex
|
109
|
-
|
110
|
-
|
109
|
+
UI.error "Problem with watch action!\n#{ ex.message }"
|
110
|
+
UI.error ex.backtrace.join("\n")
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.10.
|
4
|
+
version: 2.10.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibaud Guillaume-Gentil
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 0.2.4
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: nenv
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.1'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.1'
|
83
97
|
description: Guard is a command line tool to easily handle events on file system modifications.
|
84
98
|
email:
|
85
99
|
- thibaud@thibaud.gg
|
@@ -97,9 +111,11 @@ files:
|
|
97
111
|
- images/pending.png
|
98
112
|
- images/success.png
|
99
113
|
- lib/guard.rb
|
100
|
-
- lib/guard.rb.orig
|
101
114
|
- lib/guard/aruba_adapter.rb
|
102
115
|
- lib/guard/cli.rb
|
116
|
+
- lib/guard/cli/environments/bundler.rb
|
117
|
+
- lib/guard/cli/environments/evaluate_only.rb
|
118
|
+
- lib/guard/cli/environments/valid.rb
|
103
119
|
- lib/guard/commander.rb
|
104
120
|
- lib/guard/commands/all.rb
|
105
121
|
- lib/guard/commands/change.rb
|
@@ -108,7 +124,6 @@ files:
|
|
108
124
|
- lib/guard/commands/reload.rb
|
109
125
|
- lib/guard/commands/scope.rb
|
110
126
|
- lib/guard/commands/show.rb
|
111
|
-
- lib/guard/compat/test/helper.rb.orig
|
112
127
|
- lib/guard/config.rb
|
113
128
|
- lib/guard/deprecated/dsl.rb
|
114
129
|
- lib/guard/deprecated/evaluator.rb
|
@@ -116,7 +131,6 @@ files:
|
|
116
131
|
- lib/guard/deprecated/guardfile.rb
|
117
132
|
- lib/guard/deprecated/watcher.rb
|
118
133
|
- lib/guard/dsl.rb
|
119
|
-
- lib/guard/dsl.rb.orig
|
120
134
|
- lib/guard/dsl_describer.rb
|
121
135
|
- lib/guard/group.rb
|
122
136
|
- lib/guard/guardfile.rb
|
@@ -124,14 +138,12 @@ files:
|
|
124
138
|
- lib/guard/guardfile/generator.rb
|
125
139
|
- lib/guard/interactor.rb
|
126
140
|
- lib/guard/internals/debugging.rb
|
127
|
-
- lib/guard/internals/environment.rb
|
128
141
|
- lib/guard/internals/groups.rb
|
129
142
|
- lib/guard/internals/helpers.rb
|
130
143
|
- lib/guard/internals/plugins.rb
|
131
144
|
- lib/guard/internals/queue.rb
|
132
145
|
- lib/guard/internals/scope.rb
|
133
146
|
- lib/guard/internals/session.rb
|
134
|
-
- lib/guard/internals/session.rb.orig
|
135
147
|
- lib/guard/internals/state.rb
|
136
148
|
- lib/guard/internals/tracing.rb
|
137
149
|
- lib/guard/internals/traps.rb
|
@@ -154,18 +166,14 @@ files:
|
|
154
166
|
- lib/guard/options.rb
|
155
167
|
- lib/guard/plugin.rb
|
156
168
|
- lib/guard/plugin_util.rb
|
157
|
-
- lib/guard/plugin_util.rb.orig
|
158
169
|
- lib/guard/rake_task.rb
|
159
|
-
- lib/guard/reevaluator.rb
|
160
170
|
- lib/guard/runner.rb
|
161
171
|
- lib/guard/sheller.rb
|
162
172
|
- lib/guard/templates/Guardfile
|
163
173
|
- lib/guard/terminal.rb
|
164
174
|
- lib/guard/ui.rb
|
165
|
-
- lib/guard/ui.rb.orig
|
166
175
|
- lib/guard/ui/colors.rb
|
167
176
|
- lib/guard/version.rb
|
168
|
-
- lib/guard/version.rb.orig
|
169
177
|
- lib/guard/watcher.rb
|
170
178
|
- man/guard.1
|
171
179
|
- man/guard.1.html
|
data/lib/guard.rb.orig
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
require "thread"
|
2
|
-
require "listen"
|
3
|
-
|
4
|
-
require "guard/config"
|
5
|
-
require "guard/deprecated/guard" unless Guard::Config.new.strict?
|
6
|
-
|
7
|
-
require "guard/internals/debugging"
|
8
|
-
require "guard/internals/traps"
|
9
|
-
require "guard/internals/helpers"
|
10
|
-
|
11
|
-
require "guard/internals/queue"
|
12
|
-
require "guard/internals/state"
|
13
|
-
|
14
|
-
require "guard/options"
|
15
|
-
require "guard/commander"
|
16
|
-
require "guard/dsl"
|
17
|
-
require "guard/group"
|
18
|
-
require "guard/interactor"
|
19
|
-
require "guard/notifier"
|
20
|
-
require "guard/plugin_util"
|
21
|
-
require "guard/runner"
|
22
|
-
require "guard/sheller"
|
23
|
-
require "guard/ui"
|
24
|
-
require "guard/watcher"
|
25
|
-
require "guard/guardfile/evaluator"
|
26
|
-
|
27
|
-
# Guard is the main module for all Guard related modules and classes.
|
28
|
-
# Also Guard plugins should use this namespace.
|
29
|
-
#
|
30
|
-
module Guard
|
31
|
-
Deprecated::Guard.add_deprecated(self) unless Config.new.strict?
|
32
|
-
|
33
|
-
class << self
|
34
|
-
attr_reader :listener
|
35
|
-
|
36
|
-
# @private api
|
37
|
-
attr_reader :queue
|
38
|
-
|
39
|
-
include Internals::Helpers
|
40
|
-
|
41
|
-
# Initializes the Guard singleton:
|
42
|
-
#
|
43
|
-
# * Initialize the internal Guard state;
|
44
|
-
# * Create the interactor
|
45
|
-
# * Select and initialize the file change listener.
|
46
|
-
#
|
47
|
-
# @option options [Boolean] clear if auto clear the UI should be done
|
48
|
-
# @option options [Boolean] notify if system notifications should be shown
|
49
|
-
# @option options [Boolean] debug if debug output should be shown
|
50
|
-
# @option options [Array<String>] group the list of groups to start
|
51
|
-
# @option options [Array<String>] watchdir the directories to watch
|
52
|
-
# @option options [String] guardfile the path to the Guardfile
|
53
|
-
#
|
54
|
-
# @return [Guard] the Guard singleton
|
55
|
-
def setup(cmdline_options = {})
|
56
|
-
init(cmdline_options)
|
57
|
-
|
58
|
-
@queue = Internals::Queue.new(Guard)
|
59
|
-
|
60
|
-
_evaluate(state.session.evaluator_options)
|
61
|
-
|
62
|
-
# NOTE: this should be *after* evaluate so :directories can work
|
63
|
-
# TODO: move listener setup to session?
|
64
|
-
@listener = Listen.send(*state.session.listener_args, &_listener_callback)
|
65
|
-
|
66
|
-
ignores = state.session.guardfile_ignore
|
67
|
-
@listener.ignore(ignores) unless ignores.empty?
|
68
|
-
|
69
|
-
ignores = state.session.guardfile_ignore_bang
|
70
|
-
@listener.ignore!(ignores) unless ignores.empty?
|
71
|
-
|
72
|
-
Notifier.connect(state.session.notify_options)
|
73
|
-
|
74
|
-
traps = Internals::Traps
|
75
|
-
traps.handle("USR1") { async_queue_add([:guard_pause, :paused]) }
|
76
|
-
traps.handle("USR2") { async_queue_add([:guard_pause, :unpaused]) }
|
77
|
-
|
78
|
-
@interactor = Interactor.new(state.session.interactor_name == :sleep)
|
79
|
-
traps.handle("INT") { @interactor.handle_interrupt }
|
80
|
-
|
81
|
-
self
|
82
|
-
end
|
83
|
-
|
84
|
-
def init(cmdline_options)
|
85
|
-
@state = Internals::State.new(cmdline_options)
|
86
|
-
end
|
87
|
-
|
88
|
-
attr_reader :state
|
89
|
-
|
90
|
-
attr_reader :interactor
|
91
|
-
|
92
|
-
# Asynchronously trigger changes
|
93
|
-
#
|
94
|
-
# Currently supported args:
|
95
|
-
#
|
96
|
-
# @example Old style hash:
|
97
|
-
# async_queue_add(modified: ['foo'], added: ['bar'], removed: [])
|
98
|
-
#
|
99
|
-
# @example New style signals with args:
|
100
|
-
# async_queue_add([:guard_pause, :unpaused ])
|
101
|
-
#
|
102
|
-
def async_queue_add(changes)
|
103
|
-
@queue << changes
|
104
|
-
|
105
|
-
# Putting interactor in background puts guard into foreground
|
106
|
-
# so it can handle change notifications
|
107
|
-
Thread.new { interactor.background }
|
108
|
-
end
|
109
|
-
|
110
|
-
private
|
111
|
-
|
112
|
-
# Check if any of the changes are actually watched for
|
113
|
-
# TODO: why iterate twice? reuse this info when running tasks
|
114
|
-
def _relevant_changes?(changes)
|
115
|
-
# TODO: no coverage!
|
116
|
-
files = changes.values.flatten(1)
|
117
|
-
scope = Guard.state.scope
|
118
|
-
watchers = scope.grouped_plugins.map do |_group, plugins|
|
119
|
-
plugins.map(&:watchers).flatten
|
120
|
-
end.flatten
|
121
|
-
watchers.any? { |watcher| files.any? { |file| watcher.match(file) } }
|
122
|
-
end
|
123
|
-
|
124
|
-
def _relative_pathnames(paths)
|
125
|
-
paths.map { |path| _relative_pathname(path) }
|
126
|
-
end
|
127
|
-
|
128
|
-
def _listener_callback
|
129
|
-
lambda do |modified, added, removed|
|
130
|
-
relative_paths = {
|
131
|
-
modified: _relative_pathnames(modified),
|
132
|
-
added: _relative_pathnames(added),
|
133
|
-
removed: _relative_pathnames(removed)
|
134
|
-
}
|
135
|
-
|
136
|
-
async_queue_add(relative_paths) if _relevant_changes?(relative_paths)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# TODO: obsoleted? (move to Dsl?)
|
141
|
-
def _pluginless_guardfile?
|
142
|
-
# no Reevaluator means there was no Guardfile configured that could be
|
143
|
-
# reevaluated, so we don't have a pluginless guardfile, because we don't
|
144
|
-
# have a Guardfile to begin with...
|
145
|
-
#
|
146
|
-
# But, if we have a Guardfile, we'll at least have the built-in
|
147
|
-
# Reevaluator, so the following will work:
|
148
|
-
|
149
|
-
plugins = state.session.plugins.all
|
150
|
-
plugins.empty? || plugins.map(&:name) == ["reevaluator"]
|
151
|
-
end
|
152
|
-
|
153
|
-
def _evaluate(options)
|
154
|
-
evaluator = Guardfile::Evaluator.new(options)
|
155
|
-
evaluator.evaluate
|
156
|
-
|
157
|
-
# TODO: remove this workaround when options are removed
|
158
|
-
state.session.clearing(state.session.options[:clear])
|
159
|
-
|
160
|
-
UI.reset_and_clear
|
161
|
-
|
162
|
-
msg = "No plugins found in Guardfile, please add at least one."
|
163
|
-
UI.error msg if _pluginless_guardfile?
|
164
|
-
|
165
|
-
if evaluator.inline?
|
166
|
-
UI.info("Using inline Guardfile.")
|
167
|
-
elsif evaluator.custom?
|
168
|
-
UI.info("Using Guardfile at #{ evaluator.path }.")
|
169
|
-
end
|
170
|
-
rescue Guardfile::Evaluator::NoPluginsError => e
|
171
|
-
UI.error(e.message)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
File without changes
|
data/lib/guard/dsl.rb.orig
DELETED
@@ -1,432 +0,0 @@
|
|
1
|
-
require "guard/guardfile/evaluator"
|
2
|
-
require "guard/interactor"
|
3
|
-
require "guard/notifier"
|
4
|
-
require "guard/ui"
|
5
|
-
require "guard/watcher"
|
6
|
-
|
7
|
-
require "guard/deprecated/dsl" unless Guard::Config.new.strict?
|
8
|
-
|
9
|
-
# TODO: only for listener
|
10
|
-
require "guard"
|
11
|
-
|
12
|
-
module Guard
|
13
|
-
# The Dsl class provides the methods that are used in each `Guardfile` to
|
14
|
-
# describe the behaviour of Guard.
|
15
|
-
#
|
16
|
-
# The main keywords of the DSL are {#guard} and {#watch}. These are necessary
|
17
|
-
# to define the used Guard plugins and the file changes they are watching.
|
18
|
-
#
|
19
|
-
# You can optionally group the Guard plugins with the {#group} keyword and
|
20
|
-
# ignore and filter certain paths with the {#ignore} and {#filter} keywords.
|
21
|
-
#
|
22
|
-
# You can set your preferred system notification library with {#notification}
|
23
|
-
# and pass some optional configuration options for the library. If you don't
|
24
|
-
# configure a library, Guard will automatically pick one with default options
|
25
|
-
# (if you don't want notifications, specify `:off` as library). Please see
|
26
|
-
# {Notifier} for more information about the supported libraries.
|
27
|
-
#
|
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#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
|
-
# Guard plugins method.
|
34
|
-
# You can even insert more hooks inside these methods. Please [checkout the
|
35
|
-
# Wiki page](https://github.com/guard/guard/wiki/Hooks-and-callbacks) for
|
36
|
-
# more details.
|
37
|
-
#
|
38
|
-
# The DSL will also evaluate normal Ruby code.
|
39
|
-
#
|
40
|
-
# There are two possible locations for the `Guardfile`:
|
41
|
-
#
|
42
|
-
# * The `Guardfile` in the current directory where Guard has been started
|
43
|
-
# * The `.Guardfile` in your home directory.
|
44
|
-
#
|
45
|
-
# In addition, if a user configuration `.guard.rb` in your home directory is
|
46
|
-
# found, it will be appended to the current project `Guardfile`.
|
47
|
-
#
|
48
|
-
# @see https://github.com/guard/guard/wiki/Guardfile-examples
|
49
|
-
#
|
50
|
-
class Dsl
|
51
|
-
Deprecated::Dsl.add_deprecated(self) unless Config.new.strict?
|
52
|
-
|
53
|
-
# Wrap exceptions during parsing Guardfile
|
54
|
-
class Error < RuntimeError
|
55
|
-
end
|
56
|
-
|
57
|
-
WARN_INVALID_LOG_LEVEL = "Invalid log level `%s` ignored. "\
|
58
|
-
"Please use either :debug, :info, :warn or :error."
|
59
|
-
|
60
|
-
WARN_INVALID_LOG_OPTIONS = "You cannot specify the logger options"\
|
61
|
-
" :only and :except at the same time."
|
62
|
-
|
63
|
-
# Set notification options for the system notifications.
|
64
|
-
# You can set multiple notifications, which allows you to show local
|
65
|
-
# system notifications and remote notifications with separate libraries.
|
66
|
-
# You can also pass `:off` as library to turn off notifications.
|
67
|
-
#
|
68
|
-
# @example Define multiple notifications
|
69
|
-
# notification :ruby_gntp
|
70
|
-
# notification :ruby_gntp, host: '192.168.1.5'
|
71
|
-
#
|
72
|
-
# @param [Symbol, String] notifier the name of the notifier to use
|
73
|
-
# @param [Hash] options the notification library options
|
74
|
-
#
|
75
|
-
# @see Guard::Notifier for available notifier and its options.
|
76
|
-
#
|
77
|
-
def notification(notifier, options = {})
|
78
|
-
Notifier.add(notifier.to_sym, options.merge(silent: false))
|
79
|
-
end
|
80
|
-
|
81
|
-
# Sets the interactor options or disable the interactor.
|
82
|
-
#
|
83
|
-
# @example Pass options to the interactor
|
84
|
-
# interactor option1: 'value1', option2: 'value2'
|
85
|
-
#
|
86
|
-
# @example Turn off interactions
|
87
|
-
# interactor :off
|
88
|
-
#
|
89
|
-
# @param [Symbol, Hash] options either `:off` or a Hash with interactor
|
90
|
-
# options
|
91
|
-
#
|
92
|
-
def interactor(options)
|
93
|
-
case options
|
94
|
-
when :off
|
95
|
-
Interactor.enabled = false
|
96
|
-
when Hash
|
97
|
-
Interactor.options = options
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# Declares a group of Guard plugins to be run with `guard start --group
|
102
|
-
# group_name`.
|
103
|
-
#
|
104
|
-
# @example Declare two groups of Guard plugins
|
105
|
-
# group :backend do
|
106
|
-
# guard :spork
|
107
|
-
# guard :rspec
|
108
|
-
# end
|
109
|
-
#
|
110
|
-
# group :frontend do
|
111
|
-
# guard :passenger
|
112
|
-
# guard :livereload
|
113
|
-
# end
|
114
|
-
#
|
115
|
-
# @param [Symbol, String, Array<Symbol, String>] name the group name called
|
116
|
-
# from the CLI
|
117
|
-
# @param [Hash] options the options accepted by the group
|
118
|
-
# @yield a block where you can declare several Guard plugins
|
119
|
-
#
|
120
|
-
# @see Group
|
121
|
-
# @see Guard.add_group
|
122
|
-
# @see #guard
|
123
|
-
#
|
124
|
-
def group(*args)
|
125
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
126
|
-
groups = args
|
127
|
-
|
128
|
-
groups.each do |group|
|
129
|
-
next unless group.to_sym == :all
|
130
|
-
fail ArgumentError, "'all' is not an allowed group name!"
|
131
|
-
end
|
132
|
-
|
133
|
-
if block_given?
|
134
|
-
groups.each do |group|
|
135
|
-
Guard.state.session.groups.add(group, options)
|
136
|
-
end
|
137
|
-
|
138
|
-
@current_groups ||= []
|
139
|
-
@current_groups.push(groups)
|
140
|
-
|
141
|
-
yield
|
142
|
-
|
143
|
-
@current_groups.pop
|
144
|
-
else
|
145
|
-
UI.error \
|
146
|
-
"No Guard plugins found in the group '#{ groups.join(", ") }',"\
|
147
|
-
" please add at least one."
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# Declares a Guard plugin to be used when running `guard start`.
|
152
|
-
#
|
153
|
-
# The name parameter is usually the name of the gem without
|
154
|
-
# the 'guard-' prefix.
|
155
|
-
#
|
156
|
-
# The available options are different for each Guard implementation.
|
157
|
-
#
|
158
|
-
# @example Declare a Guard without `watch` patterns
|
159
|
-
# guard :rspec
|
160
|
-
#
|
161
|
-
# @example Declare a Guard with a `watch` pattern
|
162
|
-
# guard :rspec do
|
163
|
-
# watch %r{.*_spec.rb}
|
164
|
-
# end
|
165
|
-
#
|
166
|
-
# @param [String] name the Guard plugin name
|
167
|
-
# @param [Hash] options the options accepted by the Guard plugin
|
168
|
-
# @yield a block where you can declare several watch patterns and actions
|
169
|
-
#
|
170
|
-
# @see Plugin
|
171
|
-
# @see Guard.add_plugin
|
172
|
-
# @see #watch
|
173
|
-
# @see #group
|
174
|
-
#
|
175
|
-
def guard(name, options = {})
|
176
|
-
@plugin_options = options.merge(watchers: [], callbacks: [])
|
177
|
-
|
178
|
-
yield if block_given?
|
179
|
-
|
180
|
-
@current_groups ||= []
|
181
|
-
groups = @current_groups && @current_groups.last || [:default]
|
182
|
-
groups.each do |group|
|
183
|
-
opts = @plugin_options.merge(group: group)
|
184
|
-
Guard.state.session.plugins.add(name, opts)
|
185
|
-
end
|
186
|
-
|
187
|
-
@plugin_options = nil
|
188
|
-
end
|
189
|
-
|
190
|
-
# Defines a pattern to be watched in order to run actions on file
|
191
|
-
# modification.
|
192
|
-
#
|
193
|
-
# @example Declare watchers for a Guard
|
194
|
-
# guard :rspec do
|
195
|
-
# watch('spec/spec_helper.rb')
|
196
|
-
# watch(%r{^.+_spec.rb})
|
197
|
-
# watch(%r{^app/controllers/(.+).rb}) do |m|
|
198
|
-
# 'spec/acceptance/#{m[1]}s_spec.rb'
|
199
|
-
# end
|
200
|
-
# end
|
201
|
-
#
|
202
|
-
# @example Declare global watchers outside of a Guard
|
203
|
-
# watch(%r{^(.+)$}) { |m| puts "#{m[1]} changed." }
|
204
|
-
#
|
205
|
-
# @param [String, Regexp] pattern the pattern that Guard must watch for
|
206
|
-
# modification
|
207
|
-
#
|
208
|
-
# @yield a block to be run when the pattern is matched
|
209
|
-
# @yieldparam [MatchData] m matches of the pattern
|
210
|
-
# @yieldreturn a directory, a filename, an array of
|
211
|
-
# directories / filenames, or nothing (can be an arbitrary command)
|
212
|
-
#
|
213
|
-
# @see Guard::Watcher
|
214
|
-
# @see #guard
|
215
|
-
#
|
216
|
-
def watch(pattern, &action)
|
217
|
-
# Allow watches in the global scope (to execute arbitrary commands) by
|
218
|
-
# building a generic Guard::Plugin.
|
219
|
-
@plugin_options ||= nil
|
220
|
-
return guard(:plugin) { watch(pattern, &action) } unless @plugin_options
|
221
|
-
|
222
|
-
@plugin_options[:watchers] << Watcher.new(pattern, action)
|
223
|
-
end
|
224
|
-
|
225
|
-
# Defines a callback to execute arbitrary code before or after any of
|
226
|
-
# the `start`, `stop`, `reload`, `run_all`, `run_on_changes`,
|
227
|
-
# `run_on_additions`, `run_on_modifications` and `run_on_removals` plugin
|
228
|
-
# method.
|
229
|
-
#
|
230
|
-
# @example Add callback before the `reload` action.
|
231
|
-
# callback(:reload_begin) { puts "Let's reload!" }
|
232
|
-
#
|
233
|
-
# @example Add callback before the `start` and `stop` actions.
|
234
|
-
#
|
235
|
-
# my_lambda = lambda do |plugin, event, *args|
|
236
|
-
# puts "Let's #{event} #{plugin} with #{args}!"
|
237
|
-
# end
|
238
|
-
#
|
239
|
-
# callback(my_lambda, [:start_begin, :start_end])
|
240
|
-
#
|
241
|
-
# @param [Array] args the callback arguments
|
242
|
-
# @yield a callback block
|
243
|
-
#
|
244
|
-
def callback(*args, &block)
|
245
|
-
@plugin_options ||= nil
|
246
|
-
fail "callback must be called within a guard block" unless @plugin_options
|
247
|
-
|
248
|
-
block, events = if args.size > 1
|
249
|
-
# block must be the first argument in that case, the
|
250
|
-
# yielded block is ignored
|
251
|
-
args
|
252
|
-
else
|
253
|
-
[block, args[0]]
|
254
|
-
end
|
255
|
-
@plugin_options[:callbacks] << { events: events, listener: block }
|
256
|
-
end
|
257
|
-
|
258
|
-
# Ignores certain paths globally.
|
259
|
-
#
|
260
|
-
# @example Ignore some paths
|
261
|
-
# ignore %r{^ignored/path/}, /man/
|
262
|
-
#
|
263
|
-
# @param [Regexp] regexps a pattern (or list of patterns) for ignoring paths
|
264
|
-
#
|
265
|
-
def ignore(*regexps)
|
266
|
-
# TODO: instead, use Guard.reconfigure(ignore: regexps) or something
|
267
|
-
Guard.listener.ignore(regexps) if Guard.listener
|
268
|
-
end
|
269
|
-
|
270
|
-
# TODO: deprecate
|
271
|
-
alias filter ignore
|
272
|
-
|
273
|
-
# Replaces ignored paths globally
|
274
|
-
#
|
275
|
-
# @example Ignore only these paths
|
276
|
-
# ignore! %r{^ignored/path/}, /man/
|
277
|
-
#
|
278
|
-
# @param [Regexp] regexps a pattern (or list of patterns) for ignoring paths
|
279
|
-
#
|
280
|
-
def ignore!(*regexps)
|
281
|
-
@ignore_regexps ||= []
|
282
|
-
@ignore_regexps << regexps
|
283
|
-
Guard.listener.ignore!(@ignore_regexps) if Guard.listener
|
284
|
-
end
|
285
|
-
alias filter! ignore!
|
286
|
-
|
287
|
-
# Configures the Guard logger.
|
288
|
-
#
|
289
|
-
# * Log level must be either `:debug`, `:info`, `:warn` or `:error`.
|
290
|
-
# * Template supports the following placeholders: `:time`, `:severity`,
|
291
|
-
# `:progname`, `:pid`, `:unit_of_work_id` and `:message`.
|
292
|
-
# * Time format directives are the same as `Time#strftime` or
|
293
|
-
# `:milliseconds`.
|
294
|
-
# * The `:only` and `:except` options must be a `RegExp`.
|
295
|
-
#
|
296
|
-
# @example Set the log level
|
297
|
-
# logger level: :warn
|
298
|
-
#
|
299
|
-
# @example Set a custom log template
|
300
|
-
# logger template: '[Guard - :severity - :progname - :time] :message'
|
301
|
-
#
|
302
|
-
# @example Set a custom time format
|
303
|
-
# logger time_format: '%h'
|
304
|
-
#
|
305
|
-
# @example Limit logging to a Guard plugin
|
306
|
-
# logger only: :jasmine
|
307
|
-
#
|
308
|
-
# @example Log all but not the messages from a specific Guard plugin
|
309
|
-
# logger except: :jasmine
|
310
|
-
#
|
311
|
-
# @param [Hash] options the log options
|
312
|
-
# @option options [String, Symbol] level the log level
|
313
|
-
# @option options [String] template the logger template
|
314
|
-
# @option options [String, Symbol] time_format the time format
|
315
|
-
# @option options [Regexp] only show only messages from the matching Guard
|
316
|
-
# plugin
|
317
|
-
# @option options [Regexp] except does not show messages from the matching
|
318
|
-
# Guard plugin
|
319
|
-
#
|
320
|
-
def logger(options)
|
321
|
-
if options[:level]
|
322
|
-
options[:level] = options[:level].to_sym
|
323
|
-
|
324
|
-
unless [:debug, :info, :warn, :error].include? options[:level]
|
325
|
-
UI.warning WARN_INVALID_LOG_LEVEL % [options[:level]]
|
326
|
-
options.delete :level
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
if options[:only] && options[:except]
|
331
|
-
UI.warning WARN_INVALID_LOG_OPTIONS
|
332
|
-
|
333
|
-
options.delete :only
|
334
|
-
options.delete :except
|
335
|
-
end
|
336
|
-
|
337
|
-
# Convert the :only and :except options to a regular expression
|
338
|
-
[:only, :except].each do |name|
|
339
|
-
next unless options[name]
|
340
|
-
|
341
|
-
list = [].push(options[name]).flatten.map do |plugin|
|
342
|
-
Regexp.escape(plugin.to_s)
|
343
|
-
end
|
344
|
-
|
345
|
-
options[name] = Regexp.new(list.join("|"), Regexp::IGNORECASE)
|
346
|
-
end
|
347
|
-
|
348
|
-
UI.options.merge!(options)
|
349
|
-
end
|
350
|
-
|
351
|
-
# Sets the default scope on startup
|
352
|
-
#
|
353
|
-
# @example Scope Guard to a single group
|
354
|
-
# scope group: :frontend
|
355
|
-
#
|
356
|
-
# @example Scope Guard to multiple groups
|
357
|
-
# scope groups: [:specs, :docs]
|
358
|
-
#
|
359
|
-
# @example Scope Guard to a single plugin
|
360
|
-
# scope plugin: :test
|
361
|
-
#
|
362
|
-
# @example Scope Guard to multiple plugins
|
363
|
-
# scope plugins: [:jasmine, :rspec]
|
364
|
-
#
|
365
|
-
# @param [Hash] scopes the scope for the groups and plugins
|
366
|
-
#
|
367
|
-
def scope(scope = {})
|
368
|
-
Guard.state.session.guardfile_scope(scope)
|
369
|
-
end
|
370
|
-
|
371
|
-
def evaluate(contents, filename, lineno) # :nodoc
|
372
|
-
instance_eval(contents, filename.to_s, lineno)
|
373
|
-
rescue StandardError, ScriptError => e
|
374
|
-
prefix = "\n\t(dsl)> "
|
375
|
-
cleaned_backtrace = _cleanup_backtrace(e.backtrace)
|
376
|
-
backtrace = "#{prefix}#{cleaned_backtrace.join(prefix)}"
|
377
|
-
msg = "Invalid Guardfile, original error is: \n\n%s, \nbacktrace: %s"
|
378
|
-
raise Error, format(msg, e, backtrace)
|
379
|
-
end
|
380
|
-
|
381
|
-
# Sets the directories to pass to Listen
|
382
|
-
#
|
383
|
-
# @example watch only given directories
|
384
|
-
# directories %w(lib specs)
|
385
|
-
#
|
386
|
-
# @param [Array] directories directories for Listen to watch
|
387
|
-
#
|
388
|
-
def directories(directories)
|
389
|
-
directories.each do |dir|
|
390
|
-
fail "Directory #{dir.inspect} does not exist!" unless Dir.exist?(dir)
|
391
|
-
end
|
392
|
-
Guard.state.session.watchdirs = directories
|
393
|
-
end
|
394
|
-
|
395
|
-
# Sets Guard to clear the screen before every task is run
|
396
|
-
#
|
397
|
-
# @example switching clearing the screen on
|
398
|
-
# clearing(:on)
|
399
|
-
#
|
400
|
-
# @param [Symbol] on ':on' to turn on, ':off' (default) to turn off
|
401
|
-
#
|
402
|
-
def clearing(on)
|
403
|
-
Guard.state.session.clearing(on == :on)
|
404
|
-
end
|
405
|
-
|
406
|
-
private
|
407
|
-
|
408
|
-
def _cleanup_backtrace(backtrace)
|
409
|
-
dirs = { File.realpath(Dir.pwd) => ".", }
|
410
|
-
|
411
|
-
gem_env = ENV["GEM_HOME"] || ""
|
412
|
-
dirs[gem_env] = "$GEM_HOME" unless gem_env.empty?
|
413
|
-
|
414
|
-
gem_paths = (ENV["GEM_PATH"] || "").split(File::PATH_SEPARATOR)
|
415
|
-
gem_paths.each_with_index do |path, index|
|
416
|
-
dirs[path] = "$GEM_PATH[#{index}]"
|
417
|
-
end
|
418
|
-
|
419
|
-
backtrace.dup.map do |raw_line|
|
420
|
-
path = nil
|
421
|
-
symlinked_path = raw_line.split(":").first
|
422
|
-
begin
|
423
|
-
path = raw_line.sub(symlinked_path, File.realpath(symlinked_path))
|
424
|
-
dirs.detect { |dir, name| path.sub!(File.realpath(dir), name) }
|
425
|
-
path
|
426
|
-
rescue Errno::ENOENT
|
427
|
-
path || symlinked_path
|
428
|
-
end
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|