spackle 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +166 -0
  5. data/Rakefile +49 -0
  6. data/VERSION +1 -0
  7. data/bin/ruby-project-root +14 -0
  8. data/bin/spackle +14 -0
  9. data/bin/spackle-vim-load-quickfix +47 -0
  10. data/bin/spackle-vim-open +49 -0
  11. data/lib/spackle/commandline.rb +53 -0
  12. data/lib/spackle/configuration.rb +37 -0
  13. data/lib/spackle/error.rb +31 -0
  14. data/lib/spackle/helpers/ruby_project_root.rb +34 -0
  15. data/lib/spackle/output/base.rb +44 -0
  16. data/lib/spackle/output/vim_quickfix.rb +7 -0
  17. data/lib/spackle/output.rb +2 -0
  18. data/lib/spackle/spec/base_formatter.rb +22 -0
  19. data/lib/spackle/spec/spackle_formatter.rb +14 -0
  20. data/lib/spackle/spec.rb +1 -0
  21. data/lib/spackle.rb +104 -0
  22. data/spec/integration_spec.rb +84 -0
  23. data/spec/spackle/commandline_spec.rb +48 -0
  24. data/spec/spackle/configuration_spec.rb +43 -0
  25. data/spec/spackle/error_spec.rb +34 -0
  26. data/spec/spackle/output/base_spec.rb +53 -0
  27. data/spec/spackle/output/vim_quickfix_spec.rb +25 -0
  28. data/spec/spackle/spec/base_formatter_spec.rb +15 -0
  29. data/spec/spackle/spec/spackle_formatter_spec.rb +58 -0
  30. data/spec/spackle_error_fixture.rb +10 -0
  31. data/spec/spackle_spec.rb +203 -0
  32. data/spec/spec.opts +1 -0
  33. data/spec/spec_helper.rb +14 -0
  34. data/spec/test_app_helper.rb +55 -0
  35. data/support/vim/spackle.vim +17 -0
  36. data/test_app/lib/error_raiser.rb +7 -0
  37. data/test_app/lib/method_typo.rb +7 -0
  38. data/test_app/lib/missing_end.rb +7 -0
  39. data/test_app/lib/working_class.rb +7 -0
  40. data/test_app/spec/error_raiser_spec.rb +14 -0
  41. data/test_app/spec/failing_working_class_spec.rb +14 -0
  42. data/test_app/spec/method_typo_spec.rb +14 -0
  43. data/test_app/spec/missing_end_spec.rb +13 -0
  44. data/test_app/spec/passing_working_class_spec.rb +14 -0
  45. data/test_app/spec/spec_helper.rb +8 -0
  46. metadata +127 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Rick Lee-Morlang
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,166 @@
1
+ = Spackle
2
+
3
+ <em>Smoothing out the gaps between the Rubyist and the Ruby.</em>
4
+
5
+ Well, honestly, it only fills in the gaps between RSpec and Vim right now,
6
+ but that's a good start. Cucumber support is in the works, and perhaps a
7
+ few other surprises if I make the time.
8
+
9
+ Patches supporting other editors gladly accepted. Most people aren't very
10
+ editor-agnostic, but Spackle doesn't care! (Or, at least, it wouldn't if
11
+ you patched it with support for your amazing editor that's surely better
12
+ than mine.)
13
+
14
+ == Elevator Pitch
15
+
16
+ Spackle tells your editor about the errors in your code. No more need to
17
+ visually scan your test output for errors, filenames, and line numbers.
18
+ Just tell your editor to jump to the next error location.
19
+
20
+ == Features
21
+
22
+ * custom RSpec formatters that generate output compatible with
23
+ Vim's quickfix functionality
24
+ * a simple Vim plugin to allow a quickfix list to be loaded
25
+ from a file
26
+ * shell scripts to glue Spackle's output and Vim together
27
+ * easy to use?
28
+
29
+ == Quick Installation
30
+
31
+ gem install spackle --source http://gemcutter.org
32
+ spackle --install vim # described below
33
+ echo 'Spackle.configuration.set_defaults_for :vim' > ~/.spackle
34
+
35
+ == Configuration and Usage
36
+
37
+ For a tool that doesn't do a heck of alot, it's pretty configurable.
38
+ If it <b>could</b> do something else, it'd be easy to tell it how to do
39
+ it with either a <tt>.spackle</tt> file in your home directory, or a
40
+ <tt>.spackle</tt> file in your project's root directory.
41
+
42
+ If Spackle is useful to you, I'd love to hear about it.
43
+
44
+ === PATH
45
+
46
+ Spackle installs a few utility scripts in the bin directory where
47
+ executables are installed by your system's Rubygems. If you've installed
48
+ Spackle as root, this should be fine. If you've installed Spackle as a
49
+ regular user, you need to make sure the appropriate bin directory is
50
+ in your path.
51
+
52
+ To test your configuration, run +which spackle+ in your terminal. If
53
+ you don't see any output, your PATH variable is not correctly configured
54
+ for use with user-installed gems.
55
+
56
+ See your Rubygems documentation for more information about this.
57
+
58
+ === Spackle dotfile
59
+
60
+ Without a dotfile configured, Spackle won't do anything. This is so
61
+ you can make Spackle a dependency of your project and integrate it
62
+ into your code, yet leave its usage up to each individual developer.
63
+
64
+ Spackle reads its configuration from a <tt>.spackle</tt> file, which it looks
65
+ for in your home directory first, and in the root directory of your
66
+ project second. Spackle configuration in your project directory takes
67
+ precedence over any in your home directory, so you can override global
68
+ settings on a per-project basis if you like.
69
+
70
+ Example <tt>.spackle</tt> for Vim users.
71
+
72
+ Spackle.configure do |c|
73
+ c.set_defaults_for :vim
74
+ end
75
+
76
+ See Spackle::Configuration for more information.
77
+
78
+ === RSpec
79
+
80
+ Add to your spec_helper.rb:
81
+
82
+ require "spackle"
83
+ Spackle.init :with => :spec_formatter
84
+
85
+ Now whenever RSpec runs, Spackle will listen in to your test results and
86
+ relay information about any errors to your editor.
87
+
88
+ === Vim
89
+
90
+ Spackle needs a tiny Vim plugin installed to function properly with Vim.
91
+ Simply run +spackle install vim+ and Spackle will copy its plugin into
92
+ your <tt>.vim/plugins</tt> directory.
93
+
94
+ <b>Optional:</b>
95
+ Spackle also comes with a helper script for invoking Vim with a session
96
+ named after your project's parent directory. It's called <tt>spackle-vim-open</tt>.
97
+ If you'd like to use it, you'll probably want to add an alias to your
98
+ <tt>.profile</tt> or <tt>.bashrc</tt>. Example:
99
+
100
+ alias e='spackle-vim-open'
101
+
102
+ == Architecture
103
+
104
+ Spackle's architecture consists of three components.
105
+
106
+ NOTE: Some of this information looks forward to a future version of Spackle
107
+ that, at the moment, is fictional. So if you go looking for some of the things
108
+ referenced here and you can't find them, that's probably why. (Or it could be
109
+ an error in this document!)
110
+
111
+ Error Parser Adapters
112
+ * integrate with test harnesses like RSpec and Cucumber
113
+ * or integrate with Ruby's standard Error API
114
+ * or parse Ruby's standard backtrace output
115
+ * convert error output into a generic intermediary Spackle::Error format
116
+ * pass the errors to Spackle's core for reformatting and output
117
+ * found in Spackle::Spec, Spackle::Cucumber and Spackle::Ruby
118
+
119
+ Spackle Core
120
+ * glues all the pieces together
121
+ * loads user configuration
122
+ * tries to do as much as it can automagically
123
+ * tries to stay out of your way
124
+ * routes Spackle::Error objects from the Adapters, through an
125
+ Output Formatter, and finally to an output file
126
+ * triggers a callback after every test run that can send error
127
+ information to your editor
128
+
129
+ Output Formatters
130
+ * convert the generic Error format into an output-specific format
131
+ for your callback to handle
132
+ * found in Spackle::Output
133
+
134
+ Spackle's core configuration, tries to do as much automagically as it can,
135
+ and tries to stay out of the way. It aids the models by routing Errors to the
136
+ configured output formatter.
137
+
138
+ == Known Issues
139
+
140
+ * Spackle assumes you're using something UNIXy. If you're not, it likely
141
+ won't work. I have no interest in working on this, but I'll gladly
142
+ pull your patches.
143
+ * Spackle's current implementation only catches test failures from RSpec.
144
+ Other hooks are in the works.
145
+
146
+ == Credits
147
+
148
+ Spackle was inspired by https://wincent.com/blog/running-rspec-specs-from-inside-vim
149
+
150
+ == Note on Patches/Pull Requests
151
+
152
+ This section was generated by Jeweler's boilerplate, but it seems
153
+ pretty sensible.
154
+
155
+ * Fork the project.
156
+ * Make your feature addition or bug fix.
157
+ * Add tests for it. This is important so I don't break it in a
158
+ future version unintentionally.
159
+ * Commit, do not mess with rakefile, version, or history.
160
+ (if you want to have your own version, that is fine but
161
+ bump version in a commit by itself I can ignore when I pull)
162
+ * Send me a pull request. Bonus points for topic branches.
163
+
164
+ == Copyright
165
+
166
+ Copyright (c) 2009 Rick Lee-Morlang. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "spackle"
8
+ gem.summary = %Q{Spackle tells your editor about the errors in your code}
9
+ gem.description = %Q{
10
+ Spackle tells your editor about the errors in your code. No more need to
11
+ visually scan your test output for errors, filenames, and line numbers.
12
+ Just tell your editor to jump to the next error location.
13
+ }
14
+ gem.email = "rick@lee-morlang.com"
15
+ gem.homepage = "http://github.com/rleemorlang/spackle"
16
+ gem.authors = ["Rick Lee-Morlang"]
17
+ gem.add_development_dependency "rspec", ">= 1.2.9"
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
23
+ end
24
+
25
+ require 'spec/rake/spectask'
26
+ Spec::Rake::SpecTask.new(:spec) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.spec_files = FileList['spec/**/*_spec.rb']
29
+ end
30
+
31
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
32
+ spec.libs << 'lib' << 'spec'
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+ task :spec => :check_dependencies
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "spackle #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ spackle_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(spackle_dir) unless $LOAD_PATH.include?(spackle_dir)
4
+
5
+ require 'spackle/helpers/ruby_project_root'
6
+
7
+ project_root = Spackle::Helpers::RubyProjectRoot.search Dir.pwd
8
+
9
+ if project_root.nil?
10
+ exit 1
11
+ else
12
+ puts project_root
13
+ end
14
+
data/bin/spackle ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ spackle_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(spackle_dir) unless $LOAD_PATH.include?(spackle_dir)
4
+
5
+ require 'spackle'
6
+ require 'spackle/commandline'
7
+
8
+ begin
9
+ Spackle::Commandline.parse ARGV
10
+ rescue => err
11
+ STDERR.puts err.message
12
+ exit 1
13
+ end
14
+
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+ spackle_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(spackle_dir) unless $LOAD_PATH.include?(spackle_dir)
4
+
5
+ require 'spackle/helpers/ruby_project_root'
6
+
7
+ # Load a Vim Quickfix file in an active vim session.
8
+ #
9
+ # Usage:
10
+ # spackle-vim-load-quickfix [servername] quickfix_file
11
+ #
12
+ # If servername is specified, try to use it as the vim
13
+ # server. Otherwise, assume the name for the vim server
14
+ # is the from ruby-project-root -basename, if
15
+ # successful. If no Ruby project root was found, use
16
+ # DEFAULT as the servername.
17
+ #
18
+ # If the server doesn't exist, we'll create a new
19
+ # gvim session.
20
+ #
21
+
22
+ def servername_from_arguments
23
+ ARGV.shift if ARGV.count == 2
24
+ end
25
+
26
+ def servername_from_project_root
27
+ project_root = Spackle::Helpers::RubyProjectRoot.search Dir.pwd
28
+ File.basename(project_root) if project_root
29
+ end
30
+
31
+ def servername
32
+ @servername ||= servername_from_arguments || servername_from_project_root || "DEFAULT"
33
+ end
34
+
35
+ def server_running?
36
+ !`gvim --serverlist`.grep(/#{servername}/i).empty?
37
+ end
38
+
39
+ unless server_running?
40
+ system %{gvim --servername #{servername}}
41
+ sleep 1
42
+ end
43
+
44
+ system %{gvim --servername #{servername} --remote-send "<ESC>" &> /dev/null}
45
+ system %{gvim --servername #{servername} --remote-expr "LoadSpackleQuickfix('#{ARGV.first}')" &> /dev/null}
46
+ system %{gvim --servername #{servername} --remote-send "<ESC><C-W>p" &> /dev/null}
47
+
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ spackle_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(spackle_dir) unless $LOAD_PATH.include?(spackle_dir)
4
+
5
+ require 'spackle/helpers/ruby_project_root'
6
+
7
+ # Load a Vim Quickfix file in an active vim session.
8
+ #
9
+ # Usage:
10
+ # spackle-vim-load-quickfix [servername] quickfix_file
11
+ #
12
+ # If servername is specified, try to use it as the vim
13
+ # server. Otherwise, assume the name for the vim server
14
+ # is the from ruby-project-root -basename, if
15
+ # successful. If no Ruby project root was found, use
16
+ # DEFAULT as the servername.
17
+ #
18
+ # If the server doesn't exist, we'll create a new
19
+ # gvim session.
20
+ #
21
+
22
+ def servername_from_arguments
23
+ ARGV.count.times do |index|
24
+ if ARGV[index] == "--servername"
25
+ ARGV.delete_at index
26
+ return ARGV.delete_at_index
27
+ end
28
+ end
29
+ nil
30
+ end
31
+
32
+ def servername_from_project_root
33
+ project_root = Spackle::Helpers::RubyProjectRoot.search Dir.pwd
34
+ File.basename(project_root) if project_root
35
+ end
36
+
37
+ def servername
38
+ servername_from_arguments || servername_from_project_root || "DEFAULT"
39
+ end
40
+
41
+ def arguments
42
+ arguments = ['gvim', '--servername', servername]
43
+ unless ARGV.empty?
44
+ arguments << "--remote-silent"
45
+ arguments += ARGV
46
+ end
47
+ end
48
+
49
+ system *arguments
@@ -0,0 +1,53 @@
1
+ require 'optparse'
2
+ require 'fileutils'
3
+
4
+
5
+ module Spackle
6
+ class Commandline
7
+ class << self
8
+ def install(mod)
9
+ case mod.to_sym
10
+ when :vim
11
+ src = File.join(File.dirname(__FILE__), "/../../support/vim/spackle.vim")
12
+ dest = File.expand_path "~/.vim/plugin"
13
+ raise "No such directory #{dest} -- cannot install Vim plugin" unless File.directory?(dest)
14
+ FileUtils.copy src, dest
15
+ puts "spackle.vim installed in #{dest}"
16
+ else
17
+ raise "Unrecognized module '#{mod}' -- cannot install"
18
+ end
19
+ end
20
+
21
+ def show_error(message)
22
+ puts message
23
+ end
24
+
25
+ def parse(options)
26
+ opts = OptionParser.new do |opts|
27
+ opts.banner = "Usage: spackle --install vim\n" +
28
+ " spackle [rubyscript] [args_for_script]"
29
+
30
+ opts.separator " "
31
+ opts.separator "Options:"
32
+
33
+ opts.on("-i", "--install MODULE", "Install a Spackle module.", "Choices: vim") do |mod|
34
+ install(mod)
35
+ end
36
+
37
+ opts.on("-h", "--help", "-?", "this help screen") do
38
+ puts opts
39
+ exit
40
+ end
41
+ end
42
+
43
+ if options.empty?
44
+ puts opts
45
+ else
46
+ opts.parse!(options)
47
+ end
48
+
49
+ raise "Spackle's wrapper mode is not yet implement" unless options.empty?
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ module Spackle
2
+ class Configuration
3
+ # The command to invoke when Spackle finds errors. It will receive
4
+ # a single argument, being the path to the Spackle errors file.
5
+ # If left unspecified, no command is invoked.
6
+ attr_accessor :callback_command
7
+
8
+ # Where to store the Spackle error files. If unspecified, Spackle will
9
+ # default to /tmp
10
+ attr_accessor :tempdir
11
+
12
+ # Which ErrorFormatter class to use when formatting errors. Specified
13
+ # as a symbol or string matching a class in spackle/error_formatters.
14
+ # i.e. config.error_formatter = :vim_quickfix
15
+ attr_accessor :error_formatter
16
+
17
+ # Filename to use when writing the formatted Spackle results. If
18
+ # unspecified, defaults to a filename based on the name of your
19
+ # project's root directory, or "default.spackle" it can't figure out
20
+ # where your root directory is
21
+ attr_accessor :spackle_file
22
+
23
+ # Configure Spackle with defaults. Currently only accepts :vim as an
24
+ # argument.
25
+ def set_defaults_for(mode)
26
+ case mode.to_sym
27
+ when :vim
28
+ self.callback_command = "spackle-vim-load-quickfix"
29
+ self.error_formatter = :vim_quickfix
30
+ else
31
+ raise ArgumentError.new("unknown Spackle mode: '#{mode}'")
32
+ end
33
+ end
34
+
35
+
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ module Spackle
2
+ class BacktraceEntry
3
+ attr_reader :file, :line
4
+ def initialize(file, line)
5
+ @file, @line = file, line
6
+ end
7
+ end
8
+
9
+ class Error
10
+ attr_reader :message, :backtrace
11
+
12
+ def initialize(message)
13
+ @message = message
14
+ @backtrace = []
15
+ yield self if block_given?
16
+ end
17
+
18
+ def add_error(error_or_file, line = nil)
19
+ case error_or_file
20
+ when Error
21
+ @backtrace << error_or_file
22
+ when String
23
+ @backtrace << BacktraceEntry.new(error_or_file, line)
24
+ else
25
+ raise ArgumentError.new("unrecognized error input '#{error_or_file}'. Should be a filename or a Spackle::BacktraceEntry")
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+
@@ -0,0 +1,34 @@
1
+ module Spackle
2
+ module Helpers
3
+ module RubyProjectRoot
4
+ class << self
5
+ # Search recursively from the current working directory up for something
6
+ # that looks like the root directory of a Ruby project.
7
+ #
8
+ # Returns the path to the found project dir, if any. Nil otherwise.
9
+ #
10
+ # Stops looking when it reaches the top of the tree, or the user's
11
+ # home directory.
12
+ #
13
+ # Detects a project dir via any of:
14
+ # * a config/environment.rb file
15
+ # * a spec/spec_helper.rb file
16
+ # * a features/step_definitions directory
17
+ def search(directory)
18
+ directory = File.expand_path(directory)
19
+ while directory != '/'
20
+ return directory if is_project_dir?(directory)
21
+ directory = File.expand_path(directory + '/..')
22
+ end
23
+ nil
24
+ end
25
+
26
+ def is_project_dir?(path)
27
+ File.exists?(File.join(path, "config/environment.rb")) ||
28
+ File.exists?(File.join(path, "spec/spec_helper.rb")) ||
29
+ File.directory?(File.join(path, "features/step_definitions"))
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,44 @@
1
+ module Spackle::Output
2
+ # This is the foundation of all Spackle::Output classes, but by itself
3
+ # it does nothing.
4
+ #
5
+ # Using an Output class should be simple:
6
+ # (assuming errors is an Array of Spackle::Error objects)
7
+ # puts Spackle::Output::VimQuickfix.format(errors)
8
+ #
9
+ # The child class (VimQuickfix) only needs to implement the
10
+ # format_backtrace instance method.
11
+ #
12
+ # Spackle::Output::Base is responsible for things like:
13
+ # * iterating over the backtrace collection
14
+ # * making pathnames relative
15
+ # * limiting the number of errors that are output
16
+ # * filtering the backtrace output by filename
17
+ #
18
+ # Spackle::Output::Base interacts with Spackle's Configuration
19
+ #
20
+ # If you're writing your own Output class, it should be quite
21
+ # easy to override some of the Configuration handling if your
22
+ # class requires it.
23
+ #
24
+ class Base
25
+ attr_accessor :error
26
+ def initialize(error = nil)
27
+ self.error = error || Spackle.current_error
28
+ end
29
+
30
+ def formatted_lines
31
+ error.backtrace.map do |bt|
32
+ format_backtrace_line error.message, bt.file, bt.line
33
+ end
34
+ end
35
+
36
+ def format
37
+ formatted_lines.join("\n") + "\n"
38
+ end
39
+
40
+ def self.format(error = nil)
41
+ new(error || Spackle.current_error).format
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,7 @@
1
+ module Spackle::Output
2
+ class VimQuickfix < Base
3
+ def format_backtrace_line(message, file, line)
4
+ "%s:%d: %s" % [ file, line.to_i, message.gsub(/\n/, ' ') ]
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ require 'spackle/output/base'
2
+ require 'spackle/output/vim_quickfix'
@@ -0,0 +1,22 @@
1
+ require 'spec/runner/formatter/base_formatter'
2
+
3
+ # This is just a slightly-refactored and cut down version of RSpec's
4
+ # BaseTextFormatter.
5
+
6
+ module Spackle::Spec
7
+ class BaseFormatter < ::Spec::Runner::Formatter::BaseFormatter
8
+ attr_reader :output, :options
9
+ attr_accessor :errors
10
+
11
+ def initialize(options, output)
12
+ # we ignore output, for now
13
+ Spackle.init
14
+ @options = options
15
+ self.errors = []
16
+ end
17
+
18
+ def close
19
+ Spackle.test_finished errors
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ require 'spackle/spec/base_formatter'
2
+
3
+ module Spackle::Spec
4
+ class SpackleFormatter < BaseFormatter
5
+ def example_failed(example, counter, failure)
6
+ error = Spackle::Error.new failure.exception.message
7
+ failure.exception.backtrace.each do |frame|
8
+ file, line = frame.match(/^([^:]+):([0-9]+)/)[1,2]
9
+ error.add_error file, line
10
+ end
11
+ self.errors << error
12
+ end
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ require 'spackle/spec/spackle_formatter'