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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -10
  3. data/README.md +54 -33
  4. data/lib/guard.rb +133 -483
  5. data/lib/guard/cli.rb +78 -82
  6. data/lib/guard/commander.rb +121 -0
  7. data/lib/guard/commands/all.rb +1 -1
  8. data/lib/guard/commands/reload.rb +1 -1
  9. data/lib/guard/deprecated_methods.rb +59 -0
  10. data/lib/guard/deprecator.rb +107 -0
  11. data/lib/guard/dsl.rb +143 -329
  12. data/lib/guard/dsl_describer.rb +101 -57
  13. data/lib/guard/group.rb +27 -8
  14. data/lib/guard/guard.rb +25 -150
  15. data/lib/guard/guardfile.rb +35 -85
  16. data/lib/guard/guardfile/evaluator.rb +245 -0
  17. data/lib/guard/guardfile/generator.rb +89 -0
  18. data/lib/guard/interactor.rb +147 -163
  19. data/lib/guard/notifier.rb +83 -137
  20. data/lib/guard/notifiers/base.rb +220 -0
  21. data/lib/guard/notifiers/emacs.rb +39 -37
  22. data/lib/guard/notifiers/file_notifier.rb +29 -25
  23. data/lib/guard/notifiers/gntp.rb +68 -75
  24. data/lib/guard/notifiers/growl.rb +49 -52
  25. data/lib/guard/notifiers/growl_notify.rb +51 -56
  26. data/lib/guard/notifiers/libnotify.rb +41 -48
  27. data/lib/guard/notifiers/notifysend.rb +58 -38
  28. data/lib/guard/notifiers/rb_notifu.rb +54 -54
  29. data/lib/guard/notifiers/terminal_notifier.rb +48 -36
  30. data/lib/guard/notifiers/terminal_title.rb +23 -19
  31. data/lib/guard/notifiers/tmux.rb +110 -93
  32. data/lib/guard/options.rb +21 -0
  33. data/lib/guard/plugin.rb +66 -0
  34. data/lib/guard/plugin/base.rb +178 -0
  35. data/lib/guard/plugin/hooker.rb +123 -0
  36. data/lib/guard/plugin_util.rb +158 -0
  37. data/lib/guard/rake_task.rb +47 -0
  38. data/lib/guard/runner.rb +62 -82
  39. data/lib/guard/setuper.rb +248 -0
  40. data/lib/guard/ui.rb +24 -80
  41. data/lib/guard/ui/colors.rb +60 -0
  42. data/lib/guard/version.rb +1 -2
  43. data/lib/guard/watcher.rb +30 -30
  44. data/man/guard.1 +4 -4
  45. data/man/guard.1.html +6 -4
  46. metadata +25 -11
  47. data/lib/guard/hook.rb +0 -120
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5058ee4dcf31a41ecc9be8bc4fa80d1e07b78e7a
4
- data.tar.gz: 212550736d4d08e333f3e968f60980083f15b393
3
+ metadata.gz: ec53a40ba0d6bb529aba462d295f5959631fc2de
4
+ data.tar.gz: 730479188a61cfdafea27ee0ed417ef72ef09fc2
5
5
  SHA512:
6
- metadata.gz: df4481ed0881fa095882c6f1444dc92a9f1e04c6bd9cecaf7028d06e1ba69bf842acf2453fd6838ee44718b835f99e2ef686bd407cc50d2ea39e635c5d5c1716
7
- data.tar.gz: 94c0359e6c917b38d249ece6613ee5d80a3969c7b4424fd7da65d7d9e7dd464eed00927c88b05d10594c78328efbeb5ef5890c567fe5cabd206b0ad2000d8526
6
+ metadata.gz: b98bfa844663944ed92554b69af8edb2f8cc1f63de2d7d0ef374c828414ceb5ebbd7fb5f07b7ecb904f52c86522ac721c973062e331c5677dfa47da8572faae3
7
+ data.tar.gz: f9d2785f7edf80c6e81fac7d05f87dfb732442e9bf38b27ba3e8a2decbb2f5f3817f0e1c5d9411c5508bd61f8710ed7bebec31b0b465ef9df8b24c2daef1a4df
@@ -1,6 +1,55 @@
1
1
  ## Master
2
2
 
3
- No changes yet.
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` DSL method. ([@netzpirat][])
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!` DSL methods. ([@tarsolya][])
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 DSL to allow switching Guard interaction implementation. ([@netzpirat][])
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 `:halt_on_fail => true`. ([@rymai][])
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 DSL. ([@ianwhite][])
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 `:transient => true` to default libnotify options. ([@zonque][])
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 DSL's `group` method to accept a Symbol as group name. ([@johnbintz][])
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 DSL method: `group` allows you to group several guards. New CLI option: `--group group_name` to specify certain groups of guards to start. ([@netzpirat][])
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::Dsl`. ([@oliamb][])
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](#known-issues)_ and _[file an issue](#file-an-issue)_ sections that contains some important information.
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 190](https://rubygems.org/search?query=guard-) guard plugins.
26
- * Tested against Ruby 1.8.7, 1.9.2, 1.9.3, 2.0.0, REE and the latest versions of JRuby & Rubinius.
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 introduction screen casts to Guard are available that helps you get started:
30
+ Two nice screencasts are available to help you get started:
31
31
 
32
- * [Guard is Your Best Friend](http://net.tutsplus.com/tutorials/tools-and-tips/guard-is-your-best-friend) on Net Tuts+
33
- * [Guard](http://railscasts.com/episodes/264-guard) on RailsCast
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
- To request more detailed help on a specific task is simple: just appending the task name to the help task.
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[:clear] = true
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#shared-configurations).
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, :input => 'coffeescripts', :output => 'javascripts'
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, :input => 'coffeescripts', :output => 'javascripts'
395
- guard :coffeescript, :input => 'specs', :output => 'specs'
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, :halt_on_fail => true do
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 :plugin => :rspec
496
- scope :group => :docs
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 :plugins => [:test, :jasmine]
503
- scope :groups => [:docs, :frontend]
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, :sticky => true
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, :sticky => true, :host => '192.168.1.5', :password => 'secret'
529
- notification :gntp, :sticky => true, :host => '192.168.1.5', :password => 'secret'
530
- notification :growl_notify, :sticky => true, :priority => 0
531
- notification :libnotify, :timeout => 5, :transient => true, :append => false, :urgency => :critical
532
- notification :notifu, :time => 5, :nosound => true, :xp => true
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 :guard_rc => '~/.my_guard-rc', :history_file => '~/.my_guard_history_file'
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-filtering-and-ignoring-paths).
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-filtering-and-ignoring-paths).
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 :level => :warn,
628
- :template => '[:severity - :time - :progname] :message',
629
- :time_format => 'at %I:%M%p',
630
- :only => [:rspec, :jasmine, 'coffeescript'],
631
- :except => :jammit,
632
- :device => 'guard.log'
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/))
@@ -1,320 +1,112 @@
1
1
  require 'rbconfig'
2
- require 'thread'
3
- require 'listen'
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
- require 'guard/dsl'
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
- class << self
29
- attr_accessor :options, :interactor, :runner, :listener, :lock, :scope, :running
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
- def setup_debug
80
- if options[:debug]
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
- # Initialize the groups array with the `:default` group.
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
- def setup_groups
92
- @groups = [Group.new(:default)]
93
- end
94
-
95
- # Initialize the guards array to an empty array.
96
- #
97
- # @see Guard.guards
98
- #
99
- def setup_guards
100
- @guards = []
101
- end
102
-
103
- # Initializes the listener and registers a callback for changes.
104
- #
105
- def setup_listener
106
- listener_callback = lambda do |modified, added, removed|
107
-
108
- # Convert to relative paths (respective to the watchdir it came from)
109
- @watchdirs.each do |watchdir|
110
- [modified, added, removed].each do |paths|
111
- paths.map! do |path|
112
- if path.start_with? watchdir
113
- path.sub "#{watchdir}#{File::SEPARATOR}", ''
114
- else
115
- path
116
- end
117
- end
118
- end
119
- end
120
- ::Guard::Dsl.reevaluate_guardfile if ::Guard::Watcher.match_guardfile?(modified)
121
-
122
- ::Guard.within_preserved_state do
123
- runner.run_on_changes(modified, added, removed)
124
- end
125
- end
126
-
127
- listener_options = {}
128
- %w[latency force_polling].each do |option|
129
- listener_options[option.to_sym] = options[option] if options.key?(option)
130
- end
131
-
132
- listen_args = @watchdirs + [listener_options]
133
- @listener = Listen.to(*listen_args).change(&listener_callback)
134
- end
135
-
136
- # Sets up traps to catch signals used to control Guard.
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 Filter Guard plugins by String or Symbol
282
- # Guard.guards('rspec')
283
- # Guard.guards(:rspec)
87
+ # @example Find a plugin by String or Symbol
88
+ # Guard.plugin('rspec')
89
+ # Guard.plugin(:rspec)
284
90
  #
285
- # @example Filter Guard plugins by Regexp
286
- # Guard.guards(/rsp.+/)
91
+ # @example Find a plugin by Regexp
92
+ # Guard.plugin(/rsp.+/)
287
93
  #
288
- # @example Filter Guard plugins by Hash
289
- # Guard.guards({ :name => 'rspec', :group => 'backend' })
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 to apply to the Guard plugins
292
- # @return [Array<Guard>] the filtered Guard plugins
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 guards(filter = nil)
295
- @guards ||= []
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 a specific plugin group or several plugin groups at once.
105
+ # Smart accessor for retrieving specific groups at once.
316
106
  #
317
- # @see Guard.guards
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 groups
119
+ # @return [Array<Group>] the filtered group(s)
328
120
  #
329
121
  def groups(filter = nil)
330
- case filter
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
- # Add a Guard plugin to use.
341
- #
342
- # @param [String] name the Guard name
343
- # @param [Array<Watcher>] watchers the list of declared watchers
344
- # @param [Array<Hash>] callbacks the list of callbacks
345
- # @param [Hash] options the plugin options (see the given Guard documentation)
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
- # Add a Guard plugin group.
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
- # Runs a block where the interactor is
377
- # blocked and execution is synchronized
378
- # to avoid state inconsistency.
134
+ # Smart accessor for retrieving a specific group.
379
135
  #
380
- # @param [Boolean] restart_interactor whether to restart the interactor or not
381
- # @yield the block to run
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
- # @param [String] name the name of the Guard
411
- # @param [Boolean] fail_gracefully whether error messages should not be printed
412
- # @return [Class, nil] the loaded class
140
+ # @example Find a group by String or Symbol
141
+ # Guard.group('backend')
142
+ # Guard.group(:backend)
413
143
  #
414
- def get_guard_class(name, fail_gracefully=false)
415
- name = name.to_s
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] name the name of the Guard plugin without the prefix `guard-`
439
- # @return [String] the full path to the Guard gem
147
+ # @param [String, Symbol, Regexp] filter the filter for finding the group
148
+ # @return [Group] the group found, nil otherwise
440
149
  #
441
- def locate_guard(name)
442
- if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
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
- # Returns a list of Guard plugin Gem names installed locally.
452
- #
453
- # @return [Array<String>] a list of Guard plugin gem names
154
+ # Add a Guard plugin to use.
454
155
  #
455
- def guard_gem_names
456
- if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
457
- Gem::Specification.find_all.select do |x|
458
- if x.name =~ /^guard-/
459
- true
460
- elsif x.name != 'guard'
461
- guard_plugin_path = File.join(x.full_gem_path, "lib/guard/#{ x.name }.rb")
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 debug_command_execution
474
- Kernel.send(:alias_method, :original_system, :system)
475
- Kernel.send(:define_method, :system) do |command, *args|
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
- Kernel.send(:alias_method, :original_backtick, :'`')
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
- # Deprecation message for the `watch_all_modifications` start option
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
- def deprecated_options_warning
504
- ::Guard::UI.deprecation(WATCH_ALL_MODIFICATIONS_DEPRECATION) if options[:watch_all_modifications]
505
- ::Guard::UI.deprecation(NO_VENDOR_DEPRECATION) if options[:no_vendor]
506
- end
507
-
508
- # Convert the old scope format to the new scope format.
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
- # @example Convert old scopes
511
- # convert_scopes({ :guard => :rspec, :group => :backend })
512
- # => { :plugins => [:rspec], :groups => [:backend] }
180
+ # @see Group
513
181
  #
514
- def convert_scopes(scopes)
515
- if plugin = scopes.delete(:guard)
516
- scopes[:plugins] = [plugin]
517
- end
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
- scopes
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