qed 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
-