Class: Spectator::Runner

Inherits:
Object
  • Object
show all
Includes:
CommandLine, Control, Specs
Defined in:
lib/spectator.rb

Instance Attribute Summary

Attributes included from Control

#signal_queue

Instance Method Summary collapse

Methods included from Control

#abort!, #exit, #trap_int!

Methods included from Specs

#default_rails_matcher, #failed_message, #full_rspec_command, #match_specs, #notify, #osx?, #rspec, #rspec_all, #rspec_command, #rspec_files, #specs_for_file, #success_message

Methods included from CommandLine

#clear!, #run, #terminal_columns

Constructor Details

#initialize {|_self| ... } ⇒ Runner

Returns a new instance of Runner.

Yields:

  • (_self)

Yield Parameters:



89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/spectator.rb', line 89

def initialize &block
  yield self if block_given?

  spec_dir_glob = ENV['SPEC_DIR_GLOB'] || 'spec'
  base_dir_glob = ENV['BASE_DIR_GLOB'] || 'app|lib|script'
  matchers << %r{^#{spec_dir_glob}/(.*)_spec\.rb$}
  matchers << %r{^(?:#{base_dir_glob})/(.*)(?:\.rb|\.\w+|)$}

  trap_int!
  Thread.abort_on_exception = true
  @runner  = Thread.new { wait_for_changes }
  watch_paths!
end

Instance Method Details

#listenerObject



34
35
36
37
38
39
40
41
42
# File 'lib/spectator.rb', line 34

def listener
  @listener ||= begin
    listener = Listen.to(Dir.pwd, :relative_paths => true)
    listener = listener.filter %r{^(app|spec|lib|script)/}
    listener = listener.change do  |modified, added, removed|
      [modified, added].flatten.each { |relative| queue.push relative }
    end
  end
end

#matchersObject



21
22
23
# File 'lib/spectator.rb', line 21

def matchers
  @matchers ||= []
end

#puts(*args) ⇒ Object



45
46
47
# File 'lib/spectator.rb', line 45

def puts *args
  print args.join("\n")+"\n"
end

#queueObject



25
26
27
# File 'lib/spectator.rb', line 25

def queue
  @queue ||= Queue.new
end

#run_specs(specs) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/spectator.rb', line 49

def run_specs specs
  rules.each do |(regexp, action)|
    regexp = Regexp.new(regexp)
    if file =~ regexp
      m = regexp.match(file)
      action.call(m)
    end
  end
end

#specs_for(files) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/spectator.rb', line 77

def specs_for files
  specs = Set.new
  files = [files] unless files.respond_to? :each
  files.each do |file|
    matched = matchers.map do |matcher|
      file.scan(matcher).flatten.first.to_s.gsub(/\.rb$/,'')
    end.flatten.reject(&:empty?)
    specs += matched.uniq.map { |m| specs_for_file(m) }.flatten
  end
  specs.to_a
end

#wait_for_changesObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/spectator.rb', line 59

def wait_for_changes
  puts '--- Waiting for changes...'.cyan

  loop do
    sleep 0.1 while queue.empty? or interrupted?

    files = []
    queue.size.times do
      files << queue.pop
    end

    files.compact!
    redo if files.empty?

    rspec_files(*specs_for(files))
  end
end

#watch_paths!Object



29
30
31
32
# File 'lib/spectator.rb', line 29

def watch_paths!
  listener.start
  sleep
end