qed 2.6.3 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.ruby +4 -3
  2. data/.yardopts +3 -0
  3. data/HISTORY.rdoc +71 -35
  4. data/README.rdoc +9 -10
  5. data/bin/qed +1 -1
  6. data/bin/qedoc +2 -1
  7. data/lib/qed.rb +2 -5
  8. data/lib/qed.yml +4 -3
  9. data/lib/qed/applique.rb +57 -24
  10. data/lib/qed/cli.rb +8 -0
  11. data/lib/qed/cli/qed.rb +124 -0
  12. data/lib/qed/demo.rb +35 -39
  13. data/lib/qed/document.rb +5 -3
  14. data/lib/qed/document/template.rhtml +1 -0
  15. data/lib/qed/evaluator.rb +227 -199
  16. data/lib/qed/parser.rb +60 -282
  17. data/lib/qed/reporter/abstract.rb +54 -58
  18. data/lib/qed/reporter/dotprogress.rb +6 -4
  19. data/lib/qed/reporter/html.rb +112 -31
  20. data/lib/qed/reporter/tapy.rb +95 -125
  21. data/lib/qed/reporter/verbatim.rb +80 -38
  22. data/lib/qed/scope.rb +35 -48
  23. data/lib/qed/session.rb +35 -140
  24. data/lib/qed/settings.rb +104 -67
  25. data/lib/qed/step.rb +237 -0
  26. data/{spec → qed}/01_demos.rdoc +0 -0
  27. data/{spec → qed}/02_advice.rdoc +18 -7
  28. data/qed/03_helpers.rdoc +44 -0
  29. data/{spec → qed}/04_samples.rdoc +4 -4
  30. data/{spec → qed}/05_quote.rdoc +3 -3
  31. data/{spec → qed}/07_toplevel.rdoc +0 -0
  32. data/{spec → qed}/08_cross_script.rdoc +0 -0
  33. data/{spec → qed}/09_cross_script.rdoc +0 -0
  34. data/{spec → qed}/10_constant_lookup.rdoc +2 -2
  35. data/qed/11_embedded_rules.rdoc +46 -0
  36. data/{test/integration/topcode.rdoc → qed/99_issues/02_topcode.rdoc} +0 -0
  37. data/{spec → qed}/applique/constant.rb +0 -0
  38. data/{spec → qed}/applique/env.rb +0 -0
  39. data/{spec → qed}/applique/fileutils.rb +0 -0
  40. data/{spec → qed}/applique/markup.rb +0 -0
  41. data/{spec → qed}/applique/toplevel.rb +0 -0
  42. data/{spec → qed}/helpers/advice.rb +6 -7
  43. data/{spec → qed}/helpers/toplevel.rb +0 -0
  44. data/{spec → qed}/samples/data.txt +0 -0
  45. data/{spec → qed}/samples/table.yml +0 -0
  46. metadata +44 -39
  47. data/LICENSE.rdoc +0 -31
  48. data/SPECSHEET.rdoc +0 -456
  49. data/lib/qed/advice.rb +0 -158
  50. data/lib/qed/reporter/bullet.rb +0 -91
  51. data/lib/qed/reporter/dtrace.rb +0 -67
  52. data/lib/yard-qed.rb +0 -1
  53. data/spec/03_helpers.rdoc +0 -43
  54. data/spec/applique/quote.rb +0 -4
  55. data/spec/helpers/sample.rb +0 -4
@@ -1,43 +1,54 @@
1
- module QED
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
- # structured object to passed thru the script
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
- # but for interoperability sake it is RDoc and a bit of
14
- # support for Markdown.
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
- def initialize(file, options={})
19
- @file = file
20
- @options = options
21
- @ast = []
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
- # Abstract Syntax Tree
25
- attr :ast
30
+ # The demo to parse.
31
+ attr :demo
32
+
33
+ # Parser mode.
34
+ attr :mode
26
35
 
27
- # File to parse.
28
- attr :file
36
+ # Abstract Syntax Tree
37
+ attr :steps
29
38
 
30
- # Parser options.
31
- attr :options
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 options[:mode]
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
- =begin
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
- blocks = [[]]
92
- state = :none
93
- lines.each do |lineno, line|
94
- case line
95
- when /^$/
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
- if flush
157
- pend = true unless lineno == 0
158
- block.raw << [lineno, line]
109
+ when /^\s*$/ # blank line
110
+ blank = true
111
+ if indented
112
+ example << [lineno, line]
159
113
  else
160
- block.raw << [lineno, line]
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
- pend = false
168
- flush = false
169
- block.raw << [lineno, line]
116
+ when /\A\s+/ #/\A(\t|\ \ +)/ # indented
117
+ indented = true
118
+ blank = false
119
+ example << [lineno, line]
170
120
  else
171
- if pend || !flush
172
- tree << block.ready!(flush, tree.last)
173
- pend = false
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
- block.raw << [lineno, line]
125
+ indented = false
126
+ blank = false
127
+ explain << [lineno, line]
178
128
  end
179
129
  end
180
- tree << block.ready!(flush, tree.last)
181
- @ast = tree
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 update(type, *args)
71
+ def call(type, *args)
66
72
  __send__("count_#{type}", *args) if respond_to?("count_#{type}")
67
- __send__("#{type}", *args)
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 count_desc(step)
110
+ def count_step(step)
105
111
  @record[:step] << step
106
112
  end
107
113
 
108
- def count_code(step)
109
- @record[:step] << step
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 before_desc(step)
158
- #steps << step
147
+ def before_proc(step)
159
148
  end
160
149
 
161
150
  #
162
- def before_data(step)
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 header.
180
- def head(step)
163
+ # Right before rule section.
164
+ def rule(step)
181
165
  end
182
166
 
183
167
  # Right before text section.
184
- def desc(step) #text ?
168
+ def step(step) #show text ?
185
169
  end
186
170
 
187
- # Right before date section.
188
- def data(step)
171
+ # Right before evaluation.
172
+ def proc(step)
189
173
  end
190
174
 
191
- # Right before running code.
192
- def code(step)
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 after_data(step)
200
+ def after_eval(step)
213
201
  end
214
202
 
215
203
  #
216
- def after_code(step)
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
- io.puts mask % vars
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
- file[(idx || 0)..-1]
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