qed 2.6.3 → 2.7.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/.ruby +4 -3
- data/.yardopts +3 -0
- data/HISTORY.rdoc +71 -35
- data/README.rdoc +9 -10
- data/bin/qed +1 -1
- data/bin/qedoc +2 -1
- data/lib/qed.rb +2 -5
- data/lib/qed.yml +4 -3
- data/lib/qed/applique.rb +57 -24
- data/lib/qed/cli.rb +8 -0
- data/lib/qed/cli/qed.rb +124 -0
- data/lib/qed/demo.rb +35 -39
- data/lib/qed/document.rb +5 -3
- data/lib/qed/document/template.rhtml +1 -0
- data/lib/qed/evaluator.rb +227 -199
- data/lib/qed/parser.rb +60 -282
- data/lib/qed/reporter/abstract.rb +54 -58
- data/lib/qed/reporter/dotprogress.rb +6 -4
- data/lib/qed/reporter/html.rb +112 -31
- data/lib/qed/reporter/tapy.rb +95 -125
- data/lib/qed/reporter/verbatim.rb +80 -38
- data/lib/qed/scope.rb +35 -48
- data/lib/qed/session.rb +35 -140
- data/lib/qed/settings.rb +104 -67
- data/lib/qed/step.rb +237 -0
- data/{spec → qed}/01_demos.rdoc +0 -0
- data/{spec → qed}/02_advice.rdoc +18 -7
- data/qed/03_helpers.rdoc +44 -0
- data/{spec → qed}/04_samples.rdoc +4 -4
- data/{spec → qed}/05_quote.rdoc +3 -3
- data/{spec → qed}/07_toplevel.rdoc +0 -0
- data/{spec → qed}/08_cross_script.rdoc +0 -0
- data/{spec → qed}/09_cross_script.rdoc +0 -0
- data/{spec → qed}/10_constant_lookup.rdoc +2 -2
- data/qed/11_embedded_rules.rdoc +46 -0
- data/{test/integration/topcode.rdoc → qed/99_issues/02_topcode.rdoc} +0 -0
- data/{spec → qed}/applique/constant.rb +0 -0
- data/{spec → qed}/applique/env.rb +0 -0
- data/{spec → qed}/applique/fileutils.rb +0 -0
- data/{spec → qed}/applique/markup.rb +0 -0
- data/{spec → qed}/applique/toplevel.rb +0 -0
- data/{spec → qed}/helpers/advice.rb +6 -7
- data/{spec → qed}/helpers/toplevel.rb +0 -0
- data/{spec → qed}/samples/data.txt +0 -0
- data/{spec → qed}/samples/table.yml +0 -0
- metadata +44 -39
- data/LICENSE.rdoc +0 -31
- data/SPECSHEET.rdoc +0 -456
- data/lib/qed/advice.rb +0 -158
- data/lib/qed/reporter/bullet.rb +0 -91
- data/lib/qed/reporter/dtrace.rb +0 -67
- data/lib/yard-qed.rb +0 -1
- data/spec/03_helpers.rdoc +0 -43
- data/spec/applique/quote.rb +0 -4
- data/spec/helpers/sample.rb +0 -4
data/lib/qed/parser.rb
CHANGED
@@ -1,43 +1,54 @@
|
|
1
|
-
|
1
|
+
require 'qed/step'
|
2
2
|
|
3
|
-
|
4
|
-
def self.all_steps
|
5
|
-
@all_steps ||= []
|
6
|
-
end
|
3
|
+
module QED
|
7
4
|
|
8
|
-
# The parser breaks down a demonstandum into
|
9
|
-
#
|
10
|
-
# evaluator.
|
5
|
+
# The parser breaks down a demonstandum into structured object
|
6
|
+
# to passed thru the script evaluator.
|
11
7
|
#
|
12
|
-
# Technically is defines it's own markup language
|
13
|
-
#
|
14
|
-
#
|
8
|
+
# Technically is defines it's own markup language but for
|
9
|
+
# interoperability sake it is RDoc and/or Markdown.
|
10
|
+
#
|
15
11
|
class Parser
|
16
12
|
|
13
|
+
# Setup new parser instance.
|
14
|
+
#
|
15
|
+
# @param [Demo] demo
|
16
|
+
# This demo, which is to be parsed.
|
17
|
+
#
|
18
|
+
# @param [Hash] options
|
19
|
+
# Parsing options.
|
17
20
|
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
# @option options [Symbol] :mode
|
22
|
+
# Parse in `:comment` mode or default mode.
|
23
|
+
#
|
24
|
+
def initialize(demo, options={})
|
25
|
+
@demo = demo
|
26
|
+
@mode = options[:mode]
|
27
|
+
@steps = []
|
22
28
|
end
|
23
29
|
|
24
|
-
#
|
25
|
-
attr :
|
30
|
+
# The demo to parse.
|
31
|
+
attr :demo
|
32
|
+
|
33
|
+
# Parser mode.
|
34
|
+
attr :mode
|
26
35
|
|
27
|
-
#
|
28
|
-
attr :
|
36
|
+
# Abstract Syntax Tree
|
37
|
+
attr :steps
|
29
38
|
|
30
|
-
#
|
31
|
-
|
39
|
+
# The demo's file to parse.
|
40
|
+
def file
|
41
|
+
demo.file
|
42
|
+
end
|
32
43
|
|
33
|
-
#
|
44
|
+
# Lines of demo, prepared for parsing into steps.
|
34
45
|
def lines
|
35
46
|
@lines ||= parse_lines
|
36
47
|
end
|
37
48
|
|
38
|
-
#
|
49
|
+
# Prepare lines for parsing into steps.
|
39
50
|
def parse_lines
|
40
|
-
case
|
51
|
+
case mode
|
41
52
|
when :comment
|
42
53
|
parse_comment_lines
|
43
54
|
else
|
@@ -50,6 +61,8 @@ module QED
|
|
50
61
|
|
51
62
|
# TODO: It would be nice if we could get ther require statement for the
|
52
63
|
# comment mode to be relative to an actual loadpath.
|
64
|
+
|
65
|
+
# Parse comment lines into a format that the parse method can use.
|
53
66
|
def parse_comment_lines
|
54
67
|
ruby_omit = false
|
55
68
|
rdoc_omit = false
|
@@ -83,276 +96,41 @@ module QED
|
|
83
96
|
lines
|
84
97
|
end
|
85
98
|
|
86
|
-
|
87
|
-
# Parse the demo into an abstract syntax tree.
|
88
|
-
#
|
89
|
-
# TODO: I know there has to be a faster way to do this.
|
99
|
+
# Parse demo file into steps.
|
90
100
|
def parse
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
case state
|
97
|
-
when :code
|
98
|
-
blocks.last << line
|
99
|
-
when :blank
|
100
|
-
blocks.last << line
|
101
|
-
else
|
102
|
-
blocks.last << line
|
103
|
-
state = :blank
|
104
|
-
end
|
105
|
-
when /^\s+/
|
106
|
-
blocks << [] if state != :code
|
107
|
-
blocks.last << line
|
108
|
-
state = :code
|
109
|
-
else
|
110
|
-
blocks << [] if state != :text
|
111
|
-
blocks.last << line
|
112
|
-
state = :text
|
113
|
-
end
|
114
|
-
end
|
115
|
-
blocks.shift if blocks.first.empty?
|
116
|
-
|
117
|
-
line_cnt = 1
|
118
|
-
blocks.each do |block|
|
119
|
-
text = block.join
|
120
|
-
case text
|
121
|
-
when /\A\s+/
|
122
|
-
add_section(:code, text, line_cnt)
|
123
|
-
else
|
124
|
-
add_section(:text, text, line_cnt)
|
125
|
-
end
|
126
|
-
line_cnt += block.size
|
127
|
-
end
|
128
|
-
#@ast.reject!{ |sect| sect.type == :code && sect.text.strip.empty? }
|
129
|
-
return @ast
|
130
|
-
end
|
101
|
+
steps = []
|
102
|
+
blank = false
|
103
|
+
indented = false
|
104
|
+
explain = []
|
105
|
+
example = [] #Step.new(file)
|
131
106
|
|
132
|
-
#
|
133
|
-
def add_section(state, text, lineno)
|
134
|
-
case state
|
135
|
-
when :code
|
136
|
-
if ast.last && ast.last.cont?
|
137
|
-
@ast.last << text #clean_quote(text)
|
138
|
-
else
|
139
|
-
@ast << CodeSection.new(text, lineno)
|
140
|
-
end
|
141
|
-
else
|
142
|
-
@ast << TextSection.new(text, lineno)
|
143
|
-
#cont = (/\.\.\.\s*^/ =~ text ? true : false)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
=end
|
147
|
-
|
148
|
-
def parse
|
149
|
-
tree = []
|
150
|
-
flush = true
|
151
|
-
pend = false
|
152
|
-
block = Block.new(file)
|
153
107
|
lines.each do |lineno, line|
|
154
108
|
case line
|
155
|
-
when /^\s*$/
|
156
|
-
|
157
|
-
|
158
|
-
|
109
|
+
when /^\s*$/ # blank line
|
110
|
+
blank = true
|
111
|
+
if indented
|
112
|
+
example << [lineno, line]
|
159
113
|
else
|
160
|
-
|
161
|
-
end
|
162
|
-
when /\A\s+/
|
163
|
-
if flush
|
164
|
-
tree << block.ready!(flush, tree.last)
|
165
|
-
block = Block.new(file)
|
114
|
+
explain << [lineno, line]
|
166
115
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
116
|
+
when /\A\s+/ #/\A(\t|\ \ +)/ # indented
|
117
|
+
indented = true
|
118
|
+
blank = false
|
119
|
+
example << [lineno, line]
|
170
120
|
else
|
171
|
-
if
|
172
|
-
|
173
|
-
|
174
|
-
flush = true
|
175
|
-
block = Block.new(file)
|
121
|
+
if indented or blank
|
122
|
+
steps << Step.new(demo, explain, example, steps.last)
|
123
|
+
explain, example = [], [] #Step.new(file)
|
176
124
|
end
|
177
|
-
|
125
|
+
indented = false
|
126
|
+
blank = false
|
127
|
+
explain << [lineno, line]
|
178
128
|
end
|
179
129
|
end
|
180
|
-
|
181
|
-
@
|
182
|
-
end
|
183
|
-
|
184
|
-
# TODO: We need to preserve the indentation for the verbatim reporter.
|
185
|
-
#def clean_quote(text)
|
186
|
-
# text = text.tabto(0).chomp.sub(/\A\n/,'')
|
187
|
-
# if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(text)
|
188
|
-
# text = md[1]
|
189
|
-
# end
|
190
|
-
# text.rstrip
|
191
|
-
#end
|
192
|
-
|
193
|
-
# Section Block
|
194
|
-
class Block
|
195
|
-
# Block raw code/text.
|
196
|
-
attr :raw
|
197
|
-
|
198
|
-
# previous block
|
199
|
-
attr :back_step
|
200
|
-
|
201
|
-
# next block
|
202
|
-
attr :next_step
|
203
|
-
|
204
|
-
#
|
205
|
-
def initialize(file)
|
206
|
-
QED.all_steps << self
|
207
|
-
|
208
|
-
@file = file
|
209
|
-
@raw = []
|
210
|
-
@type = :description
|
211
|
-
@back_step = nil
|
212
|
-
@next_step = nil
|
213
|
-
end
|
214
|
-
|
215
|
-
#
|
216
|
-
def ready!(flush, back_step)
|
217
|
-
@flush = flush
|
218
|
-
@back_step = back_step
|
219
|
-
|
220
|
-
@text = raw.map{ |lineno, line| line }.join
|
221
|
-
@type = parse_type
|
222
|
-
|
223
|
-
@back_step.next_step = self if @back_step
|
224
|
-
|
225
|
-
self
|
226
|
-
end
|
227
|
-
|
228
|
-
#
|
229
|
-
def to_s
|
230
|
-
case type
|
231
|
-
when :description
|
232
|
-
text
|
233
|
-
else
|
234
|
-
text
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
#
|
239
|
-
def text
|
240
|
-
@text
|
241
|
-
end
|
242
|
-
|
243
|
-
#
|
244
|
-
def flush?
|
245
|
-
@flush
|
246
|
-
end
|
247
|
-
|
248
|
-
# Returns an Array of prepared example text
|
249
|
-
# for use in advice.
|
250
|
-
def arguments
|
251
|
-
if next_step && next_step.data?
|
252
|
-
[next_step.sample_text]
|
253
|
-
else
|
254
|
-
[]
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
# What type of block is this?
|
259
|
-
def type
|
260
|
-
@type
|
261
|
-
end
|
262
|
-
|
263
|
-
#
|
264
|
-
def head? ; @type == :head ; end
|
265
|
-
|
266
|
-
#
|
267
|
-
def desc? ; @type == :desc ; end
|
268
|
-
|
269
|
-
#
|
270
|
-
def code? ; @type == :code ; end
|
271
|
-
|
272
|
-
# Any commentary ending in `...` or `:` will mark the following
|
273
|
-
# block as a plain text *sample* and not example code to be evaluated.
|
274
|
-
def data? ; @type == :data ; end
|
275
|
-
|
276
|
-
#
|
277
|
-
alias_method :header?, :head?
|
278
|
-
|
279
|
-
#
|
280
|
-
alias_method :description?, :desc?
|
281
|
-
|
282
|
-
|
283
|
-
# First line of example text.
|
284
|
-
def lineno
|
285
|
-
@line ||= @raw.first.first
|
286
|
-
end
|
287
|
-
|
288
|
-
#
|
289
|
-
def code
|
290
|
-
@code ||= tweak_code
|
291
|
-
end
|
292
|
-
|
293
|
-
# Clean up the example text, removing unccesseary white lines
|
294
|
-
# and triple quote brackets, but keep indention intact.
|
295
|
-
def clean_text
|
296
|
-
str = text.chomp.sub(/\A\n/,'')
|
297
|
-
if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(str)
|
298
|
-
str = md[1]
|
299
|
-
end
|
300
|
-
str.rstrip
|
301
|
-
end
|
302
|
-
|
303
|
-
# When the text is sample text and passed to an adivce block, this
|
304
|
-
# provides the prepared form of the example text, removing white lines,
|
305
|
-
# triple quote brackets and indention.
|
306
|
-
def sample_text
|
307
|
-
str = text.tabto(0).chomp.sub(/\A\n/,'')
|
308
|
-
if md = /\A["]{3,}(.*?)["]{3,}\Z/.match(str)
|
309
|
-
str = md[1]
|
310
|
-
end
|
311
|
-
str.rstrip
|
312
|
-
end
|
313
|
-
|
314
|
-
# TODO: object_hexid
|
315
|
-
def inspect
|
316
|
-
%[#<Block:#{object_id} "#{text[0..25]} ...">]
|
317
|
-
end
|
318
|
-
|
319
|
-
protected
|
320
|
-
|
321
|
-
#
|
322
|
-
def next_step=(n)
|
323
|
-
@next_step = n
|
324
|
-
end
|
325
|
-
|
326
|
-
private
|
327
|
-
|
328
|
-
#
|
329
|
-
def parse_type
|
330
|
-
if flush?
|
331
|
-
if /\A[=#]/ =~ text
|
332
|
-
:head
|
333
|
-
else
|
334
|
-
:desc
|
335
|
-
end
|
336
|
-
else
|
337
|
-
if back_step && /(\.\.\.|\:)\s*\Z/m =~ back_step.text.strip
|
338
|
-
:data
|
339
|
-
else
|
340
|
-
:code
|
341
|
-
end
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
#
|
346
|
-
def tweak_code
|
347
|
-
code = text.dup
|
348
|
-
code.gsub!(/\n\s*\#\ ?\=\>/, '.assert = ')
|
349
|
-
code.gsub!(/\s*\#\ ?\=\>/, '.assert = ')
|
350
|
-
code
|
351
|
-
end
|
352
|
-
|
130
|
+
steps << Step.new(demo, explain, example, steps.last)
|
131
|
+
@steps = steps
|
353
132
|
end
|
354
133
|
|
355
134
|
end
|
356
135
|
|
357
136
|
end
|
358
|
-
|
@@ -14,10 +14,16 @@ module Reporter
|
|
14
14
|
# Serves as the base class for all other output formats.
|
15
15
|
class Abstract
|
16
16
|
|
17
|
+
# Does the system support INFO signal?
|
18
|
+
INFO_SIGNAL = Signal.list['INFO']
|
19
|
+
|
20
|
+
#
|
17
21
|
attr :session
|
18
22
|
|
23
|
+
#
|
19
24
|
attr :io
|
20
25
|
|
26
|
+
#
|
21
27
|
attr :record
|
22
28
|
|
23
29
|
# TODO: pass session into initialize
|
@@ -62,9 +68,9 @@ module Reporter
|
|
62
68
|
end
|
63
69
|
|
64
70
|
#
|
65
|
-
def
|
71
|
+
def call(type, *args)
|
66
72
|
__send__("count_#{type}", *args) if respond_to?("count_#{type}")
|
67
|
-
__send__(
|
73
|
+
__send__(type, *args) if respond_to?(type)
|
68
74
|
end
|
69
75
|
|
70
76
|
def self.When(type, &block)
|
@@ -101,13 +107,13 @@ module Reporter
|
|
101
107
|
@record[:demo] << demo
|
102
108
|
end
|
103
109
|
|
104
|
-
def
|
110
|
+
def count_step(step)
|
105
111
|
@record[:step] << step
|
106
112
|
end
|
107
113
|
|
108
|
-
def
|
109
|
-
|
110
|
-
end
|
114
|
+
#def count_eval(step)
|
115
|
+
# @record[:eval] << step
|
116
|
+
#end
|
111
117
|
|
112
118
|
def count_pass(step)
|
113
119
|
@record[:pass] << step
|
@@ -133,33 +139,16 @@ module Reporter
|
|
133
139
|
#demos << demo
|
134
140
|
end
|
135
141
|
|
136
|
-
#
|
137
|
-
def load(demo)
|
138
|
-
end
|
139
|
-
|
140
|
-
#
|
141
|
-
def import(file)
|
142
|
-
end
|
143
|
-
|
144
|
-
#def comment(elem)
|
145
|
-
#end
|
146
|
-
|
147
142
|
#
|
148
143
|
def before_step(step)
|
149
|
-
#@steps += 1
|
150
|
-
end
|
151
|
-
|
152
|
-
#
|
153
|
-
def before_head(step)
|
154
144
|
end
|
155
145
|
|
156
146
|
#
|
157
|
-
def
|
158
|
-
#steps << step
|
147
|
+
def before_proc(step)
|
159
148
|
end
|
160
149
|
|
161
150
|
#
|
162
|
-
def
|
151
|
+
def before_eval(step)
|
163
152
|
end
|
164
153
|
|
165
154
|
# Before running a step that is omitted.
|
@@ -167,31 +156,30 @@ module Reporter
|
|
167
156
|
# @omit << step
|
168
157
|
#end
|
169
158
|
|
170
|
-
#
|
171
|
-
def before_code(step)
|
172
|
-
#steps << step
|
173
|
-
end
|
174
|
-
|
175
159
|
# Reight before demo.
|
176
160
|
def demo(demo)
|
177
161
|
end
|
178
162
|
|
179
|
-
# Right before
|
180
|
-
def
|
163
|
+
# Right before rule section.
|
164
|
+
def rule(step)
|
181
165
|
end
|
182
166
|
|
183
167
|
# Right before text section.
|
184
|
-
def
|
168
|
+
def step(step) #show text ?
|
185
169
|
end
|
186
170
|
|
187
|
-
# Right before
|
188
|
-
def
|
171
|
+
# Right before evaluation.
|
172
|
+
def proc(step)
|
189
173
|
end
|
190
174
|
|
191
|
-
# Right before
|
192
|
-
def
|
175
|
+
# Right before evaluation.
|
176
|
+
def eval(step)
|
193
177
|
end
|
194
178
|
|
179
|
+
# Right before evaluation.
|
180
|
+
#def code(step)
|
181
|
+
#end
|
182
|
+
|
195
183
|
# After running a step that passed.
|
196
184
|
def pass(step)
|
197
185
|
#@pass << step
|
@@ -209,29 +197,17 @@ module Reporter
|
|
209
197
|
end
|
210
198
|
|
211
199
|
#
|
212
|
-
def
|
200
|
+
def after_eval(step)
|
213
201
|
end
|
214
202
|
|
215
203
|
#
|
216
|
-
def
|
217
|
-
end
|
218
|
-
|
219
|
-
#
|
220
|
-
def after_desc(step)
|
221
|
-
end
|
222
|
-
|
223
|
-
#
|
224
|
-
def after_head(step)
|
204
|
+
def after_proc(step)
|
225
205
|
end
|
226
206
|
|
227
207
|
#
|
228
208
|
def after_step(step)
|
229
209
|
end
|
230
210
|
|
231
|
-
#
|
232
|
-
def unload
|
233
|
-
end
|
234
|
-
|
235
211
|
# End of a demonstration.
|
236
212
|
def after_demo(demo) #demo(demo)
|
237
213
|
end
|
@@ -241,10 +217,6 @@ module Reporter
|
|
241
217
|
def after_session(session)
|
242
218
|
end
|
243
219
|
|
244
|
-
# TODO: should we rename b/c of keyword?
|
245
|
-
def when(*args)
|
246
|
-
end
|
247
|
-
|
248
220
|
private
|
249
221
|
|
250
222
|
def print_time
|
@@ -252,14 +224,25 @@ module Reporter
|
|
252
224
|
end
|
253
225
|
|
254
226
|
def print_tally
|
227
|
+
#assert_count = AE::Assertor.counts[:total]
|
228
|
+
#assert_fails = AE::Assertor.counts[:fail]
|
229
|
+
#assert_delta = assert_count - assert_fails
|
230
|
+
|
231
|
+
mask = "%s demos, %s steps: %s failures, %s errors (%s/%s assertions)"
|
232
|
+
#vars = [demos.size, steps.size, fails.size, errors.size, assert_delta, assert_count] #, @pass.size ]
|
233
|
+
|
234
|
+
io.puts mask % get_tally
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
def get_tally
|
255
239
|
assert_count = AE::Assertor.counts[:total]
|
256
240
|
assert_fails = AE::Assertor.counts[:fail]
|
257
241
|
assert_delta = assert_count - assert_fails
|
258
242
|
|
259
|
-
mask = "%s demos, %s steps: %s failures, %s errors (%s/%s assertions)"
|
260
243
|
vars = [demos.size, steps.size, fails.size, errors.size, assert_delta, assert_count] #, @pass.size ]
|
261
244
|
|
262
|
-
|
245
|
+
vars
|
263
246
|
end
|
264
247
|
|
265
248
|
#
|
@@ -437,8 +420,21 @@ module Reporter
|
|
437
420
|
idx = (0...pwd.size).find do |i|
|
438
421
|
file[i,1] != pwd[i,1]
|
439
422
|
end
|
440
|
-
|
423
|
+
idx ||= 1
|
424
|
+
file[(idx-1)..-1]
|
441
425
|
end
|
426
|
+
|
427
|
+
#
|
428
|
+
def localize_file(file)
|
429
|
+
j = 0
|
430
|
+
[file.to_s.size, Dir.pwd.size].max.times do |i|
|
431
|
+
if Dir.pwd[i,1] != file[i,1]
|
432
|
+
break j = i
|
433
|
+
end
|
434
|
+
end
|
435
|
+
file[j..-1]
|
436
|
+
end
|
437
|
+
|
442
438
|
end
|
443
439
|
|
444
440
|
end
|