diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4040c6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.gem +.bundle +Gemfile.lock +pkg/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..dc72d16 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source 'http://rubygems.org' + +# See gem's dependencies in: rspec-rails-watchr.gemspec +gemspec diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..3993f02 --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011 Elia Schito + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e675e51 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Usage + +In your specs.watchr file just add: + + @specs_watchr ||= Rspec::Rails::Watchr.new(self) + +Then launch `watchr` as usual (probably `bundle exec watchr`). + +## Instructions + +The normal behavior is similar to `autotest --fast-start --no-full-after-failed` +but gives the user a bit more control over execution. By hitting CTRL+C (or CMD+. on OSX) +you get the following prompt: + + ^C (Interrupted with CTRL+C) + --- What to do now? (q=quit, a=all-specs, r=reload): + +## Advanced + +If you want to override some path matching: + + @specs_watchr ||= Rspec::Rails::Watchr.new(self) do |path, specs| + case path + when %r{lib/calibration_with_coefficients} + specs.grep(%r{models/(logarithmic|polynomial)_calibration}) + when %r{app/models/telemetry_parameter} + specs.grep(%r{models/telemetry_parameter}) + end + end + + + + +Copyright (c) 2011 Elia Schito, released under the MIT license diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..c702cfc --- /dev/null +++ b/Rakefile @@ -0,0 +1 @@ +require 'bundler/gem_tasks' diff --git a/lib/rspec-rails-watchr.rb b/lib/rspec-rails-watchr.rb new file mode 100644 index 0000000..937b725 --- /dev/null +++ b/lib/rspec-rails-watchr.rb @@ -0,0 +1,143 @@ +require 'rspec-rails-watchr/version' +require 'term/ansicolor' + +module Rspec + module Rails + class Watchr + String.send :include, Term::ANSIColor + + module CommandLine + def terminal_columns + cols = `stty -a`.scan(/ (\d+) columns/).flatten.first + $?.success? ? cols.to_i : nil + end + + def run cmd + puts "=== running: #{cmd} ".ljust(terminal_columns, '=').cyan + success = system cmd + puts "===".ljust(terminal_columns, '=').cyan + success + end + + def clear! + system 'clear' + end + end + + module Specs + def notify message + Thread.new do + begin + require 'notify' + Notify.notify 'RSpec Result:', message + rescue + nil + end + end + end + + def rspec_command + @rspec_command ||= File.exist?('./.rspec') ? 'rspec' : 'spec' + end + + def rspec options + unless options.empty? + success = run("bundle exec #{rspec_command} #{options}") + notify( success ? '♥♥ SUCCESS :) ♥♥' : '♠♠ FAILED >:( ♠♠' ) + end + end + + def rspec_all + rspec 'spec' + end + + def rspec_files *files + rspec files.join(' ') + end + + def specs_for(path) + print "--- Searching specs for #{path.inspect}...".yellow + specs = match_specs path, Dir['spec/**/*_spec.rb'] + puts specs.empty? ? ' nothing found.'.red : " #{specs.size} matched.".green + specs + end + + def default_rails_matcher path, specs + specs.grep(/\b#{path}((_spec)?\.rb)?$/) + end + + def match_specs path, specs + matched_specs = @custom_matcher.call(path, specs) if @custom_matcher + matched_specs = default_rails_matcher(path, specs) if matched_specs.nil? + end + end + + module Control + def exit_watchr + @exiting = true + puts '--- Exiting...'.white + exit + end + + def abort_watchr! + puts '--- Forcing abort...'.white + abort("\n") + end + + def reload! + # puts ARGV.join(' ') + exec('bundle exec watchr') + end + + def reload_file_list + require 'shellwords' + system "touch #{__FILE__.shellescape}" + # puts '--- Watch\'d file list reloaded.'.green + end + + def trap_int! + # Ctrl-C + + @interrupted ||= false + + Signal.trap('INT') { + puts ' (Interrupted with CTRL+C)'.red + if @interrupted + @exiting ? abort_watchr : exit_watchr + else + @interrupted = true + # reload_file_list + print '--- What to do now? (q=quit, a=all-specs, r=reload): '.yellow + case STDIN.gets.chomp.strip.downcase + when 'q'; @interrupted = false; exit_watchr + when 'a'; @interrupted = false; rspec_all + when 'r'; @interrupted = false; reload! + else + @interrupted = false + puts '--- Bad input, ignored.'.yellow + end + puts '--- Waiting for changes...'.cyan + end + } + end + end + + + include CommandLine + include Specs + include Control + + def initialize watchr, &block + @custom_matcher = block if block_given? + @watchr = watchr + + watchr.watch('^spec/(.*)_spec\.rb$') {|m| rspec_files specs_for(m[1])} + watchr.watch('^(?:app|lib|script)/(.*)(?:\.rb|\.\w+|)$') {|m| rspec_files specs_for(m[1].gsub(/\.rb$/,''))} + + trap_int! + + puts '--- Waiting for changes...'.cyan + end + end + end +end diff --git a/lib/rspec-rails-watchr/version.rb b/lib/rspec-rails-watchr/version.rb new file mode 100644 index 0000000..08e3bf2 --- /dev/null +++ b/lib/rspec-rails-watchr/version.rb @@ -0,0 +1,7 @@ +module Rspec + module Rails + module Watchr + VERSION = "1.0" + end + end +end diff --git a/rspec-rails-watchr.gemspec b/rspec-rails-watchr.gemspec new file mode 100644 index 0000000..f560cf7 --- /dev/null +++ b/rspec-rails-watchr.gemspec @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "rspec-rails-watchr/version" + +Gem::Specification.new do |s| + s.name = 'rspec-rails-watchr' + s.version = Rspec::Rails::Watchr::VERSION + s.authors = %w[Elia Schito] + s.email = %w[perlelia@gmail.com] + s.homepage = '' + s.summary = %q{Watches specs for a Rails (2 or 3) project} + s.description = %q{Watches specs for a Rails (2 or 3) project} + s.license = 'MIT' + + s.rubyforge_project = 'rspec-rails-watchr' + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = %w[lib] + + s.add_dependency 'watchr' + s.add_dependency 'term-ansicolor' + s.add_dependency 'notify' +end