qed 2.5.1 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY.rdoc +259 -0
- data/LICENSE.rdoc +35 -0
- data/README.rdoc +20 -28
- data/bin/qedoc +2 -2
- data/lib/{qedoc/command.rb → qed/cli/qedoc.rb} +9 -26
- data/lib/qed/demo.rb +16 -4
- data/lib/{qedoc → qed}/document.rb +82 -36
- data/lib/{qedoc → qed}/document/jquery.js +0 -0
- data/lib/{qedoc → qed}/document/markup.rb +0 -0
- data/lib/{qedoc → qed}/document/template.rhtml +3 -8
- data/lib/qed/evaluator.rb +1 -1
- data/lib/qed/parser.rb +7 -0
- data/lib/qed/reporter/abstract.rb +136 -18
- data/lib/qed/reporter/bullet.rb +29 -17
- data/lib/qed/reporter/dotprogress.rb +14 -11
- data/lib/qed/reporter/dtrace.rb +67 -0
- data/lib/qed/reporter/tapy.rb +224 -0
- data/lib/qed/reporter/verbatim.rb +2 -2
- data/lib/qed/scope.rb +46 -31
- data/lib/qed/session.rb +28 -7
- metadata +12 -33
- data/LICENSE +0 -204
@@ -13,57 +13,86 @@ module QED
|
|
13
13
|
|
14
14
|
DEFAULT_TITLE = "Demonstration"
|
15
15
|
DEFAULT_CSS = nil #"../assets/styles/spec.css"
|
16
|
-
DEFAULT_OUTPUT = "
|
17
|
-
DEFAULT_PATH = "
|
16
|
+
DEFAULT_OUTPUT = "qed.html"
|
17
|
+
DEFAULT_PATH = "qed"
|
18
18
|
|
19
19
|
attr_accessor :title
|
20
|
+
|
20
21
|
attr_accessor :css
|
21
|
-
|
22
|
+
|
22
23
|
attr_accessor :dryrun
|
24
|
+
|
23
25
|
attr_accessor :quiet
|
24
26
|
|
25
27
|
# Ouput file.
|
26
28
|
attr_accessor :output
|
27
29
|
|
30
|
+
# Either html or plain.
|
31
|
+
# Defaults to extension of output file.
|
32
|
+
attr_accessor :format
|
33
|
+
|
34
|
+
#
|
35
|
+
attr_reader :paths
|
36
|
+
|
37
|
+
#
|
38
|
+
def paths=(paths)
|
39
|
+
@paths = [paths].flatten
|
40
|
+
end
|
41
|
+
|
28
42
|
# New Spec Document object.
|
29
43
|
def initialize(options={})
|
30
44
|
options.each do |k,v|
|
31
45
|
__send__("#{k}=", v)
|
32
46
|
end
|
33
47
|
|
48
|
+
@paths ||= []
|
49
|
+
|
50
|
+
@output ||= DEFAULT_OUTPUT
|
34
51
|
@title ||= DEFAULT_TITLE
|
35
52
|
@css ||= DEFAULT_CSS
|
36
|
-
|
37
|
-
@
|
53
|
+
|
54
|
+
if File.directory?(@output)
|
55
|
+
@output = File.join(@output, 'qed.html')
|
56
|
+
end
|
57
|
+
|
58
|
+
@format ||= File.extname(@output).sub('.','')
|
38
59
|
|
39
60
|
if @paths.empty?
|
40
|
-
dir = Dir['{test/demos,demos,demo}'].first || DEFAULT_PATH
|
41
|
-
|
61
|
+
#dir = Dir['{test/demos,demos,demo}'].first || DEFAULT_PATH
|
62
|
+
#@paths = File.join(dir, '**', '*')
|
63
|
+
abort "No files to document."
|
42
64
|
end
|
43
65
|
end
|
44
66
|
|
45
67
|
# Demo files.
|
46
68
|
def demo_files
|
47
69
|
@demo_files ||= (
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
70
|
+
files = []
|
71
|
+
paths.each do |f|
|
72
|
+
if File.directory?(f)
|
73
|
+
files.concat Dir[File.join(f,'**','*')]
|
74
|
+
else
|
75
|
+
files.concat Dir[f]
|
76
|
+
end
|
53
77
|
end
|
54
|
-
|
78
|
+
files = files.reject{ |f| File.directory?(f) }
|
79
|
+
files = files.reject{ |f| File.extname(f) == '.rb' }
|
80
|
+
files = files.reject{ |f| /(fixtures|helpers)\// =~ f }
|
81
|
+
files.sort
|
55
82
|
)
|
56
83
|
end
|
57
84
|
|
58
85
|
# Supress output.
|
59
|
-
def quiet?
|
86
|
+
def quiet?
|
87
|
+
@quiet
|
88
|
+
end
|
60
89
|
|
61
90
|
# Generate specification document.
|
62
91
|
def generate
|
63
|
-
copy_support_files
|
92
|
+
#copy_support_files
|
64
93
|
|
65
|
-
|
66
|
-
files
|
94
|
+
out = ''
|
95
|
+
files = []
|
67
96
|
|
68
97
|
#paths.each do |path|
|
69
98
|
# files.concat(Dir.glob(path).select{ |f| File.file?(f) })
|
@@ -102,33 +131,49 @@ module QED
|
|
102
131
|
when '.rd', '.rdoc'
|
103
132
|
require_rdoc
|
104
133
|
require_qedoc
|
105
|
-
|
106
|
-
|
107
|
-
|
134
|
+
if html?
|
135
|
+
markup = Markup.new(txt)
|
136
|
+
text << markup.to_html
|
137
|
+
#text << markup.convert(iotext, formatter)
|
138
|
+
else
|
139
|
+
text << txt
|
140
|
+
end
|
108
141
|
when '.md', '.markdown'
|
109
142
|
require_rdiscount
|
110
|
-
|
111
|
-
|
143
|
+
if html?
|
144
|
+
markdown = RDiscount.new(txt)
|
145
|
+
text << markdown.to_html
|
146
|
+
else
|
147
|
+
text << txt
|
148
|
+
end
|
112
149
|
end
|
113
150
|
|
114
|
-
|
151
|
+
out << "#{text}\n"
|
115
152
|
end
|
116
153
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
154
|
+
if html?
|
155
|
+
temp = Template.new(template, output, title, css)
|
156
|
+
html = temp.parse_template
|
157
|
+
save(html)
|
158
|
+
else
|
159
|
+
save(out)
|
160
|
+
end
|
121
161
|
end
|
122
162
|
|
123
163
|
#
|
124
|
-
def
|
125
|
-
|
126
|
-
%w{jquery.js}.each do |fname|
|
127
|
-
file = File.join(File.dirname(__FILE__), 'document', fname)
|
128
|
-
FileUtils.cp(file, output)
|
129
|
-
end
|
164
|
+
def html?
|
165
|
+
format == 'html'
|
130
166
|
end
|
131
167
|
|
168
|
+
#
|
169
|
+
#def copy_support_files
|
170
|
+
# make_output_directory
|
171
|
+
# %w{jquery.js}.each do |fname|
|
172
|
+
# file = File.join(File.dirname(__FILE__), 'document', fname)
|
173
|
+
# FileUtils.cp(file, output)
|
174
|
+
# end
|
175
|
+
#end
|
176
|
+
|
132
177
|
# Load specification HTML template.
|
133
178
|
def template
|
134
179
|
@template ||= (
|
@@ -143,14 +188,15 @@ module QED
|
|
143
188
|
puts "\nwrite #{output}"
|
144
189
|
else
|
145
190
|
make_output_directory
|
146
|
-
File.open(output
|
191
|
+
File.open(output, 'wb') do |f|
|
147
192
|
f << text
|
148
193
|
end
|
149
194
|
end
|
150
195
|
end
|
151
196
|
|
152
197
|
def make_output_directory
|
153
|
-
|
198
|
+
dir = File.dirname(output)
|
199
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
154
200
|
end
|
155
201
|
|
156
202
|
private
|
@@ -173,7 +219,7 @@ module QED
|
|
173
219
|
#
|
174
220
|
def require_qedoc
|
175
221
|
@require_qedoc ||= (
|
176
|
-
require '
|
222
|
+
require 'qed/document/markup'
|
177
223
|
true
|
178
224
|
)
|
179
225
|
end
|
File without changes
|
File without changes
|
@@ -103,17 +103,12 @@
|
|
103
103
|
.title { font-size: 2em; }
|
104
104
|
</style>
|
105
105
|
|
106
|
-
<!-- TODO: only include if these files exists -->
|
107
|
-
<link href="../assets/styles/spec.css" type="text/css" rel="stylesheet">
|
108
|
-
<!-- spec.css might be a problem with clobber -->
|
109
|
-
<link href="spec.css" type="text/css" rel="stylesheet">
|
110
|
-
|
111
106
|
<% if css %>
|
112
107
|
<link rel="stylesheet" href="<%= css %>" type="text/css">
|
113
108
|
<% end %>
|
114
109
|
|
115
110
|
<!-- JQuery is needed -->
|
116
|
-
<script src="jquery.js" type="text/javascript" language="javascript"></script>
|
111
|
+
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript" language="javascript"></script>
|
117
112
|
|
118
113
|
</head>
|
119
114
|
|
@@ -122,7 +117,7 @@
|
|
122
117
|
<!-- Side Table of Contents -->
|
123
118
|
<div id="sidebar" style="position: fixed; top: 10; right: 10; background: white;">
|
124
119
|
<a href="javascript: toc_toggle();">
|
125
|
-
<img src="
|
120
|
+
<img src="http://www.cdnjs.com/images/poweredbycloudflare.png" style="border: none;" alt="TOC" align="right"/>
|
126
121
|
</a>
|
127
122
|
|
128
123
|
<div id="toc_side" class="toc">
|
@@ -131,7 +126,7 @@
|
|
131
126
|
|
132
127
|
<div id="container">
|
133
128
|
<div id="header">
|
134
|
-
<img src="
|
129
|
+
<img src="http://www.cdnjs.com/images/poweredbycloudflare.png" align="left" style="padding-right: 10px;" alt=""/>
|
135
130
|
|
136
131
|
<div class="title"><%= title %></div>
|
137
132
|
|
data/lib/qed/evaluator.rb
CHANGED
data/lib/qed/parser.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module QED
|
2
2
|
|
3
|
+
#
|
4
|
+
def self.all_steps
|
5
|
+
@all_steps ||= []
|
6
|
+
end
|
7
|
+
|
3
8
|
# The parser breaks down a demonstandum into
|
4
9
|
# structured object to passed thru the script
|
5
10
|
# evaluator.
|
@@ -198,6 +203,8 @@ module QED
|
|
198
203
|
|
199
204
|
#
|
200
205
|
def initialize(file)
|
206
|
+
QED.all_steps << self
|
207
|
+
|
201
208
|
@file = file
|
202
209
|
@raw = []
|
203
210
|
@type = :description
|
@@ -2,16 +2,25 @@ module QED
|
|
2
2
|
module Reporter
|
3
3
|
|
4
4
|
require 'facets/string'
|
5
|
-
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'ansi/core'
|
8
|
+
rescue LoadError
|
9
|
+
require 'ansi/code'
|
10
|
+
end
|
6
11
|
|
7
12
|
# = Reporter Absract Base Class
|
8
13
|
#
|
9
14
|
# Serves as the base class for all other output formats.
|
10
15
|
class Abstract
|
11
16
|
|
17
|
+
attr :session
|
18
|
+
|
12
19
|
attr :io
|
20
|
+
|
13
21
|
attr :record
|
14
22
|
|
23
|
+
# TODO: pass session into initialize
|
15
24
|
def initialize(options={})
|
16
25
|
@io = options[:io] || STDOUT
|
17
26
|
@trace = options[:trace]
|
@@ -110,6 +119,7 @@ module Reporter
|
|
110
119
|
|
111
120
|
# At the start of a session, before running any demonstrations.
|
112
121
|
def before_session(session)
|
122
|
+
@session = session
|
113
123
|
@start_time = Time.now
|
114
124
|
end
|
115
125
|
|
@@ -248,12 +258,24 @@ module Reporter
|
|
248
258
|
end
|
249
259
|
|
250
260
|
#
|
251
|
-
|
252
|
-
|
261
|
+
INTERNALS = /(lib|bin)[\\\/](qed|ae)/
|
262
|
+
|
263
|
+
#
|
264
|
+
def sane_backtrace(exception)
|
265
|
+
if trace_count
|
266
|
+
clean_backtrace(*exception.backtrace[0, trace_count])
|
267
|
+
else
|
268
|
+
clean_backtrace(*exception.backtrace)
|
269
|
+
end
|
253
270
|
end
|
254
271
|
|
255
272
|
#
|
256
|
-
|
273
|
+
def clean_backtrace(*btrace)
|
274
|
+
stack = btrace.reject{ |bt| bt =~ INTERNALS } unless $DEBUG
|
275
|
+
stack.map do |bt|
|
276
|
+
bt.chomp(":in \`__binding__'")
|
277
|
+
end
|
278
|
+
end
|
257
279
|
|
258
280
|
=begin
|
259
281
|
# Clean the backtrace of any reference to ko/ paths and code.
|
@@ -269,44 +291,140 @@ module Reporter
|
|
269
291
|
end
|
270
292
|
=end
|
271
293
|
|
294
|
+
# Produce a pretty code snippet given an exception.
|
272
295
|
#
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
296
|
+
# @param exception [Exception, String]
|
297
|
+
# An exception or backtrace.
|
298
|
+
#
|
299
|
+
# @param radius [Integer]
|
300
|
+
# The number of surrounding lines to show.
|
301
|
+
#
|
302
|
+
# @return [String] pretty code snippet
|
303
|
+
def code_snippet(exception, radius=2)
|
304
|
+
radius = radius.to_i
|
305
|
+
|
306
|
+
file, lineno = file_and_line(exception)
|
277
307
|
|
278
|
-
|
308
|
+
return nil if file.empty?
|
309
|
+
|
310
|
+
source = source(file)
|
279
311
|
|
280
|
-
|
281
|
-
|
282
|
-
[source_line + radius, source.length].min
|
312
|
+
region = [lineno - radius, 1].max ..
|
313
|
+
[lineno + radius, source.length].min
|
283
314
|
|
284
315
|
# ensure proper alignment by zero-padding line numbers
|
285
316
|
format = " %2s %0#{region.last.to_s.length}d %s"
|
286
317
|
|
287
318
|
pretty = region.map do |n|
|
288
|
-
format % [('=>' if n ==
|
319
|
+
format % [('=>' if n == lineno), n, source[n-1].chomp]
|
289
320
|
end #.unshift "[#{region.inspect}] in #{source_file}"
|
290
321
|
|
291
322
|
pretty
|
292
323
|
end
|
293
324
|
|
325
|
+
# Return a structure code snippet in an array of lineno=>line
|
326
|
+
# hash elements.
|
327
|
+
#
|
328
|
+
# @param exception [Exception, String]
|
329
|
+
# An exception or backtrace.
|
330
|
+
#
|
331
|
+
# @param radius [Integer]
|
332
|
+
# The number of surrounding lines to show.
|
333
|
+
#
|
334
|
+
# @return [Hash] structured code snippet
|
335
|
+
def structured_code_snippet(exception, radius=2)
|
336
|
+
radius = radius.to_i
|
337
|
+
|
338
|
+
file, lineno = file_and_line(exception)
|
339
|
+
|
340
|
+
return {} if file.empty?
|
341
|
+
|
342
|
+
source = source(file)
|
343
|
+
|
344
|
+
region = [lineno - radius, 1].max ..
|
345
|
+
[lineno + radius, source.length].min
|
346
|
+
|
347
|
+
region.map do |n|
|
348
|
+
{n => source[n-1].chomp}
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
# Cache the source code of a file.
|
353
|
+
#
|
354
|
+
# @param file [String] full pathname to file
|
294
355
|
#
|
356
|
+
# @return [String] source code
|
295
357
|
def source(file)
|
296
358
|
@source[file] ||= (
|
297
359
|
File.readlines(file)
|
298
360
|
)
|
299
361
|
end
|
300
362
|
|
363
|
+
# @param exception [Exception,Array,String]
|
364
|
+
# An exception or backtrace.
|
365
|
+
#
|
366
|
+
#--
|
301
367
|
# TODO: Show more of the file name than just the basename.
|
368
|
+
#++
|
302
369
|
def file_and_line(exception)
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
370
|
+
backtrace = case exception
|
371
|
+
when Exception
|
372
|
+
exception.backtrace.reject{ |bt| bt =~ INTERNALS }.first
|
373
|
+
when Array
|
374
|
+
exception.first
|
375
|
+
else
|
376
|
+
exception
|
377
|
+
end
|
378
|
+
|
379
|
+
backtrace =~ /(.+?):(\d+(?=:|\z))/ or return ""
|
380
|
+
|
381
|
+
file, lineno = $1, $2.to_i
|
382
|
+
|
383
|
+
return file, lineno
|
384
|
+
|
385
|
+
#i = backtrace.rindex(':in')
|
386
|
+
#line = i ? line[0...i] : line
|
387
|
+
#relative_file(line)
|
308
388
|
end
|
309
389
|
|
390
|
+
# Same as file_and_line, exception return file path is relative.
|
391
|
+
def file_line(exception)
|
392
|
+
file, lineno = file_and_line(exception)
|
393
|
+
return relative_file(file), lineno
|
394
|
+
end
|
395
|
+
|
396
|
+
# Default trace count. This is the number of backtrace lines that
|
397
|
+
# will be provided on errors and failed assertions, unless otherwise
|
398
|
+
# overridden with ENV['trace'].
|
399
|
+
DEFAULT_TRACE_COUNT = 3
|
400
|
+
|
401
|
+
# Looks at ENV['trace'] to determine how much trace output to provide.
|
402
|
+
# If it is not set, or set to`false` or `off`, then the default trace count
|
403
|
+
# is used. If set to `0`, `true`, 'on' or 'all' then aa complete trace dump
|
404
|
+
# is provided. Otherwise the value is converted to an integer and that many
|
405
|
+
# line of trace is given.
|
406
|
+
#
|
407
|
+
# @return [Integer, nil] trace count
|
408
|
+
def trace_count
|
409
|
+
cnt = ENV['trace']
|
410
|
+
case cnt
|
411
|
+
when nil, 'false', 'off'
|
412
|
+
DEFAULT_TRACE_COUNT
|
413
|
+
when 0, 'all', 'true', 'on'
|
414
|
+
nil
|
415
|
+
else
|
416
|
+
Integer(cnt)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
#
|
421
|
+
def relative_file(file)
|
422
|
+
pwd = Dir.pwd
|
423
|
+
idx = (0...pwd.size).find do |i|
|
424
|
+
file[i,1] != pwd[i,1]
|
425
|
+
end
|
426
|
+
file[(idx || 0)..-1]
|
427
|
+
end
|
310
428
|
end
|
311
429
|
|
312
430
|
end
|