guard 1.1.1 → 1.2.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.
- data/CHANGELOG.md +10 -1
- data/README.md +28 -6
- data/lib/guard.rb +21 -14
- data/lib/guard/interactor.rb +80 -47
- data/lib/guard/interactors/coolline.rb +62 -0
- data/lib/guard/interactors/helpers/completion.rb +30 -0
- data/lib/guard/interactors/helpers/terminal.rb +46 -0
- data/lib/guard/interactors/readline.rb +35 -57
- data/lib/guard/runner.rb +15 -17
- data/lib/guard/version.rb +1 -1
- data/lib/guard/version.rbc +11 -7
- metadata +9 -7
- data/bin/fsevent_watch_guard +0 -0
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## Master
|
2
|
+
|
3
|
+
### 1.2.0 - 20 June, 2012
|
4
|
+
|
5
|
+
- Add a [Coolline](https://github.com/Mon-Ouie/coolline) based interactor (Ruby 1.9.3 only). ([@netzpirat][])
|
6
|
+
- More flexible command parser for all interactors. ([@netzpirat][])
|
7
|
+
- Add 'show' command to describe all plugins in the interactor. ([@netzpirat][])
|
8
|
+
- Add 'change' command to trigger a file change event in the interactor. ([@netzpirat][])
|
9
|
+
|
1
10
|
## 1.1.1 - 3 June, 2012
|
2
11
|
|
3
12
|
### Bug fix
|
@@ -600,4 +609,4 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
600
609
|
[@waldo]: https://github.com/waldo
|
601
610
|
[@wereHamster]: https://github.com/wereHamster
|
602
611
|
[@yannlugrin]: https://github.com/yannlugrin
|
603
|
-
[@zonque]: https://github.com/zonque
|
612
|
+
[@zonque]: https://github.com/zonque
|
data/README.md
CHANGED
@@ -397,6 +397,8 @@ You can interact with Guard and enter commands when Guard has nothing to do. Gua
|
|
397
397
|
* `↩`: Run all Guards.
|
398
398
|
* `h`, `help`: Show a help of the available interactor commands.
|
399
399
|
* `r`, `reload`: Reload all Guards.
|
400
|
+
* `c`, `change`: Show a help of the available interactor commands.
|
401
|
+
* `s`, `show`: Show Guard plugin configuration.
|
400
402
|
* `n`, `notification`: Toggle system notifications on and off.
|
401
403
|
* `p`, `pause`: Toggles the file modification listener. The prompt will change to `p>` when paused.
|
402
404
|
This is useful when switching Git branches, rebase Git or change whitespace.
|
@@ -426,6 +428,18 @@ This will reload only the Ronn Guard. You can also reload all Guards within a gr
|
|
426
428
|
> backend reload
|
427
429
|
```
|
428
430
|
|
431
|
+
The action and plugin or group name can have any order, so you can also write:
|
432
|
+
|
433
|
+
```bash
|
434
|
+
> reload backend
|
435
|
+
```
|
436
|
+
|
437
|
+
You can pass a list of filenames to the `change` command to trigger manually a file modification:
|
438
|
+
|
439
|
+
```bash
|
440
|
+
> change spec/guard_spec.rb
|
441
|
+
```
|
442
|
+
|
429
443
|
### Readline support
|
430
444
|
|
431
445
|
With Readline enabled, you'll see a command prompt `>` when Guard is ready to accept a command. The command line
|
@@ -443,6 +457,18 @@ end
|
|
443
457
|
Guard will automatically enable Readline support if your environment supports it, but you can disable Readline with the
|
444
458
|
`interactor` DSL method or turn off completely with the `--no-interactions` option.
|
445
459
|
|
460
|
+
### Coolline support
|
461
|
+
|
462
|
+
With Ruby 1.9.3 you can use a [Coolline](https://github.com/Mon-Ouie/coolline) based interactor, which uses the new
|
463
|
+
`io/console` from stdlib. Just add it to your `Gemfile`
|
464
|
+
|
465
|
+
```ruby
|
466
|
+
gem 'coolline'
|
467
|
+
```
|
468
|
+
|
469
|
+
Guard will automatically enable Coolline support if your environment supports it, but you can disable Coolline with the
|
470
|
+
`interactor` DSL method or turn off completely with the `--no-interactions` option.
|
471
|
+
|
446
472
|
### Signals
|
447
473
|
|
448
474
|
You can also interact with Guard by sending POSIX signals to the Guard process (all but Windows).
|
@@ -591,15 +617,11 @@ notification :off
|
|
591
617
|
|
592
618
|
### interactor
|
593
619
|
|
594
|
-
You can disable the interactor auto detection and
|
620
|
+
You can disable the interactor auto detection and select a specific implementation:
|
595
621
|
|
596
622
|
```ruby
|
623
|
+
interactor :coolline
|
597
624
|
interactor :readline
|
598
|
-
```
|
599
|
-
|
600
|
-
will select Readline interactor. You can also force the simple interactor without Readline support with:
|
601
|
-
|
602
|
-
```ruby
|
603
625
|
interactor :simple
|
604
626
|
```
|
605
627
|
|
data/lib/guard.rb
CHANGED
@@ -104,7 +104,10 @@ module Guard
|
|
104
104
|
def setup_listener
|
105
105
|
listener_callback = lambda do |modified, added, removed|
|
106
106
|
Dsl.reevaluate_guardfile if Watcher.match_guardfile?(modified)
|
107
|
-
|
107
|
+
|
108
|
+
::Guard.within_preserved_state do
|
109
|
+
runner.run_on_changes(modified, added, removed)
|
110
|
+
end
|
108
111
|
end
|
109
112
|
|
110
113
|
listener_options = { :relative_paths => true }
|
@@ -126,7 +129,6 @@ module Guard
|
|
126
129
|
def setup_interactor
|
127
130
|
unless options[:no_interactions]
|
128
131
|
@interactor = Interactor.fabricate
|
129
|
-
@interactor.start if @interactor
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
@@ -151,19 +153,20 @@ module Guard
|
|
151
153
|
setup(options)
|
152
154
|
UI.info "Guard is now watching at '#{ @watchdir }'"
|
153
155
|
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
within_preserved_state do
|
157
|
+
runner.run(:start)
|
158
|
+
end
|
159
|
+
|
157
160
|
listener.start
|
158
161
|
end
|
159
162
|
|
160
163
|
# Stop Guard listening to file changes
|
161
164
|
#
|
162
165
|
def stop
|
163
|
-
UI.info 'Bye bye...', :reset => true
|
164
|
-
interactor.stop if interactor
|
165
166
|
listener.stop
|
167
|
+
interactor.stop if interactor
|
166
168
|
runner.run(:stop)
|
169
|
+
UI.info 'Bye bye...', :reset => true
|
167
170
|
end
|
168
171
|
|
169
172
|
# Reload Guardfile and all Guards currently enabled.
|
@@ -171,10 +174,12 @@ module Guard
|
|
171
174
|
# @param [Hash] scopes an hash with a guard or a group scope
|
172
175
|
#
|
173
176
|
def reload(scopes)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
177
|
+
within_preserved_state do
|
178
|
+
UI.clear
|
179
|
+
UI.action_with_scopes('Reload', scopes)
|
180
|
+
Dsl.reevaluate_guardfile if scopes.empty?
|
181
|
+
runner.run(:reload, scopes)
|
182
|
+
end
|
178
183
|
end
|
179
184
|
|
180
185
|
# Trigger `run_all` on all Guards currently enabled.
|
@@ -182,9 +187,11 @@ module Guard
|
|
182
187
|
# @param [Hash] scopes an hash with a guard or a group scope
|
183
188
|
#
|
184
189
|
def run_all(scopes)
|
185
|
-
|
186
|
-
|
187
|
-
|
190
|
+
within_preserved_state do
|
191
|
+
UI.clear
|
192
|
+
UI.action_with_scopes('Run', scopes)
|
193
|
+
runner.run(:run_all, scopes)
|
194
|
+
end
|
188
195
|
end
|
189
196
|
|
190
197
|
# Pause Guard listening to file changes.
|
data/lib/guard/interactor.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Guard
|
2
2
|
|
3
3
|
autoload :ReadlineInteractor, 'guard/interactors/readline'
|
4
|
+
autoload :CoollineInteractor, 'guard/interactors/coolline'
|
4
5
|
autoload :SimpleInteractor, 'guard/interactors/simple'
|
6
|
+
autoload :DslDescriber, 'guard/dsl_describer'
|
7
|
+
autoload :UI, 'guard/ui'
|
5
8
|
|
6
9
|
# The interactor triggers specific action from input
|
7
10
|
# read by a interactor implementation.
|
@@ -14,15 +17,19 @@ module Guard
|
|
14
17
|
# - r, reload => Reload Guard
|
15
18
|
# - p, pause => Toggle file modification listener
|
16
19
|
# - n, notification => Toggle notifications
|
20
|
+
# - s, show => Show Guard plugin configuration
|
21
|
+
# - c, change => Trigger a file change
|
17
22
|
# - <enter> => Run all
|
18
23
|
#
|
19
24
|
# It's also possible to scope `reload` and `run all` actions to only a specified group or a guard.
|
20
25
|
#
|
21
26
|
# @example Reload backend group
|
22
27
|
# backend reload
|
28
|
+
# reload backend
|
23
29
|
#
|
24
30
|
# @example Reload rspec guard
|
25
31
|
# spork reload
|
32
|
+
# reload spork
|
26
33
|
#
|
27
34
|
# @example Run all jasmine specs
|
28
35
|
# jasmine
|
@@ -31,11 +38,15 @@ module Guard
|
|
31
38
|
#
|
32
39
|
class Interactor
|
33
40
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
41
|
+
ACTIONS = {
|
42
|
+
:help => %w[help h],
|
43
|
+
:reload => %w[reload r],
|
44
|
+
:stop => %w[exit e quit q],
|
45
|
+
:pause => %w[pause p],
|
46
|
+
:notification => %w[notification n],
|
47
|
+
:show => %w[show s],
|
48
|
+
:change => %w[change c]
|
49
|
+
}
|
39
50
|
|
40
51
|
# Set the interactor implementation
|
41
52
|
#
|
@@ -52,8 +63,10 @@ module Guard
|
|
52
63
|
#
|
53
64
|
def self.fabricate
|
54
65
|
case @interactor
|
66
|
+
when :coolline
|
67
|
+
CoollineInteractor.new if CoollineInteractor.available?
|
55
68
|
when :readline
|
56
|
-
ReadlineInteractor.new
|
69
|
+
ReadlineInteractor.new if ReadlineInteractor.available?
|
57
70
|
when :simple
|
58
71
|
SimpleInteractor.new
|
59
72
|
when :off
|
@@ -77,26 +90,34 @@ module Guard
|
|
77
90
|
# @return [Interactor] an interactor implementation
|
78
91
|
#
|
79
92
|
def self.auto_detect
|
80
|
-
|
93
|
+
[CoollineInteractor, ReadlineInteractor, SimpleInteractor].detect { |interactor| interactor.available?(true) }.new
|
94
|
+
end
|
81
95
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
96
|
+
# Template method for checking if the Interactor is
|
97
|
+
# available in the current environment?
|
98
|
+
#
|
99
|
+
# @param [Boolean] silent true if no error messages should be shown
|
100
|
+
# @return [Boolean] the availability status
|
101
|
+
#
|
102
|
+
def self.available?(silent = false)
|
103
|
+
true
|
87
104
|
end
|
88
105
|
|
89
106
|
# Start the line reader in its own thread.
|
90
107
|
#
|
91
108
|
def start
|
92
109
|
return if ENV['GUARD_ENV'] == 'test'
|
110
|
+
|
111
|
+
::Guard::UI.debug 'Start interactor'
|
93
112
|
@thread = Thread.new { read_line } if !@thread || !@thread.alive?
|
94
113
|
end
|
95
114
|
|
96
115
|
# Kill interactor thread if not current
|
97
116
|
#
|
98
117
|
def stop
|
99
|
-
return if ENV['GUARD_ENV'] == 'test'
|
118
|
+
return if !@thread || ENV['GUARD_ENV'] == 'test'
|
119
|
+
|
120
|
+
::Guard::UI.debug 'Stop interactor'
|
100
121
|
unless Thread.current == @thread
|
101
122
|
@thread.kill
|
102
123
|
end
|
@@ -116,11 +137,13 @@ module Guard
|
|
116
137
|
# @param [String] line the input line
|
117
138
|
#
|
118
139
|
def process_input(line)
|
119
|
-
scopes, action = extract_scopes_and_action(line)
|
140
|
+
scopes, action, rest = extract_scopes_and_action(line)
|
120
141
|
|
121
142
|
case action
|
122
143
|
when :help
|
123
144
|
help
|
145
|
+
when :show
|
146
|
+
DslDescriber.show(::Guard.options)
|
124
147
|
when :stop
|
125
148
|
::Guard.stop
|
126
149
|
exit
|
@@ -128,6 +151,10 @@ module Guard
|
|
128
151
|
::Guard.pause
|
129
152
|
when :reload
|
130
153
|
::Guard.reload(scopes)
|
154
|
+
when :change
|
155
|
+
::Guard.within_preserved_state do
|
156
|
+
::Guard.runner.run_on_changes(rest, [], [])
|
157
|
+
end
|
131
158
|
when :run_all
|
132
159
|
::Guard.run_all(scopes)
|
133
160
|
when :notification
|
@@ -156,6 +183,8 @@ module Guard
|
|
156
183
|
puts '[p]ause Toggle file modification listener'
|
157
184
|
puts '[r]eload Reload Guard'
|
158
185
|
puts '[n]otification Toggle notifications'
|
186
|
+
puts '[s]how Show available Guard plugins'
|
187
|
+
puts '[c]hange <file> Trigger a file change'
|
159
188
|
puts '<enter> Run all Guards'
|
160
189
|
puts ''
|
161
190
|
puts 'You can scope the reload action to a specific guard or group:'
|
@@ -171,69 +200,73 @@ module Guard
|
|
171
200
|
end
|
172
201
|
|
173
202
|
# Extract the Guard or group scope and action from the
|
174
|
-
# input line.
|
203
|
+
# input line. There's no strict order for scopes and
|
204
|
+
# actions.
|
175
205
|
#
|
176
206
|
# @example `spork reload` will only reload rspec
|
177
207
|
# @example `jasmine` will only run all jasmine specs
|
178
208
|
#
|
179
209
|
# @param [String] line the readline input
|
180
|
-
# @return [Array] the group or guard scope and the
|
210
|
+
# @return [Array] the group or guard scope, the action and the rest
|
181
211
|
#
|
182
212
|
def extract_scopes_and_action(line)
|
183
|
-
scopes = { }
|
184
213
|
entries = line.split(' ')
|
185
214
|
|
186
|
-
|
187
|
-
|
188
|
-
unless action = action_from_entry(entries[0])
|
189
|
-
scopes = scopes_from_entry(entries[0])
|
190
|
-
end
|
191
|
-
when 2
|
192
|
-
scopes = scopes_from_entry(entries[0])
|
193
|
-
action = action_from_entry(entries[1])
|
194
|
-
end
|
215
|
+
scopes = extract_scopes(entries)
|
216
|
+
action = extract_action(entries)
|
195
217
|
|
196
218
|
action = :run_all if !action && (!scopes.empty? || entries.empty?)
|
197
219
|
|
198
|
-
[scopes, action]
|
220
|
+
[scopes, action, entries]
|
199
221
|
end
|
200
222
|
|
201
223
|
private
|
202
224
|
|
203
|
-
# Extract guard or group scope from entry if valid
|
225
|
+
# Extract a guard or group scope from entry if valid.
|
226
|
+
# Any entry found will be removed from the entries.
|
204
227
|
#
|
205
|
-
# @param [String]
|
228
|
+
# @param [Array<String>] entries the user entries
|
206
229
|
# @return [Hash] a hash with a Guard or a group scope
|
207
230
|
#
|
208
|
-
def
|
231
|
+
def extract_scopes(entries)
|
209
232
|
scopes = { }
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
233
|
+
|
234
|
+
entries.delete_if do |entry|
|
235
|
+
if guard = ::Guard.guards(entry)
|
236
|
+
scopes[:guard] ||= guard
|
237
|
+
true
|
238
|
+
|
239
|
+
elsif group = ::Guard.groups(entry)
|
240
|
+
scopes[:group] ||= group
|
241
|
+
true
|
242
|
+
|
243
|
+
else
|
244
|
+
false
|
245
|
+
end
|
215
246
|
end
|
216
247
|
|
217
248
|
scopes
|
218
249
|
end
|
219
250
|
|
220
251
|
# Find the action for the given input entry.
|
252
|
+
# Any action found will be removed from the entries.
|
221
253
|
#
|
222
|
-
# @param [String]
|
254
|
+
# @param [Array<String>] entries the user entries
|
223
255
|
# @return [Symbol] a Guard action
|
224
256
|
#
|
225
|
-
def
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
:notification
|
257
|
+
def extract_action(entries)
|
258
|
+
action = nil
|
259
|
+
|
260
|
+
entries.delete_if do |entry|
|
261
|
+
if command = ACTIONS.detect { |k, list| list.include?(entry) }
|
262
|
+
action ||= command.first
|
263
|
+
true
|
264
|
+
else
|
265
|
+
false
|
266
|
+
end
|
236
267
|
end
|
268
|
+
|
269
|
+
action
|
237
270
|
end
|
238
271
|
|
239
272
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Guard
|
2
|
+
|
3
|
+
autoload :TerminalHelper, 'guard/interactors/helpers/terminal'
|
4
|
+
autoload :CompletionHelper, 'guard/interactors/helpers/completion'
|
5
|
+
autoload :UI, 'guard/ui'
|
6
|
+
|
7
|
+
# Interactor that uses coolline for getting the user input.
|
8
|
+
# This enables history support and auto-completion,
|
9
|
+
#
|
10
|
+
class CoollineInteractor < Interactor
|
11
|
+
include ::Guard::CompletionHelper
|
12
|
+
include ::Guard::TerminalHelper
|
13
|
+
|
14
|
+
# Test if the Interactor is
|
15
|
+
# available in the current environment?
|
16
|
+
#
|
17
|
+
# @param [Boolean] silent true if no error messages should be shown
|
18
|
+
# @return [Boolean] the availability status
|
19
|
+
#
|
20
|
+
def self.available?(silent = false)
|
21
|
+
if RbConfig::CONFIG['RUBY_PROGRAM_VERSION'] == '1.9.3'
|
22
|
+
require 'coolline'
|
23
|
+
true
|
24
|
+
else
|
25
|
+
::Guard::UI.error 'The :coolline interactor runs only on Ruby 1.9.3.' unless silent
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue LoadError => e
|
30
|
+
::Guard::UI.error "Please add \"gem 'coolline'\" to your Gemfile and run Guard with \"bundle exec\"." unless silent
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
# Read a line from stdin with Readline.
|
35
|
+
#
|
36
|
+
def read_line
|
37
|
+
coolline = Coolline.new do |cool|
|
38
|
+
cool.transform_proc = proc do
|
39
|
+
cool.line
|
40
|
+
end
|
41
|
+
|
42
|
+
cool.completion_proc = proc do
|
43
|
+
word = cool.completed_word
|
44
|
+
auto_complete(word)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
while line = coolline.readline(prompt)
|
49
|
+
process_input(line)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# The current interactor prompt
|
54
|
+
#
|
55
|
+
# @return [String] the prompt to show
|
56
|
+
#
|
57
|
+
def prompt
|
58
|
+
::Guard.listener.paused? ? 'p> ' : '>> '
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Guard
|
2
|
+
|
3
|
+
# Module for providing word completion to an interactor.
|
4
|
+
#
|
5
|
+
module CompletionHelper
|
6
|
+
|
7
|
+
COMPLETION_ACTIONS = %w[help reload exit pause notification show]
|
8
|
+
|
9
|
+
# Auto complete the given word.
|
10
|
+
#
|
11
|
+
# @param [String] word the partial word
|
12
|
+
# @return [Array<String>] the matching words
|
13
|
+
#
|
14
|
+
def auto_complete(word)
|
15
|
+
completion_list.grep(/^#{ Regexp.escape(word) }/)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the auto completion list.
|
19
|
+
#
|
20
|
+
# @return [Array<String>] the list of words
|
21
|
+
#
|
22
|
+
def completion_list
|
23
|
+
groups = ::Guard.groups.map { |group| group.name.to_s }
|
24
|
+
guards = ::Guard.guards.map { |guard| guard.class.to_s.downcase.sub('guard::', '') }
|
25
|
+
|
26
|
+
COMPLETION_ACTIONS + groups + guards - ['default']
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Guard
|
2
|
+
|
3
|
+
# Module for resetting terminal options for an interactor.
|
4
|
+
#
|
5
|
+
module TerminalHelper
|
6
|
+
|
7
|
+
# Start the interactor.
|
8
|
+
#
|
9
|
+
def start
|
10
|
+
store_terminal_settings if stty_exists?
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
# Stop the interactor.
|
15
|
+
#
|
16
|
+
def stop
|
17
|
+
super
|
18
|
+
restore_terminal_settings if stty_exists?
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Detects whether or not the stty command exists
|
24
|
+
# on the user machine.
|
25
|
+
#
|
26
|
+
# @return [Boolean] the status of stty
|
27
|
+
#
|
28
|
+
def stty_exists?
|
29
|
+
@stty_exists ||= system('hash', 'stty')
|
30
|
+
end
|
31
|
+
|
32
|
+
# Stores the terminal settings so we can resore them
|
33
|
+
# when stopping.
|
34
|
+
#
|
35
|
+
def store_terminal_settings
|
36
|
+
@stty_save = `stty -g 2>/dev/null`.chomp
|
37
|
+
end
|
38
|
+
|
39
|
+
# Restore terminal settings
|
40
|
+
#
|
41
|
+
def restore_terminal_settings
|
42
|
+
system('stty', @stty_save, '2>/dev/null') if @stty_save
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module Guard
|
2
2
|
|
3
|
+
autoload :TerminalHelper, 'guard/interactors/helpers/terminal'
|
4
|
+
autoload :CompletionHelper, 'guard/interactors/helpers/completion'
|
5
|
+
autoload :UI, 'guard/ui'
|
6
|
+
|
3
7
|
# Interactor that used readline for getting the user input.
|
4
8
|
# This enables history support and auto-completion, but is
|
5
9
|
# broken on OS X without installing `rb-readline` or using JRuby.
|
@@ -7,18 +11,31 @@ module Guard
|
|
7
11
|
# @see http://bugs.ruby-lang.org/issues/5539
|
8
12
|
#
|
9
13
|
class ReadlineInteractor < Interactor
|
14
|
+
include ::Guard::CompletionHelper
|
15
|
+
include ::Guard::TerminalHelper
|
16
|
+
|
17
|
+
# Test if the Interactor is
|
18
|
+
# available in the current environment?
|
19
|
+
#
|
20
|
+
# @param [Boolean] silent true if no error messages should be shown
|
21
|
+
# @return [Boolean] the availability status
|
22
|
+
#
|
23
|
+
def self.available?(silent = false)
|
24
|
+
require 'readline'
|
10
25
|
|
11
|
-
|
26
|
+
if defined?(RbReadline) || defined?(JRUBY_VERSION) || RbConfig::CONFIG['target_os'] =~ /linux/i
|
27
|
+
true
|
28
|
+
else
|
29
|
+
::Guard::UI.error 'The :readline interactor runs only fine on JRuby, Linux or with the gem \'rb-readline\' installed.' unless silent
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
12
33
|
|
13
34
|
# Initialize the interactor.
|
14
35
|
#
|
15
36
|
def initialize
|
16
37
|
require 'readline'
|
17
38
|
|
18
|
-
unless defined?(RbReadline) || defined?(JRUBY_VERSION) || RbConfig::CONFIG['target_os'] =~ /linux/i
|
19
|
-
::Guard::UI.info 'Please add rb-readline for proper Readline support.'
|
20
|
-
end
|
21
|
-
|
22
39
|
Readline.completion_proc = proc { |word| auto_complete(word) }
|
23
40
|
|
24
41
|
begin
|
@@ -28,23 +45,27 @@ module Guard
|
|
28
45
|
end
|
29
46
|
end
|
30
47
|
|
31
|
-
# Start the interactor.
|
32
|
-
#
|
33
|
-
def start
|
34
|
-
store_terminal_settings if stty_exists?
|
35
|
-
super
|
36
|
-
end
|
37
|
-
|
38
48
|
# Stop the interactor.
|
39
49
|
#
|
40
50
|
def stop
|
51
|
+
# Erase the current line for Ruby Readline
|
52
|
+
if Readline.respond_to?(:refresh_line)
|
53
|
+
Readline.refresh_line
|
54
|
+
end
|
55
|
+
|
56
|
+
# Erase the current line for Rb-Readline
|
57
|
+
if defined?(RbReadline) && RbReadline.rl_outstream
|
58
|
+
RbReadline._rl_erase_entire_line
|
59
|
+
end
|
60
|
+
|
41
61
|
super
|
42
|
-
restore_terminal_settings if stty_exists?
|
43
62
|
end
|
44
|
-
|
63
|
+
|
45
64
|
# Read a line from stdin with Readline.
|
46
65
|
#
|
47
66
|
def read_line
|
67
|
+
require 'readline'
|
68
|
+
|
48
69
|
while line = Readline.readline(prompt, true)
|
49
70
|
line.gsub!(/^\W*/, '')
|
50
71
|
if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line
|
@@ -55,26 +76,6 @@ module Guard
|
|
55
76
|
end
|
56
77
|
end
|
57
78
|
|
58
|
-
# Auto complete the given word.
|
59
|
-
#
|
60
|
-
# @param [String] word the partial word
|
61
|
-
# @return [Array<String>] the matching words
|
62
|
-
#
|
63
|
-
def auto_complete(word)
|
64
|
-
completion_list.grep(/^#{ Regexp.escape(word) }/)
|
65
|
-
end
|
66
|
-
|
67
|
-
# Get the auto completion list.
|
68
|
-
#
|
69
|
-
# @return [Array<String>] the list of words
|
70
|
-
#
|
71
|
-
def completion_list
|
72
|
-
groups = ::Guard.groups.map { |group| group.name.to_s }
|
73
|
-
guards = ::Guard.guards.map { |guard| guard.class.to_s.downcase.sub('guard::', '') }
|
74
|
-
|
75
|
-
COMPLETION_ACTIONS + groups + guards - ['default']
|
76
|
-
end
|
77
|
-
|
78
79
|
# The current interactor prompt
|
79
80
|
#
|
80
81
|
# @return [String] the prompt to show
|
@@ -83,28 +84,5 @@ module Guard
|
|
83
84
|
::Guard.listener.paused? ? 'p> ' : '> '
|
84
85
|
end
|
85
86
|
|
86
|
-
private
|
87
|
-
|
88
|
-
# Detects whether or not the stty command exists
|
89
|
-
# on the user machine.
|
90
|
-
#
|
91
|
-
# @return [Boolean] the status of stty
|
92
|
-
#
|
93
|
-
def stty_exists?
|
94
|
-
system('hash', 'stty')
|
95
|
-
end
|
96
|
-
|
97
|
-
# Stores the terminal settings so we can resore them
|
98
|
-
# when stopping.
|
99
|
-
#
|
100
|
-
def store_terminal_settings
|
101
|
-
@stty_save = `stty -g 2>/dev/null`.chomp
|
102
|
-
end
|
103
|
-
|
104
|
-
# Restore terminal settings
|
105
|
-
#
|
106
|
-
def restore_terminal_settings
|
107
|
-
system('stty', @stty_save, '2>/dev/null')
|
108
|
-
end
|
109
87
|
end
|
110
88
|
end
|
data/lib/guard/runner.rb
CHANGED
@@ -84,26 +84,24 @@ module Guard
|
|
84
84
|
# @raise [:task_has_failed] when task has failed
|
85
85
|
#
|
86
86
|
def run_supervised_task(guard, task, *args)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
87
|
+
begin
|
88
|
+
catch Runner.stopping_symbol_for(guard) do
|
89
|
+
guard.hook("#{ task }_begin", *args)
|
90
|
+
result = guard.send(task, *args)
|
91
|
+
guard.hook("#{ task }_end", result)
|
92
|
+
result
|
93
|
+
end
|
95
94
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
rescue NoMethodError
|
96
|
+
# Do nothing
|
97
|
+
rescue Exception => ex
|
98
|
+
UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
|
99
|
+
"\n#{ ex.class }: #{ ex.message }\n#{ ex.backtrace.join("\n") }")
|
101
100
|
|
102
|
-
|
103
|
-
|
101
|
+
::Guard.guards.delete guard
|
102
|
+
UI.info("\n#{ guard.class.name } has just been fired")
|
104
103
|
|
105
|
-
|
106
|
-
end
|
104
|
+
ex
|
107
105
|
end
|
108
106
|
end
|
109
107
|
|
data/lib/guard/version.rb
CHANGED
data/lib/guard/version.rbc
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
!RBIX
|
2
|
-
|
2
|
+
9595534255132031488
|
3
3
|
x
|
4
4
|
M
|
5
5
|
1
|
@@ -141,25 +141,29 @@ s
|
|
141
141
|
constant
|
142
142
|
s
|
143
143
|
5
|
144
|
-
0.
|
144
|
+
1.0.0
|
145
145
|
x
|
146
146
|
9
|
147
147
|
const_set
|
148
148
|
p
|
149
|
-
|
149
|
+
7
|
150
150
|
I
|
151
151
|
2
|
152
152
|
I
|
153
153
|
2
|
154
154
|
I
|
155
|
+
26
|
156
|
+
I
|
157
|
+
4
|
158
|
+
I
|
155
159
|
2f
|
156
160
|
I
|
157
161
|
0
|
158
162
|
I
|
159
163
|
30
|
160
164
|
x
|
161
|
-
|
162
|
-
/Users/
|
165
|
+
52
|
166
|
+
/Users/michi/Repositories/guard/lib/guard/version.rb
|
163
167
|
p
|
164
168
|
0
|
165
169
|
x
|
@@ -174,7 +178,7 @@ I
|
|
174
178
|
I
|
175
179
|
1c
|
176
180
|
x
|
177
|
-
|
178
|
-
/Users/
|
181
|
+
52
|
182
|
+
/Users/michi/Repositories/guard/lib/guard/version.rb
|
179
183
|
p
|
180
184
|
0
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -82,7 +82,7 @@ dependencies:
|
|
82
82
|
requirements:
|
83
83
|
- - ~>
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
85
|
+
version: 1.1.0
|
86
86
|
type: :development
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -90,7 +90,7 @@ dependencies:
|
|
90
90
|
requirements:
|
91
91
|
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
93
|
+
version: 1.1.0
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: yard
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,7 +147,6 @@ executables:
|
|
147
147
|
extensions: []
|
148
148
|
extra_rdoc_files: []
|
149
149
|
files:
|
150
|
-
- bin/fsevent_watch_guard
|
151
150
|
- bin/guard
|
152
151
|
- images/failed.png
|
153
152
|
- images/pending.png
|
@@ -160,6 +159,9 @@ files:
|
|
160
159
|
- lib/guard/guardfile.rb
|
161
160
|
- lib/guard/hook.rb
|
162
161
|
- lib/guard/interactor.rb
|
162
|
+
- lib/guard/interactors/coolline.rb
|
163
|
+
- lib/guard/interactors/helpers/completion.rb
|
164
|
+
- lib/guard/interactors/helpers/terminal.rb
|
163
165
|
- lib/guard/interactors/readline.rb
|
164
166
|
- lib/guard/interactors/simple.rb
|
165
167
|
- lib/guard/notifier.rb
|
@@ -195,7 +197,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
195
197
|
version: '0'
|
196
198
|
segments:
|
197
199
|
- 0
|
198
|
-
hash:
|
200
|
+
hash: -1561498034094566001
|
199
201
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
202
|
none: false
|
201
203
|
requirements:
|
@@ -204,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
206
|
version: 1.3.6
|
205
207
|
requirements: []
|
206
208
|
rubyforge_project: guard
|
207
|
-
rubygems_version: 1.8.
|
209
|
+
rubygems_version: 1.8.24
|
208
210
|
signing_key:
|
209
211
|
specification_version: 3
|
210
212
|
summary: Guard keeps an eye on your file modifications
|
data/bin/fsevent_watch_guard
DELETED
Binary file
|