qed 1.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/qed.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module QED
2
- VERSION="1.2" #:till: VERSION="<%= version %>"
2
+ VERSION="2.0.0" #:till: VERSION="<%= version %>"
3
3
  end
4
4
 
5
- require 'qed/runner'
5
+ require 'qed/session'
6
6
 
data/lib/qed/advice.rb ADDED
@@ -0,0 +1,61 @@
1
+ module QED
2
+
3
+ require 'qed/advice/events'
4
+ require 'qed/advice/patterns'
5
+
6
+ # = Advice
7
+ #
8
+ # This class tracks advice defined by demo scripts
9
+ # and helpers. It is instantiated in Scope, so that
10
+ # the advice methods will have access to the same
11
+ # local binding and the demo scripts themselves.
12
+ #
13
+ class Advice
14
+
15
+ attr :patterns
16
+
17
+ attr :events
18
+
19
+ def initialize
20
+ @patterns = Patterns.new
21
+ @events = Events.new
22
+ end
23
+
24
+ def call(type, *args)
25
+ case type
26
+ when :when
27
+ @patterns.call(*args)
28
+ else
29
+ @events.call(type, *args)
30
+ end
31
+ end
32
+ end
33
+
34
+ #
35
+ module Advisable
36
+
37
+ def __advice__
38
+ @__advice__ ||= Advice.new
39
+ end
40
+
41
+ def When(pattern, &procedure)
42
+ case pattern
43
+ when Symbol
44
+ __advice__.events.add(:"#{pattern}", &procedure)
45
+ else
46
+ __advice__.patterns.add(pattern, &procedure)
47
+ end
48
+ end
49
+
50
+ def Before(type=:code, &procedure)
51
+ __advice__.events.add(:"before_#{type}", &procedure)
52
+ end
53
+
54
+ def After(type=:code, &procedure)
55
+ __advice__.events.add(:"after_#{type}", &procedure)
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
@@ -0,0 +1,54 @@
1
+ module QED
2
+
3
+ class Advice
4
+
5
+ # Event advice: Before, After and Upon.
6
+ #
7
+ class Events
8
+
9
+ #
10
+ attr :signals
11
+
12
+ #
13
+ def initialize
14
+ @signals = [{}]
15
+ end
16
+
17
+ #
18
+ def add(type, &procedure)
19
+ @signals.last[type.to_sym] = procedure
20
+ end
21
+
22
+ #
23
+ def call(type, *args)
24
+ @signals.each do |set|
25
+ proc = set[type.to_sym]
26
+ proc.call(*args) if proc
27
+ end
28
+ end
29
+
30
+ # Clear last set of advice.
31
+ def reset
32
+ @signals.pop
33
+ end
34
+
35
+ #
36
+ def setup
37
+ @signals.push {}
38
+ end
39
+
40
+ # Clear advice.
41
+ def clear(type=nil)
42
+ if type
43
+ @signals.each{ |set| set.delete(type.to_sym) }
44
+ else
45
+ @signals = [{}]
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,64 @@
1
+ module QED
2
+
3
+ # = Patter Advice (When)
4
+ #
5
+ # This class tracks When advice defined by demo scripts
6
+ # and helpers. It is instantiated in Scope, so that
7
+ # the advice methods will have access to the same
8
+ # local binding and the demo scripts themselves.
9
+ #
10
+ class Patterns
11
+
12
+ attr :when
13
+
14
+ def initialize
15
+ @when = []
16
+ end
17
+
18
+ #
19
+ def add(pattern, &procedure)
20
+ @when << [pattern, procedure]
21
+ end
22
+
23
+ #
24
+ def call(match, *args)
25
+ @when.each do |(pattern, proc)|
26
+ case pattern
27
+ when Regexp
28
+ regex = pattern
29
+ else
30
+ regex = when_string_to_regexp(pattern)
31
+ end
32
+ if md = regex.match(match)
33
+ proc.call(*md[1..-1])
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ #
41
+ def when_string_to_regexp(str)
42
+ str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
43
+ x =~ /\A\(\((.*)\)\)\z/ ? $1 : Regexp.escape(x)
44
+ }.join
45
+ str = str.gsub(/(\\\ )+/, '\s+')
46
+ Regexp.new(str, Regexp::IGNORECASE)
47
+
48
+ #rexps = []
49
+ #str = str.gsub(/\(\((.*?)\)\)/) do |m|
50
+ # rexps << '(' + $1 + ')'
51
+ # "\0"
52
+ #end
53
+ #str = Regexp.escape(str)
54
+ #rexps.each do |r|
55
+ # str = str.sub("\0", r)
56
+ #end
57
+ #str = str.gsub(/(\\\ )+/, '\s+')
58
+ #Regexp.new(str, Regexp::IGNORECASE)
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
data/lib/qed/command.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'qed'
4
4
  require 'optparse'
5
5
  require 'shellwords'
6
+ require 'tilt'
6
7
 
7
8
  module QED
8
9
 
@@ -13,6 +14,11 @@ module QED
13
14
  # Configuration directory.
14
15
  CONFDIR = "{.,}config/qed"
15
16
 
17
+ # Default location of demonstrations if no
18
+ # specific files or locations given. This
19
+ # is use in Dir.glob.
20
+ DEFAULT_DEMOS_LOCATION = '{qed}'
21
+
16
22
  # Initialize and execute.
17
23
  def self.execute
18
24
  new.execute
@@ -50,18 +56,18 @@ module QED
50
56
  attr_accessor :requires
51
57
 
52
58
  #
53
- attr_accessor :env
59
+ attr_accessor :extension
54
60
 
55
- #
61
+ # TODO: Should extension and profile have a common reference?
56
62
 
57
63
  def initialize
58
- @format = nil
59
- @env = nil
60
- @profile = nil
61
- @requires = []
62
- @loadpath = []
63
- @files = []
64
- @options = {}
64
+ @format = :dotprogress
65
+ @extension = :default
66
+ @profile = :default
67
+ @requires = []
68
+ @loadpath = []
69
+ @files = []
70
+ @options = {}
65
71
  end
66
72
 
67
73
  # Instance of OptionParser
@@ -75,31 +81,39 @@ module QED
75
81
  o = "--#{name}"
76
82
  opt.on(o, "#{name} custom profile") do
77
83
  @profile = name
78
- end
84
+ end
79
85
  end
80
86
 
81
- opt.separator("Report Options (pick one):")
87
+ opt.separator("Report Formats (pick one):")
82
88
 
83
89
  opt.on('--dotprogress', '-d', "use dot-progress reporter [default]") do
84
- @options[:format] = :summary
90
+ @options[:format] = :dotprogress
85
91
  end
86
92
 
87
93
  opt.on('--verbatim', '-v', "use verbatim reporter") do
88
94
  @options[:format] = :verbatim
89
95
  end
90
96
 
91
- opt.on('--summary', '-s', "use summary reporter") do
92
- @options[:format] = :summary
97
+ opt.on('--bullet', '-b', "use bullet-point reporter") do
98
+ @options[:format] = :bullet
99
+ end
100
+
101
+ opt.on('--html', '-h', "use underlying HTML reporter") do
102
+ @options[:format] = :html
93
103
  end
94
104
 
95
- opt.on('--script', "psuedo-reporter") do
96
- @options[:script] # psuedo-reporter
105
+ opt.on('--format', '-f FORMAT', "use custom reporter") do |format|
106
+ @options[:format] = format
97
107
  end
98
108
 
109
+ #opt.on('--script', "psuedo-reporter") do
110
+ # @options[:format] = :script # psuedo-reporter
111
+ #end
112
+
99
113
  opt.separator("Control Options:")
100
114
 
101
- opt.on('--env', '-e [NAME]', "runtime environment [default]") do |name|
102
- @options[:env] = name
115
+ opt.on('--ext', '-e [NAME]', "runtime extension [default]") do |name|
116
+ @options[:extension] = name
103
117
  end
104
118
 
105
119
  opt.on('--loadpath', "-I PATH", "add paths to $LOAD_PATH") do |arg|
@@ -144,46 +158,32 @@ module QED
144
158
  #
145
159
 
146
160
  def demos
147
- demo_files
148
- end
149
-
150
- #
151
-
152
- def demo_files
153
161
  files = self.files
154
-
155
- #if files.empty?
156
- # if File.directory?('test')
157
- # files << 'test/doc{,s}'
158
- # files << 'test/demo{,s}'
159
- # end
160
- #end
161
-
162
+ types = Tilt.mappings.keys
163
+ if files.empty?
164
+ files << DEFAULT_DEMOS_LOCATION
165
+ end
162
166
  files = files.map do |pattern|
163
167
  Dir[pattern]
164
168
  end.flatten.uniq
165
-
166
169
  files = files.map do |file|
167
170
  if File.directory?(file)
168
- Dir[File.join(file,'**','*{.qed,.rd,.rdoc,.md,.markdown}')]
171
+ Dir[File.join(file,'**','*.{' + types.join(',') + '}')]
169
172
  else
170
173
  file
171
174
  end
172
175
  end
173
-
174
- files = files.flatten.uniq
175
-
176
+ files = files.flatten.uniq.sort
176
177
  #files = files.select do |file|
177
178
  # %w{.yml .yaml .rb}.include?(File.extname(file))
178
179
  #end
179
-
180
180
  files
181
181
  end
182
182
 
183
- # Instance of Runner class.
183
+ # Session instance.
184
184
 
185
- def runner
186
- Runner.new(demos, :format=>format, :trace=>trace)
185
+ def session
186
+ @session ||= Session.new(demos, :format=>format, :trace=>trace)
187
187
  end
188
188
 
189
189
  # Parse command-line options along with profile options.
@@ -194,12 +194,13 @@ module QED
194
194
  opts.parse!(argv)
195
195
  @files.concat(argv)
196
196
 
197
- if profile
198
- args = profiles[profile]
197
+ #if profile
198
+ if args = profiles[profile]
199
199
  argv = Shellwords.shellwords(args)
200
200
  opts.parse!(argv)
201
201
  @files.concat(argv)
202
202
  end
203
+ #end
203
204
 
204
205
  options.each do |k,v|
205
206
  __send__("#{k}=", v)
@@ -216,17 +217,9 @@ module QED
216
217
  prepare_loadpath
217
218
 
218
219
  require_libraries
219
- require_environment
220
+ require_profile
220
221
 
221
- # TODO: Remove case, can :script be done with Reporter or do we ne need selectable Runner?
222
- case format
223
- when :script
224
- demos.each do |spec|
225
- puts spec.to_script
226
- end
227
- else
228
- runner.check
229
- end
222
+ session.run
230
223
  end
231
224
 
232
225
  # Profile configurations.
@@ -250,22 +243,40 @@ module QED
250
243
  requires.each{ |file| require(file) }
251
244
  end
252
245
 
253
- # Require requirement file (from -e option.
246
+ # Require requirement file (from -e option).
254
247
 
255
- def require_environment
256
- if env
257
- if file = Dir["#{CONFDIR}/{env,environments}/#{env}.rb"].first
258
- require(file)
259
- end
260
- else
261
- if file = Dir["#{CONFDIR}/env.rb"].first
262
- require(file)
263
- elsif file = Dir["#{CONFDIR}/{env,environments}/default.rb"].first
264
- require(file)
265
- end
248
+ def require_profile
249
+ return unless root
250
+
251
+ # common environment, always loaded if present.
252
+ #if file = Dir["#{root}/#{CONFDIR}/default.rb"].first
253
+ # require(file)
254
+ #end
255
+
256
+ #env = env() || 'default'
257
+
258
+ if file = Dir["#{root}/#{CONFDIR}/#{extension}.rb"].first
259
+ require(file)
266
260
  end
267
261
  end
268
262
 
263
+ #
264
+ def root
265
+ QED.root
266
+ end
267
+
268
+ end
269
+
270
+ # Is there no perfect way to find root directory of a project?
271
+ def self.root(path=nil)
272
+ path ||= Dir.pwd
273
+ path = File.dirname(path) unless File.directory?(path)
274
+ until path == File.dirname(path)
275
+ mark = Dir[File.join(path, 'README*')].first
276
+ return path if mark
277
+ path = File.dirname(path)
278
+ end
279
+ nil
269
280
  end
270
281
 
271
282
  end
data/lib/qed/config.rb CHANGED
@@ -1,25 +1,60 @@
1
1
  module QED
2
2
 
3
- class Config
3
+ =begin
4
+ # Setup global configuration.
5
+ #
6
+ # QED.config do
7
+ #
8
+ # Before(:session) do
9
+ # # ...
10
+ # end
11
+ #
12
+ # After(:session) do
13
+ # # ...
14
+ # end
15
+ #
16
+ # end
17
+ #
18
+ def self.configure(&block)
19
+ @config ||= Profile.new #(nil)
20
+ @config.instance_eval(&block) if block
21
+ @config
22
+ end
23
+ =end
4
24
 
5
- def initialize
6
- @local = ['qed', 'demos', 'test/demos']
25
+ #
26
+ class Profile
7
27
 
8
- if file = File.glob('{.,}config/qed.{yml,yaml}')
9
- YAML.load(File.new(file)).each do |k,v|
10
- __send__("#{k}=", v)
11
- end
12
- end
28
+ #
29
+ def initialize
30
+ #@local = ['test/demos', 'demos', 'qed']
31
+
32
+ @before = { :session=>[], :demo=>[], :step=>[] }
33
+ @after = { :session=>[], :demo=>[], :step=>[] }
34
+
35
+ #if file = Dir.glob('{.,}config/qed.{yml,yaml}').first
36
+ # YAML.load(File.new(file)).each do |k,v|
37
+ # __send__("#{k}=", v)
38
+ # end
39
+ #end
13
40
  end
14
41
 
15
- attr_accessor :local
42
+ #
43
+ #attr_accessor :local
16
44
 
17
- # How ot identify a header?
18
- #attr_accessor :header
45
+ #
46
+ def Before(type=:session, &procedure)
47
+ @before[type] << procedure if procedure
48
+ @before[type]
49
+ end
19
50
 
20
- # How ot identify a footer?
21
- #attr_accessor :footer
51
+ #
52
+ def After(type=:session, &procedure)
53
+ @after[type] << procedure if procedure
54
+ @after[type]
55
+ end
22
56
 
23
57
  end
24
58
 
25
59
  end
60
+