guard 1.8.3 → 2.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -10
- data/README.md +54 -33
- data/lib/guard.rb +133 -483
- data/lib/guard/cli.rb +78 -82
- data/lib/guard/commander.rb +121 -0
- data/lib/guard/commands/all.rb +1 -1
- data/lib/guard/commands/reload.rb +1 -1
- data/lib/guard/deprecated_methods.rb +59 -0
- data/lib/guard/deprecator.rb +107 -0
- data/lib/guard/dsl.rb +143 -329
- data/lib/guard/dsl_describer.rb +101 -57
- data/lib/guard/group.rb +27 -8
- data/lib/guard/guard.rb +25 -150
- data/lib/guard/guardfile.rb +35 -85
- data/lib/guard/guardfile/evaluator.rb +245 -0
- data/lib/guard/guardfile/generator.rb +89 -0
- data/lib/guard/interactor.rb +147 -163
- data/lib/guard/notifier.rb +83 -137
- data/lib/guard/notifiers/base.rb +220 -0
- data/lib/guard/notifiers/emacs.rb +39 -37
- data/lib/guard/notifiers/file_notifier.rb +29 -25
- data/lib/guard/notifiers/gntp.rb +68 -75
- data/lib/guard/notifiers/growl.rb +49 -52
- data/lib/guard/notifiers/growl_notify.rb +51 -56
- data/lib/guard/notifiers/libnotify.rb +41 -48
- data/lib/guard/notifiers/notifysend.rb +58 -38
- data/lib/guard/notifiers/rb_notifu.rb +54 -54
- data/lib/guard/notifiers/terminal_notifier.rb +48 -36
- data/lib/guard/notifiers/terminal_title.rb +23 -19
- data/lib/guard/notifiers/tmux.rb +110 -93
- data/lib/guard/options.rb +21 -0
- data/lib/guard/plugin.rb +66 -0
- data/lib/guard/plugin/base.rb +178 -0
- data/lib/guard/plugin/hooker.rb +123 -0
- data/lib/guard/plugin_util.rb +158 -0
- data/lib/guard/rake_task.rb +47 -0
- data/lib/guard/runner.rb +62 -82
- data/lib/guard/setuper.rb +248 -0
- data/lib/guard/ui.rb +24 -80
- data/lib/guard/ui/colors.rb +60 -0
- data/lib/guard/version.rb +1 -2
- data/lib/guard/watcher.rb +30 -30
- data/man/guard.1 +4 -4
- data/man/guard.1.html +6 -4
- metadata +25 -11
- data/lib/guard/hook.rb +0 -120
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec53a40ba0d6bb529aba462d295f5959631fc2de
|
4
|
+
data.tar.gz: 730479188a61cfdafea27ee0ed417ef72ef09fc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b98bfa844663944ed92554b69af8edb2f8cc1f63de2d7d0ef374c828414ceb5ebbd7fb5f07b7ecb904f52c86522ac721c973062e331c5677dfa47da8572faae3
|
7
|
+
data.tar.gz: f9d2785f7edf80c6e81fac7d05f87dfb732442e9bf38b27ba3e8a2decbb2f5f3817f0e1c5d9411c5508bd61f8710ed7bebec31b0b465ef9df8b24c2daef1a4df
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,55 @@
|
|
1
1
|
## Master
|
2
2
|
|
3
|
-
No changes
|
3
|
+
No changes.
|
4
|
+
|
5
|
+
## 2.0.0.pre - 12 September, 2013
|
6
|
+
|
7
|
+
### Removals & deprecations
|
8
|
+
|
9
|
+
- Remove `Guard::Guardfile.duplicate_definitions?`. ([@rymai][])
|
10
|
+
- Remove the deprecated `watch_all_modifications` start option. ([@rymai][])
|
11
|
+
- Remove the deprecated `no_vendor` start option. ([@rymai][])
|
12
|
+
- Remove the deprecated `reset_color` UI method. ([@rymai][])
|
13
|
+
- Remove the deprecated `match_file?` Watcher method. ([@rymai][])
|
14
|
+
- Remove the deprecated `ignore_paths` DSL method. ([@rymai][])
|
15
|
+
- Remove the deprecation warning for the `interactor` DSL method. ([@rymai][])
|
16
|
+
- Remove the deprecation warning for when a plugin defines the `run_on_change` method. ([@rymai][])
|
17
|
+
- Remove the deprecation warning for when a plugin defines the `run_on_deletion` method. ([@rymai][])
|
18
|
+
- Deprecate `Guard.guards(filter)` in favor of `Guard.plugins(filter)`. ([@rymai][])
|
19
|
+
- Deprecate `Guard.add_guard(name, options = {})` in favor of `Guard.add_plugin(name, options = {})`. ([@rymai][])
|
20
|
+
- Deprecate `Guard.get_guard_class(name, fail_gracefully)` in favor of `Guard::PluginUtil.new(name).plugin_class(fail_gracefully: fail_gracefully)`. ([@rymai][])
|
21
|
+
- Deprecate `Guard.locate_guard(name)` in favor of `Guard::PluginUtil.new(name).plugin_location`. ([@rymai][])
|
22
|
+
- Deprecate `Guard.guard_gem_names` in favor of `Guard::PluginUtil.plugin_names`. ([@rymai][])
|
23
|
+
- Deprecate `Guard::Guard` in favor of `Guard::Plugin`. ([@rymai][])
|
24
|
+
- Deprecate `Guard::Dsl.evaluate_guardfile(options)` in favor of `Guard::Guardfile::Evaluator.new(options).evaluate_guardfile`. ([@rymai][])
|
25
|
+
- Deprecate `Guard::Guardfile.create_guardfile(options)` in favor of `Guard::Guardfile::Generator.new(options).create_guardfile`. ([@rymai][])
|
26
|
+
- Deprecate `Guard::Guardfile.initialize_template(plugin_name)` in favor of `Guard::Guardfile::Generator.new.initialize_template(plugin_name)`. ([@rymai][])
|
27
|
+
- Deprecate `Guard::Guardfile.initialize_all_templates` in favor of `Guard::Guardfile::Generator.new.initialize_all_templates`. ([@rymai][])
|
28
|
+
|
29
|
+
### New features & improvements
|
30
|
+
|
31
|
+
- [#469][] List available notifiers. ([@netzpirat][])
|
32
|
+
- Refactor `Guard::Notifier` and the whole notifiers system. ([@rymai][])
|
33
|
+
- Allow to pass symbols or actual Guard plugins / groups for the `scope` parameter to `Guard::Runner#run`. ([@rymai][])
|
34
|
+
- Ensure Guard API calls are not order dependent. ([@rymai][])
|
35
|
+
- Ensure Guard has sensible defaults. ([@rymai][])
|
36
|
+
- New `#title` method for `Guard::Group` & `Guard::Plugin`. ([@rymai][])
|
37
|
+
- New `Guard::Plugin::Base` module common to `Guard::Guard` (deprecated) & `Guard::Plugin`. ([@rymai][])
|
38
|
+
- New `Guard::PluginUtil` that contains useful methods to find and instantiate Guard plugins. ([@rymai][])
|
39
|
+
- New `Guard.plugin` method to find the first plugin matching a filter. ([@rymai][])
|
40
|
+
- New `Guard.group` method to find the first group matching a filter. ([@rymai][])
|
41
|
+
- Don't swallow exceptions when evaluating the Guardfile. ([@rymai][])
|
42
|
+
- Rename `Guard::Hook` to `Guard::Plugin::Hooker`. ([@rymai][])
|
43
|
+
- Move setup stuff into a new `Guard::Setuper` module. ([@rymai][])
|
44
|
+
- Move deprecation stuff inside a new `Guard::Deprecator` class. ([@rymai][])
|
45
|
+
|
46
|
+
### Bug fixes
|
47
|
+
|
48
|
+
- [#472][] Clear terminal title notification on exit. Fixes [#472][]. ([@netzpirat][])
|
49
|
+
- [#457][] Raise an exception when a group is called "all". Fixes [#457][]. (reported by [@rweng][], fixed by [@rymai][])
|
50
|
+
- [#471][] Only init once per plugin when running `guard init` (reported by [@simon-ohara][], fixed by [@thibaudgg][])
|
51
|
+
- [#456][] Fix notifu notifier. ([@netzpirat][])
|
52
|
+
- [#435][] Fix pressing `C-c` when interactor thread is not started. ([@netzpirat][])
|
4
53
|
|
5
54
|
## 1.8.2 - 30 July, 2013
|
6
55
|
|
@@ -25,6 +74,7 @@ No changes yet.
|
|
25
74
|
|
26
75
|
### Improvements
|
27
76
|
|
77
|
+
- Listen 1.0.0 support. ([@thibaudgg][])
|
28
78
|
- [#416][] Support .guardrc file on the folder from which Guard is executed as well. ([@Nerian][])
|
29
79
|
- Display an info message when a plugin throws `:task_has_failed`. ([@rymai][])
|
30
80
|
- Ensure compatibility with new Listen's API. ([@rymai][])
|
@@ -79,10 +129,10 @@ No changes yet.
|
|
79
129
|
|
80
130
|
### New features
|
81
131
|
|
82
|
-
- Allow the Guard scope to be defined from the `Guardfile` with the `scope`
|
132
|
+
- Allow the Guard scope to be defined from the `Guardfile` with the `scope` Dsl method. ([@netzpirat][])
|
83
133
|
- [#378][] Scope plugins and groups from CLI and interactor. ([@netzpirat][])
|
84
134
|
- [#369][] Allow Guard plugins to specify their template location. ([@schmurfy][])
|
85
|
-
- [#364][] Add `ignore!` and `filter!`
|
135
|
+
- [#364][] Add `ignore!` and `filter!` Dsl methods. ([@tarsolya][])
|
86
136
|
- [#362][] Add interactor options `:history_file` and `:guard_rc`. ([@netzpirat][])
|
87
137
|
|
88
138
|
### Improvements
|
@@ -310,7 +360,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
310
360
|
|
311
361
|
### Improvements
|
312
362
|
|
313
|
-
- Add `interactor` to
|
363
|
+
- Add `interactor` to Dsl to allow switching Guard interaction implementation. ([@netzpirat][])
|
314
364
|
- Add quit action to the interactor. ([@Maher4Ever][])
|
315
365
|
|
316
366
|
## 0.9.1 - December 19, 2011
|
@@ -410,7 +460,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
410
460
|
### New feature
|
411
461
|
|
412
462
|
- [#136][] New CLI `:watch_all_modifications`/`-A` option to watch for deleted and moved files too. ([@limeyd][] and [@netzpirat][])
|
413
|
-
- [#97][] Guard dependencies. Task execution can now be halted if a Guard throws `:task_has_failed` and `Guard::Dsl#group` options include
|
463
|
+
- [#97][] Guard dependencies. Task execution can now be halted if a Guard throws `:task_has_failed` and `Guard::Dsl#group` options include `halt_on_fail: true`. ([@rymai][])
|
414
464
|
- [#121][] `Guard.guards` and `Guard.groups` are now smart accessors. Filters can be passed to find a specific Guard/group or several Guard plugins/groups that match (see YARDoc). ([@rymai][] and [@ches][])
|
415
465
|
- New `Guard::Group` class to store groups defined in Guardfile (with `Guard::Dsl#group`). ([@rymai][])
|
416
466
|
|
@@ -441,7 +491,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
441
491
|
|
442
492
|
### New features
|
443
493
|
|
444
|
-
- [#130][] Add `ignore_paths` method to
|
494
|
+
- [#130][] Add `ignore_paths` method to Dsl. ([@ianwhite][])
|
445
495
|
- [#128][] Users can add additional settings to `~/.guard.rb` that augment the existing Guardfile. ([@tpope][])
|
446
496
|
|
447
497
|
## 0.6.2 - August 17, 2011
|
@@ -481,7 +531,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
481
531
|
### Improvements
|
482
532
|
|
483
533
|
- [#99][] [OS X] Switch from growl gem to growl_notify gem. ([@johnbintz][])
|
484
|
-
- [#115][] [Linux] Add
|
534
|
+
- [#115][] [Linux] Add `transient: true` to default libnotify options. ([@zonque][])
|
485
535
|
- [#95][] Output system commands and options to be executed when in debug mode. ([@uk-ar][] and [@netzpirat][])
|
486
536
|
- `Guard::Dsl.revaluate_guardfile` has been renamed to `Guard::Dsl.reevaluate_guardfile`. ([@rymai][])
|
487
537
|
- New CLI options: ([@nestegg][])
|
@@ -537,7 +587,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
537
587
|
|
538
588
|
### New features
|
539
589
|
|
540
|
-
- [#73][] Allow
|
590
|
+
- [#73][] Allow Dsl's `group` method to accept a Symbol as group name. ([@johnbintz][])
|
541
591
|
- [#51][] Allow options (like `:priority`) to be passed through to the Notifier. ([@indirect][] and [@netzpirat][])
|
542
592
|
|
543
593
|
### Improvement
|
@@ -612,7 +662,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
612
662
|
### New features
|
613
663
|
|
614
664
|
- The whole directory is now watched during `run_on_change` to detect new files modifications. ([@thibaudgg][])
|
615
|
-
- [#26][] New
|
665
|
+
- [#26][] New Dsl method: `group` allows you to group several guards. New CLI option: `--group group_name` to specify certain groups of guards to start. ([@netzpirat][])
|
616
666
|
- `watch` patterns are now more strict: strings are matched with `String#==`, `Regexp` are matched with `Regexp#match`. ([@rymai][])
|
617
667
|
- A deprecation warning is displayed if your `Guardfile` contains `String` that look like `Regexp` (bad!). ([@rymai][])
|
618
668
|
- It's now possible to return an `Enumerable` in the `watch` optional blocks in the `Guardfile`. ([@rymai][])
|
@@ -620,7 +670,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
620
670
|
### New specs
|
621
671
|
|
622
672
|
- `Guard::Watcher`. ([@rymai][])
|
623
|
-
- [#13][] `Guard::
|
673
|
+
- [#13][] `Guard::DSL`. ([@oliamb][])
|
624
674
|
|
625
675
|
## 0.2.2 - October 25, 2010
|
626
676
|
|
@@ -786,11 +836,17 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
786
836
|
[#413]: https://github.com/guard/guard/issues/413
|
787
837
|
[#414]: https://github.com/guard/guard/issues/414
|
788
838
|
[#416]: https://github.com/guard/guard/issues/416
|
839
|
+
[#435]: https://github.com/guard/guard/issues/435
|
789
840
|
[#443]: https://github.com/guard/guard/issues/443
|
790
841
|
[#450]: https://github.com/guard/guard/issues/450
|
791
842
|
[#453]: https://github.com/guard/guard/issues/453
|
843
|
+
[#456]: https://github.com/guard/guard/issues/456
|
844
|
+
[#457]: https://github.com/guard/guard/issues/457
|
792
845
|
[#460]: https://github.com/guard/guard/issues/460
|
793
846
|
[#463]: https://github.com/guard/guard/issues/463
|
847
|
+
[#469]: https://github.com/guard/guard/issues/469
|
848
|
+
[#471]: https://github.com/guard/guard/issues/471
|
849
|
+
[#472]: https://github.com/guard/guard/issues/472
|
794
850
|
[@Gazer]: https://github.com/Gazer
|
795
851
|
[@Maher4Ever]: https://github.com/Maher4Ever
|
796
852
|
[@Nerian]: https://github.com/Nerian
|
@@ -861,10 +917,12 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
|
|
861
917
|
[@royvandewater]: https://github.com/royvandewater
|
862
918
|
[@rudicode]: https://github.com/rudicode
|
863
919
|
[@rupert654]: https://github.com/rupert654
|
920
|
+
[@rweng]: https://github.com/rweng
|
864
921
|
[@rymai]: https://github.com/rymai
|
865
922
|
[@schmurfy]: https://github.com/schmurfy
|
866
923
|
[@scottdavis]: https://github.com/scottdavis
|
867
924
|
[@semperos]: https://github.com/semperos
|
925
|
+
[@simon-ohara]: https://github.com/simon-ohara
|
868
926
|
[@spadin]: https://github.com/spadin
|
869
927
|
[@steakknife]: https://github.com/steakknife
|
870
928
|
[@stereobooster]: https://github.com/stereobooster
|
data/README.md
CHANGED
@@ -16,21 +16,21 @@ the following places:
|
|
16
16
|
Information on advanced topics like creating your own Guard plugin, programatic use of Guard, hooks and callbacks and
|
17
17
|
more can be found in the [Guard wiki](https://github.com/guard/guard/wiki).
|
18
18
|
|
19
|
-
Before you file an issue, make sure you have read the _[known issues](#
|
19
|
+
Before you file an issue, make sure you have read the _[known issues](#issues)_ and _[file an issue](#file-an-issue)_ sections that contains some important information.
|
20
20
|
|
21
21
|
#### Features
|
22
22
|
|
23
23
|
* File system changes handled by our awesome [Listen](https://github.com/guard/listen) gem.
|
24
24
|
* Support for visual system notifications.
|
25
|
-
* Huge eco-system with [more than
|
26
|
-
* Tested against Ruby 1.
|
25
|
+
* Huge eco-system with [more than 220](https://rubygems.org/search?query=guard-) Guard plugins.
|
26
|
+
* Tested against Ruby 1.9.2, 1.9.3, 2.0.0, JRuby (1.9 mode) & Rubinius (1.9 mode).
|
27
27
|
|
28
28
|
#### Screencast
|
29
29
|
|
30
|
-
Two nice
|
30
|
+
Two nice screencasts are available to help you get started:
|
31
31
|
|
32
|
-
* [Guard
|
33
|
-
* [Guard](http://
|
32
|
+
* [Guard](http://railscasts.com/episodes/264-guard) on RailsCast.
|
33
|
+
* [Guard is Your Best Friend](http://net.tutsplus.com/tutorials/tools-and-tips/guard-is-your-best-friend) on Net Tuts+.
|
34
34
|
|
35
35
|
Installation
|
36
36
|
------------
|
@@ -57,6 +57,7 @@ Generate an empty `Guardfile` with:
|
|
57
57
|
$ guard init
|
58
58
|
```
|
59
59
|
|
60
|
+
|
60
61
|
Run Guard through Bundler with:
|
61
62
|
|
62
63
|
```bash
|
@@ -99,7 +100,7 @@ You can always get help on the available tasks with the `help` task:
|
|
99
100
|
$ guard help
|
100
101
|
```
|
101
102
|
|
102
|
-
|
103
|
+
Requesting more detailed help on a specific task is simple: just append the task name to the help task.
|
103
104
|
For example, to get help for the `start` task, simply run:
|
104
105
|
|
105
106
|
```bash
|
@@ -172,7 +173,7 @@ $ guard -c # shortcut
|
|
172
173
|
You can add the following snippet to your `~/.guardrc` to have the clear option always be enabled:
|
173
174
|
|
174
175
|
```
|
175
|
-
Guard.options
|
176
|
+
Guard.options.clear = true
|
176
177
|
```
|
177
178
|
|
178
179
|
#### `-n`/`--notify` option
|
@@ -312,7 +313,26 @@ $ guard show
|
|
312
313
|
```
|
313
314
|
|
314
315
|
This shows the internal structure of the evaluated `Guardfile` or `.Guardfile`, with the `.guard.rb` file. You can
|
315
|
-
read more about these files in the [shared configuration section](https://github.com/guard/guard
|
316
|
+
read more about these files in the [shared configuration section](https://github.com/guard/guard/wiki/Shared-configurations).
|
317
|
+
|
318
|
+
### Notifiers
|
319
|
+
|
320
|
+
You can show the notifiers, their availablity and options with the `notifier` task:
|
321
|
+
|
322
|
+
```bash
|
323
|
+
$ guard notifiers
|
324
|
+
+-------------------+-----------+------+------------------------+-------------------+
|
325
|
+
| Name | Available | Used | Option | Value |
|
326
|
+
+-------------------+-----------+------+------------------------+-------------------+
|
327
|
+
| gntp | ✔ | ✘ | sticky | false |
|
328
|
+
+-------------------+-----------+------+------------------------+-------------------+
|
329
|
+
| growl | ✘ | ✘ | sticky | false |
|
330
|
+
| | | | priority | 0 |
|
331
|
+
+-------------------+-----------+------+------------------------+-------------------+
|
332
|
+
```
|
333
|
+
|
334
|
+
This shows if a notifier is available on the current system, it it's being used and the
|
335
|
+
current options (which reflects your custom options merged into the default options).
|
316
336
|
|
317
337
|
Interactions
|
318
338
|
------------
|
@@ -385,14 +405,14 @@ The `guard` method allows you to add a Guard plugin to your toolchain and config
|
|
385
405
|
options after the name of the plugin:
|
386
406
|
|
387
407
|
```ruby
|
388
|
-
guard :coffeescript, :
|
408
|
+
guard :coffeescript, input: 'coffeescripts', output: 'javascripts'
|
389
409
|
```
|
390
410
|
|
391
411
|
You can define the same plugin more than once:
|
392
412
|
|
393
413
|
```ruby
|
394
|
-
guard :coffeescript, :
|
395
|
-
guard :coffeescript, :
|
414
|
+
guard :coffeescript, input: 'coffeescripts', output: 'javascripts'
|
415
|
+
guard :coffeescript, input: 'specs', output: 'specs'
|
396
416
|
```
|
397
417
|
|
398
418
|
### watch
|
@@ -472,7 +492,7 @@ to make this work, the group needs to have the `halt_on_fail` option enabled and
|
|
472
492
|
needs to throw `:task_has_failed` to indicate that the action was not successful.
|
473
493
|
|
474
494
|
```ruby
|
475
|
-
group :specs, :
|
495
|
+
group :specs, halt_on_fail: true do
|
476
496
|
guard :rspec do
|
477
497
|
watch(/.../)
|
478
498
|
end
|
@@ -492,20 +512,22 @@ the DSL scope configuration.
|
|
492
512
|
You can define either a single plugin or group:
|
493
513
|
|
494
514
|
```ruby
|
495
|
-
scope :
|
496
|
-
scope :
|
515
|
+
scope plugin: :rspec
|
516
|
+
scope group: :docs
|
497
517
|
```
|
498
518
|
|
499
519
|
or specify multiple plugins or groups.
|
500
520
|
|
501
521
|
```ruby
|
502
|
-
scope :
|
503
|
-
scope :
|
522
|
+
scope plugins: [:test, :jasmine]
|
523
|
+
scope groups: [:docs, :frontend]
|
504
524
|
```
|
505
525
|
|
506
526
|
If you define both the plugin and group scope, the plugin scope has precedence. If you use both the
|
507
527
|
plural and the singular option, the plural has precedence.
|
508
528
|
|
529
|
+
**Please be sure to call the `scope` method after you've declared your Guard plugins!**
|
530
|
+
|
509
531
|
### notification
|
510
532
|
|
511
533
|
If you don't specify any notification configuration in your `Guardfile`, Guard goes through the list of available
|
@@ -519,17 +541,17 @@ notification :growl
|
|
519
541
|
will select the `growl` gem for notifications. You can also set options for a notifier:
|
520
542
|
|
521
543
|
```ruby
|
522
|
-
notification :growl, :
|
544
|
+
notification :growl, sticky: true
|
523
545
|
```
|
524
546
|
|
525
547
|
Each notifier has a slightly different set of supported options:
|
526
548
|
|
527
549
|
```ruby
|
528
|
-
notification :growl, :
|
529
|
-
notification :gntp, :
|
530
|
-
notification :growl_notify, :
|
531
|
-
notification :libnotify, :
|
532
|
-
notification :notifu, :
|
550
|
+
notification :growl, sticky: true, host: '192.168.1.5', password: 'secret'
|
551
|
+
notification :gntp, sticky: true, host: '192.168.1.5', password: 'secret'
|
552
|
+
notification :growl_notify, sticky: true, priority: 0
|
553
|
+
notification :libnotify, timeout: 5, transient: true, append: false, urgency: :critical
|
554
|
+
notification :notifu, time: 5, nosound: true, xp: true
|
533
555
|
notification :emacs
|
534
556
|
```
|
535
557
|
|
@@ -548,7 +570,7 @@ notification :off
|
|
548
570
|
You can customize the Pry interactor history and RC file like:
|
549
571
|
|
550
572
|
```ruby
|
551
|
-
interactor :
|
573
|
+
interactor guard_rc: '~/.my_guard-rc', history_file: '~/.my_guard_history_file'
|
552
574
|
```
|
553
575
|
|
554
576
|
If you do not need the Pry interactions with Guard at all, you can turn it off:
|
@@ -585,7 +607,7 @@ This comes in handy when you have large amounts of non-source data in you projec
|
|
585
607
|
are ignored.
|
586
608
|
|
587
609
|
Please note that method only accept regexps. More on the
|
588
|
-
[Listen README](https://github.com/guard/listen#the-patterns-for-
|
610
|
+
[Listen README](https://github.com/guard/listen#note-on-the-patterns-for-ignoring-and-filtering-paths).
|
589
611
|
|
590
612
|
To append to the default ignored files and directories, use the `ignore` method:
|
591
613
|
|
@@ -606,7 +628,7 @@ The `filter` method allows you to focus by filtering files and directories witho
|
|
606
628
|
the `filter` method.
|
607
629
|
|
608
630
|
Please note that method only accept regexps. More on the
|
609
|
-
[Listen README](https://github.com/guard/listen#the-patterns-for-
|
631
|
+
[Listen README](https://github.com/guard/listen#note-on-the-patterns-for-ignoring-and-filtering-paths).
|
610
632
|
|
611
633
|
```ruby
|
612
634
|
filter /\.txt$/, /.*\.zip/
|
@@ -624,12 +646,12 @@ The `logger` method allows you to customize the [Lumberjack](https://github.com/
|
|
624
646
|
needs by specifying one or more options like:
|
625
647
|
|
626
648
|
```ruby
|
627
|
-
logger :
|
628
|
-
:
|
629
|
-
:
|
630
|
-
:
|
631
|
-
:
|
632
|
-
:
|
649
|
+
logger level: :warn,
|
650
|
+
template: '[:severity - :time - :progname] :message',
|
651
|
+
time_format: 'at %I:%M%p',
|
652
|
+
only: [:rspec, :jasmine, 'coffeescript'],
|
653
|
+
except: :jammit,
|
654
|
+
device: 'guard.log'
|
633
655
|
```
|
634
656
|
|
635
657
|
Log `:level` option must be either `:debug`, `:info`, `:warn` or `:error`. If Guard is started in debug mode, the log
|
@@ -713,7 +735,6 @@ Please try to follow these simple rules:
|
|
713
735
|
|
714
736
|
#### Core Team
|
715
737
|
|
716
|
-
* [Maher Sallam](https://github.com/Maher4Ever) ([@mahersalam](http://twitter.com/mahersalam))
|
717
738
|
* [Michael Kessler](https://github.com/netzpirat) ([@netzpirat](http://twitter.com/netzpirat), [mksoft.ch](https://mksoft.ch))
|
718
739
|
* [Rémy Coutable](https://github.com/rymai) ([@rymai](http://twitter.com/rymai), [rymai.me](http://rymai.me))
|
719
740
|
* [Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](http://twitter.com/thibaudgg), [thibaud.me](http://thibaud.me/))
|
data/lib/guard.rb
CHANGED
@@ -1,320 +1,112 @@
|
|
1
1
|
require 'rbconfig'
|
2
|
-
|
3
|
-
require '
|
2
|
+
|
3
|
+
require 'guard/commander'
|
4
|
+
require 'guard/deprecated_methods'
|
5
|
+
require 'guard/deprecator'
|
6
|
+
require 'guard/dsl'
|
7
|
+
require 'guard/group'
|
8
|
+
require 'guard/guardfile'
|
9
|
+
require 'guard/interactor'
|
10
|
+
require 'guard/notifier'
|
11
|
+
require 'guard/plugin_util'
|
12
|
+
require 'guard/runner'
|
13
|
+
require 'guard/setuper'
|
14
|
+
require 'guard/ui'
|
15
|
+
require 'guard/watcher'
|
4
16
|
|
5
17
|
# Guard is the main module for all Guard related modules and classes.
|
6
18
|
# Also Guard plugins should use this namespace.
|
7
19
|
#
|
8
20
|
module Guard
|
9
21
|
|
10
|
-
|
11
|
-
require 'guard/guardfile'
|
12
|
-
require 'guard/group'
|
13
|
-
require 'guard/interactor'
|
14
|
-
require 'guard/notifier'
|
15
|
-
require 'guard/runner'
|
16
|
-
require 'guard/ui'
|
17
|
-
require 'guard/watcher'
|
18
|
-
|
19
|
-
# The Guardfile template for `guard init`
|
20
|
-
GUARDFILE_TEMPLATE = File.expand_path('../guard/templates/Guardfile', __FILE__)
|
21
|
-
|
22
|
-
# The location of user defined templates
|
23
|
-
HOME_TEMPLATES = File.expand_path('~/.guard/templates')
|
24
|
-
|
25
|
-
WINDOWS = RbConfig::CONFIG['host_os'] =~ %r!(msdos|mswin|djgpp|mingw)!
|
22
|
+
WINDOWS = RbConfig::CONFIG['host_os'] =~ %r!(msdos|mswin|djgpp|mingw)!
|
26
23
|
DEV_NULL = WINDOWS ? 'NUL' : '/dev/null'
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
# Initialize the Guard singleton:
|
32
|
-
#
|
33
|
-
# - Initialize the internal Guard state.
|
34
|
-
# - Create the interactor when necessary for user interaction.
|
35
|
-
# - Select and initialize the file change listener.
|
36
|
-
#
|
37
|
-
# @option options [Boolean] clear if auto clear the UI should be done
|
38
|
-
# @option options [Boolean] notify if system notifications should be shown
|
39
|
-
# @option options [Boolean] debug if debug output should be shown
|
40
|
-
# @option options [Array<String>] group the list of groups to start
|
41
|
-
# @option options [Array<String>] watchdir the directories to watch
|
42
|
-
# @option options [String] guardfile the path to the Guardfile
|
43
|
-
# @deprecated @option options [Boolean] watch_all_modifications watches all file modifications if true
|
44
|
-
# @deprecated @option options [Boolean] no_vendor ignore vendored dependencies
|
45
|
-
#
|
46
|
-
def setup(options = {})
|
47
|
-
@running = true
|
48
|
-
@lock = Mutex.new
|
49
|
-
@options = options.dup
|
50
|
-
@runner = ::Guard::Runner.new
|
51
|
-
@scope = { :plugins => [], :groups => [] }
|
52
|
-
|
53
|
-
@watchdirs = [Dir.pwd]
|
54
|
-
|
55
|
-
if options[:watchdir]
|
56
|
-
# Ensure we have an array
|
57
|
-
@watchdirs = Array(options[:watchdir]).map { |dir| File.expand_path dir }
|
58
|
-
end
|
59
|
-
|
60
|
-
::Guard::UI.clear(:force => true)
|
61
|
-
setup_debug
|
62
|
-
deprecated_options_warning
|
63
|
-
|
64
|
-
setup_groups
|
65
|
-
setup_guards
|
66
|
-
setup_listener
|
67
|
-
setup_signal_traps
|
68
|
-
setup_from_guardfile
|
69
|
-
setup_scopes
|
70
|
-
|
71
|
-
runner.deprecation_warning if options[:show_deprecations]
|
72
|
-
|
73
|
-
setup_notifier
|
74
|
-
setup_interactor
|
75
|
-
|
76
|
-
self
|
77
|
-
end
|
25
|
+
extend Commander
|
26
|
+
extend DeprecatedMethods
|
27
|
+
extend Setuper
|
78
28
|
|
79
|
-
|
80
|
-
|
81
|
-
Thread.abort_on_exception = true
|
82
|
-
::Guard::UI.options[:level] = :debug
|
83
|
-
debug_command_execution
|
84
|
-
end
|
85
|
-
end
|
29
|
+
class << self
|
30
|
+
attr_accessor :evaluator, :interactor, :runner, :listener, :lock, :scope, :running
|
86
31
|
|
87
|
-
#
|
32
|
+
# Smart accessor for retrieving specific plugins at once.
|
88
33
|
#
|
34
|
+
# @see Guard.plugin
|
35
|
+
# @see Guard.group
|
89
36
|
# @see Guard.groups
|
90
37
|
#
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
#
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
#
|
137
|
-
#
|
138
|
-
# Currently two signals are caught:
|
139
|
-
# - `USR1` which pauses listening to changes.
|
140
|
-
# - `USR2` which resumes listening to changes.
|
141
|
-
# - 'INT' which is delegated to Pry if active, otherwise stops Guard.
|
142
|
-
#
|
143
|
-
def setup_signal_traps
|
144
|
-
unless defined?(JRUBY_VERSION)
|
145
|
-
if Signal.list.keys.include?('USR1')
|
146
|
-
Signal.trap('USR1') { ::Guard.pause unless listener.paused? }
|
147
|
-
end
|
148
|
-
|
149
|
-
if Signal.list.keys.include?('USR2')
|
150
|
-
Signal.trap('USR2') { ::Guard.pause if listener.paused? }
|
151
|
-
end
|
152
|
-
|
153
|
-
if Signal.list.keys.include?('INT')
|
154
|
-
Signal.trap('INT') do
|
155
|
-
if interactor
|
156
|
-
interactor.thread.raise(Interrupt)
|
157
|
-
else
|
158
|
-
::Guard.stop
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def setup_from_guardfile
|
166
|
-
::Guard::Dsl.evaluate_guardfile(options)
|
167
|
-
::Guard::UI.error 'No guards found in Guardfile, please add at least one.' if @guards.empty?
|
168
|
-
end
|
169
|
-
|
170
|
-
def setup_scopes
|
171
|
-
scope[:groups] = options[:group].map { |g| ::Guard.groups(g) } if options[:group]
|
172
|
-
scope[:plugins] = options[:plugin].map { |p| ::Guard.guards(p) } if options[:plugin]
|
173
|
-
end
|
174
|
-
|
175
|
-
# Enables or disables the notifier based on user's configurations.
|
176
|
-
#
|
177
|
-
def setup_notifier
|
178
|
-
options[:notify] && ENV['GUARD_NOTIFY'] != 'false' ? ::Guard::Notifier.turn_on : ::Guard::Notifier.turn_off
|
179
|
-
end
|
180
|
-
|
181
|
-
# Initializes the interactor unless the user has specified not to.
|
182
|
-
#
|
183
|
-
def setup_interactor
|
184
|
-
unless options[:no_interactions] || !::Guard::Interactor.enabled
|
185
|
-
@interactor = ::Guard::Interactor.new
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
# Start Guard by evaluating the `Guardfile`, initializing declared Guard plugins
|
190
|
-
# and starting the available file change listener.
|
191
|
-
# Main method for Guard that is called from the CLI when Guard starts.
|
192
|
-
#
|
193
|
-
# - Setup Guard internals
|
194
|
-
# - Evaluate the `Guardfile`
|
195
|
-
# - Configure Notifiers
|
196
|
-
# - Initialize the declared Guard plugins
|
197
|
-
# - Start the available file change listener
|
198
|
-
#
|
199
|
-
# @option options [Boolean] clear if auto clear the UI should be done
|
200
|
-
# @option options [Boolean] notify if system notifications should be shown
|
201
|
-
# @option options [Boolean] debug if debug output should be shown
|
202
|
-
# @option options [Array<String>] group the list of groups to start
|
203
|
-
# @option options [String] watchdir the director to watch
|
204
|
-
# @option options [String] guardfile the path to the Guardfile
|
205
|
-
#
|
206
|
-
def start(options = {})
|
207
|
-
setup(options)
|
208
|
-
|
209
|
-
within_preserved_state do
|
210
|
-
::Guard::UI.debug 'Guard starts all plugins'
|
211
|
-
runner.run(:start)
|
212
|
-
::Guard::UI.info "Guard is now watching at '#{ @watchdirs.join "', '" }'"
|
213
|
-
listener.start
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
# Stop Guard listening to file changes
|
218
|
-
#
|
219
|
-
def stop
|
220
|
-
within_preserved_state(false) do
|
221
|
-
::Guard::UI.debug 'Guard stops all plugins'
|
222
|
-
runner.run(:stop)
|
223
|
-
::Guard::Notifier.turn_off
|
224
|
-
::Guard::UI.info 'Bye bye...', :reset => true
|
225
|
-
listener.stop
|
226
|
-
@running = false
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
# Reload Guardfile and all Guard plugins currently enabled.
|
231
|
-
# If no scope is given, then the Guardfile will be re-evaluated,
|
232
|
-
# which results in a stop/start, which makes the reload obsolete.
|
233
|
-
#
|
234
|
-
# @param [Hash] scopes hash with a Guard plugin or a group scope
|
235
|
-
#
|
236
|
-
def reload(scopes = {})
|
237
|
-
scopes = convert_scopes(scopes)
|
238
|
-
|
239
|
-
within_preserved_state do
|
240
|
-
::Guard::UI.clear(:force => true)
|
241
|
-
::Guard::UI.action_with_scopes('Reload', scopes)
|
242
|
-
|
243
|
-
if scopes.empty?
|
244
|
-
::Guard::Dsl.reevaluate_guardfile
|
245
|
-
else
|
246
|
-
runner.run(:reload, scopes)
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
# Trigger `run_all` on all Guard plugins currently enabled.
|
252
|
-
#
|
253
|
-
# @param [Hash] scopes hash with a Guard plugin or a group scope
|
254
|
-
#
|
255
|
-
def run_all(scopes = {})
|
256
|
-
scopes = convert_scopes(scopes)
|
257
|
-
|
258
|
-
within_preserved_state do
|
259
|
-
::Guard::UI.clear(:force => true)
|
260
|
-
::Guard::UI.action_with_scopes('Run', scopes)
|
261
|
-
runner.run(:run_all, scopes)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
# Pause Guard listening to file changes.
|
266
|
-
#
|
267
|
-
def pause
|
268
|
-
if listener.paused?
|
269
|
-
::Guard::UI.info 'Un-paused files modification listening', :reset => true
|
270
|
-
listener.unpause
|
271
|
-
else
|
272
|
-
::Guard::UI.info 'Paused files modification listening', :reset => true
|
273
|
-
listener.pause
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
# Smart accessor for retrieving a specific Guard plugin or several Guard plugins at once.
|
278
|
-
#
|
38
|
+
# @example Filter plugins by String or Symbol
|
39
|
+
# Guard.plugins('rspec')
|
40
|
+
# Guard.plugins(:rspec)
|
41
|
+
#
|
42
|
+
# @example Filter plugins by Regexp
|
43
|
+
# Guard.plugins(/rsp.+/)
|
44
|
+
#
|
45
|
+
# @example Filter plugins by Hash
|
46
|
+
# Guard.plugins(name: 'rspec', group: 'backend')
|
47
|
+
#
|
48
|
+
# @param [String, Symbol, Regexp, Hash] filter the filter to apply to the plugins
|
49
|
+
# @return [Plugin, Array<Plugin>] the filtered plugin(s)
|
50
|
+
#
|
51
|
+
def plugins(filter = nil)
|
52
|
+
@plugins ||= []
|
53
|
+
|
54
|
+
return @plugins if filter.nil?
|
55
|
+
|
56
|
+
filtered_plugins = case filter
|
57
|
+
when String, Symbol
|
58
|
+
@plugins.find_all do |plugin|
|
59
|
+
plugin.name == filter.to_s.downcase.gsub('-', '')
|
60
|
+
end
|
61
|
+
when Regexp
|
62
|
+
@plugins.find_all do |plugin|
|
63
|
+
plugin.name =~ filter
|
64
|
+
end
|
65
|
+
when Hash
|
66
|
+
@plugins.find_all do |plugin|
|
67
|
+
filter.all? do |k, v|
|
68
|
+
case k
|
69
|
+
when :name
|
70
|
+
plugin.name == v.to_s.downcase.gsub('-', '')
|
71
|
+
when :group
|
72
|
+
plugin.group.name == v.to_sym
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
filtered_plugins
|
79
|
+
end
|
80
|
+
|
81
|
+
# Smart accessor for retrieving a specific plugin.
|
82
|
+
#
|
83
|
+
# @see Guard.plugins
|
84
|
+
# @see Guard.group
|
279
85
|
# @see Guard.groups
|
280
86
|
#
|
281
|
-
# @example
|
282
|
-
# Guard.
|
283
|
-
# Guard.
|
87
|
+
# @example Find a plugin by String or Symbol
|
88
|
+
# Guard.plugin('rspec')
|
89
|
+
# Guard.plugin(:rspec)
|
284
90
|
#
|
285
|
-
# @example
|
286
|
-
# Guard.
|
91
|
+
# @example Find a plugin by Regexp
|
92
|
+
# Guard.plugin(/rsp.+/)
|
287
93
|
#
|
288
|
-
# @example
|
289
|
-
# Guard.
|
94
|
+
# @example Find a plugin by Hash
|
95
|
+
# Guard.plugin(name: 'rspec', group: 'backend')
|
290
96
|
#
|
291
|
-
# @param [String, Symbol, Regexp, Hash] filter the filter
|
292
|
-
#
|
97
|
+
# @param [String, Symbol, Regexp, Hash] filter the filter for finding the plugin
|
98
|
+
# the Guard plugin
|
99
|
+
# @return [Plugin, nil] the plugin found, nil otherwise
|
293
100
|
#
|
294
|
-
def
|
295
|
-
|
296
|
-
|
297
|
-
case filter
|
298
|
-
when String, Symbol
|
299
|
-
@guards.find { |guard| guard.class.to_s.downcase.sub('guard::', '') == filter.to_s.downcase.gsub('-', '') }
|
300
|
-
when Regexp
|
301
|
-
@guards.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') =~ filter }
|
302
|
-
when Hash
|
303
|
-
filter.inject(@guards) do |matches, (k, v)|
|
304
|
-
if k.to_sym == :name
|
305
|
-
matches.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') == v.to_s.downcase.gsub('-', '') }
|
306
|
-
else
|
307
|
-
matches.find_all { |guard| guard.send(k).to_sym == v.to_sym }
|
308
|
-
end
|
309
|
-
end
|
310
|
-
else
|
311
|
-
@guards
|
312
|
-
end
|
101
|
+
def plugin(filter)
|
102
|
+
plugins(filter).first
|
313
103
|
end
|
314
104
|
|
315
|
-
# Smart accessor for retrieving
|
105
|
+
# Smart accessor for retrieving specific groups at once.
|
316
106
|
#
|
317
|
-
# @see Guard.
|
107
|
+
# @see Guard.plugin
|
108
|
+
# @see Guard.plugins
|
109
|
+
# @see Guard.group
|
318
110
|
#
|
319
111
|
# @example Filter groups by String or Symbol
|
320
112
|
# Guard.groups('backend')
|
@@ -324,219 +116,77 @@ module Guard
|
|
324
116
|
# Guard.groups(/(back|front)end/)
|
325
117
|
#
|
326
118
|
# @param [String, Symbol, Regexp] filter the filter to apply to the Groups
|
327
|
-
# @return [Array<Group>] the filtered
|
119
|
+
# @return [Array<Group>] the filtered group(s)
|
328
120
|
#
|
329
121
|
def groups(filter = nil)
|
330
|
-
|
331
|
-
when String, Symbol
|
332
|
-
@groups.find { |group| group.name == filter.to_sym }
|
333
|
-
when Regexp
|
334
|
-
@groups.find_all { |group| group.name.to_s =~ filter }
|
335
|
-
else
|
336
|
-
@groups
|
337
|
-
end
|
338
|
-
end
|
122
|
+
return @groups if filter.nil?
|
339
123
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
# @return [Guard::Guard] the added Guard plugin
|
347
|
-
#
|
348
|
-
def add_guard(name, watchers = [], callbacks = [], options = {})
|
349
|
-
if name.to_sym == :ego
|
350
|
-
::Guard::UI.deprecation('Guard::Ego is now part of Guard. You can remove it from your Guardfile.')
|
351
|
-
else
|
352
|
-
guard_class = get_guard_class(name)
|
353
|
-
callbacks.each { |callback| Hook.add_callback(callback[:listener], guard_class, callback[:events]) }
|
354
|
-
guard = guard_class.new(watchers, options)
|
355
|
-
@guards << guard
|
356
|
-
guard
|
357
|
-
end
|
358
|
-
end
|
124
|
+
filtered_groups = case filter
|
125
|
+
when String, Symbol
|
126
|
+
@groups.find_all { |group| group.name == filter.to_sym }
|
127
|
+
when Regexp
|
128
|
+
@groups.find_all { |group| group.name.to_s =~ filter }
|
129
|
+
end
|
359
130
|
|
360
|
-
|
361
|
-
#
|
362
|
-
# @param [String] name the group name
|
363
|
-
# @option options [Boolean] halt_on_fail if a task execution
|
364
|
-
# should be halted for all Guard plugins in this group if one Guard throws `:task_has_failed`
|
365
|
-
# @return [Guard::Group] the group added (or retrieved from the `@groups` variable if already present)
|
366
|
-
#
|
367
|
-
def add_group(name, options = {})
|
368
|
-
group = groups(name)
|
369
|
-
if group.nil?
|
370
|
-
group = ::Guard::Group.new(name, options)
|
371
|
-
@groups << group
|
372
|
-
end
|
373
|
-
group
|
131
|
+
filtered_groups
|
374
132
|
end
|
375
133
|
|
376
|
-
#
|
377
|
-
# blocked and execution is synchronized
|
378
|
-
# to avoid state inconsistency.
|
134
|
+
# Smart accessor for retrieving a specific group.
|
379
135
|
#
|
380
|
-
# @
|
381
|
-
# @
|
382
|
-
#
|
383
|
-
def within_preserved_state(restart_interactor = true)
|
384
|
-
lock.synchronize do
|
385
|
-
begin
|
386
|
-
interactor.stop if interactor
|
387
|
-
@result = yield
|
388
|
-
rescue Interrupt
|
389
|
-
# Bring back Pry when the block is halted with Ctrl-C
|
390
|
-
end
|
391
|
-
|
392
|
-
interactor.start if interactor && restart_interactor
|
393
|
-
end
|
394
|
-
|
395
|
-
@result
|
396
|
-
end
|
397
|
-
|
398
|
-
# Tries to load the Guard plugin main class. This transforms the supplied Guard plugin
|
399
|
-
# name into a class name:
|
400
|
-
#
|
401
|
-
# * `guardname` will become `Guard::Guardname`
|
402
|
-
# * `dashed-guard-name` will become `Guard::DashedGuardName`
|
403
|
-
# * `underscore_guard_name` will become `Guard::UnderscoreGuardName`
|
404
|
-
#
|
405
|
-
# When no class is found with the strict case sensitive rules, another
|
406
|
-
# try is made to locate the class without matching case:
|
407
|
-
#
|
408
|
-
# * `rspec` will find a class `Guard::RSpec`
|
136
|
+
# @see Guard.plugin
|
137
|
+
# @see Guard.plugins
|
138
|
+
# @see Guard.groups
|
409
139
|
#
|
410
|
-
# @
|
411
|
-
#
|
412
|
-
#
|
140
|
+
# @example Find a group by String or Symbol
|
141
|
+
# Guard.group('backend')
|
142
|
+
# Guard.group(:backend)
|
413
143
|
#
|
414
|
-
|
415
|
-
|
416
|
-
try_require = false
|
417
|
-
const_name = name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.gsub(/(?:^|[_-])(.)/) { $1.upcase }
|
418
|
-
begin
|
419
|
-
require "guard/#{ name.downcase }" if try_require
|
420
|
-
self.const_get(self.constants.find { |c| c.to_s == const_name } || self.constants.find { |c| c.to_s.downcase == const_name.downcase })
|
421
|
-
rescue TypeError
|
422
|
-
if try_require
|
423
|
-
::Guard::UI.error "Could not find class Guard::#{ const_name.capitalize }"
|
424
|
-
else
|
425
|
-
try_require = true
|
426
|
-
retry
|
427
|
-
end
|
428
|
-
rescue LoadError => loadError
|
429
|
-
unless fail_gracefully
|
430
|
-
::Guard::UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ const_name.capitalize }"
|
431
|
-
::Guard::UI.error loadError.to_s
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
# Locate a path to a Guard plugin gem.
|
144
|
+
# @example Find a group by Regexp
|
145
|
+
# Guard.group(/(back|front)end/)
|
437
146
|
#
|
438
|
-
# @param [String
|
439
|
-
# @return [
|
147
|
+
# @param [String, Symbol, Regexp] filter the filter for finding the group
|
148
|
+
# @return [Group] the group found, nil otherwise
|
440
149
|
#
|
441
|
-
def
|
442
|
-
|
443
|
-
Gem::Specification.find_by_name("guard-#{ name }").full_gem_path
|
444
|
-
else
|
445
|
-
Gem.source_index.find_name("guard-#{ name }").last.full_gem_path
|
446
|
-
end
|
447
|
-
rescue
|
448
|
-
::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
|
150
|
+
def group(filter)
|
151
|
+
groups(filter).first
|
449
152
|
end
|
450
153
|
|
451
|
-
#
|
452
|
-
#
|
453
|
-
# @return [Array<String>] a list of Guard plugin gem names
|
154
|
+
# Add a Guard plugin to use.
|
454
155
|
#
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
File.exists?( guard_plugin_path )
|
463
|
-
end
|
464
|
-
end
|
465
|
-
else
|
466
|
-
Gem.source_index.find_name(/^guard-/)
|
467
|
-
end.map { |x| x.name.sub(/^guard-/, '') }
|
468
|
-
end
|
469
|
-
|
470
|
-
# Adds a command logger in debug mode. This wraps common command
|
471
|
-
# execution functions and logs the executed command before execution.
|
156
|
+
# @param [String] name the Guard name
|
157
|
+
# @param [Hash] options the plugin options (see the given Guard documentation)
|
158
|
+
# @option options [String] group the group to which the Guard plugin belongs
|
159
|
+
# @option options [Array<Watcher>] watchers the list of declared watchers
|
160
|
+
# @option options [Array<Hash>] callbacks the list of callbacks
|
161
|
+
# @return [Plugin] the added Guard plugin
|
162
|
+
# @see Plugin
|
472
163
|
#
|
473
|
-
def
|
474
|
-
|
475
|
-
|
476
|
-
::Guard::UI.debug "Command execution: #{ command } #{ args.join(' ') }"
|
477
|
-
original_system command, *args
|
478
|
-
end
|
164
|
+
def add_plugin(name, options = {})
|
165
|
+
plugin_instance = ::Guard::PluginUtil.new(name).initialize_plugin(options)
|
166
|
+
@plugins << plugin_instance
|
479
167
|
|
480
|
-
|
481
|
-
Kernel.send(:define_method, :'`') do |command|
|
482
|
-
::Guard::UI.debug "Command execution: #{ command }"
|
483
|
-
original_backtick command
|
484
|
-
end
|
168
|
+
plugin_instance
|
485
169
|
end
|
486
170
|
|
487
|
-
#
|
488
|
-
WATCH_ALL_MODIFICATIONS_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
|
489
|
-
Starting with Guard v1.1 the 'watch_all_modifications' option is removed and is now always on.
|
490
|
-
EOS
|
491
|
-
|
492
|
-
# Deprecation message for the `no_vendor` start option
|
493
|
-
NO_VENDOR_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
|
494
|
-
Starting with Guard v1.1 the 'no_vendor' option is removed because the monitoring
|
495
|
-
gems are now part of a new gem called Listen. (https://github.com/guard/listen)
|
496
|
-
|
497
|
-
You can specify a custom version of any monitoring gem directly in your Gemfile
|
498
|
-
if you want to overwrite Listen's default monitoring gems.
|
499
|
-
EOS
|
500
|
-
|
501
|
-
# Displays a warning for each deprecated options used.
|
171
|
+
# Add a Guard plugin group.
|
502
172
|
#
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
#
|
173
|
+
# @param [String] name the group name
|
174
|
+
# @option options [Boolean] halt_on_fail if a task execution
|
175
|
+
# should be halted for all Guard plugins in this group if
|
176
|
+
# one Guard throws `:task_has_failed`
|
177
|
+
# @return [Group] the group added (or retrieved from the `@groups`
|
178
|
+
# variable if already present)
|
509
179
|
#
|
510
|
-
# @
|
511
|
-
# convert_scopes({ :guard => :rspec, :group => :backend })
|
512
|
-
# => { :plugins => [:rspec], :groups => [:backend] }
|
180
|
+
# @see Group
|
513
181
|
#
|
514
|
-
def
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
if group = scopes.delete(:group)
|
520
|
-
scopes[:groups] = [group]
|
182
|
+
def add_group(name, options = {})
|
183
|
+
unless group = group(name)
|
184
|
+
group = ::Guard::Group.new(name, options)
|
185
|
+
@groups << group
|
521
186
|
end
|
522
187
|
|
523
|
-
|
188
|
+
group
|
524
189
|
end
|
525
190
|
|
526
|
-
# Determine if Guard needs to quit. This
|
527
|
-
# checks for Ctrl-D pressed.
|
528
|
-
#
|
529
|
-
# @return [Boolean] whether to quit or not
|
530
|
-
#
|
531
|
-
def quit?
|
532
|
-
STDIN.read_nonblock(1)
|
533
|
-
false
|
534
|
-
rescue Errno::EINTR
|
535
|
-
false
|
536
|
-
rescue Errno::EAGAIN
|
537
|
-
false
|
538
|
-
rescue EOFError
|
539
|
-
true
|
540
|
-
end
|
541
191
|
end
|
542
192
|
end
|