Merge with current guard (commit '5352528530f29d3db523261560ee6920063c85b5')

This commit is contained in:
slavic 2011-05-07 15:17:41 +03:00
commit 92f81d383a
23 changed files with 558 additions and 432 deletions

4
.travis.yml Normal file
View File

@ -0,0 +1,4 @@
rvm:
- 1.8.7
- 1.9.2
- ree

90
CHANGELOG.markdown Normal file
View File

@ -0,0 +1,90 @@
### Bugs fixes:
- Issue [#41](https://github.com/guard/guard/issues/41): Removed useless Bundler requirement. ([@thibaudgg](https://github.com/thibaudgg))
### New features:
- Changed CHANGELOG from RDOC to Markdown and cleaned it! Let's celebrate! ([@rymai](https://github.com/rymai))
- Changed README from RDOC to Markdown! Let's celebrate! ([@thibaudgg](https://github.com/thibaudgg))
- Issue [#48](https://github.com/guard/guard/issues/48): Adding support for inline Guard classes rather than requiring a gem. ([@jrsacks](https://github.com/jrsacks))
## 0.3.3 - April 18, 2011
### Bugs fixes:
- Fixed `new_modified_files` rerun conditions on `Guard.run_on_change_for_all_guards`. ([@thibaudgg](https://github.com/thibaudgg))
## 0.3.2 - April 17, 2011
### Bugs fixes:
- Pull request [#43](https://github.com/guard/guard/issues/43): Fixed `guard init` command. ([@brainopia](https://github.com/brainopia))
## 0.3.1 - April 14, 2011
### Bugs fixes:
- Return unique filenames from Linux listener. (Marian Schubert)
- `Guard.get_guard_class` return wrong class when loaded nested class. ([@koshigoe](https://github.com/koshigoe))
- Issue [#35](https://github.com/guard/guard/issues/35): Fixed open-gem/gem_open dependency problem by using `gem which` to locate guards gem path. (reported by [@thierryhenrio](https://github.com/thierryhenrio), fixed by [@thibaudgg](https://github.com/thibaudgg))
- Issue [#38](https://github.com/guard/guard/issues/38) & Pull request [#39](https://github.com/guard/guard/issues/39): Fixed an invalid ANSI escape code in `Guard::UI.reset_line`. ([@gix](https://github.com/gix))
### New features:
- Issue [#28](https://github.com/guard/guard/issues/28): New `-n` command line option to disable notifications (Growl / Libnotify). ([@thibaudgg](https://github.com/thibaudgg))
## 0.3.0 - January 19, 2011
### Bugs fixes:
- Avoid launching run_on_change guards method when no files matched. --clear guard argument is now usable. ([@thibaudgg](https://github.com/thibaudgg))
### New features:
- The whole directory is now watched during `run_on_change` to detect new files modifications. ([@thibaudgg](https://github.com/thibaudgg))
- Pull request [#26](https://github.com/guard/guard/issues/26): New DSL method: `group` allows you to group several guards. ([@netzpirat](https://github.com/netzpirat))
- Pull request [#26](https://github.com/guard/guard/issues/26): New CLI option: `--group group_name` to specify certain groups of guards to start. ([@netzpirat](https://github.com/netzpirat))
- `watch` patterns are now more strict: strings are matched with `String#==`, `Regexp` are matched with `Regexp#match`. ([@rymai](https://github.com/rymai))
- A deprecation warning is displayed if your `Guardfile` contains `String` that look like `Regexp` (bad!). ([@rymai](https://github.com/rymai))
- It's now possible to return an `Enumerable` in the `watch` optional blocks in the `Guardfile`. ([@rymai](https://github.com/rymai))
### New specs:
- Guard::Watcher. ([@rymai](https://github.com/rymai))
- Pull request [#13](https://github.com/guard/guard/issues/13): Guard::Dsl. ([@oliamb](https://github.com/oliamb))
## 0.2.2 - October 25, 2010
### Bugs fixes:
- Issue [#5](https://github.com/guard/guard/issues/5): avoid creating new copy of `fsevent_watch` every time a file is changed. (reported by [@stouset](https://github.com/stouset), fixed by [@thibaudgg](https://github.com/thibaudgg))
## 0.2.1 - October 24, 2010
### Bugs fixes:
- Pull request [#7](https://github.com/guard/guard/issues/7): Fixes for Linux support. ([@yannlugrin](https://github.com/yannlugrin)))
- Pull request [#6](https://github.com/guard/guard/issues/6): Locate guard now chomp newline in result path. ([@yannlugrin](https://github.com/yannlugrin)))
## 0.2.0 - October 21, 2010
### Bugs fixes:
- Issue [#3](https://github.com/guard/guard/issues/3): `guard init <guard-name>` no more need `Gemfile` but `open_gem` is required now. (reported by [@wereHamster](https://github.com/wereHamster), fixed by [@thibaudgg](https://github.com/thibaudgg))
- Issue [#2](https://github.com/guard/guard/issues/2): 1.8.6 compatibility. (reported by [@veged](https://github.com/veged), fixed by [@thibaudgg](https://github.com/thibaudgg))
- Removes Growl & Libnotify dependencies. ([@thibaudgg](https://github.com/thibaudgg))
## 0.2.0.beta.1 - October 17, 2010
### New features:
- Improved listeners support (`rb-fsevent` & `rb-inotify`). ([@thibaudgg](https://github.com/thibaudgg))
- Added polling listening fallback. ([@thibaudgg](https://github.com/thibaudgg))

View File

@ -1,77 +0,0 @@
== 0.3.3 (Avril 18, 2011)
Bugs fixes:
- Fixed new_modified_files rerun conditions on Guard.run_on_change_for_all_guards
== 0.3.2 (Avril 17, 2011)
Bugs fixes:
- Fixed "guard init" command (@brainopia)
== 0.3.1 (Avril 14, 2011)
Features:
- Added a command line option (-n false) to disable notifications (growl/libnotify)
Bugs fixes:
- Return unique filenames from Linux listener (Marian Schubert)
- Guard.get_guard_class return wrong class when loaded nested class. (@koshigoe)
- Fixed open-gem/gem_open dependency problem by using `gem which` to locate guards gem path
- Fixed an invalid ANSI escape code in UI.reset_line (@gix)
== 0.3.0 (Jan 19, 2011)
== Jan 19, 2011 [by thibaudgg]
Features:
- The whole directory are now watched after that run_on_change was launched on all guards to detect new files modifications.
== Dec 17, 2010 [by netzpirat]
Features:
- New DSL method: `group` allows you to group several guards.
- New CLI option: `--group group_name` to specify certain groups of guards to start.
== Dec 16, 2010 [by rymai]
Features:
- 'watch' patterns are now more strict: Strings are matched with '==', Regexp are matched with Regexp#match.
- A deprecation warning is displayed if your Guardfile contains String that look like Regexp (bad!).
== Nov 26, 2010 [by rymai]
Features:
- It's now possible to return an enumerable in the 'watch' optional blocks in the Guardfile.
Specs:
- Guard::Watcher
Bugs fixes:
- Avoid launching run_on_change guards method when no files matched. --clear guard argument is now usable.
== 0.2.2 (Oct 25, 2010)
Bugs fixes:
- Avoid creating new copy of fsevent_watch every time a file is changed. (issue #5)
== 0.2.1 (Oct 24, 2010)
Bugs fixes:
- Fixes for Linux support
== 0.2.0 (Oct 21, 2010)
Bugs fixes:
- Fixes for 1.8.6 compatibility (issue #2)
- guard init <guard-name> no more need Gemfile presence but open_gem is required now (issue #3)
- Removes growl & libnotify dependencies
== 0.2.0.beta.1 (Oct 17, 2010)
Features:
- Improved listeners support (rb-fsevent & rb-inotify)
- Added polling listening fallback

View File

@ -5,12 +5,12 @@ gemspec
require 'rbconfig' require 'rbconfig'
if Config::CONFIG['target_os'] =~ /darwin/i if Config::CONFIG['target_os'] =~ /darwin/i
gem 'rb-fsevent', '>= 0.3.9' gem 'rb-fsevent', '>= 0.3.9', :require => false
gem 'growl', '~> 1.0.3' gem 'growl', '~> 1.0.3', :require => false
end end
if Config::CONFIG['target_os'] =~ /linux/i if Config::CONFIG['target_os'] =~ /linux/i
gem 'rb-inotify', '>= 0.5.1' gem 'rb-inotify', '>= 0.5.1', :require => false
gem 'libnotify', '~> 0.1.3' gem 'libnotify', '~> 0.1.3', :require => false
end end
if Config::CONFIG['target_os'] =~ /mswin|mingw/i if Config::CONFIG['target_os'] =~ /mswin|mingw/i
gem 'win32console' gem 'win32console'

View File

@ -1,4 +1,4 @@
guard('rspec', :cli => '-f doc', :version => 2) do guard('rspec', :version => 2) do
watch(%r{^spec/(.*)_spec\.rb}) watch(%r{^spec/(.*)_spec\.rb})
watch(%r{^lib/(.*)\.rb}) { |m| "spec/#{m[1]}_spec.rb" } watch(%r{^lib/(.*)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" } watch('spec/spec_helper.rb') { "spec" }

273
README.markdown Normal file
View File

@ -0,0 +1,273 @@
Guard
=====
![travis-ci](http://travis-ci.org/guard/guard.png)
Guard is a command line tool that easily handle events on files modifications.
Features
--------
* [FSEvent](http://en.wikipedia.org/wiki/FSEvents) support on Mac OS X 10.5+ (without RubyCocoa!, [rb-fsevent gem, >= 0.3.5](https://rubygems.org/gems/rb-fsevent) required).
* [Inotify](http://en.wikipedia.org/wiki/Inotify) support on Linux ([rb-inotify gem, >= 0.5.1](https://rubygems.org/gems/rb-inotify) required).
* Polling on the other operating systems (help us to support more OS).
* Automatic & Super fast (when polling is not used) files modifications detection (even new files are detected).
* Growl notifications ([growlnotify](http://growl.info/documentation/growlnotify.php) & [growl gem](https://rubygems.org/gems/growl) required).
* Libnotify notifications ([libnotify gem](https://rubygems.org/gems/libnotify) required).
* Tested on Ruby 1.8.7, 1.9.2 && ree.
Install
-------
Install the gem:
$ gem install guard
Add it to your Gemfile (inside the <tt>test</tt> group):
``` ruby
gem 'guard'
```
Generate an empty Guardfile with:
$ guard init
Add the guards you need to your Guardfile (see the existing guards below).
### On Mac OS X
Install the rb-fsevent gem for [FSEvent](http://en.wikipedia.org/wiki/FSEvents) support:
$ gem install rb-fsevent
Install the Growl gem if you want notification support:
$ gem install growl
And add it to you Gemfile:
``` ruby
gem 'growl'
```
### On Linux
Install the rb-inotify gem for [inotify](http://en.wikipedia.org/wiki/Inotify) support:
$ gem install rb-inotify
Install the Libnotify gem if you want notification support:
$ gem install libnotify
And add it to you Gemfile:
``` ruby
gem 'libnotify'
```
Usage
-----
Just launch Guard inside your Ruby / Rails project with:
$ guard [start]
or if you use Bundler, to run the Guard executable specific to your bundle:
$ bundle exec guard
Command line options
--------------------
Shell can be cleared after each change with:
$ guard --clear
$ guard -c # shortcut
Notifications (growl/libnotify) can be disabled with:
$ guard --notify false
$ guard -n false # shortcut
Notifications can also be disabled by setting a `GUARD_NOTIFY` environment variable to `false`
The guards to start can be specified by group (see the Guardfile DSL below) specifying the <tt>--group</tt> (or <tt>-g</tt>) option:
$ guard --group group_name another_group_name
$ guard -g group_name another_group_name # shortcut
Options list is available with:
$ guard help [TASK]
Signal handlers
---------------
Signal handlers are used to interact with Guard:
* <tt>Ctrl-C</tt> - Calls each guard's <tt>stop</tt> method, in the same order they are declared in the Guardfile, and then quits Guard itself.
* <tt>Ctrl-\\</tt> - Calls each guard's <tt>run_all</tt> method, in the same order they are declared in the Guardfile.
* <tt>Ctrl-Z</tt> - Calls each guard's <tt>reload</tt> method, in the same order they are declared in the Guardfile.
Available Guards
----------------
[Available Guards list](https://github.com/guard/guard/wiki/List-of-available-Guards) (on the wiki now)
### Add a guard to your Guardfile
Add it to your Gemfile (inside the <tt>test</tt> group):
``` ruby
gem '<guard-name>'
```
Insert default guard's definition to your Guardfile by running this command:
$ guard init <guard-name>
You are good to go!
Guardfile DSL
-------------
The Guardfile DSL consists of just three simple methods: <tt>guard</tt>, <tt>watch</tt> & <tt>group</tt>.
Required:
* The <tt>guard</tt> method allows you to add a guard with an optional hash of options.
* The <tt>watch</tt> method allows you to define which files are supervised by this guard. An optional block can be added to overwrite the paths sent to the <tt>run_on_change</tt> guard method or to launch any arbitrary command.
Optional:
* The <tt>group</tt> method allows you to group several guards together. Groups to be run can be specified with the Guard DSL option <tt>--group</tt> (or <tt>-g</tt>). This comes in handy especially when you have a huge Guardfile and want to focus your development on a certain part.
Example:
``` ruby
group 'backend' do
guard 'bundler' do
watch('Gemfile')
end
guard 'rspec', :cli => '--color --format doc' do
# Regexp watch patterns are matched with Regexp#match
watch(%r{^spec/.+_spec\.rb})
watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^spec/models/.+\.rb}) { ["spec/models", "spec/acceptance"] }
watch(%r{^spec/.+\.rb}) { `say hello` }
# String watch patterns are matched with simple '=='
watch('spec/spec_helper.rb') { "spec" }
end
end
group 'frontend' do
guard 'coffeescript', :output => 'public/javascripts/compiled' do
watch(%r{^app/coffeescripts/.+\.coffee})
end
guard 'livereload' do
watch(%r{^app/.+\.(erb|haml)})
end
end
```
Create a new guard
------------------
Creating a new guard is very easy, just create a new gem (<tt>bundle gem</tt> if you use Bundler) with this basic structure:
lib/
guard/
guard-name/
templates/
Guardfile (needed for guard init <guard-name>)
guard-name.rb
<tt>Guard::GuardName</tt> (in <tt>lib/guard/guard-name.rb</tt>) must inherit from <tt>Guard::Guard</tt> and should overwrite at least one of the five basic <tt>Guard::Guard</tt> instance methods. Example:
``` ruby
require 'guard'
require 'guard/guard'
module Guard
class GuardName < Guard
def initialize(watchers=[], options={})
super
# init stuff here, thx!
end
# =================
# = Guard methods =
# =================
# If one of those methods raise an exception, the Guard::GuardName instance
# will be removed from the active guards.
# Called once when Guard starts
# Please override initialize method to init stuff
def start
true
end
# Called on Ctrl-C signal (when Guard quits)
def stop
true
end
# Called on Ctrl-Z signal
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
def reload
true
end
# Called on Ctrl-/ signal
# This method should be principally used for long action like running all specs/tests/...
def run_all
true
end
# Called on file(s) modifications
def run_on_change(paths)
true
end
end
end
```
Please take a look at the existing guards' source code (see the list above) for more concrete example.
Alternatively, a new guard can be added inline to a Guardfile with this basic structure:
``` ruby
require 'guard/guard'
module ::Guard
class Example < ::Guard::Guard
def run_all
true
end
def run_on_change(paths)
true
end
end
end
```
Development
-----------
* Source hosted at [GitHub](https://github.com/guard/guard).
* Report Issues/Questions/Feature requests on [GitHub Issues](https://github.com/guard/guard/issues).
Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
you make.
Author
------
[Thibaud Guillaume-Gentil](https://github.com/thibaudgg)

View File

@ -1,235 +0,0 @@
= Guard
Guard is a command line tool that easily handle events on files modifications.
== Features
- {FSEvent}[http://en.wikipedia.org/wiki/FSEvents] support on Mac OS X 10.5+ (without RubyCocoa!, {rb-fsevent gem, >= 0.3.5}[https://rubygems.org/gems/rb-fsevent] required).
- {Inotify}[http://en.wikipedia.org/wiki/Inotify] support on Linux ({rb-inotify gem, >= 0.5.1}[https://rubygems.org/gems/rb-inotify] required).
- {Directory Change Notification}[http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx] suuport on Windows ({rb-fchange, >= 0.0.2}[https://github.com/stereobooster/rb-fchange] required)
- Polling on the other operating systems (help us to support more OS).
- Automatic & Super fast (when polling is not used) files modifications detection (even new files are detected).
- Growl notifications ({growlnotify}[http://growl.info/documentation/growlnotify.php] & {growl gem}[https://rubygems.org/gems/growl] required).
- Libnotify notifications ({libnotify gem}[https://rubygems.org/gems/libnotify] required).
- Tested on Ruby 1.8.7 & 1.9.2.
== Install
Install the gem:
$ gem install guard
Add it to your Gemfile (inside the <tt>test</tt> group):
gem 'guard'
Generate an empty Guardfile with:
$ guard init
Add the guards you need to your Guardfile (see the existing guards below).
=== On Mac OS X
Install the rb-fsevent gem for {FSEvent}[http://en.wikipedia.org/wiki/FSEvents] support:
$ gem install rb-fsevent
Install the Growl gem if you want notification support:
$ gem install growl
And add it to you Gemfile:
gem 'growl'
=== On Linux
Install the rb-inotify gem for {inotify}[http://en.wikipedia.org/wiki/Inotify] support:
$ gem install rb-inotify
Install the Libnotify gem if you want notification support:
$ gem install libnotify
And add it to you Gemfile:
gem 'libnotify'
=== On Windows
Install the rb-fchange gem for {Directory Change Notification}[http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx] support:
$ gem install rb-fchange
== Usage
Just launch Guard inside your Ruby / Rails project with:
$ guard [start]
or if you use Bundler, to run the Guard executable specific to your bundle:
$ bundle exec guard
== Command line options
Shell can be cleared after each change with:
$ guard --clear
$ guard -c # shortcut
Notifications (growl/libnotify) can be disabled with:
$ guard --notify false
$ guard -n false # shortcut
The guards to start can be specified by group (see the Guardfile DSL below) specifying the <tt>--group</tt> (or <tt>-g</tt>) option:
$ guard --group group_name another_group_name
$ guard -g group_name another_group_name # shortcut
Options list is available with:
$ guard help [TASK]
== Signal handlers
Signal handlers are used to interact with Guard:
- <tt>Ctrl-C</tt> - Calls each guard's <tt>stop</tt> method, in the same order they are declared in the Guardfile, and then quits Guard itself.
- <tt>Ctrl-\\</tt> - Calls each guard's <tt>run_all</tt> method, in the same order they are declared in the Guardfile.
- <tt>Ctrl-Z</tt> - Calls each guard's <tt>reload</tt> method, in the same order they are declared in the Guardfile.
== Available Guards
{Available Guards list}[https://github.com/guard/guard/wiki/List-of-available-Guards] (on the wiki now)
=== Add a guard to your Guardfile
Add it to your Gemfile (inside the <tt>test</tt> group):
gem '<guard-name>'
Insert default guard's definition to your Guardfile by running this command:
$ guard init <guard-name>
You are good to go!
== Guardfile DSL
The Guardfile DSL consists of just three simple methods: <tt>guard</tt>, <tt>watch</tt> & <tt>group</tt>.
Required:
- The <tt>guard</tt> method allows you to add a guard with an optional hash of options.
- The <tt>watch</tt> method allows you to define which files are supervised by this guard. An optional block can be added to overwrite the paths sent to the <tt>run_on_change</tt> guard method or to launch any arbitrary command.
Optional:
- The <tt>group</tt> method allows you to group several guards together. Groups to be run can be specified with the Guard DSL option <tt>--group</tt> (or <tt>-g</tt>). This comes in handy especially when you have a huge Guardfile and want to focus your development on a certain part.
Example:
group 'backend' do
guard 'bundler' do
watch('Gemfile')
end
guard 'rspec', :cli => '--color --format doc' do
# Regexp watch patterns are matched with Regexp#match
watch(%r{^spec/.+_spec\.rb})
watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^spec/models/.+\.rb}) { ["spec/models", "spec/acceptance"] }
watch(%r{^spec/.+\.rb}) { `say hello` }
# String watch patterns are matched with simple '=='
watch('spec/spec_helper.rb') { "spec" }
end
end
group 'frontend' do
guard 'coffeescript', :output => 'public/javascripts/compiled' do
watch(%r{^app/coffeescripts/.+\.coffee})
end
guard 'livereload' do
watch(%r{^app/.+\.(erb|haml)})
end
end
== Create a new guard
Creating a new guard is very easy, just create a new gem (<tt>bundle gem</tt> if you use Bundler) with this basic structure:
lib/
guard/
guard-name/
templates/
Guardfile (needed for guard init <guard-name>)
guard-name.rb
<tt>Guard::GuardName</tt> (in <tt>lib/guard/guard-name.rb</tt>) must inherit from <tt>Guard::Guard</tt> and should overwrite at least one of the five basic <tt>Guard::Guard</tt> instance methods. Example:
require 'guard'
require 'guard/guard'
module Guard
class GuardName < Guard
def initialize(watchers=[], options={})
super
# init stuff here, thx!
end
# =================
# = Guard methods =
# =================
# If one of those methods raise an exception, the Guard::GuardName instance
# will be removed from the active guards.
# Called once when Guard starts
# Please override initialize method to init stuff
def start
true
end
# Called on Ctrl-C signal (when Guard quits)
def stop
true
end
# Called on Ctrl-Z signal
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
def reload
true
end
# Called on Ctrl-/ signal
# This method should be principally used for long action like running all specs/tests/...
def run_all
true
end
# Called on file(s) modifications
def run_on_change(paths)
true
end
end
end
Please take a look at the existing guards' source code (see the list above) for more concrete example.
== Development
- Source hosted at {GitHub}[https://github.com/guard/guard].
- Report Issues/Questions/Feature requests on {GitHub Issues}[https://github.com/guard/guard/issues].
Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
you make.
== Authors
{Thibaud Guillaume-Gentil}[https://github.com/thibaudgg]

View File

@ -8,7 +8,7 @@ task :default => :spec
namespace(:spec) do namespace(:spec) do
desc "Run all specs on multiple ruby versions (requires rvm)" desc "Run all specs on multiple ruby versions (requires rvm)"
task(:portability) do task(:portability) do
%w[1.8.6 1.8.7 1.9.2].each do |version| %w[1.8.7 1.9.2 ree].each do |version|
system <<-BASH system <<-BASH
bash -c 'source ~/.rvm/scripts/rvm; bash -c 'source ~/.rvm/scripts/rvm;
rvm #{version}; rvm #{version};

View File

@ -21,7 +21,7 @@ Gem::Specification.new do |s|
s.add_dependency 'thor', '~> 0.14.6' s.add_dependency 'thor', '~> 0.14.6'
s.files = Dir.glob('{bin,images,lib}/**/*') + %w[LICENSE README.rdoc] s.files = Dir.glob('{bin,images,lib}/**/*') + %w[LICENSE README.markdown]
s.executable = 'guard' s.executable = 'guard'
s.require_path = 'lib' s.require_path = 'lib'
end end

View File

@ -1,5 +1,3 @@
require 'bundler'
module Guard module Guard
autoload :UI, 'guard/ui' autoload :UI, 'guard/ui'
@ -18,7 +16,8 @@ module Guard
@listener = Listener.select_and_init @listener = Listener.select_and_init
@guards = [] @guards = []
Notifier.turn_off unless options[:notify] options[:notify] = false if ENV["GUARD_NOTIFY"] == 'false'
options[:notify] ? Notifier.turn_on : Notifier.turn_off
self self
end end
@ -90,12 +89,16 @@ module Guard
end end
def try_to_load_gem(name) def try_to_load_gem(name)
Kernel.require "guard/#{name.downcase}" require "guard/#{name.downcase}"
rescue LoadError rescue LoadError
end end
def locate_guard(name) def locate_guard(name)
Gem.source_index.find_name("guard-#{name}").last.full_gem_path if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
Gem::Specification.find_by_name("guard-#{name}").full_gem_path
else
Gem.source_index.find_name("guard-#{name}").last.full_gem_path
end
rescue rescue
UI.error "Could not find 'guard-#{name}' gem path." UI.error "Could not find 'guard-#{name}' gem path."
end end

View File

@ -1,13 +1,31 @@
module Guard module Guard
module Interactor module Interactor
extend self
def self.init_signal_traps def run_all
::Guard.run do
::Guard.guards.each { |guard| ::Guard.supervised_task(guard, :run_all) }
end
end
def stop
UI.info "Bye bye...\n", :reset => true
::Guard.listener.stop
::Guard.guards.each { |guard| ::Guard.supervised_task(guard, :stop) }
abort
end
def reload
::Guard.run do
::Guard.guards.each { |guard| ::Guard.supervised_task(guard, :reload) }
end
end
def self.init_signal_traps
# Run all (Ctrl-\) # Run all (Ctrl-\)
if Signal.list.has_key?('QUIT') if Signal.list.has_key?('QUIT')
Signal.trap('QUIT') do Signal.trap('QUIT') do
::Guard.run do run_all
::Guard.guards.each { |guard| ::Guard.supervised_task(guard, :run_all) }
end
end end
else else
UI.info "Your system doesn't support QUIT signal, so Ctrl-\\ (Run all) won't work" UI.info "Your system doesn't support QUIT signal, so Ctrl-\\ (Run all) won't work"
@ -16,10 +34,7 @@ module Guard
# Stop (Ctrl-C) # Stop (Ctrl-C)
if Signal.list.has_key?('INT') if Signal.list.has_key?('INT')
Signal.trap('INT') do Signal.trap('INT') do
UI.info "Bye bye...", :reset => true stop
::Guard.listener.stop
::Guard.guards.each { |guard| ::Guard.supervised_task(guard, :stop) }
abort("\n")
end end
else else
UI.info "Your system doesn't support INT signal, so Ctrl-C (stop) won't work" UI.info "Your system doesn't support INT signal, so Ctrl-C (stop) won't work"
@ -28,14 +43,12 @@ module Guard
# Reload (Ctrl-Z) # Reload (Ctrl-Z)
if Signal.list.has_key?('TSTP') if Signal.list.has_key?('TSTP')
Signal.trap('TSTP') do Signal.trap('TSTP') do
::Guard.run do reload
::Guard.guards.each { |guard| ::Guard.supervised_task(guard, :reload) }
end
end end
else else
UI.info "Your system doesn't support TSTP signal, so Ctrl-Z (Reload) won't work" UI.info "Your system doesn't support TSTP signal, so Ctrl-Z (Reload) won't work"
end end
end
end
end end
end end

View File

@ -51,7 +51,7 @@ module Guard
def watch_change def watch_change
@watch_change = true @watch_change = true
while !@stop until @stop
if Config::CONFIG['build'] =~ /java/ || IO.select([inotify.to_io], [], [], latency) if Config::CONFIG['build'] =~ /java/ || IO.select([inotify.to_io], [], [], latency)
break if @stop break if @stop

View File

@ -23,7 +23,7 @@ module Guard
private private
def watch_change def watch_change
while !@stop until @stop
start = Time.now.to_f start = Time.now.to_f
files = modified_files([Dir.pwd + '/'], :all => true) files = modified_files([Dir.pwd + '/'], :all => true)
update_last_event update_last_event

View File

@ -8,23 +8,33 @@ module Guard
@disable = true @disable = true
end end
def self.turn_on
@disable = false
case Config::CONFIG['target_os']
when /darwin/i
require_growl
when /linux/i
require_libnotify
end
end
def self.notify(message, options = {}) def self.notify(message, options = {})
unless @disable || ENV["GUARD_ENV"] == "test" unless @disable
image = options[:image] || :success image = options[:image] || :success
title = options[:title] || "Guard" title = options[:title] || "Guard"
case Config::CONFIG['target_os'] case Config::CONFIG['target_os']
when /darwin/i when /darwin/i
if growl_installed? Growl.notify message, :title => title, :icon => image_path(image), :name => "Guard"
Growl.notify message, :title => title, :icon => image_path(image), :name => "Guard"
end
when /linux/i when /linux/i
if libnotify_installed? Libnotify.show :body => message, :summary => title, :icon_path => image_path(image)
Libnotify.show :body => message, :summary => title, :icon_path => image_path(image)
end
end end
end end
end end
def self.disabled?
@disable
end
private private
def self.image_path(image) def self.image_path(image)
@ -42,24 +52,18 @@ module Guard
end end
end end
def self.growl_installed? def self.require_growl
@installed ||= begin require 'growl'
require 'growl' rescue LoadError
true @disable = true
rescue LoadError UI.info "Please install growl gem for Mac OS X notification support and add it to your Gemfile"
UI.info "Please install growl gem for Mac OS X notification support and add it to your Gemfile"
false
end
end end
def self.libnotify_installed? def self.require_libnotify
@installed ||= begin require 'libnotify'
require 'libnotify' rescue LoadError
true @disable = true
rescue LoadError UI.info "Please install libnotify gem for Linux notification support and add it to your Gemfile"
UI.info "Please install libnotify gem for Linux notification support and add it to your Gemfile"
false
end
end end
end end

View File

@ -2,29 +2,6 @@ module Guard
module UI module UI
class << self class << self
@color_enabled = true
@color_tested = false
@new_line = "\r"
def color_enabled?
if !@color_tested
@color_tested = true
if Config::CONFIG['target_os'] =~ /mswin|mingw/i
@new_line = "\r\n"
unless ENV['ANSICON']
begin
require 'rubygems' unless ENV['NO_RUBYGEMS']
require 'Win32/Console/ANSI'
rescue LoadError
@color_enabled = false
info "You must 'gem install win32console' to use color on Windows"
end
end
end
end
return @color_enabled
end
def info(message, options = {}) def info(message, options = {})
unless ENV["GUARD_ENV"] == "test" unless ENV["GUARD_ENV"] == "test"
reset_line if options[:reset] reset_line if options[:reset]
@ -47,10 +24,10 @@ module Guard
end end
def reset_line def reset_line
if color_enabled? if color_enabled?
print @new_line + "\e[0m" print "\r\e[0m"
else else
print @new_line print "\r\n"
end end
end end
@ -72,6 +49,22 @@ module Guard
end end
end end
def color_enabled?
@color_enabled ||= if Config::CONFIG['target_os'] =~ /mswin|mingw/i
unless ENV['ANSICON']
begin
require 'rubygems' unless ENV['NO_RUBYGEMS']
require 'Win32/Console/ANSI'
rescue LoadError
info "You must 'gem install win32console' to use color on Windows"
false
end
end
else
true
end
end
end end
end end
end end

View File

@ -1,3 +1,3 @@
module Guard module Guard
VERSION = "0.3.3" VERSION = "0.3.4"
end end

View File

@ -0,0 +1,27 @@
require 'spec_helper'
describe Guard::Interactor do
subject { Guard::Interactor }
let(:guard) { mock "guard" }
before :each do
Guard.stub!(:guards).and_return([guard])
Guard.stub!(:options).and_return({})
Guard.stub!(:listener).and_return(mock(:start => nil, :stop => nil))
end
it ".run_all should send :run_all to all guards" do
guard.should_receive(:run_all)
subject.run_all
end
it ".stop should send :stop to all guards" do
guard.should_receive(:stop)
lambda { subject.stop }.should raise_error(SystemExit)
end
it ".reload should send :reload to all guards" do
guard.should_receive(:reload)
subject.reload
end
end

View File

@ -10,7 +10,7 @@ describe Guard::Darwin do
end end
end end
if mac? if mac? && Guard::Darwin.usable?
it "is usable on 10.6" do it "is usable on 10.6" do
subject.should be_usable subject.should be_usable
end end

View File

@ -11,7 +11,7 @@ describe Guard::Linux do
end end
end end
if linux? if linux? && Guard::Linux.usable?
it "is usable on linux" do it "is usable on linux" do
subject.should be_usable subject.should be_usable
end end

View File

@ -4,56 +4,55 @@ describe Guard::Notifier do
subject { Guard::Notifier } subject { Guard::Notifier }
describe ".notify" do describe ".notify" do
before(:each) do before(:each) { subject.turn_on }
@saved_guard_env = ENV["GUARD_ENV"]
ENV["GUARD_ENV"] = 'dont_mute_notify'
end
if mac? if mac?
require 'growl' if growl_installed?
it "uses Growl on Mac OS X" do it "uses Growl on Mac OS X" do
Growl.should_receive(:notify).with("great", Growl.should_receive(:notify).with("great",
:title => "Guard", :title => "Guard",
:icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s, :icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s,
:name => "Guard" :name => "Guard"
) )
subject.notify 'great', :title => 'Guard' subject.notify 'great', :title => 'Guard'
end
else
it { should be_disabled }
end end
end end
if linux? if linux?
require 'libnotify' if libnotify_installed?
it "uses Libnotify on Linux" do it "uses Libnotify on Linux" do
Libnotify.should_receive(:show).with( Libnotify.should_receive(:show).with(
:body => "great", :body => "great",
:summary => 'Guard', :summary => 'Guard',
:icon_path => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s :icon_path => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s
) )
subject.notify 'great', :title => 'Guard'
end
else
it { should be_disabled }
end
end
end
describe ".turn_off" do
if mac? && growl_installed?
it "does nothing" do
Growl.should_not_receive(:notify)
subject.notify 'great', :title => 'Guard' subject.notify 'great', :title => 'Guard'
end end
end end
describe ".turn_off" do if linux? && libnotify_installed?
before(:each) { subject.turn_off } it "does nothing" do
Libnotify.should_not_receive(:show)
if mac? subject.notify 'great', :title => 'Guard'
require 'growl'
it "does nothing" do
Growl.should_not_receive(:notify)
subject.notify 'great', :title => 'Guard'
end
end
if linux?
require 'libnotify'
it "does nothing" do
Libnotify.should_not_receive(:show)
subject.notify 'great', :title => 'Guard'
end
end end
end end
after(:each) { ENV["GUARD_ENV"] = @saved_guard_env } it { should be_disabled }
end end
end end

View File

@ -23,10 +23,22 @@ describe Guard do
::Guard.listener.should be_kind_of(Guard::Listener) ::Guard.listener.should be_kind_of(Guard::Listener)
end end
it "should turn on by default" do
::Guard::Notifier.should_receive(:turn_on)
::Guard.setup(:notify => true)
end
it "should turn off notifier if notify option is false" do it "should turn off notifier if notify option is false" do
::Guard::Notifier.should_receive(:turn_off) ::Guard::Notifier.should_receive(:turn_off)
::Guard.setup(:notify => false) ::Guard.setup(:notify => false)
end end
it "should turn off notifier if env[GUARD_NOTIFY] is false" do
::Guard::Notifier.should_receive(:turn_off)
ENV["GUARD_NOTIFY"] = 'false'
::Guard.setup(:notify => true)
ENV["GUARD_NOTIFY"] = nil
end
end end
describe ".get_guard_class" do describe ".get_guard_class" do
@ -37,8 +49,8 @@ describe Guard do
context 'loaded some nested classes' do context 'loaded some nested classes' do
it "should find and return loaded class" do it "should find and return loaded class" do
Kernel.should_receive(:require) { |file_name| Guard.should_receive(:try_to_load_gem) { |className|
file_name.should == 'guard/classname' className.should == 'classname'
class Guard::Classname class Guard::Classname
end end
} }
@ -111,7 +123,13 @@ describe Guard do
describe ".locate_guard" do describe ".locate_guard" do
it "returns the path of the guard gem" do it "returns the path of the guard gem" do
Guard.locate_guard('rspec').should == Gem.source_index.find_name("guard-rspec").last.full_gem_path if Gem::Version.create(Gem::VERSION) >= Gem::Version.create('1.8.0')
gem_location = Gem::Specification.find_by_name("guard-rspec").full_gem_path
else
gem_location = Gem.source_index.find_name("guard-rspec").last.full_gem_path
end
Guard.locate_guard('rspec').should == gem_location
end end
end end
end end

View File

@ -15,6 +15,7 @@ RSpec.configure do |config|
config.run_all_when_everything_filtered = true config.run_all_when_everything_filtered = true
config.before(:each) do config.before(:each) do
Guard::Notifier.turn_off
@fixture_path = Pathname.new(File.expand_path('../fixtures/', __FILE__)) @fixture_path = Pathname.new(File.expand_path('../fixtures/', __FILE__))
end end

View File

@ -0,0 +1,13 @@
def growl_installed?
require 'growl'
true
rescue LoadError
false
end
def libnotify_installed?
require 'libnotify'
true
rescue LoadError
false
end