Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' into clear

Conflicts:
	lib/guard.rb
  • Loading branch information...
commit 2fe5b280999494aa645d6eb03de0874312b05d3f 2 parents 3c6f508 + 2a16651
Thibaud Guillaume-Gentil authored
Showing with 824 additions and 404 deletions.
  1. +9 −5 .travis.yml
  2. +41 −5 CHANGELOG.md
  3. +35 −16 Gemfile
  4. +6 −20 Guardfile
  5. +82 −44 README.md
  6. +2 −5 guard.gemspec
  7. +69 −68 lib/guard.rb
  8. +24 −13 lib/guard/cli.rb
  9. +32 −23 lib/guard/dsl.rb
  10. +14 −15 lib/guard/dsl_describer.rb
  11. +6 −3 lib/guard/group.rb
  12. +41 −41 lib/guard/guard.rb
  13. +3 −0  lib/guard/guardfile.rb
  14. +5 −3 lib/guard/hook.rb
  15. +18 −14 lib/guard/interactor.rb
  16. +7 −5 lib/guard/interactors/coolline.rb
  17. +2 −0  lib/guard/interactors/helpers/completion.rb
  18. +3 −3 lib/guard/interactors/helpers/terminal.rb
  19. +14 −8 lib/guard/interactors/readline.rb
  20. +3 −1 lib/guard/interactors/simple.rb
  21. +56 −37 lib/guard/notifier.rb
  22. +69 −0 lib/guard/notifiers/emacs.rb
  23. +2 −1  lib/guard/notifiers/gntp.rb
  24. +1 −0  lib/guard/notifiers/growl.rb
  25. +2 −1  lib/guard/notifiers/growl_notify.rb
  26. +1 −0  lib/guard/notifiers/libnotify.rb
  27. +1 −0  lib/guard/notifiers/notifysend.rb
  28. +1 −0  lib/guard/notifiers/rb_notifu.rb
  29. +66 −0 lib/guard/notifiers/terminal_notifier.rb
  30. +22 −19 lib/guard/runner.rb
  31. +2 −2 lib/guard/ui.rb
  32. +1 −1  lib/guard/version.rb
  33. +13 −11 lib/guard/watcher.rb
  34. +18 −9 man/guard.1
  35. +20 −11 man/guard.1.html
  36. +19 −10 man/guard.1.ronn
  37. +7 −0 spec/guard/cli_spec.rb
  38. +2 −2 spec/guard/dsl_spec.rb
  39. +1 −1  spec/guard/hook_spec.rb
  40. +2 −0  spec/guard/notifier_spec.rb
  41. +24 −0 spec/guard/notifiers/emacs_spec.rb
  42. +3 −3 spec/guard/notifiers/gntp_spec.rb
  43. +57 −0 spec/guard/notifiers/terminal_notifier_spec.rb
  44. +17 −4 spec/guard_spec.rb
  45. +1 −0  spec/spec_helper.rb
View
14 .travis.yml
@@ -1,23 +1,27 @@
+language: ruby
+bundler_args: --without development
rvm:
- 1.8.7
- 1.9.2
- 1.9.3
- ruby-head
- ree
- # - jruby-18mode
- # - jruby-19mode
- # - jruby-head
+ - jruby-18mode
+ - jruby-19mode
+ - jruby-head
- rbx-18mode
- rbx-19mode
+matrix:
+ allow_failures:
+ - rvm: ruby-head
+ - rvm: jruby-head
branches:
only:
- master
- - listen
notifications:
recipients:
- thibaud@thibaud.me
- rymai@rymai.me
- michi@netzpiraten.ch
- - yann.lugrin@sans-savoir.net
- maher@sallam.me
irc: "irc.freenode.org#guard"
View
46 CHANGELOG.md
@@ -1,4 +1,33 @@
-## Master
+## 1.3.1 - 14 August, 2012
+
+### Improvements
+
+- [#317][] Switch to Terminal-Notifier-Guard gem. ([@foxycoder][])
+- [#315][] Improve Emacs detection. ([@maio][])
+
+## 1.3.0 - 3 August, 2012
+
+### Bug fix
+
+- [#299][] Fix Readline interactor on JRruby. ([@netzpirat][])
+
+### Improvements
+
+- Add support for OS X notification center ([@foxycoder][])
+- Add support for Emacs notifications ([@maio][])
+- Add support for multiple guards being passed to `guard init`. ([@jredville][])
+
+### 1.2.1 - 2 Juli, 2012
+
+### Bug fix
+
+- Fix template methods in the Guard plugin class that causes loss of listen changes. ([@netzpirat][])
+
+### 1.2.2 - 2 Juli, 2012
+
+### Bug fix
+
+- [#298][] Deprecations must be explicit enabled. ([@netzpirat][])
### 1.2.1 - 20 June, 2012
@@ -31,7 +60,7 @@
- New `--force-polling`/`-p` option to force usage of the Listen polling listener.
- `--watch-all-modifications`/`-A` option is removed and is now always on.
- `--no-vendor`/`-I` option is removed because the monitoring gems are now part of the [Listen gem](https://github.com/guard/listen). You can specify a custom version of any monitoring gem directly in your Gemfile if you want to overwrite Listen's default monitoring gems.
-- Guards implementations must now implement `run_on_additions`, `run_on_modifications`, `run_on_removals` and / or `run_on_changes`. The `run_on_change` and `run_on_deletion` methods are deprecated and should be removed as soon as possible. See the [Upgrade guide for existing guards to Guard v1.1](https://github.com/guard/guard/wiki/Upgrade-guide-for-existing-guards-to-Guard-v1.1) for more info.
+- Guard plugins must now implement `run_on_additions`, `run_on_modifications`, `run_on_removals` and / or `run_on_changes`. The `run_on_change` and `run_on_deletion` methods are deprecated and should be removed as soon as possible. See the [Upgrade guide for existing guards to Guard v1.1](https://github.com/guard/guard/wiki/Upgrade-guide-for-existing-guards-to-Guard-v1.1) for more info.
The Listen integration has been supervised by [@thibaudgg][] and executed by [@Maher4Ever][], [@rymai][] and [@thibaudgg][].
@@ -219,7 +248,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
- [#136][] New CLI `:watch_all_modifications`/`-A` option to watch for deleted and moved files too. ([@limeyd][] and [@netzpirat][])
- [#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][])
-- [#121][] `Guard.guards` and `Guard.groups` are now smart accessors. Filters can be passed to find a specific Guard/group or several Guards/groups that match (see YARDoc). ([@rymai][] and [@ches][])
+- [#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][])
- New `Guard::Group` class to store groups defined in Guardfile (with `Guard::Dsl#group`). ([@rymai][])
### Improvements
@@ -262,7 +291,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
### New features
- Groups are now stored in a `groups` instance variable (will be used for future features). ([@rymai][])
-- Guards will now receive their group in the options hash at initialization (will be used for future features). ([@rymai][])
+- Guard plugins will now receive their group in the options hash at initialization (will be used for future features). ([@rymai][])
### Improvement
@@ -308,7 +337,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
### New features
- Guard::Ego is now part of Guard, so Guardfile is automagically re-evaluated when modified. ([@thibaudgg][])
-- [#91][] Show Guards in Guardfile with the `guard -T`. ([@johnbintz][])
+- [#91][] Show Guard plugins in Guardfile with the `guard -T`. ([@johnbintz][])
### Improvements
@@ -549,6 +578,10 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
[#274]: https://github.com/guard/guard/issues/274
[#275]: https://github.com/guard/guard/issues/275
[#283]: https://github.com/guard/guard/issues/283
+[#298]: https://github.com/guard/guard/issues/298
+[#299]: https://github.com/guard/guard/issues/299
+[#315]: https://github.com/guard/guard/issues/315
+[#317]: https://github.com/guard/guard/issues/317
[@Gazer]: https://github.com/Gazer
[@Maher4Ever]: https://github.com/Maher4Ever
[@alandipert]: https://github.com/alandipert
@@ -569,6 +602,7 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
[@f1sherman]: https://github.com/f1sherman
[@fabioyamate]: https://github.com/fabioyamate
[@fnichol]: https://github.com/fnichol
+[@foxycoder]: https://github.com/foxycoder
[@gix]: https://github.com/gix
[@hardipe]: https://github.com/hardipe
[@hashrocketeer]: https://github.com/hashrocketeer
@@ -578,11 +612,13 @@ The Listen integration has been supervised by [@thibaudgg][] and executed by [@M
[@indirect]: https://github.com/indirect
[@jeffutter]: https://github.com/jeffutter
[@johnbintz]: https://github.com/johnbintz
+[@jredville]: https://github.com/jredville
[@jrsacks]: https://github.com/jrsacks
[@koshigoe]: https://github.com/koshigoe
[@laserlemon]: https://github.com/laserlemon
[@limeyd]: https://github.com/limeyd
[@madtrick]: https://github.com/madtrick
+[@maio]: https://github.com/maio
[@mcmire]: https://github.com/mcmire
[@mislav]: https://github.com/mislav
[@monocle]: https://github.com/monocle
View
51 Gemfile
@@ -3,27 +3,46 @@ source :rubygems
gemspec
gem 'rake'
+gem 'listen', :github => 'guard/listen'
-platform :ruby do
- gem 'coolline'
-end
+# The development group will no be
+# installed on Travis CI.
+#
+group :development do
+
+ gem 'pry'
-group :guard do
gem 'guard-ronn'
-end
-require 'rbconfig'
+ gem 'yard'
+ gem 'redcarpet'
-if RbConfig::CONFIG['target_os'] =~ /darwin/i
- gem 'growl', :require => false
-elsif RbConfig::CONFIG['target_os'] =~ /linux/i
- gem 'libnotify', '~> 0.7.1', :require => false
-elsif RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
- gem 'win32console', :require => false
- gem 'rb-notifu', '>= 0.0.4', :require => false
-end
+ platform :ruby_19 do
+ gem 'coolline'
+ end
+ require 'rbconfig'
-gem 'listen', :github => 'guard/listen'
-gem 'guard-rspec', :github => 'guard/guard-rspec', :branch => 'guard_1_1'
+ if RbConfig::CONFIG['target_os'] =~ /darwin/i
+ gem 'growl', :require => false
+ if `uname`.strip == 'Darwin' && `sw_vers -productVersion`.strip >= '10.8'
+ gem 'terminal-notifier-guard', '~> 1.5.3', :require => false
+ end rescue Errno::ENOENT
+
+ elsif RbConfig::CONFIG['target_os'] =~ /linux/i
+ gem 'libnotify', '~> 0.7.1', :require => false
+
+ elsif RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
+ gem 'win32console', :require => false
+ gem 'rb-notifu', '>= 0.0.4', :require => false
+ end
+end
+
+# The test group will be
+# installed on Travis CI
+#
+group :test do
+ gem 'rspec'
+ gem 'guard-rspec'
+end
View
26 Guardfile
@@ -1,29 +1,15 @@
notification :off
group :specs do
- guard :rspec, :all_on_start => false, :all_after_pass => false, :cli => '--fail-fast --format doc' do
+ guard :rspec, :cli => '--fail-fast --format doc' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
end
end
-# group :docs do
-# guard :ronn do
-# watch(%r{^man/.+\.ronn?$})
-# end
-# end
-
-# require 'guard/guard'
-#
-# module ::Guard
-# class Breaking < ::Guard::Guard
-# def run_all
-# raise "Fool !"
-# end
-# end
-# end
-#
-# group "exceptional" do
-# guard :breaking
-# end
+#group :docs do
+# guard :ronn do
+# watch(%r{^man/.+\.ronn?$})
+# end
+#end
View
126 README.md
@@ -7,7 +7,7 @@ This document contains a lot of information, please take your time and read thes
any questions, ask them in our [Google group](http://groups.google.com/group/guard-dev) or on `#guard`
(irc.freenode.net).
-Information on advanced topics like create your own Guard plugin, programatic use of Guard, hooks and callbacks and
+Information on advanced topics like creating your own Guard plugin, programatic use of Guard, hooks and callbacks and
more can be found in the [Guard wiki](https://github.com/guard/guard/wiki).
Before you file an issue, make sure you have read the _[file an issue](#file-an-issue)_ section that contains some
@@ -18,7 +18,7 @@ Features
* File system changes handled by our awesome [Listen](https://github.com/guard/listen) gem.
* Support for visual system notifications.
-* Huge ([more than 120](https://rubygems.org/search?query=guard-)) guard extensions eco-system.
+* Huge eco-system with [more than 130](https://rubygems.org/search?query=guard-) guard plugins.
* Tested against Ruby 1.8.7, 1.9.2, 1.9.3, REE and the latest versions of JRuby & Rubinius.
Screencast
@@ -171,22 +171,41 @@ group :development do
end
```
-Add more Guards
----------------
+#### Emacs
-Guard is now ready to use and you should add some Guards for your specific use. Start exploring the many Guards
-available by browsing the [Guard organization](https://github.com/guard) on GitHub or by searching for `guard-` on
-[RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=guard-).
+* Runs on any platform with Emacs + emacsclient (http://www.emacswiki.org/emacs/EmacsClient)
-When you have found a Guard of your interest, add it to your `Gemfile`:
+#### Terminal Notifier
+
+* Runs on Mac OS X 10.8 only
+
+The [terminal-notifier-guard](https://github.com/Springest/terminal-notifier-guard) sends notifications to the OS X
+Notification Center.
+
+To use `terminal-notifier-guard` you have to add it to your `Gemfile` and run bundler:
```ruby
group :development do
- gem '<guard-name>'
+ gem 'terminal-notifier-guard'
end
```
-See the init section of the Guard usage below to see how to install the supplied Guard template that you can install and
+Add Guard plugins
+-----------------
+
+Guard is now ready to use and you should add some Guard plugins for your specific use. Start exploring the many Guard
+plugins available by browsing the [Guard organization](https://github.com/guard) on GitHub or by searching for `guard-`
+on [RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=guard-).
+
+When you have found a Guard plugin of your interest, add it to your `Gemfile`:
+
+```ruby
+group :development do
+ gem '<guard-plugin-name>'
+end
+```
+
+See the init section of the Guard usage below to see how to install the supplied plugin template that you can install and
to suit your needs.
Usage
@@ -211,20 +230,27 @@ $ guard help start
### Init
-You can generate a Guardfile and have all installed guards be automatically added into
+You can generate a Guardfile and have all installed plugins be automatically added into
it by running the `init` task without any option:
```bash
$ guard init
```
-You can also specify the name of an installed Guard to only get that Guard
+You can also specify the name of an installed plugin to only get that plugin template
in the generated Guardfile:
```bash
$ guard init <guard-name>
```
+You can also specify the names of multiple plugins to only get those plugin templates
+in the generated Guardfile:
+
+```bash
+$ guard init <guard1-name> <guard2-name>
+```
+
You can also define your own templates in `~/.guard/templates/` which can be appended in the same way to your existing
`Guardfile`:
@@ -233,8 +259,7 @@ $ guard init <template-name>
```
**Note**: If you already have a `Guardfile` in the current directory, the `init` task can be used
-to append a supplied Guard template from an installed Guard to your existing
-`Guardfile`.
+to append a supplied template from an installed plugin to your existing `Guardfile`.
#### `-b`/`--bare` option
@@ -279,7 +304,7 @@ Notifications can also be disabled globally by setting a `GUARD_NOTIFY` environm
#### `-g`/`--group` option
-Only certain Guard groups can be run:
+Only certain plugin groups can be run:
```bash
$ guard --group group_name another_group_name
@@ -300,7 +325,7 @@ $ guard -d # shortcut
#### `-w`/`--watchdir` option
-Guard can watch in any directory instead of the current directory:
+Guard can watch any directory instead of the current directory:
```bash
$ guard --watchdir ~/your/fancy/project
@@ -354,7 +379,7 @@ $ guard start --force-polling
### List
-You can list the available Guards with the `list` task:
+You can list the available plugins with the `list` task:
```bash
$ guard list
@@ -374,7 +399,7 @@ See also https://github.com/guard/guard/wiki/List-of-available-Guards
### Show
-You can show the structure of the groups and their Guards with the `show` task:
+You can show the structure of the groups and their plugins with the `show` task:
```bash
$ guard show
@@ -397,41 +422,41 @@ Interactions
You can interact with Guard and enter commands when Guard has nothing to do. Guard understands the following commands:
-* `↩`: Run all Guards.
+* `↩`: Run all plugins.
* `h`, `help`: Show a help of the available interactor commands.
-* `r`, `reload`: Reload all Guards.
-* `c`, `change`: Show a help of the available interactor commands.
-* `s`, `show`: Show Guard plugin configuration.
+* `r`, `reload`: Reload all plugins.
+* `c`, `change`: Trigger a file change to the plugins.
+* `s`, `show`: Show the plugin configurations.
* `n`, `notification`: Toggle system notifications on and off.
* `p`, `pause`: Toggles the file modification listener. The prompt will change to `p>` when paused.
This is useful when switching Git branches, rebase Git or change whitespace.
-* `e`, `exit`: Stop all Guards and quit Guard.
+* `e`, `exit`: Stop all plugins and quit Guard.
-Instead of running all Guards with the `↩` key, you can also run a single Guard by entering its name:
+Instead of running all plugins with the `↩` key, you can also run a single plugin by entering its name:
```bash
> rspec
```
-It's also possible to run all Guards within a group by entering the group name:
+It's also possible to run all plugins within a group by entering the group name:
```bash
> frontend
```
-The same applies to Guard reloading. You can reload a Guard with the following command:
+The same applies to reloading. You can reload a plugin with the following command:
```bash
> ronn reload
```
-This will reload only the Ronn Guard. You can also reload all Guards within a group:
+This will reload only the Ronn plugin. You can also reload all plugins within a group:
```bash
> backend reload
```
-The action and plugin or group name can have any order, so you can also write:
+The action and plugin/group name can have any order, so you can also write:
```bash
> reload backend
@@ -474,7 +499,7 @@ Guard will automatically enable Coolline support if your environment supports it
### Signals
-You can also interact with Guard by sending POSIX signals to the Guard process (all but Windows).
+You can also interact with Guard by sending POSIX signals to the Guard process (all but Windows and JRuby).
#### Pause watching
@@ -496,14 +521,14 @@ Guard itself provides the following DSL methods that can be used for configurati
### guard
-The `guard` method allows you to add a Guard to your toolchain and configure it by passing the
-options after the name of the Guard:
+The `guard` method allows you to add a Guard plugin to your toolchain and configure it by passing the
+options after the name of the plugin:
```ruby
guard :coffeescript, :input => 'coffeescripts', :output => 'javascripts'
```
-You can define the same Guard more than once:
+You can define the same plugin more than once:
```ruby
guard :coffeescript, :input => 'coffeescripts', :output => 'javascripts'
@@ -529,13 +554,13 @@ guard :jessie do
end
```
-This instructs the jessie Guard to watch for file changes in the `spec` folder,
+This instructs the jessie plugin to watch for file changes in the `spec` folder,
but only for file names that ends with `_spec` or `Spec` and have a file type of `js` or `coffee`.
You can easily test your watcher regular expressions with [Rubular](http://rubular.com/).
When you add a block to the watch expression, you can modify the file name that has been
-detected before sending it to the Guard for processing:
+detected before sending it to the plugin for processing:
```ruby
guard :rspec do
@@ -557,7 +582,7 @@ end
### group
-The `group` method allows you to group several Guards together. This comes in handy especially when you
+The `group` method allows you to group several plugins together. This comes in handy especially when you
have a huge `Guardfile` and want to focus your development on a certain part.
```ruby
@@ -580,7 +605,7 @@ Groups to be run can be specified with the Guard DSL option `--group` (or `-g`):
$ guard -g specs
```
-Guards that don't belong to a group are considered global and are always run.
+Guard plugins that don't belong to a group are considered global and are always run.
### notification
@@ -606,6 +631,7 @@ notification :gntp, :sticky => true, :host => '192.168.1.5', :password => 'secre
notification :growl_notify, :sticky => true, :priority => 0
notification :libnotify, :timeout => 5, :transient => true, :append => false, :urgency => :critical
notification :notifu, :time => 5, :nosound => true, :xp => true
+notification :emacs
```
It's possible to use more than one notifier. This allows you to configure different notifiers for different OS if your
@@ -637,7 +663,8 @@ interactor :off
### callback
The `callback` method allows you to execute arbitrary code before or after any of the `start`, `stop`, `reload`,
-`run_all` and `run_on_change` Guards' method. You can even insert more hooks inside these methods.
+`run_all`, `run_on_changes`, `run_on_additions`, `run_on_modifications` and `run_on_removals` Guard plugins method.
+You can even insert more hooks inside these methods.
```ruby
guard :rspec do
@@ -652,9 +679,16 @@ more details.
### ignore
-The `ignore` method allows you to ignore specific paths. This comes is handy when you have large
-amounts of non-source data in you project. By default [`.rbx`, `.bundle`, `.git`, `.svn`, `log`, `tmp`, `vendor`](https://github.com/guard/listen/blob/master/lib/listen/directory_record.rb#L14) are ignored.
-Please note that method only accept regexps. More on the [Listen README](https://github.com/guard/listen#the-patterns-for-filtering-and-ignoring-paths).
+The `ignore` method can be used to exclude files and directories from the set of files being watched. Let's say you have
+used the `watch` method to monitor a directory, but you are not interested in changes happening to images, you could use
+the ignore method to exclude them.
+
+This comes in handy when you have large amounts of non-source data in you project. By default
+[`.rbx`, `.bundle`, `.git`, `.svn`, `log`, `tmp`, `vendor`](https://github.com/guard/listen/blob/master/lib/listen/directory_record.rb#L14)
+are ignored.
+
+Please note that method only accept regexps. More on the
+[Listen README](https://github.com/guard/listen#the-patterns-for-filtering-and-ignoring-paths).
```ruby
ignore %r{^ignored/path/}, /public/
@@ -662,8 +696,12 @@ ignore %r{^ignored/path/}, /public/
### filter
-The `filter` method allows you to filter specific paths.
-Please note that method only accept regexps. More on the [Listen README](https://github.com/guard/listen#the-patterns-for-filtering-and-ignoring-paths).
+The `filter` method allows you to focus by filtering files and directories without having to specify them by hand in the
+`watch` method. E.g. if you are watching multiple directories but only interested in changes to the Ruby files, then use
+the `filter` method.
+
+Please note that method only accept regexps. More on the
+[Listen README](https://github.com/guard/listen#the-patterns-for-filtering-and-ignoring-paths).
```ruby
filter /\.txt$/, /.*\.zip/
@@ -728,7 +766,7 @@ You can report bugs and feature requests to [GitHub Issues](https://github.com/g
**Please don't ask question in the issue tracker**, instead ask them in our
[Google group](http://groups.google.com/group/guard-dev) or on `#guard` (irc.freenode.net).
-Try to figure out where the issue belongs to: Is it an issue with Guard itself or with a Guard implementation you're
+Try to figure out where the issue belongs to: Is it an issue with Guard itself or with a Guard plugin you're
using?
When you file a bug, please try to follow these simple rules if applicable:
@@ -740,7 +778,7 @@ When you file a bug, please try to follow these simple rules if applicable:
**It's most likely that your bug gets resolved faster if you provide as much information as possible!**
-Development [![Dependency Status](https://gemnasium.com/guard/guard.png?branch=master)](https://gemnasium.com/guard/guard)
+Development [![Dependency Status](https://gemnasium.com/guard/guard.png?branch=master)](https://gemnasium.com/guard/guard) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/guard/guard)
-----------
* Documentation hosted at [RubyDoc](http://rubydoc.info/github/guard/guard/master/frames).
View
7 guard.gemspec
@@ -19,11 +19,8 @@ Gem::Specification.new do |s|
s.add_dependency 'listen', '>= 0.4.2'
s.add_development_dependency 'bundler'
- s.add_development_dependency 'rspec', '~> 2.10.0'
- s.add_development_dependency 'guard-rspec', '~> 1.1.0'
- s.add_development_dependency 'yard'
- s.add_development_dependency 'redcarpet'
- s.add_development_dependency 'pry'
+ s.add_development_dependency 'rspec', '~> 2.11.0'
+ s.add_development_dependency 'guard-rspec', '~> 1.2.1'
s.files = Dir.glob('{bin,images,lib}/**/*') + %w[CHANGELOG.md LICENSE man/guard.1 man/guard.1.html README.md]
s.executable = 'guard'
View
137 lib/guard.rb
@@ -2,23 +2,22 @@
require 'listen'
# Guard is the main module for all Guard related modules and classes.
-# Also other Guard implementation should use this namespace.
+# Also Guard plugins should use this namespace.
#
module Guard
- autoload :UI, 'guard/ui'
- autoload :Guardfile, 'guard/guardfile'
- autoload :Dsl, 'guard/dsl'
- autoload :DslDescriber, 'guard/dsl_describer'
- autoload :Group, 'guard/group'
- autoload :Interactor, 'guard/interactor'
- autoload :Watcher, 'guard/watcher'
- autoload :Notifier, 'guard/notifier'
- autoload :Runner, 'guard/runner'
- autoload :Hook, 'guard/hook'
+ require 'guard/dsl'
+ require 'guard/guardfile'
+ require 'guard/group'
+ require 'guard/interactor'
+ require 'guard/notifier'
+ require 'guard/runner'
+ require 'guard/ui'
+ require 'guard/watcher'
# The Guardfile template for `guard init`
GUARDFILE_TEMPLATE = File.expand_path('../guard/templates/Guardfile', __FILE__)
+
# The location of user defined templates
HOME_TEMPLATES = File.expand_path('~/.guard/templates')
@@ -44,10 +43,10 @@ def setup(options = {})
@lock = Mutex.new
@options = options
@watchdir = (options[:watchdir] && File.expand_path(options[:watchdir])) || Dir.pwd
- @runner = Runner.new
+ @runner = ::Guard::Runner.new
@allow_stop = Listen::Turnstile.new
- UI.clear(force: true)
+ ::Guard::UI.clear(force: true)
deprecated_options_warning
setup_groups
@@ -57,10 +56,10 @@ def setup(options = {})
debug_command_execution if @options[:debug]
- Dsl.evaluate_guardfile(options)
- UI.error 'No guards found in Guardfile, please add at least one.' if @guards.empty?
+ ::Guard::Dsl.evaluate_guardfile(options)
+ ::Guard::UI.error 'No guards found in Guardfile, please add at least one.' if @guards.empty?
- runner.deprecation_warning # Guard deprecation go here
+ runner.deprecation_warning if @options[:show_deprecations]
setup_notifier
setup_interactor
@@ -84,19 +83,21 @@ def setup_guards
@guards = []
end
- # Sets up traps to catch signlas used to control Guard.
+ # Sets up traps to catch signals used to control Guard.
#
- # Currently two signals are cought:
+ # Currently two signals are caught:
# - `USR1` which pauses listening to changes.
# - `USR2` which resumes listening to changes.
#
def setup_signal_traps
- if Signal.list.keys.include?('USR1')
- Signal.trap('USR1') { ::Guard.pause unless @listener.paused? }
- end
+ unless defined?(JRUBY_VERSION)
+ if Signal.list.keys.include?('USR1')
+ Signal.trap('USR1') { ::Guard.pause unless @listener.paused? }
+ end
- if Signal.list.keys.include?('USR2')
- Signal.trap('USR2') { ::Guard.pause if @listener.paused? }
+ if Signal.list.keys.include?('USR2')
+ Signal.trap('USR2') { ::Guard.pause if @listener.paused? }
+ end
end
end
@@ -104,7 +105,7 @@ def setup_signal_traps
#
def setup_listener
listener_callback = lambda do |modified, added, removed|
- Dsl.reevaluate_guardfile if Watcher.match_guardfile?(modified)
+ ::Guard::Dsl.reevaluate_guardfile if ::Guard::Watcher.match_guardfile?(modified)
::Guard.within_preserved_state do
runner.run_on_changes(modified, added, removed)
@@ -122,25 +123,25 @@ def setup_listener
# Enables or disables the notifier based on user's configurations.
#
def setup_notifier
- options[:notify] && ENV['GUARD_NOTIFY'] != 'false' ? Notifier.turn_on : Notifier.turn_off
+ options[:notify] && ENV['GUARD_NOTIFY'] != 'false' ? ::Guard::Notifier.turn_on : ::Guard::Notifier.turn_off
end
# Initializes the interactor unless the user has specified not to.
#
def setup_interactor
unless options[:no_interactions]
- @interactor = Interactor.fabricate
+ @interactor = ::Guard::Interactor.fabricate
end
end
- # Start Guard by evaluate the `Guardfile`, initialize the declared Guards
- # and start the available file change listener.
- # Main method for Guard that is called from the CLI when guard starts.
+ # Start Guard by evaluating the `Guardfile`, initializing declared Guard plugins
+ # and starting the available file change listener.
+ # Main method for Guard that is called from the CLI when Guard starts.
#
# - Setup Guard internals
# - Evaluate the `Guardfile`
# - Configure Notifiers
- # - Initialize the declared Guards
+ # - Initialize the declared Guard plugins
# - Start the available file change listener
#
# @option options [Boolean] clear if auto clear the UI should be done
@@ -152,7 +153,7 @@ def setup_interactor
#
def start(options = {})
setup(options)
- UI.info "Guard is now watching at '#{ @watchdir }'"
+ ::Guard::UI.info "Guard is now watching at '#{ @watchdir }'"
within_preserved_state do
runner.run(:start)
@@ -169,32 +170,32 @@ def stop
listener.stop
interactor.stop if interactor
runner.run(:stop)
- UI.info 'Bye bye...', :reset => true
+ ::Guard::UI.info 'Bye bye...', :reset => true
@allow_stop.signal if @allow_stop
end
- # Reload Guardfile and all Guards currently enabled.
+ # Reload Guardfile and all Guard plugins currently enabled.
#
- # @param [Hash] scopes an hash with a guard or a group scope
+ # @param [Hash] scopes hash with a Guard plugin or a group scope
#
- def reload(scopes)
+ def reload(scopes = {})
within_preserved_state do
- UI.clear(force: true)
- UI.action_with_scopes('Reload', scopes)
- Dsl.reevaluate_guardfile if scopes.empty?
+ ::Guard::UI.clear(force: true)
+ ::Guard::UI.action_with_scopes('Reload', scopes)
+ ::Guard::Dsl.reevaluate_guardfile if scopes.empty?
runner.run(:reload, scopes)
end
end
- # Trigger `run_all` on all Guards currently enabled.
+ # Trigger `run_all` on all Guard plugins currently enabled.
#
- # @param [Hash] scopes an hash with a guard or a group scope
+ # @param [Hash] scopes hash with a Guard plugin or a group scope
#
- def run_all(scopes)
+ def run_all(scopes = {})
within_preserved_state do
- UI.clear(force: true)
- UI.action_with_scopes('Run', scopes)
+ ::Guard::UI.clear(force: true)
+ ::Guard::UI.action_with_scopes('Run', scopes)
runner.run(:run_all, scopes)
end
end
@@ -203,30 +204,30 @@ def run_all(scopes)
#
def pause
if listener.paused?
- UI.info 'Un-paused files modification listening', :reset => true
+ ::Guard::UI.info 'Un-paused files modification listening', :reset => true
listener.unpause
else
- UI.info 'Paused files modification listening', :reset => true
+ ::Guard::UI.info 'Paused files modification listening', :reset => true
listener.pause
end
end
- # Smart accessor for retrieving a specific guard or several guards at once.
+ # Smart accessor for retrieving a specific Guard plugin or several Guard plugins at once.
#
# @see Guard.groups
#
- # @example Filter Guards by String or Symbol
+ # @example Filter Guard plugins by String or Symbol
# Guard.guards('rspec')
# Guard.guards(:rspec)
#
- # @example Filter Guards by Regexp
+ # @example Filter Guard plugins by Regexp
# Guard.guards(/rsp.+/)
#
- # @example Filter Guards by Hash
+ # @example Filter Guard plugins by Hash
# Guard.guards({ :name => 'rspec', :group => 'backend' })
#
- # @param [String, Symbol, Regexp, Hash] filter the filter to apply to the Guards
- # @return [Array<Guard>] the filtered Guards
+ # @param [String, Symbol, Regexp, Hash] filter the filter to apply to the Guard plugins
+ # @return [Array<Guard>] the filtered Guard plugins
#
def guards(filter = nil)
@guards ||= []
@@ -249,7 +250,7 @@ def guards(filter = nil)
end
end
- # Smart accessor for retrieving a specific group or several groups at once.
+ # Smart accessor for retrieving a specific plugin group or several plugin groups at once.
#
# @see Guard.guards
#
@@ -274,17 +275,17 @@ def groups(filter = nil)
end
end
- # Add a Guard to use.
+ # Add a Guard plugin to use.
#
# @param [String] name the Guard name
# @param [Array<Watcher>] watchers the list of declared watchers
# @param [Array<Hash>] callbacks the list of callbacks
- # @param [Hash] options the Guard options (see the given Guard documentation)
- # @return [Guard::Guard] the guard added
+ # @param [Hash] options the plugin options (see the given Guard documentation)
+ # @return [Guard::Guard] the added Guard plugin
#
def add_guard(name, watchers = [], callbacks = [], options = {})
if name.to_sym == :ego
- UI.deprecation('Guard::Ego is now part of Guard. You can remove it from your Guardfile.')
+ ::Guard::UI.deprecation('Guard::Ego is now part of Guard. You can remove it from your Guardfile.')
else
guard_class = get_guard_class(name)
callbacks.each { |callback| Hook.add_callback(callback[:listener], guard_class, callback[:events]) }
@@ -294,17 +295,17 @@ def add_guard(name, watchers = [], callbacks = [], options = {})
end
end
- # Add a Guard group.
+ # Add a Guard plugin group.
#
# @param [String] name the group name
# @option options [Boolean] halt_on_fail if a task execution
- # should be halted for all Guards in this group if one Guard throws `:task_has_failed`
+ # should be halted for all Guard plugins in this group if one Guard throws `:task_has_failed`
# @return [Guard::Group] the group added (or retrieved from the `@groups` variable if already present)
#
def add_group(name, options = {})
group = groups(name)
if group.nil?
- group = Group.new(name, options)
+ group = ::Guard::Group.new(name, options)
@groups << group
end
group
@@ -329,7 +330,7 @@ def within_preserved_state
@result
end
- # Tries to load the Guard main class. This transforms the supplied Guard
+ # Tries to load the Guard plugin main class. This transforms the supplied Guard plugin
# name into a class name:
#
# * `guardname` will become `Guard::Guardname`
@@ -357,19 +358,19 @@ def get_guard_class(name, fail_gracefully=false)
try_require = true
retry
else
- UI.error "Could not find class Guard::#{ const_name.capitalize }"
+ ::Guard::UI.error "Could not find class Guard::#{ const_name.capitalize }"
end
rescue LoadError => loadError
unless fail_gracefully
- UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ const_name.capitalize }"
- UI.error loadError.to_s
+ ::Guard::UI.error "Could not load 'guard/#{ name.downcase }' or find class Guard::#{ const_name.capitalize }"
+ ::Guard::UI.error loadError.to_s
end
end
end
- # Locate a path to a Guard gem.
+ # Locate a path to a Guard plugin gem.
#
- # @param [String] name the name of the Guard without the prefix `guard-`
+ # @param [String] name the name of the Guard plugin without the prefix `guard-`
# @return [String] the full path to the Guard gem
#
def locate_guard(name)
@@ -379,12 +380,12 @@ def locate_guard(name)
Gem.source_index.find_name("guard-#{ name }").last.full_gem_path
end
rescue
- UI.error "Could not find 'guard-#{ name }' gem path."
+ ::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
end
- # Returns a list of guard Gem names installed locally.
+ # Returns a list of Guard plugin Gem names installed locally.
#
- # @return [Array<String>] a list of guard gem names
+ # @return [Array<String>] a list of Guard plugin gem names
#
def guard_gem_names
if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
View
37 lib/guard/cli.rb
@@ -1,5 +1,4 @@
require 'thor'
-require 'guard/version'
module Guard
@@ -9,6 +8,11 @@ module Guard
#
class CLI < Thor
+ require 'guard'
+ require 'guard/version'
+ require 'guard/dsl_describer'
+ require 'guard/guardfile'
+
default_task :start
desc 'start', 'Starts Guard'
@@ -73,6 +77,11 @@ class CLI < Thor
:aliases => '-B',
:banner => 'Turn off warning when Bundler is not present'
+ method_option :show_deprecations,
+ :type => :boolean,
+ :default => false,
+ :banner => 'Turn on deprecation warnings'
+
# Listen options
method_option :latency,
:type => :numeric,
@@ -85,7 +94,7 @@ class CLI < Thor
:aliases => '-p',
:banner => 'Force usage of the Listen polling listener'
- # Start Guard by initialize the defined Guards and watch the file system.
+ # Start Guard by initializing the defined Guard plugins and watch the file system.
# This is the default task, so calling `guard` is the same as calling `guard start`.
#
# @see Guard.start
@@ -100,7 +109,7 @@ def start
desc 'list', 'Lists guards that can be used with init'
- # List the Guards that are available for use in your system and marks
+ # List the Guard plugins that are available for use in your system and marks
# those that are currently used in your `Guardfile`.
#
# @see Guard::DslDescriber.list
@@ -122,7 +131,7 @@ def version
::Guard::UI.info "Guard version #{ ::Guard::VERSION }"
end
- desc 'init [GUARD]', 'Generates a Guardfile at the current directory (if it is not already there) and adds all installed guards or the given GUARD into it'
+ desc 'init [GUARDS]', 'Generates a Guardfile at the current directory (if it is not already there) and adds all installed guards or the given GUARDS into it'
method_option :bare,
:type => :boolean,
@@ -130,33 +139,35 @@ def version
:aliases => '-b',
:banner => 'Generate a bare Guardfile without adding any installed guard into it'
- # Initializes the templates of all installed Guards and adds them
- # to the `Guardfile` when no Guard name is passed. When passed
- # a guard name is does the same but only for that Guard.
+ # Initializes the templates of all installed Guard plugins and adds them
+ # to the `Guardfile` when no Guard name is passed. When passing
+ # Guard plugin names it does the same but only for those Guard plugins.
#
# @see Guard::Guard.initialize_template
# @see Guard::Guard.initialize_all_templates
#
- # @param [String] guard_name the name of the Guard to initialize
+ # @param [Array<String>] guard_names the name of the Guard plugins to initialize
#
- def init(guard_name = nil)
+ def init(*guard_names)
verify_bundler_presence
::Guard::Guardfile.create_guardfile(:abort_on_existence => options[:bare])
return if options[:bare]
- if guard_name.nil?
+ if guard_names.empty?
::Guard::Guardfile::initialize_all_templates
else
- ::Guard::Guardfile.initialize_template(guard_name)
+ guard_names.each do |guard_name|
+ ::Guard::Guardfile.initialize_template(guard_name)
+ end
end
end
- desc 'show', 'Show all defined Guards and their options'
+ desc 'show', 'Show all defined Guard plugins and their options'
map %w(-T) => :show
- # Shows all Guards and their options that are defined in
+ # Shows all Guard plugins and their options that are defined in
# the `Guardfile`
#
# @see Guard::DslDescriber.show
View
55 lib/guard/dsl.rb
@@ -4,9 +4,9 @@ module Guard
# the behaviour of Guard.
#
# The main keywords of the DSL are `guard` and `watch`. These are necessary to define
- # the used Guards and the file changes they are watching.
+ # the used Guard plugins and the file changes they are watching.
#
- # You can optionally group the Guards with the `group` keyword and ignore and filter certain paths
+ # You can optionally group the Guard plugins with the `group` keyword and ignore and filter certain paths
# with the `ignore` and `filter` keywords.
#
# You can set your preferred system notification library with `notification` and pass
@@ -15,8 +15,9 @@ module Guard
# specify `:off` as library). @see ::Guard::Notifier for more information about the supported libraries.
#
# A more advanced DSL use is the `callback` keyword that allows you to execute arbitrary
- # code before or after any of the `start`, `stop`, `reload`, `run_all` and `run_on_change`
- # Guards' method. You can even insert more hooks inside these methods.
+ # code before or after any of the `start`, `stop`, `reload`, `run_all`, `run_on_changes`,
+ # `run_on_additions`, `run_on_modifications` and `run_on_removals` Guard plugins method.
+ # You can even insert more hooks inside these methods.
# Please [checkout the Wiki page](https://github.com/guard/guard/wiki/Hooks-and-callbacks) for more details.
#
# The DSL will also evaluate normal Ruby code.
@@ -83,6 +84,13 @@ module Guard
#
class Dsl
+ require 'guard'
+ require 'guard/dsl'
+ require 'guard/interactor'
+ require 'guard/notifier'
+ require 'guard/ui'
+ require 'guard/watcher'
+
# Deprecation message for the `ignore_paths` method
IGNORE_PATHS_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
Starting with Guard v1.1 the use of the 'ignore_paths' Guardfile dsl method is deprecated.
@@ -115,11 +123,11 @@ def evaluate_guardfile(options = {})
#
def reevaluate_guardfile
before_reevaluate_guardfile
- Dsl.evaluate_guardfile(@@options)
+ ::Guard::Dsl.evaluate_guardfile(@@options)
after_reevaluate_guardfile
end
- # Stop Guards and clear internal state
+ # Stop Guard and clear internal state
# before the Guardfile will be re-evaluated.
#
def before_reevaluate_guardfile
@@ -131,7 +139,7 @@ def before_reevaluate_guardfile
@@options.delete(:guardfile_contents)
end
- # Start Guards and notification and show a message
+ # Start Guard and notification and show a message
# after the Guardfile has been re-evaluated.
#
def after_reevaluate_guardfile
@@ -155,10 +163,10 @@ def after_reevaluate_guardfile
def instance_eval_guardfile(contents)
new.instance_eval(contents, @@options[:guardfile_path], 1)
rescue
- UI.error "Invalid Guardfile, original error is:\n#{ $! }"
+ ::Guard::UI.error "Invalid Guardfile, original error is:\n#{ $! }"
end
- # Test if the current `Guardfile` contains a specific Guard.
+ # Test if the current `Guardfile` contains a specific Guard plugin.
#
# @param [String] guard_name the name of the Guard
# @return [Boolean] whether the Guard has been declared
@@ -175,7 +183,7 @@ def read_guardfile(guardfile_path)
@@options[:guardfile_path] = guardfile_path
@@options[:guardfile_contents] = File.read(guardfile_path)
rescue
- UI.error("Error reading file #{ guardfile_path }")
+ ::Guard::UI.error("Error reading file #{ guardfile_path }")
exit 1
end
@@ -184,15 +192,15 @@ def read_guardfile(guardfile_path)
#
def fetch_guardfile_contents
if @@options[:guardfile_contents]
- UI.info 'Using inline Guardfile.'
+ ::Guard::UI.info 'Using inline Guardfile.'
@@options[:guardfile_path] = 'Inline Guardfile'
elsif @@options[:guardfile]
if File.exist?(@@options[:guardfile])
read_guardfile(@@options[:guardfile])
- UI.info "Using Guardfile at #{ @@options[:guardfile] }."
+ ::Guard::UI.info "Using Guardfile at #{ @@options[:guardfile] }."
else
- UI.error "No Guardfile exists at #{ @@options[:guardfile] }."
+ ::Guard::UI.error "No Guardfile exists at #{ @@options[:guardfile] }."
exit 1
end
@@ -200,13 +208,13 @@ def fetch_guardfile_contents
if File.exist?(guardfile_default_path)
read_guardfile(guardfile_default_path)
else
- UI.error 'No Guardfile found, please create one with `guard init`.'
+ ::Guard::UI.error 'No Guardfile found, please create one with `guard init`.'
exit 1
end
end
unless guardfile_contents_usable?
- UI.error 'No Guards found in Guardfile, please add at least one.'
+ ::Guard::UI.error 'No Guard plugins found in Guardfile, please add at least one.'
end
end
@@ -320,9 +328,9 @@ def interactor(interactor)
::Guard::Interactor.interactor = interactor.to_sym
end
- # Declares a group of guards to be run with `guard start --group group_name`.
+ # Declares a group of Guard plugins to be run with `guard start --group group_name`.
#
- # @example Declare two groups of Guards
+ # @example Declare two groups of Guard plugins
#
# group 'backend' do
# guard 'spork'
@@ -334,7 +342,7 @@ def interactor(interactor)
# guard 'livereload'
# end
#
- # @param [Symbol, String] name the group's name called from the CLI
+ # @param [Symbol, String] name the group name called from the CLI
# @param [Hash] options the options accepted by the group
# @yield a block where you can declare several guards
#
@@ -356,7 +364,7 @@ def group(name, options = {})
end
end
- # Declare a guard to be used when running `guard start`.
+ # Declare a Guard plugin to be used when running `guard start`.
#
# The name parameter is usually the name of the gem without
# the 'guard-' prefix.
@@ -411,7 +419,8 @@ def watch(pattern, &action)
end
# Define a callback to execute arbitrary code before or after any of
- # the `start`, `stop`, `reload`, `run_all` and `run_on_change` guards' method.
+ # the `start`, `stop`, `reload`, `run_all`, `run_on_changes` `run_on_additions`, `run_on_modifications`
+ # and `run_on_removals` plugin method.
#
# @param [Array] args the callback arguments
# @yield a block with listeners
@@ -431,7 +440,7 @@ def callback(*args, &listener)
# @param [Array] paths the list of paths to ignore
#
def ignore_paths(*paths)
- UI.deprecation(IGNORE_PATHS_DEPRECATION)
+ ::Guard::UI.deprecation(IGNORE_PATHS_DEPRECATION)
end
# Ignore certain patterns paths globally.
@@ -439,7 +448,7 @@ def ignore_paths(*paths)
# @example Ignore some paths
# ignore %r{^ignored/path/}, /man/
#
- # @param [Regexp] regexp a pattern for ignoring paths
+ # @param [Regexp] regexps a pattern for ignoring paths
#
def ignore(*regexps)
::Guard.listener = ::Guard.listener.ignore(*regexps)
@@ -450,7 +459,7 @@ def ignore(*regexps)
# @example Filter some files
# ignore /\.txt$/, /.*\.zip/
#
- # @param [Regexp] regexp a pattern for filtering paths
+ # @param [Regexp] regexps a pattern for filtering paths
#
def filter(*regexps)
::Guard.listener = ::Guard.listener.filter(*regexps)
View
29 lib/guard/dsl_describer.rb
@@ -1,9 +1,5 @@
-require 'guard/dsl'
-
module Guard
- autoload :UI, 'guard/ui'
-
# The DslDescriber overrides methods to create an internal structure
# of the Guardfile that is used in some inspection utility methods
# like the CLI commands `show` and `list`.
@@ -13,6 +9,9 @@ module Guard
#
class DslDescriber < Dsl
+ require 'guard/dsl'
+ require 'guard/ui'
+
class << self
# Evaluate the DSL methods in the `Guardfile`.
@@ -27,7 +26,7 @@ def evaluate_guardfile(options = {})
super options
end
- # List the Guards that are available for use in your system and marks
+ # List the Guard plugins that are available for use in your system and marks
# those that are currently used in your `Guardfile`.
#
# @example Guard list output
@@ -52,18 +51,18 @@ def list(options)
installed
end
- UI.info 'Available guards:'
+ ::Guard::UI.info 'Available guards:'
::Guard.guard_gem_names.sort.uniq.each do |name|
- UI.info " #{ name }#{ installed_guards.include?(name) ? '*' : '' }"
+ ::Guard::UI.info " #{ name }#{ installed_guards.include?(name) ? '*' : '' }"
end
- UI.info ''
- UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
- UI.info '* denotes ones already in your Guardfile'
+ ::Guard::UI.info ''
+ ::Guard::UI.info 'See also https://github.com/guard/guard/wiki/List-of-available-Guards'
+ ::Guard::UI.info '* denotes ones already in your Guardfile'
end
- # Shows all Guards and their options that are defined in
+ # Shows all Guard plugins and their options that are defined in
# the `Guardfile`.
#
# @example guard show output
@@ -82,9 +81,9 @@ def show(options)
guardfile_structure.each do |group|
unless group[:guards].empty?
if group[:group]
- UI.info "Group #{ group[:group] }:"
+ ::Guard::UI.info "Group #{ group[:group] }:"
else
- UI.info '(global):'
+ ::Guard::UI.info '(global):'
end
group[:guards].each do |guard|
@@ -94,12 +93,12 @@ def show(options)
line += ": #{ guard[:options].inject({}) { |options, (k, v)| options[k.to_s] = v; options }.sort.collect { |k, v| "#{ k } => #{ v.inspect }" }.join(', ') }"
end
- UI.info line
+ ::Guard::UI.info line
end
end
end
- UI.info ''
+ ::Guard::UI.info ''
end
private
View
9 lib/guard/group.rb
@@ -1,6 +1,6 @@
module Guard
- # A group of Guards. There are two reasons why you want to group your guards:
+ # A group of Guard plugins. There are two reasons why you want to group your guards:
#
# - You can start only certain Groups from the command line by passing the `--group` option.
# - Abort task execution chain on failure within a group.
@@ -25,17 +25,20 @@ class Group
# @param [String] name the name of the group
# @param [Hash] options the group options
# @option options [Boolean] halt_on_fail if a task execution
- # should be halted for all Guards in this group if one Guard throws `:task_has_failed`
+ # should be halted for all Guard plugins in this group if a Guard plugin throws `:task_has_failed`
#
def initialize(name, options = {})
@name = name.to_sym
@options = options
end
+ # String representation of the Guard group.
+ #
+ # @return [String] the group name
+ #
def to_s
"#{@name} group"
end
end
-
end
View
82 lib/guard/guard.rb
@@ -1,6 +1,6 @@
module Guard
- # Base class that every Guard implementation must inherit from.
+ # Base class that every Guard plugin implementation must inherit from.
#
# Guard will trigger the `start`, `stop`, `reload`, `run_all` and `run_on_changes`
# (`run_on_additions`, `run_on_modifications` and `run_on_removals`) task methods
@@ -13,8 +13,8 @@ module Guard
# In each of these Guard task methods you have to implement some work when you want to
# support this kind of task. The return value of each Guard task method is not evaluated
# by Guard, but I'll be passed to the "_end" hook for further evaluation. You can
- # throw `:task_has_failed` to indicate that your Guard method was not successful,
- # and successive guard tasks will be aborted when the group has set the `:halt_on_fail`
+ # throw `:task_has_failed` to indicate that your Guard plugin method was not successful,
+ # and successive Guard plugin tasks will be aborted when the group has set the `:halt_on_fail`
# option.
#
# @see Guard::Hook
@@ -28,26 +28,29 @@ module Guard
# end
# end
#
- # Each Guard should provide a template Guardfile located within the Gem
+ # Each Guard plugin should provide a template Guardfile located within the Gem
# at `lib/guard/guard-name/templates/Guardfile`.
#
- # By default all watchers for a Guard are returning strings of paths to the
- # Guard, but if your Guard want to allow any return value from a watcher,
+ # By default all watchers for a Guard plugin have to return strings of paths to the
+ # Guard, but if your Guard plugin wants to allow any return value from a watcher,
# you can set the `any_return` option to true.
#
# If one of those methods raise an exception other than `:task_has_failed`,
# the Guard::GuardName instance will be removed from the active guards.
#
class Guard
- include Hook
+ require 'guard/hook'
+ require 'guard/ui'
+
+ include ::Guard::Hook
attr_accessor :watchers, :options, :group
- # Initializes a Guard.
+ # Initializes a Guard plugin.
#
- # @param [Array<Guard::Watcher>] watchers the Guard file watchers
- # @param [Hash] options the custom Guard options
- # @option options [Symbol] group the group this Guard belongs to
+ # @param [Array<Guard::Watcher>] watchers the Guard plugin file watchers
+ # @param [Hash] options the custom Guard plugin options
+ # @option options [Symbol] group the group this Guard plugin belongs to
# @option options [Boolean] any_return allow any object to be returned from a watcher
#
def initialize(watchers = [], options = {})
@@ -55,10 +58,10 @@ def initialize(watchers = [], options = {})
@watchers, @options = watchers, options
end
- # Initialize the Guard. This will copy the Guardfile template inside the Guard gem.
+ # Initialize the Guard plugin. This will copy the Guardfile template inside the Guard plugin gem.
# The template Guardfile must be located within the Gem at `lib/guard/guard-name/templates/Guardfile`.
#
- # @param [String] name the name of the Guard
+ # @param [String] name the name of the Guard plugin
#
def self.init(name)
if ::Guard::Dsl.guardfile_include?(name)
@@ -77,25 +80,19 @@ def self.init(name)
end
end
- def to_s
- self.class.to_s
- end
-
# Call once when Guard starts. Please override initialize method to init stuff.
#
# @raise [:task_has_failed] when start has failed
# @return [Object] the task result
#
- # def start
- # end
+ # @!method start
# Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
#
# @raise [:task_has_failed] when stop has failed
# @return [Object] the task result
#
- # def stop
- # end
+ # @!method stop
# Called when `reload|r|z + enter` is pressed.
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
@@ -103,8 +100,7 @@ def to_s
# @raise [:task_has_failed] when reload has failed
# @return [Object] the task result
#
- # def reload
- # end
+ # @!method reload
# Called when just `enter` is pressed
# This method should be principally used for long action like running all specs/tests/...
@@ -112,44 +108,48 @@ def to_s
# @raise [:task_has_failed] when run_all has failed
# @return [Object] the task result
#
- # def run_all
- # end
+ # @!method run_all
- # Default behaviour on file(s) changes that the Guard watches.
+ # Default behaviour on file(s) changes that the Guard plugin watches.
#
# @param [Array<String>] paths the changes files or paths
- # @raise [:task_has_failed] when run_on_change has failed
+ # @raise [:task_has_failed] when run_on_changes has failed
# @return [Object] the task result
#
- # def run_on_changes(paths)
- # end
+ # @!method run_on_changes(paths)
- # Called on file(s) additions that the Guard watches.
+ # Called on file(s) additions that the Guard plugin watches.
#
# @param [Array<String>] paths the changes files or paths
- # @raise [:task_has_failed] when run_on_change has failed
+ # @raise [:task_has_failed] when run_on_additions has failed
# @return [Object] the task result
#
- # def run_on_additions(paths)
- # end
+ # @!method run_on_additions(paths)
- # Called on file(s) modifications that the Guard watches.
+ # Called on file(s) modifications that the Guard plugin watches.
#
# @param [Array<String>] paths the changes files or paths
- # @raise [:task_has_failed] when run_on_change has failed
+ # @raise [:task_has_failed] when run_on_modifications has failed
# @return [Object] the task result
#
- # def run_on_modifications(paths)
- # end
+ # @!method run_on_modifications(paths)
- # Called on file(s) removals that the Guard watches.
+ # Called on file(s) removals that the Guard plugin watches.
#
# @param [Array<String>] paths the changes files or paths
- # @raise [:task_has_failed] when run_on_change has failed
+ # @raise [:task_has_failed] when run_on_removals has failed
# @return [Object] the task result
#
- # def run_on_removals(paths)
- # end
+ # @!method run_on_removals(paths)
+
+ # Convert plugin to string representation. The
+ # default just uses the plugin class name.
+ #
+ # @return [String] the string representation
+ #
+ def to_s
+ self.class.to_s
+ end
end
View
3  lib/guard/guardfile.rb
@@ -7,6 +7,9 @@ module Guard
#
class Guardfile
+ require 'guard'
+ require 'guard/ui'
+
class << self
# Creates the initial Guardfile template when it does not
View
8 lib/guard/hook.rb
@@ -1,7 +1,7 @@
module Guard
- # Guard has a hook mechanism that allows you to insert callbacks for individual Guards.
- # By default, each of the Guard instance methods has a "_begin" and an "_end" hook.
+ # Guard has a hook mechanism that allows you to insert callbacks for individual Guard plugins.
+ # By default, each of the Guard plugin instance methods has a "_begin" and an "_end" hook.
# For example, the Guard::Guard#start method has a :start_begin hook that is runs immediately
# before Guard::Guard#start, and a :start_end hook that runs immediately after Guard::Guard#start.
#
@@ -9,6 +9,8 @@ module Guard
#
module Hook
+ require 'guard/ui'
+
# The Hook module gets included.
#
# @param [Class] base the class that includes the module
@@ -57,7 +59,7 @@ def hook(event, *args)
event
end.to_sym
- UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
+ ::Guard::UI.debug "Hook :#{ hook_name } executed for #{ self.class }"
Hook.notify(self.class, hook_name, *args)
end
View
32 lib/guard/interactor.rb
@@ -1,11 +1,5 @@
module Guard
- autoload :ReadlineInteractor, 'guard/interactors/readline'
- autoload :CoollineInteractor, 'guard/interactors/coolline'
- autoload :SimpleInteractor, 'guard/interactors/simple'
- autoload :DslDescriber, 'guard/dsl_describer'
- autoload :UI, 'guard/ui'
-
# The interactor triggers specific action from input
# read by a interactor implementation.
#
@@ -38,6 +32,14 @@ module Guard
#
class Interactor
+ require 'guard'
+ require 'guard/ui'
+ require 'guard/dsl_describer'
+ require 'guard/notifier'
+ require 'guard/interactors/readline'
+ require 'guard/interactors/coolline'
+ require 'guard/interactors/simple'
+
ACTIONS = {
:help => %w[help h],
:reload => %w[reload r],
@@ -64,11 +66,11 @@ def self.interactor=(interactor)
def self.fabricate
case @interactor
when :coolline
- CoollineInteractor.new if CoollineInteractor.available?
+ ::Guard::CoollineInteractor.new if ::Guard::CoollineInteractor.available?
when :readline
- ReadlineInteractor.new if ReadlineInteractor.available?
+ ::Guard::ReadlineInteractor.new if ::Guard::ReadlineInteractor.available?
when :simple
- SimpleInteractor.new
+ ::Guard::SimpleInteractor.new
when :off
nil
else
@@ -90,7 +92,9 @@ def self.fabricate
# @return [Interactor] an interactor implementation
#
def self.auto_detect
- [CoollineInteractor, ReadlineInteractor, SimpleInteractor].detect { |interactor| interactor.available?(true) }.new
+ [::Guard::CoollineInteractor, ::Guard::ReadlineInteractor, ::Guard::SimpleInteractor].detect do |interactor|
+ interactor.available?(true)
+ end.new
end
# Template method for checking if the Interactor is
@@ -143,7 +147,7 @@ def process_input(line)
when :help
help
when :show
- DslDescriber.show(::Guard.options)
+ ::Guard::DslDescriber.show(::Guard.options)
when :stop
::Guard.stop
exit
@@ -185,17 +189,17 @@ def help
puts '[n]otification Toggle notifications'
puts '[s]how Show available Guard plugins'
puts '[c]hange <file> Trigger a file change'
- puts '<enter> Run all Guards'
+ puts '<enter> Run all Guard plugins'
puts ''
puts 'You can scope the reload action to a specific guard or group:'
puts ''
puts 'rspec reload Reload the RSpec Guard'
puts 'backend reload Reload the backend group'
puts ''
- puts 'You can also run only a specific Guard or all Guards in a specific group:'
+ puts 'You can also run only a specific Guard or all Guard plugins in a specific group:'
puts ''
puts 'jasmine Run the jasmine Guard'
- puts 'frontend Run all Guards in the frontend group'
+ puts 'frontend Run all Guard plugins in the frontend group'
puts ''
end
View
12 lib/guard/interactors/coolline.rb
@@ -1,13 +1,15 @@
-module Guard
+require 'guard'
+require 'guard/ui'
+require 'guard/interactor'
+require 'guard/interactors/helpers/terminal'
+require 'guard/interactors/helpers/completion'
- autoload :TerminalHelper, 'guard/interactors/helpers/terminal'
- autoload :CompletionHelper, 'guard/interactors/helpers/completion'
- autoload :UI, 'guard/ui'
+module Guard
# Interactor that uses coolline for getting the user input.
# This enables history support and auto-completion,
#
- class CoollineInteractor < Interactor
+ class CoollineInteractor < ::Guard::Interactor
include ::Guard::CompletionHelper
include ::Guard::TerminalHelper
View
2  lib/guard/interactors/helpers/completion.rb
@@ -1,3 +1,5 @@
+require 'guard'
+
module Guard
# Module for providing word completion to an interactor.
View
6 lib/guard/interactors/helpers/terminal.rb
@@ -39,8 +39,8 @@ def store_terminal_settings
# Restore terminal settings
#
def restore_terminal_settings
- system('stty', @stty_save, '2>/dev/null') if @stty_save
+ system("stty #{ @stty_save } 2>/dev/null") if @stty_save
end
-
+
end
-end
+end
View
22 lib/guard/interactors/readline.rb
@@ -1,8 +1,10 @@
-module Guard
+require 'guard'
+require 'guard/ui'
+require 'guard/interactor'
+require 'guard/interactors/helpers/terminal'
+require 'guard/interactors/helpers/completion'
- autoload :TerminalHelper, 'guard/interactors/helpers/terminal'
- autoload :CompletionHelper, 'guard/interactors/helpers/completion'
- autoload :UI, 'guard/ui'
+module Guard
# Interactor that used readline for getting the user input.
# This enables history support and auto-completion, but is
@@ -10,7 +12,7 @@ module Guard
#
# @see http://bugs.ruby-lang.org/issues/5539
#
- class ReadlineInteractor < Interactor
+ class ReadlineInteractor < ::Guard::Interactor
include ::Guard::CompletionHelper
include ::Guard::TerminalHelper
@@ -29,6 +31,10 @@ def self.available?(silent = false)
::Guard::UI.error 'The :readline interactor runs only fine on JRuby, Linux or with the gem \'rb-readline\' installed.' unless silent
false
end
+
+ rescue LoadError => e
+ ::Guard::UI.error "Please install Ruby Readline support or add \"gem 'rb-readline'\" to your Gemfile and run Guard with \"bundle exec\"." unless silent
+ false
end
# Initialize the interactor.
@@ -49,10 +55,10 @@ def initialize
#
def stop
# Erase the current line for Ruby Readline
- if Readline.respond_to?(:refresh_line)
+ if Readline.respond_to?(:refresh_line) && !defined?(::JRUBY_VERSION)
Readline.refresh_line
end
-
+
# Erase the current line for Rb-Readline
if defined?(RbReadline) && RbReadline.rl_outstream
RbReadline._rl_erase_entire_line
@@ -60,7 +66,7 @@ def stop
super
end
-
+
# Read a line from stdin with Readline.
#
def read_line
View
4 lib/guard/interactors/simple.rb
@@ -1,9 +1,11 @@
+require 'guard/interactor'
+
module Guard
# Simple interactor that that reads user
# input from standard input.
#
- class SimpleInteractor < Interactor
+ class SimpleInteractor < ::Guard::Interactor
# Read a line from stdin with Readline.
#
View
93 lib/guard/notifier.rb
@@ -1,14 +1,6 @@
require 'yaml'
-
require 'rbconfig'
require 'pathname'
-require 'guard/ui'
-require 'guard/notifiers/gntp'
-require 'guard/notifiers/growl'
-require 'guard/notifiers/growl_notify'
-require 'guard/notifiers/libnotify'
-require 'guard/notifiers/notifysend'
-require 'guard/notifiers/rb_notifu'
module Guard
@@ -40,17 +32,32 @@ module Guard
# Guard can be configured to make use of more than one notifier at once, @see Guard::Dsl
#
module Notifier
+
+ require 'guard'
+ require 'guard/ui'
+ require 'guard/notifiers/gntp'
+ require 'guard/notifiers/growl'
+ require 'guard/notifiers/growl_notify'
+ require 'guard/notifiers/libnotify'
+ require 'guard/notifiers/notifysend'
+ require 'guard/notifiers/rb_notifu'
+ require 'guard/notifiers/emacs'
+ require 'guard/notifiers/terminal_notifier'
+
extend self
- # List of available notifiers.
- NOTIFIERS = {
- :gntp => ::Guard::Notifier::GNTP,
- :growl => ::Guard::Notifier::Growl,
- :growl_notify => ::Guard::Notifier::GrowlNotify,
- :libnotify => ::Guard::Notifier::Libnotify,
- :notifysend => ::Guard::Notifier::NotifySend,
- :notifu => ::Guard::Notifier::Notifu
- }
+ # List of available notifiers. It needs to be a nested hash instead of
+ # a simpler Hash, because it maintains its order on Ruby 1.8.7 also.
+ NOTIFIERS = [
+ [:growl, ::Guard::Notifier::Growl],
+ [:gntp, ::Guard::Notifier::GNTP],
+ [:growl_notify, ::Guard::Notifier::GrowlNotify],
+ [:libnotify, ::Guard::Notifier::Libnotify],
+ [:notifysend, ::Guard::Notifier::NotifySend],
+ [:notifu, ::Guard::Notifier::Notifu],
+ [:emacs, ::Guard::Notifier::Emacs],
+ [:terminal_notifier, ::Guard::Notifier::TerminalNotifier]
+ ]
# Get the available notifications.
#
@@ -85,7 +92,7 @@ def turn_on
ENV['GUARD_NOTIFY'] = 'false'
else
notifications.each do |notification|
- ::Guard::UI.info "Guard uses #{ NOTIFIERS[notification[:name]].to_s.split('::').last } to send notifications."
+ ::Guard::UI.info "Guard uses #{ get_notifier_module(notification[:name]).to_s.split('::').last } to send notifications."
end
ENV['GUARD_NOTIFY'] = 'true'
@@ -116,7 +123,9 @@ def enabled?
def add_notification(name, options = { }, silent = false)
return turn_off if name == :off
- if NOTIFIERS.has_key?(name) && NOTIFIERS[name].available?(silent)
+ notifier = get_notifier_module(name)
+
+ if notifier && notifier.available?(silent)
self.notifications = notifications << { :name => name, :options => options }
true
else
@@ -138,7 +147,7 @@ def notify(message, options = { })
notifications.each do |notification|
begin
- NOTIFIERS[notification[:name]].notify(type, title, message, image, options.merge(notification[:options]))
+ get_notifier_module(notification[:name]).notify(type, title, message, image, options.merge(notification[:options]))
rescue Exception => e
::Guard::UI.error "Error sending notification with #{ notification[:name] }: #{ e.message }"
end
@@ -148,12 +157,22 @@ def notify(message, options = { })
private
+ # Get the notifier module for the given name.
+ #
+ # @param [Symbol] the notifier name
+ # @return [Module] the notifier module
+ #
+ def get_notifier_module(name)
+ notifier = NOTIFIERS.detect { |n| n.first == name }
+ notifier ? notifier.last : notifier
+ end
+
# Auto detect the available notification library. This goes through
# the list of supported notification gems and picks the first that
# is available.
#
def auto_detect_notification
- available = [:growl_notify, :gntp, :growl, :libnotify, :notifysend, :notifu].any? { |notifier| add_notification(notifier, { }, true) }
+ available = NOTIFIERS.map { |n| n.first }.any? { |notifier| add_notification(notifier, { }, true) }
::Guard::UI.info('Guard could not detect any of the supported notification libraries.') unless available
end
@@ -171,14 +190,14 @@ def auto_detect_notification
#
def image_path(image)
case image
- when :failed
- images_path.join('failed.png').to_s
- when :pending
- images_path.join('pending.png').to_s
- when :success
- images_path.join('success.png').to_s
- else
- image
+ when :failed
+ images_path.join('failed.png').to_s
+ when :pending
+ images_path.join('pending.png').to_s
+ when :success
+ images_path.join('success.png').to_s
+ else
+ image
end
end
@@ -198,14 +217,14 @@ def images_path
#
def notification_type(image)
case image
- when :failed
- 'failed'
- when :pending
- 'pending'
- when :success
- 'success'
- else
- 'notify'
+ when :failed
+ 'failed'
+ when :pending
+ 'pending'
+ when :success
+ 'success'
+ else
+ 'notify'
end
end
end
View
69 lib/guard/notifiers/emacs.rb
@@ -0,0 +1,69 @@
+require 'rbconfig'
+
+module Guard
+ module Notifier
+
+ # Default options for EmacsClient
+ DEFAULTS = {
+ :client => 'emacsclient',
+ :success => 'ForestGreen',
+ :failed => 'Firebrick',
+ :default => 'Black',
+ }
+
+ # Send a notification to Emacs with emacsclient (http://www.emacswiki.org/emacs/EmacsClient).
+ #
+ # @example Add the `:emacs` notifier to your `Guardfile`
+ # notification :emacs
+ #
+ module Emacs
+ extend self
+
+ # Test if Emacs with running server is available.
+ #
+ # @param [Boolean] silent true if no error messages should be shown
+ # @return [Boolean] the availability status
+ #
+ def available?(silent = false)
+ result = `#{DEFAULTS[:client]} --eval '1' 2> /dev/null || echo 'N/A'`
+
+ if result.chomp! == "N/A"
+ false
+ else
+ true
+ end
+ end
+
+ # Show a system notification.
+ #
+ # @param [String] type the notification type. Either 'success', 'pending', 'failed' or 'notify'
+ # @param [String] title the notification title
+ # @param [String] message the notification message body
+ # @param [String] image the path to the notification image
+ # @param [Hash] options additional notification library options
+ # @option options [Boolean] sticky make the notification sticky
+ # @option options [String, Integer] priority specify an int or named key (default is 0)
+ #
+ def notify(type, title, message, image, options = { })
+ system(%(#{DEFAULTS[:client]} --eval "(set-face-background 'modeline \\"#{emacs_color(type)}\\")"))
+ end
+
+ # Get the Emacs color for the notification type.
+ # You can configure your own color by overwrite the defaults.
+ #
+ # @param [String] type the notification type
+ # @return [String] the name of the emacs color
+ #
+ def emacs_color(type)
+ case type
+ when 'success'
+ DEFAULTS[:success]
+ when 'failed'
+ DEFAULTS[:failed]
+ else
+ DEFAULTS[:default]
+ end
+ end
+ end
+ end
+end
View
3  lib/guard/notifiers/gntp.rb
@@ -1,4 +1,5 @@
require 'rbconfig'
+require 'guard/ui'
module Guard
module Notifier
@@ -104,7 +105,7 @@ def notify(type, title, message, image, options = { })