From 1831bf752fd7ce15eb23934e8d5fa59c59bb5243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Coutable?= Date: Thu, 16 Dec 2010 01:22:42 +0100 Subject: [PATCH] Guard no more automatically convert String into Regexp in "watch" method patterns. It allows to define: watch("foo_bar.rb") without meaning /foo_bar.rb/ (where "foo_bar_rb.rb" would have been matched) However, during the deprecation phase, strings that look like a regexes (e.g. "^foo_bar.rb", "foo_bar.rb$", "foo_.*bar.rb" or "foo_(bar|baz).rb" are converted automatically to Regexp and a *very annoying* deprecation message is displayed. --- CHANGELOG.rdoc | 6 +++ Guardfile | 6 +-- README.rdoc | 63 +++++++++++++++++++------------- lib/guard.rb | 4 +- lib/guard/watcher.rb | 17 ++++++++- spec/guard/watcher_spec.rb | 75 +++++++++++++++++++++++++++----------- 6 files changed, 117 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 54690a7..b35110a 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,9 @@ +== 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: diff --git a/Guardfile b/Guardfile index 7a6e758..d5c6bd9 100644 --- a/Guardfile +++ b/Guardfile @@ -1,5 +1,5 @@ guard('rspec', :version => 2) do - watch(%|^spec/(.*)_spec\.rb|) - watch(%|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" } - watch(%|^spec/spec_helper\.rb|) { "spec" } + watch(%r{^spec/(.*)_spec\.rb}) + watch(%r{^lib/(.*)\.rb}) { |m| "spec/#{m[1]}_spec.rb" } + watch('spec/spec_helper.rb') { "spec" } end \ No newline at end of file diff --git a/README.rdoc b/README.rdoc index 37b4b26..32cdad2 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,6 +1,6 @@ = Guard -Guard is a command line tool to easly handle events on files modifications. +Guard is a command line tool that easily handle events on files modifications. == Features @@ -27,33 +27,33 @@ Generate an empty Guardfile with: guard init -Add guard(s) you need (see available guards below) +Add the guards you need (see available guards below) === On Mac OS X -Install rb-fsevent for {FSEvent}[http://en.wikipedia.org/wiki/FSEvents] support +Install rb-fsevent for {FSEvent}[http://en.wikipedia.org/wiki/FSEvents] support: gem install rb-fsevent -Install growl for Growl notification support +Install growl for Growl notification support: gem install growl -And add it to you Gemfile +And add it to you Gemfile: gem 'growl' === On Linux -Install rb-inotify for {inotify}[http://en.wikipedia.org/wiki/Inotify] support +Install rb-inotify for {inotify}[http://en.wikipedia.org/wiki/Inotify] support: gem install rb-inotify -Install libnotify for libonity notification support +Install libnotify for libonity notification support: gem install libnotify -And add it to you Gemfile +And add it to you Gemfile: gem 'libnotify' @@ -63,6 +63,12 @@ Just launch Guard inside your ruby/rails project with: guard +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 -c @@ -71,11 +77,13 @@ Options list is available with: guard help [TASK] +== Signal handlers + Signal handlers are used to interact with Guard: -- Ctrl-C - Quit Guard (call stop guard(s) method before) -- Ctrl-\ - Call run_all guard(s) method -- Ctrl-Z - Call reload guard(s) method +- Ctrl-C - Quit Guard (call each guard's run_all method, in the same order they are declared in the Guarfile) +- Ctrl-\ - Call each guard's run_all method, in the same order they are declared in the Guarfile +- Ctrl-Z - Call each guard's reload method, in the same order they are declared in the Guarfile == Available Guards @@ -109,6 +117,24 @@ Add guard definition to your Guardfile by running this command: You are good to go! +== Guardfile DSL + +Guardfile DSL consists of just two simple methods: guard & watch. Example: + + guard 'rspec', :version => 2 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 + +- "guard" method allow to add a guard with an optional options hash +- "watch" method allow to define which files are supervised per this guard. A optional block can be added to overwrite path sending to run_on_change guard method or launch simple command. + == Create a guard Create a new guard is very easy, just create a new gem with this basic structure: @@ -173,21 +199,6 @@ lib/guard/guard-name.rb inherit from guard/guard and should overwrite at least o Looks at available guards code for more concrete example. -== Guardfile DSL - -Guardfile DSL consists of just two simple methods: guard & watch. Example: - - guard 'rspec', :version => 2 do - watch(%|^spec/(.*)_spec\.rb|) - watch(%|^lib/(.*)\.rb|) { |m| "spec/lib/#{m[1]}_spec.rb" } - watch(%|^spec/spec_helper\.rb|) { "spec" } - watch(%|^spec/models/.*\.rb|) { ["spec/models", "spec/acceptance"] } - watch(%|^spec/spec_helper\.rb|) { `say hello` } - end - -- "guard" method allow to add a guard with an optional options hash -- "watch" method allow to define which files are supervised per this guard. A optional block can be added to overwrite path sending to run_on_change guard method or launch simple command. - == TODO - Add more specs! Shame on me :) diff --git a/lib/guard.rb b/lib/guard.rb index ddeb7e3..5f9f5e4 100644 --- a/lib/guard.rb +++ b/lib/guard.rb @@ -53,8 +53,8 @@ module Guard end end - # Let a guard execute his task but - # fire it if his work lead to system failure + # Let a guard execute its task but + # fire it if his work leads to a system failure def supervised_task(guard, task_to_supervise, *args) guard.send(task_to_supervise, *args) rescue Exception diff --git a/lib/guard/watcher.rb b/lib/guard/watcher.rb index bbda600..723f452 100644 --- a/lib/guard/watcher.rb +++ b/lib/guard/watcher.rb @@ -4,6 +4,17 @@ module Guard def initialize(pattern, action = nil) @pattern, @action = pattern, action + @@warning_printed ||= false + + # deprecation warning + if @pattern.is_a?(String) && @pattern =~ /(^(\^))|(>?(\\\.)|(\.\*))|(\(.*\))|(\[.*\])|(\$$)/ + unless @@warning_printed + UI.info "DEPRECATED!\nYou have strings in your Guardfile's watch patterns that seem to represent regexps.\nGuard matchs String with == and Regexp with Regexp#match.\nYou should either use plain String (without Regexp special characters) or real Regexp.\n" + @@warning_printed = true + end + UI.info "\"#{@pattern}\" has been converted to #{Regexp.new(@pattern).inspect}\n" + @pattern = Regexp.new(@pattern) + end end def self.match_files(guard, files) @@ -31,7 +42,11 @@ module Guard end def match_file?(file) - file.match(@pattern) + if @pattern.is_a?(Regexp) + file.match(@pattern) + else + file == @pattern + end end def call_action(matches) diff --git a/spec/guard/watcher_spec.rb b/spec/guard/watcher_spec.rb index abaca88..2c01345 100644 --- a/spec/guard/watcher_spec.rb +++ b/spec/guard/watcher_spec.rb @@ -8,19 +8,32 @@ describe Guard::Watcher do expect { Guard::Watcher.new }.to raise_error(ArgumentError) end - it "should be set" do - Guard::Watcher.new(%|spec_helper\.rb|).pattern.should == %|spec_helper\.rb| + it "can be a string" do + Guard::Watcher.new('spec_helper.rb').pattern.should == 'spec_helper.rb' + end + + it "can be a regexp" do + Guard::Watcher.new(/spec_helper\.rb/).pattern.should == /spec_helper\.rb/ + end + + describe "string looking like a regex" do + before(:each) { Guard::UI.should_receive(:info).any_number_of_times } + + specify { Guard::Watcher.new('^spec_helper.rb').pattern.should == /^spec_helper.rb/ } + specify { Guard::Watcher.new('spec_helper.rb$').pattern.should == /spec_helper.rb$/ } + specify { Guard::Watcher.new('spec_helper\.rb').pattern.should == /spec_helper\.rb/ } + specify { Guard::Watcher.new('.*_spec.rb').pattern.should == /.*_spec.rb/ } end end describe "action" do it "should set action to nil by default" do - Guard::Watcher.new(%|spec_helper\.rb|).action.should be_nil + Guard::Watcher.new(/spec_helper\.rb/).action.should be_nil end it "should set action with a block" do action = lambda { |m| "spec/#{m[1]}_spec.rb" } - Guard::Watcher.new(%|^lib/(.*).rb|, action).action.should == action + Guard::Watcher.new(%r{^lib/(.*).rb}, action).action.should == action end end @@ -28,7 +41,7 @@ describe Guard::Watcher do before(:all) { @guard = Guard::Guard.new } describe "a watcher's with no action" do - before(:all) { @guard.watchers = [Guard::Watcher.new(%|.*_spec\.rb|)] } + before(:all) { @guard.watchers = [Guard::Watcher.new(/.*_spec\.rb/)] } it "should return paths as they came" do Guard::Watcher.match_files(@guard, ['guard_rocks_spec.rb']).should == ['guard_rocks_spec.rb'] @@ -38,12 +51,12 @@ describe Guard::Watcher do describe "a watcher's action with an arity equal to 0" do before(:all) do @guard.watchers = [ - Guard::Watcher.new(%|spec_helper\.rb|, lambda { 'spec' }), - Guard::Watcher.new(%|addition\.rb|, lambda { 1 + 1 }), - Guard::Watcher.new(%|hash\.rb|, lambda { Hash[:foo, 'bar'] }), - Guard::Watcher.new(%|array\.rb|, lambda { ['foo', 'bar'] }), - Guard::Watcher.new(%|blank\.rb|, lambda { '' }), - Guard::Watcher.new(%|uptime\.rb|, lambda { `uptime > /dev/null` }) + Guard::Watcher.new(/spec_helper\.rb/, lambda { 'spec' }), + Guard::Watcher.new(/addition\.rb/, lambda { 1 + 1 }), + Guard::Watcher.new(/hash\.rb/, lambda { Hash[:foo, 'bar'] }), + Guard::Watcher.new(/array\.rb/, lambda { ['foo', 'bar'] }), + Guard::Watcher.new(/blank\.rb/, lambda { '' }), + Guard::Watcher.new(/uptime\.rb/, lambda { `uptime > /dev/null` }) ] end @@ -70,12 +83,12 @@ describe Guard::Watcher do describe "a watcher's action with an arity equal to 1" do before(:all) do @guard.watchers = [ - Guard::Watcher.new(%|lib/(.*)\.rb|, lambda { |m| "spec/#{m[1]}_spec.rb" }), - Guard::Watcher.new(%|addition(.*)\.rb|, lambda { |m| 1 + 1 }), - Guard::Watcher.new(%|hash\.rb|, lambda { Hash[:foo, 'bar'] }), - Guard::Watcher.new(%|array(.*)\.rb|, lambda { |m| ['foo', 'bar'] }), - Guard::Watcher.new(%|blank(.*)\.rb|, lambda { |m| '' }), - Guard::Watcher.new(%|uptime(.*)\.rb|, lambda { |m| `uptime > /dev/null` }) + Guard::Watcher.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }), + Guard::Watcher.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }), + Guard::Watcher.new(/hash\.rb/, lambda { Hash[:foo, 'bar'] }), + Guard::Watcher.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }), + Guard::Watcher.new(/blank(.*)\.rb/, lambda { |m| '' }), + Guard::Watcher.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` }) ] end @@ -111,8 +124,8 @@ describe Guard::Watcher do describe ".match_files?" do before(:all) do - @guard1 = Guard::Guard.new([Guard::Watcher.new(%|.*_spec\.rb|)]) - @guard2 = Guard::Guard.new([Guard::Watcher.new(%|spec_helper\.rb|, 'spec')]) + @guard1 = Guard::Guard.new([Guard::Watcher.new(/.*_spec\.rb/)]) + @guard2 = Guard::Guard.new([Guard::Watcher.new(/spec_helper\.rb/, 'spec')]) @guards = [@guard1, @guard2] end @@ -126,10 +139,28 @@ describe Guard::Watcher do end describe "#match_file?" do - subject { Guard::Watcher.new(%|.*_spec\.rb|) } + describe "string pattern" do + describe "normal string" do + subject { Guard::Watcher.new('guard_rocks_spec.rb') } + + specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false } + specify { subject.match_file?('guard_rocks_spec.rb').should be_true } + end + + describe "string representing a regexp converted (while deprecation is active)" do + subject { Guard::Watcher.new('^guard_rocks_spec\.rb$') } + + specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false } + specify { subject.match_file?('guard_rocks_spec.rb').should be_true } + end + end - specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false } - specify { subject.match_file?('guard_rocks_spec.rb').should be_true } + describe "regexp pattern" do + subject { Guard::Watcher.new(/.*_spec\.rb/) } + + specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false } + specify { subject.match_file?('guard_rocks_spec.rb').should be_true } + end end end \ No newline at end of file