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.
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