Emit file and line for failure source (use gF to jump straight to it!). vim-stuff
authorMahlon E. Smith <mahlon@martini.nu>
Fri, 24 Dec 2010 20:01:10 -0800
branchvim-stuff
changeset 21 cd1f3381c1ed
parent 20 09c4f575f627
child 22 ed72213b1788
Emit file and line for failure source (use gF to jump straight to it!). Show context lines for exception source. Put spec summary run at the top of the screen. Small documentation fixes.
specky/doc/specky.txt
specky/ruby/specky_formatter.rb
specky/syntax/specrun.vim
--- a/specky/doc/specky.txt	Sat Dec 18 23:38:55 2010 -0800
+++ b/specky/doc/specky.txt	Fri Dec 24 20:01:10 2010 -0800
@@ -91,11 +91,11 @@
 Otherwise, you'll need to locate it, and tell rspec to use it in one of two
 ways.
 
-	1) Set the *g:speckyRunSpecCmd* variable explicitly:
+	1) Set the 'g:speckyRunSpecCmd' variable explicitly:
 
-		let g:speckyRunRdocCmd = "rspec -r ~/.vim/ruby/specky_formatter.rb -f SpeckyFormatter" ~
+		let g:speckyRunSpecCmd = "rspec -r ~/.vim/ruby/specky_formatter.rb -f SpeckyFormatter" ~
 
-	2) or, leave *g:speckyRunSpecCmd* at its default value, and instead use
+	2) or, leave 'g:speckyRunSpecCmd' at its default value, and instead use
 	   an '.rspec' settings file in the root directory of the the project
 	   you're working in.  I find this method much more flexible -- the
 	   '.rspec' file can be carried with your project, and customized to
--- a/specky/ruby/specky_formatter.rb	Sat Dec 18 23:38:55 2010 -0800
+++ b/specky/ruby/specky_formatter.rb	Fri Dec 24 20:01:10 2010 -0800
@@ -14,8 +14,11 @@
 		@indent_level  = 0
 		@failure_index = 0
 		@failures      = []
+		@txt           = ''
+		@summary       = ''
 	end
 
+
 	########################################################################
 	### R S P E C  H O O K S
 	########################################################################
@@ -23,7 +26,6 @@
 	### Example group hook -- increase indentation, emit description
 	###
 	def example_group_started( example_group )
-		output.puts
 		self.out '+', '-' * (example_group.description.length + 2), '+'
 		self.out '| ', example_group.description, ' |'
 		self.out '+', '-' * (example_group.description.length + 2), '+'
@@ -73,13 +75,18 @@
 	### for Vim to fold.
 	###
 	def dump_failures
-		self.out "\n\n\n" unless @failures.empty?
+		self.out "\n" unless @failures.empty?
 
 		@failures.each_with_index do |example, index|
 			desc      = example.metadata[ :full_description ]
 			exception = example.execution_result[ :exception ]
+			file = line = nil
 
+			if exception.backtrace.first =~ /(.*):(\d+)/
+				file, line = $1, $2.to_i
+			end
 			self.out "FAILURE - #%d)" % [ index + 1 ]
+			self.out "%s:%d" % [ file, line ]
 
 			if RSpec::Core::PendingExampleFixedError === exception
 				self.out "%s FIXED" % [ desc ]
@@ -100,27 +107,55 @@
 					end
 				end
 			end
-			self.out "\n"
+
+			self.out exception_source( file, line ) if file && line
 		end
 	end
 
 
+	### Emit the source of the exception, with context lines.
+	###
+	def exception_source( file, line )
+		context = ''
+		low, high = line - 3, line + 3
+
+		File.open( file ).each_with_index do |cline, i|
+			cline.chomp!.rstrip!
+			next unless i >= low && i <= high
+			context << "  %s%4d: %s\n" % [ ( i == line ? '>>' : ' |' ), i, cline ]
+		end
+
+		return context
+
+	rescue
+		'Unable to parse exception context lines.'
+	end
+
+
 	### Emit summary data for all examples.
 	###
 	def dump_summary( duration, example_count, failure_count, pending_count )
 		succeeded = example_count - failure_count - pending_count
-		self.out '+', '-' * 49, '+'
-		self.out '|', ' ' * 18, '-- Summary --', ' ' * 18, '|'
-		self.out '+----------+-----------+--------+---------+-------+'
-		self.out '| Duration | Succeeded | Failed | Pending | Total |'
-		self.out '+----------+-----------+--------+---------+-------+'
+		@summary << "+%s+\n" % [ '-' * 49 ]
+		@summary << "|%s-- Summary --%s|\n" % [ ' ' * 18, ' ' * 18 ]
+		@summary << "+----------+-----------+--------+---------+-------+\n"
+		@summary << "| Duration | Succeeded | Failed | Pending | Total |\n"
+		@summary << "+----------+-----------+--------+---------+-------+\n"
 
-		self.out "| %7ss | %9s | %6s | %7s | %5s |" % [
+		@summary << "| %7ss | %9s | %6s | %7s | %5s |\n" % [
 			"%0.3f" % duration, succeeded, failure_count,
 			pending_count, example_count
 		]
 
-		self.out '+----------+-----------+--------+---------+-------+'
+		@summary << "+----------+-----------+--------+---------+-------+\n\n"
+	end
+
+
+	### End of run.  Dump it all out!
+	###
+	def close
+		output.puts @summary
+		output.puts @txt
 	end
 
 
@@ -132,7 +167,7 @@
 	###
 	def out( *msg )
 		msg = msg.join
-		output.puts "%s%s" % [ '  ' * @indent_level, msg ]
+		@txt << "%s%s\n" % [ '  ' * @indent_level, msg ]
 	end
 
 	### Format the basic example information, along with the run duration.
--- a/specky/syntax/specrun.vim	Sat Dec 18 23:38:55 2010 -0800
+++ b/specky/syntax/specrun.vim	Fri Dec 24 20:01:10 2010 -0800
@@ -27,7 +27,9 @@
 syntax keyword specFailedKeyword Failed
 
 " Failure details
-syntax region specFailedDetails start="^FAILURE - #\d\+)" end="^$" fold contains=specCallout
+syntax region specFailedDetails start="^FAILURE - #\d\+)" end="^$" fold contains=specCallout,specErrorLine
+syntax match specErrorLine /^  >>/
+
 
 " Boxes
 syntax match specBox /^\(\s\+\)\?\(+[+-]\+\||.*|\)$/ contains=specFailedKeyword,specDurationKeyword,specPendingKeyword,specPassedKeyword,specBoxContent
@@ -51,6 +53,7 @@
 highlight def link specBox LineNr
 highlight def link specBoxContent Constant
 highlight def link specBoxLine LineNr
+highlight def link specErrorLine ErrorMsg
 
 let b:current_syntax = "specrun"