guard 2.10.2 → 2.10.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|