qed 2.2.0 → 2.2.1

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  = RELEASE HISTORY
2
2
 
3
+ == 2.2.1 / 2010-06-21
4
+
5
+ Remove dependencies to Tilt and Nokogiri. Should have
6
+ done this in last release but alas --there is so
7
+ much to do.
8
+
9
+ Change:
10
+
11
+ * Removed HTML parsing dependencies.
12
+ * Reduce Advice to a single class.
13
+
14
+
3
15
  == 2.2.0 / 2010-06-20
4
16
 
5
17
  This release returns to a text-based evaluator, rather
data/REQUIRE CHANGED
@@ -2,8 +2,6 @@ runtime:
2
2
  - ae
3
3
  - ansi
4
4
  - facets
5
- - tilt
6
- - nokogiri
7
5
 
8
6
  development:
9
7
  - syckle
data/VERSION CHANGED
@@ -1,5 +1,5 @@
1
1
  name : qed
2
2
  major: 2
3
3
  minor: 2
4
- patch: 0
4
+ patch: 1
5
5
  date : 2010-06-20
@@ -1,34 +1,152 @@
1
1
  module QED
2
2
 
3
- require 'qed/advice/events'
4
- require 'qed/advice/patterns'
5
-
6
3
  # = Advice
7
4
  #
8
- # This class tracks advice defined by demo scripts
9
- # and helpers. It is instantiated in Scope, so that
5
+ # This class tracks advice defined by demonstrandum
6
+ # and applique. It is instantiated in Scope, so that
10
7
  # the advice methods will have access to the same
11
- # local binding and the scripts themselves.
8
+ # local binding as the scripts themselves.
9
+ #
10
+ # There are two types of advice: *pattern matchers*
11
+ # and *event signals*.
12
+ #
13
+ # == Pattern Matchers (When)
14
+ #
15
+ # Matchers are evaluated in Scope context, via #instance_exec,
16
+ # so that the advice methods will have access to the same
17
+ # scope as the demonstrandum themselves.
18
+ #
19
+ # == Event Signals (Before, After)
20
+ #
21
+ # Event advice are triggered on symbolic targets which
22
+ # represent an event in the evaluation process, such as
23
+ # before any demo is run, or after all demo finish running.
12
24
  #
13
25
  class Advice
14
26
 
15
- attr :patterns
27
+ #
28
+ attr :matchers
16
29
 
17
- attr :events
30
+ #
31
+ attr :signals
18
32
 
33
+ #
19
34
  def initialize
20
- @patterns = Patterns.new
21
- @events = Events.new
35
+ @matchers = []
36
+ @signals = [{}]
22
37
  end
23
38
 
39
+ #
24
40
  def call(scope, type, *args)
25
41
  case type
26
42
  when :when
27
- @patterns.call(scope, *args)
43
+ call_matchers(scope, *args)
44
+ else
45
+ #@events.call(scope, type, *args)
46
+ call_signals(scope, type, *args)
47
+ end
48
+ end
49
+
50
+ #
51
+ def add_event(type, &procedure)
52
+ @signals.last[type.to_sym] = procedure
53
+ end
54
+
55
+ #
56
+ def add_match(patterns, &procedure)
57
+ @matchers << [patterns, procedure]
58
+ end
59
+
60
+ # React to an event.
61
+ def call_signals(scope, type, *args)
62
+ @signals.each do |set|
63
+ proc = set[type.to_sym]
64
+ #proc.call(*args) if proc
65
+ scope.instance_exec(*args, &proc) if proc
66
+ end
67
+ end
68
+
69
+ #
70
+ def call_matchers(scope, section)
71
+ match = section.text
72
+ args = section.args
73
+
74
+ @matchers.each do |(patterns, proc)|
75
+ compare = match
76
+ matched = true
77
+ params = []
78
+ patterns.each do |pattern|
79
+ case pattern
80
+ when Regexp
81
+ regex = pattern
82
+ else
83
+ regex = match_string_to_regexp(pattern)
84
+ end
85
+ if md = regex.match(compare)
86
+ params.concat(md[1..-1])
87
+ compare = md.post_match
88
+ else
89
+ matched = false
90
+ break
91
+ end
92
+ end
93
+ if matched
94
+ params += args
95
+ #proc.call(*params)
96
+ scope.instance_exec(*params, &proc)
97
+ end
98
+ end
99
+ end
100
+
101
+ # Clear last set of advice.
102
+ def signals_reset
103
+ @signals.pop
104
+ end
105
+
106
+ #
107
+ def signals_setup
108
+ @signals.push({})
109
+ end
110
+
111
+ # Clear advice.
112
+ def signals_clear(type=nil)
113
+ if type
114
+ @signals.each{ |set| set.delete(type.to_sym) }
28
115
  else
29
- @events.call(scope, type, *args)
116
+ @signals = [{}]
30
117
  end
31
118
  end
119
+
120
+ private
121
+
122
+ # Convert matching string into a regular expression. If the string
123
+ # contains double parenthesis, such as ((.*?)), then the text within
124
+ # them is treated as in regular expression and kept verbatium.
125
+ #
126
+ # TODO: Better way to isolate regexp. Maybe "?:(.*?)".
127
+ #
128
+ # TODO: Now that we can use multi-patterns, do we still need this?
129
+ #
130
+ def match_string_to_regexp(str)
131
+ str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
132
+ x =~ /\A\(\((.*)\)\)\Z/ ? $1 : Regexp.escape(x)
133
+ }.join
134
+ str = str.gsub(/\\\s+/, '\s+')
135
+ Regexp.new(str, Regexp::IGNORECASE)
136
+
137
+ #rexps = []
138
+ #str = str.gsub(/\(\((.*?)\)\)/) do |m|
139
+ # rexps << '(' + $1 + ')'
140
+ # "\0"
141
+ #end
142
+ #str = Regexp.escape(str)
143
+ #rexps.each do |r|
144
+ # str = str.sub("\0", r)
145
+ #end
146
+ #str = str.gsub(/(\\\ )+/, '\s+')
147
+ #Regexp.new(str, Regexp::IGNORECASE)
148
+ end
149
+
32
150
  end
33
151
 
34
152
  end
@@ -40,25 +40,23 @@ module QED
40
40
  @__advice__
41
41
  end
42
42
 
43
- # Because patterns are mathced against HTML documents
44
- # HTML special charaters +<+, +>+ and +&+ should not be
45
- # used.
43
+ # Pattern matchers and "upon" events.
46
44
  def When(*patterns, &procedure)
47
45
  if patterns.size == 1 && Symbol === patterns.first
48
- __advice__.events.add(:"#{patterns.first}", &procedure)
46
+ __advice__.add_event(patterns.first, &procedure)
49
47
  else
50
- __advice__.patterns.add(patterns, &procedure)
48
+ __advice__.add_match(patterns, &procedure)
51
49
  end
52
50
  end
53
51
 
54
52
  # Before advice.
55
53
  def Before(type=:code, &procedure)
56
- __advice__.events.add(:"before_#{type}", &procedure)
54
+ __advice__.add_event(:"before_#{type}", &procedure)
57
55
  end
58
56
 
59
57
  # After advice.
60
58
  def After(type=:code, &procedure)
61
- __advice__.events.add(:"after_#{type}", &procedure)
59
+ __advice__.add_event(:"after_#{type}", &procedure)
62
60
  end
63
61
 
64
62
  # Code match-and-transform procedure.
@@ -8,11 +8,12 @@ module QED
8
8
  #
9
9
  def initialize(script, *observers)
10
10
  @script = script
11
- @file = script.file
12
11
  @ast = script.parse
13
- @scope = script.scope
14
- @binding = script.binding
15
- @advice = script.advice
12
+
13
+ #@file = script.file
14
+ #@scope = script.scope
15
+ #@binding = script.binding
16
+ #@advice = script.advice
16
17
 
17
18
  @observers = observers
18
19
  end
@@ -38,18 +39,17 @@ module QED
38
39
 
39
40
  #
40
41
  def evaluate_code(section)
41
- advise!(:before_code, section, @file)
42
+ advise!(:before_code, section, @script.file)
42
43
  begin
43
44
  advise!(:code, section)
44
- eval(section.text, @binding, @file, section.line)
45
- #@scope.module_eval(section.text, @file, section.line)
45
+ @script.evaluate(section.text, section.line)
46
46
  pass!(section)
47
47
  rescue Assertion => exception
48
48
  fail!(section, exception)
49
49
  rescue Exception => exception
50
50
  error!(section, exception)
51
51
  end
52
- advise!(:after_code, section, @file)
52
+ advise!(:after_code, section, @script.file)
53
53
  end
54
54
 
55
55
  #
@@ -97,15 +97,14 @@ module QED
97
97
  #
98
98
  def import!(file)
99
99
  advise!(:unload)
100
- eval(File.read(file), @binding, file)
100
+ eval(File.read(file), @script.binding, file)
101
101
  advise!(:load, file)
102
102
  end
103
103
 
104
- #
104
+ # Dispatch event to observers and advice.
105
105
  def advise!(signal, *args)
106
106
  @observers.each{ |o| o.update(signal, *args) }
107
- #@scope.__advice__.call(signal, *args)
108
- @advice.call(@scope, signal, *args)
107
+ @script.advise(signal, *args)
109
108
  end
110
109
 
111
110
  #
@@ -1,5 +1,5 @@
1
1
  name : qed
2
2
  major: 2
3
3
  minor: 2
4
- patch: 0
4
+ patch: 1
5
5
  date : 2010-06-20
@@ -40,6 +40,11 @@ module QED
40
40
  @applique.__advice__
41
41
  end
42
42
 
43
+ #
44
+ def advise(signal, *args)
45
+ advice.call(@scope, signal, *args)
46
+ end
47
+
43
48
  # Expanded dirname of +file+.
44
49
  def directory
45
50
  @directory ||= File.expand_path(File.dirname(file))
@@ -50,6 +55,12 @@ module QED
50
55
  @name ||= File.basename(file).chomp(File.extname(file))
51
56
  end
52
57
 
58
+ #
59
+ def evaluate(code, line)
60
+ eval(code, @binding, @file, line)
61
+ #@scope.module_eval(section.text, @file, section.line)
62
+ end
63
+
53
64
  #
54
65
  #def source
55
66
  # @source ||= (
@@ -63,6 +74,8 @@ module QED
63
74
  # )
64
75
  #end
65
76
 
77
+ # Parse script.
78
+ # Retruns an abstract syntax tree.
66
79
  def parse
67
80
  Parser.new(file).parse
68
81
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qed
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 2
9
- - 0
10
- version: 2.2.0
9
+ - 1
10
+ version: 2.2.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Thomas Sawyer <transfire@gmail.com>
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-19 00:00:00 -04:00
18
+ date: 2010-06-20 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -60,38 +60,10 @@ dependencies:
60
60
  version: "0"
61
61
  type: :runtime
62
62
  version_requirements: *id003
63
- - !ruby/object:Gem::Dependency
64
- name: tilt
65
- prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
67
- none: false
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- hash: 3
72
- segments:
73
- - 0
74
- version: "0"
75
- type: :runtime
76
- version_requirements: *id004
77
- - !ruby/object:Gem::Dependency
78
- name: nokogiri
79
- prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- hash: 3
86
- segments:
87
- - 0
88
- version: "0"
89
- type: :runtime
90
- version_requirements: *id005
91
63
  - !ruby/object:Gem::Dependency
92
64
  name: syckle
93
65
  prerelease: false
94
- requirement: &id006 !ruby/object:Gem::Requirement
66
+ requirement: &id004 !ruby/object:Gem::Requirement
95
67
  none: false
96
68
  requirements:
97
69
  - - ">="
@@ -101,7 +73,7 @@ dependencies:
101
73
  - 0
102
74
  version: "0"
103
75
  type: :development
104
- version_requirements: *id006
76
+ version_requirements: *id004
105
77
  description: QED (Quality Ensured Demonstrations) is a TDD/BDD framework utilizing Literate Programming techniques.
106
78
  email:
107
79
  executables:
@@ -137,8 +109,6 @@ files:
137
109
  - eg/hello_world.rdoc
138
110
  - eg/view_error.rdoc
139
111
  - eg/website.rdoc
140
- - lib/qed/advice/events.rb
141
- - lib/qed/advice/patterns.rb
142
112
  - lib/qed/advice.rb
143
113
  - lib/qed/applique.rb
144
114
  - lib/qed/command.rb
@@ -1,57 +0,0 @@
1
- module QED
2
-
3
- class Advice
4
-
5
- # This class encapsulates advice on symbolic targets,
6
- # such as Before, After and Upon.
7
- #
8
- class Events
9
-
10
- #
11
- attr :signals
12
-
13
- #
14
- def initialize
15
- @signals = [{}]
16
- end
17
-
18
- #
19
- def add(type, &procedure)
20
- @signals.last[type.to_sym] = procedure
21
- end
22
-
23
- #
24
- def call(scope, type, *args)
25
-
26
- @signals.each do |set|
27
- proc = set[type.to_sym]
28
- #proc.call(*args) if proc
29
- scope.instance_exec(*args, &proc) if proc
30
- end
31
- end
32
-
33
- # Clear last set of advice.
34
- def reset
35
- @signals.pop
36
- end
37
-
38
- #
39
- def setup
40
- @signals.push {}
41
- end
42
-
43
- # Clear advice.
44
- def clear(type=nil)
45
- if type
46
- @signals.each{ |set| set.delete(type.to_sym) }
47
- else
48
- @signals = [{}]
49
- end
50
- end
51
-
52
- end
53
-
54
- end
55
-
56
- end
57
-
@@ -1,82 +0,0 @@
1
- module QED
2
-
3
- # = Pattern Advice (When)
4
- #
5
- # This class encapsulates "When" advice on plain text.
6
- #
7
- # Matches are evaluated in Scope context, via #instance_exec,
8
- # so that the advice methods will have access to the same
9
- # scope as the demonstrandum themselves.
10
- #
11
- class Patterns
12
-
13
- attr :when
14
-
15
- def initialize
16
- @when = []
17
- end
18
-
19
- #
20
- def add(patterns, &procedure)
21
- @when << [patterns, procedure]
22
- end
23
-
24
- #
25
- def call(scope, section)
26
- match = section.text
27
- args = section.args
28
-
29
- @when.each do |(patterns, proc)|
30
- compare = match
31
- matched = true
32
- params = []
33
- patterns.each do |pattern|
34
- case pattern
35
- when Regexp
36
- regex = pattern
37
- else
38
- regex = when_string_to_regexp(pattern)
39
- end
40
- if md = regex.match(compare)
41
- params.concat(md[1..-1])
42
- compare = md.post_match
43
- else
44
- matched = false
45
- break
46
- end
47
- end
48
- if matched
49
- params += args
50
- #proc.call(*params)
51
- scope.instance_exec(*params, &proc)
52
- end
53
- end
54
- end
55
-
56
- private
57
-
58
- # TODO: Now that we can use multi-patterns, we might not need this any more.
59
- def when_string_to_regexp(str)
60
- str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
61
- x =~ /\A\(\((.*)\)\)\Z/ ? $1 : Regexp.escape(x)
62
- }.join
63
- str = str.gsub(/\\\s+/, '\s+')
64
- Regexp.new(str, Regexp::IGNORECASE)
65
-
66
- #rexps = []
67
- #str = str.gsub(/\(\((.*?)\)\)/) do |m|
68
- # rexps << '(' + $1 + ')'
69
- # "\0"
70
- #end
71
- #str = Regexp.escape(str)
72
- #rexps.each do |r|
73
- # str = str.sub("\0", r)
74
- #end
75
- #str = str.gsub(/(\\\ )+/, '\s+')
76
- #Regexp.new(str, Regexp::IGNORECASE)
77
- end
78
-
79
- end
80
-
81
- end
82
-