ontomde-core 1.0.2

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.txt ADDED
@@ -0,0 +1,5 @@
1
+ == 1.0.0 / 2007-10-27
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,37 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/ontomde-core
6
+ lib/ontomde-core.rb
7
+ lib/ontomde-core/version.rb
8
+ lib/ontomde-core/context.rb
9
+ lib/ontomde-core/loader.rb
10
+ lib/ontomde-core/bootstrap_rdfs.rb
11
+ lib/ontomde-core/delayed.rb
12
+ lib/ontomde-core/profil.rb
13
+ lib/ontomde-core/resource.rb
14
+ lib/ontomde-core/helper.rb
15
+ lib/ontomde-core/meta.rb
16
+ lib/ontomde-core/exceptions.rb
17
+ lib/ontomde-core/demoInstaller.rb
18
+ lib/ontomde-core/customERB.rb
19
+ lib/ontomde-core/triplet.rb
20
+ lib/ontomde-core/log.rb
21
+ lib/ontomde-core/fileTypes.rb
22
+ lib/ontomde-core/fileLoader.rb
23
+ lib/ontomde-core/custom_method_missing.rb
24
+ lib/ontomde-core/resourceSet.rb
25
+ lib/ontomde-core/clone.rb
26
+ test/test_uri.rb
27
+ test/test_ontomde-core.rb
28
+ test/protege/etatCivil.rdfs
29
+ test/protege/etatCivil.rdf
30
+ test/protege/test_demo.rb
31
+ test/protege/demo.sh
32
+ test/protege/etatCivil.pprj
33
+ test/test_protected.rb
34
+ test/unit_test_protected_sample
35
+ test/unit_test_crash.rb
36
+ test/test_context.rb
37
+ test/unit_test_protected_wrongEnd
data/README.txt ADDED
@@ -0,0 +1,48 @@
1
+ ontomde-core
2
+ by FIX (your name)
3
+ FIX (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * FIX (list of requirements)
20
+
21
+ == INSTALL:
22
+
23
+ * FIX (sudo gem install, anything else)
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2007 FIX
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/ontomde-core/version.rb'
6
+
7
+ Hoe.new('ontomde-core', Ontomde::Core::VERSION) do |p|
8
+ p.rubyforge_name = 'ontomde'
9
+ p.author = 'Stephane (Pierre) Carrie'
10
+ p.email = 'stephanepierre.carrie@orange-ftgroup.com'
11
+ p.summary = 'OntoMDE core cartridge (RDF/RDFS handling,helpers)'
12
+ # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
13
+ # p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
14
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
+ p.spec_extras[:required_ruby_version] = '>= 1.8.4'
16
+ p.extra_deps=[ ['ontomde-redland-win','= 1.0.3'] ]
17
+ end
18
+
19
+ # vim: syntax=Ruby
data/bin/ontomde-core ADDED
File without changes
@@ -0,0 +1,35 @@
1
+ # In order to use ontomde-core just include this file
2
+ #
3
+ # include 'ontomde-core'
4
+ #
5
+ # NOTE: cf demo/etatCivil for sample raw use of ontomde-core.
6
+ #
7
+ #:include: shared/license.rdoc
8
+
9
+ require "#{__FILE__[0..-4]}/version.rb"
10
+
11
+ require 'set'
12
+ require 'ontomde-redland-win'
13
+
14
+ here="#{File.dirname(__FILE__)}/ontomde-core"
15
+
16
+ require "#{here}/log.rb"
17
+ require "#{here}/fileLoader.rb"
18
+ require "#{here}/custom_method_missing"
19
+ require "#{here}/triplet.rb"
20
+ require "#{here}/exceptions.rb"
21
+ require "#{here}/meta.rb"
22
+ require "#{here}/resource.rb"
23
+ require "#{here}/resourceSet.rb"
24
+ require "#{here}/bootstrap_rdfs.rb"
25
+ require "#{here}/clone.rb"
26
+ require "#{here}/fileTypes.rb"
27
+ require "#{here}/helper.rb"
28
+ require "#{here}/context.rb"
29
+ require "#{here}/delayed.rb"
30
+
31
+ #MTKRunner.rb
32
+ require "#{here}/loader.rb"
33
+ #require "#{here}/profil.rb"
34
+ require "#{here}/customERB.rb"
35
+
@@ -0,0 +1,37 @@
1
+ # Bootstrap of rdfs metamodel
2
+ #:include: ../shared/license.rdoc
3
+
4
+ module Mrdfs_Resource
5
+ end
6
+
7
+ module Mrdfs_Class
8
+ end
9
+
10
+ class Crdfs_Class < Crdf_Resource
11
+ include Mrdfs_Class
12
+ attr_reader :ClassGenerated
13
+ attr_writer :ClassGenerated
14
+ def initialize(model,uri)
15
+ super(model,uri)
16
+ @mtk_rubyClassGenerated=false
17
+ end
18
+ end
19
+ module Mrdf_Property
20
+ end
21
+
22
+ class Crdf_Property < Crdf_Resource
23
+ include Mrdf_Property
24
+ attr_reader :rdfs_domain, :rdfs_range
25
+ attr_reader :sys_inverseProperty
26
+ @rdfs_domain=ArrayOrSingleElement.new()
27
+ #attr_writer :rdfs_domain, :rdfs_range
28
+ end
29
+
30
+ module Mrdfs_Literal
31
+ end
32
+
33
+ class Crdfs_Literal < Crdf_Resource
34
+ include Mrdfs_Literal
35
+ attr_reader :rdfs_domain, :rdfs_range
36
+ #attr_writer :rdfs_domain, :rdfs_range
37
+ end
@@ -0,0 +1,73 @@
1
+ #Model transformation methods
2
+ #:include: ../shared/license.rdoc
3
+
4
+ class String
5
+ # Clones a string
6
+ # return self by default.(String are not cloned)
7
+ def rdfx_clone
8
+ return self
9
+ end
10
+ end
11
+
12
+ module Mrdf_Resource
13
+ # Clones a uml resource.
14
+ # Referenced objects are cloned if rdfx_copyOnClone says so.
15
+ def rdfx_clone
16
+ c=self.clone
17
+ c.rdf_uri="_transient_#{c.object_id}"
18
+ c.rdf_model[c.rdf_uri]=c
19
+
20
+ instance_variables.each { |v|
21
+ ivg=instance_variable_get(v)
22
+ next if (!ivg.kind_of?(ArrayOrSingleElement)) ||
23
+ (!isResetable?(v)) ||
24
+ (!rdfx_copyOnClone?(v))
25
+
26
+ newVal=createEmptyAttributeValue
27
+ #puts "clone v=#{v}"
28
+ self.instance_variable_get(v).each { | res|
29
+ newVal.push(res.rdfx_clone)
30
+ c.instance_variable_set(v,newVal)
31
+ }
32
+ }
33
+ return c
34
+ end
35
+
36
+ # Returns true if object should be copied on clone for this property.
37
+ # NOTE:
38
+ # returns true if property name contains "_owned". (works for UML)
39
+ def rdfx_copyOnClone?(prop)
40
+ return prop.include?('_owned')
41
+ #copyOrClone=copyOnCloneProperties[prop]
42
+ #if copyOrClone.nil?
43
+ #puts "WARNING: unspecified copy on clone for #{prop} on #{self.class.name}"
44
+ #end
45
+ #return copyOrClone
46
+ end
47
+ end
48
+ #module Mrdf_Resource
49
+ # #CopyOnCloneProperties={ }
50
+ # def copyOnCloneProperties
51
+ # #CopyOnCloneProperties
52
+ # end
53
+ #end
54
+ #module Muml_Class
55
+ # CopyOnCloneProperties={ '@uml_packageableElement_packageableElement_visibility' => true,
56
+ # '@uml_structuredClassifier_ownedAttribute' => true,
57
+ # '@mtk_rubyClassGenerated' => true,
58
+ # '@uml_classifier_generalization' => true,
59
+ # '@uml_namedElement_visibility' => true,
60
+ # '@uml_namedElement_clientDependency' => true,
61
+ # '@umlx_packageableElement_owner' => true,
62
+ # '@ext_isReferencedBy' => true,
63
+ # '@uml_class_ownedOperation' => true,
64
+ # '@uml_behavioredClassifier_implementation' => true,
65
+ # '@uml_namedElement_name' => true }
66
+ # #def copyOnCloneProperties
67
+ # # CopyOnCloneProperties #_class
68
+ # #end
69
+ #end
70
+
71
+
72
+
73
+
@@ -0,0 +1,115 @@
1
+ # Context management
2
+ #:include: ../shared/license.rdoc
3
+
4
+ require 'fileutils'
5
+ #require 'ontomde-core/exceptions.rb'
6
+
7
+ #Internal use.
8
+ #
9
+ #Used for storing context.
10
+ class WarningHash < Hash
11
+
12
+ #Returns context value associated to key.
13
+ #Raises an error if key is not found.
14
+ # Returns default, when context is undefined for key, and a default value is provided.
15
+ def [](key,default=Object.class)
16
+ val=super(key)
17
+ return val unless val.nil?
18
+ #Note: Object.class is used as a magic number.
19
+ return default unless default==Object.class
20
+ raise Warning.new(), <<FINCODE
21
+ Evaluation interrompue:
22
+ La session ne contient pas la variable :#{key}.
23
+ L'exemple de code suivant permet de definir une variable de contexte:
24
+
25
+ votre code
26
+ mtk_context(:#{key}=>'valeur'){
27
+ votre code
28
+ puts context[:#{key}]
29
+ votre code
30
+ }
31
+ FINCODE
32
+ end
33
+ def get(key)
34
+ return self[key] if self.include?(key)
35
+ return nil
36
+ end
37
+ end
38
+
39
+ module Mrdf_Model
40
+ @@context=WarningHash.new()
41
+
42
+ def context
43
+ return @@context
44
+ end
45
+
46
+ # Similar to mtk_context but preserves already defined context.
47
+ # Used to provide a default context.
48
+ def mtk_default_context(*additional_context,&block)
49
+ filtered_context=Array.new
50
+ additional_context.each { |item| item.each { |k,v|
51
+ next if @@context.include?(k)
52
+ filtered_context << item
53
+ }}
54
+ mtk_context(*filtered_context,&block)
55
+ end
56
+
57
+ #Defines context variables for use in block passed as parameter.
58
+ #Existing context variable are redefined. (cf. mtk_default_context )
59
+ #When exiting block, previously defined context variables are restored.
60
+ #
61
+ #Example 1:
62
+ # mtk_context( :build => "build\", :option => true) {
63
+ # your-code
64
+ # puts context[:build]
65
+ # your-code
66
+ # puts context[:option]
67
+ # your-code
68
+ # }
69
+ #
70
+ #Example 2:
71
+ # mtk_context( :build => "BUILD_ONE\") {
72
+ # your-code
73
+ # puts context[:build] # BUILD_ONE
74
+ # mtk_context( :build => "NEW_DIR", :option => true) {
75
+ # your-code
76
+ # puts context[:build] # NEW_DIR\
77
+ # your-code
78
+ # puts context[:option]
79
+ # your-code
80
+ # }
81
+ # puts context[:build] # BUILD_ONE
82
+ # }
83
+ def mtk_context(*additional_context,&block)
84
+ context_save=@@context
85
+ @@context=context_save.clone
86
+ additional_context.each { |item| item.each { |k,v|
87
+ @@context[k]=v
88
+ }}
89
+ yield
90
+ @@context=context_save
91
+ return nil
92
+ end
93
+
94
+ end
95
+
96
+ module Mrdf_Resource
97
+
98
+ # returns current context
99
+ def context
100
+ return @rdf_model.context
101
+ end
102
+
103
+ # cf: Mrdf_Model::mtk_context
104
+ def mtk_context(*args,&block)
105
+ return @rdf_model.mtk_context(*args,&block)
106
+ end
107
+ #
108
+ # cf: Mrdf_Model::mtk_default_context
109
+ def mtk_default_context(*args,&block)
110
+ return @rdf_model.mtk_default_context(*args,&block)
111
+ end
112
+
113
+ end
114
+
115
+
@@ -0,0 +1,842 @@
1
+
2
+ class Crdf_Ressource
3
+ def loadTPL(name)
4
+ tpl=""
5
+ File.open(name) { |f|
6
+ f.each { |l|
7
+ tpl=tpl+l
8
+ }
9
+ }
10
+ return CustomERB.new(tpl)
11
+ end
12
+ end
13
+
14
+
15
+
16
+ # = CustomERB -- Ruby Templating
17
+ #
18
+ # Author:: Masatoshi SEKI
19
+ # Documentation:: James Edward Gray II and Gavin Sinclair
20
+ #
21
+ # See CustomERB for primary documentation and CustomERB::Util for a couple of utility
22
+ # routines.
23
+ #
24
+ # Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI
25
+ #
26
+ # You can redistribute it and/or modify it under the same terms as Ruby.
27
+
28
+ #
29
+ # = CustomERB -- Ruby Templating
30
+ #
31
+ # == Introduction
32
+ #
33
+ # CustomERB provides an easy to use but powerful templating system for Ruby. Using
34
+ # CustomERB, actual Ruby code can be added to any plain text document for the
35
+ # purposes of generating document information details and/or flow control.
36
+ #
37
+ # A very simple example is this:
38
+ #
39
+ # require 'erb'
40
+ #
41
+ # x = 42
42
+ # template = CustomERB.new <<-EOF
43
+ # The value of x is: <@= x @>
44
+ # EOF
45
+ # puts template.result(binding)
46
+ #
47
+ # <em>Prints:</em> The value of x is: 42
48
+ #
49
+ # More complex examples are given below.
50
+ #
51
+ #
52
+ # == Recognized Tags
53
+ #
54
+ # CustomERB recognizes certain tags in the provided template and converts them based
55
+ # on the rules below:
56
+ #
57
+ # <@ Ruby code -- inline with output @>
58
+ # <@= Ruby expression -- replace with result @>
59
+ # <@# comment -- ignored -- useful in testing @>
60
+ # @ a line of Ruby code -- treated as <@ line @> (optional -- see CustomERB.new)
61
+ # @@ replaced with @ if first thing on a line and @ processing is used
62
+ # <@@ or @@> -- replace with <@ or @> respectively
63
+ #
64
+ # All other text is passed through CustomERB filtering unchanged.
65
+ #
66
+ #
67
+ # == Options
68
+ #
69
+ # There are several settings you can change when you use CustomERB:
70
+ # * the nature of the tags that are recognized;
71
+ # * the value of <tt>$SAFE</tt> under which the template is run;
72
+ # * the binding used to resolve local variables in the template.
73
+ #
74
+ # See the CustomERB.new and CustomERB#result methods for more detail.
75
+ #
76
+ #
77
+ # == Examples
78
+ #
79
+ # === Plain Text
80
+ #
81
+ # CustomERB is useful for any generic templating situation. Note that in this example, we use the
82
+ # convenient "@ at start of line" tag, and we quote the template literally with
83
+ # <tt>@q{...}</tt> to avoid trouble with the backslash.
84
+ #
85
+ # require "erb"
86
+ #
87
+ # # Create template.
88
+ # template = @q{
89
+ # From: James Edward Gray II <james@grayproductions.net>
90
+ # To: <@= to @>
91
+ # Subject: Addressing Needs
92
+ #
93
+ # <@= to[/\w+/] @>:
94
+ #
95
+ # Just wanted to send a quick note assuring that your needs are being
96
+ # addressed.
97
+ #
98
+ # I want you to know that my team will keep working on the issues,
99
+ # especially:
100
+ #
101
+ # <@# ignore numerous minor requests -- focus on priorities @>
102
+ # @ priorities.each do |priority|
103
+ # * <@= priority @>
104
+ # @ end
105
+ #
106
+ # Thanks for your patience.
107
+ #
108
+ # James Edward Gray II
109
+ # }.gsub(/^ /, '')
110
+ #
111
+ # message = CustomERB.new(template, 0, "@<>")
112
+ #
113
+ # # Set up template data.
114
+ # to = "Community Spokesman <spokesman@ruby_community.org>"
115
+ # priorities = [ "Run Ruby Quiz",
116
+ # "Document Modules",
117
+ # "Answer Questions on Ruby Talk" ]
118
+ #
119
+ # # Produce result.
120
+ # email = message.result
121
+ # puts email
122
+ #
123
+ # <i>Generates:</i>
124
+ #
125
+ # From: James Edward Gray II <james@grayproductions.net>
126
+ # To: Community Spokesman <spokesman@ruby_community.org>
127
+ # Subject: Addressing Needs
128
+ #
129
+ # Community:
130
+ #
131
+ # Just wanted to send a quick note assuring that your needs are being addressed.
132
+ #
133
+ # I want you to know that my team will keep working on the issues, especially:
134
+ #
135
+ # * Run Ruby Quiz
136
+ # * Document Modules
137
+ # * Answer Questions on Ruby Talk
138
+ #
139
+ # Thanks for your patience.
140
+ #
141
+ # James Edward Gray II
142
+ #
143
+ # === Ruby in HTML
144
+ #
145
+ # CustomERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby). Notice the need in
146
+ # this example to provide a special binding when the template is run, so that the instance
147
+ # variables in the Product object can be resolved.
148
+ #
149
+ # require "erb"
150
+ #
151
+ # # Build template data class.
152
+ # class Product
153
+ # def initialize( code, name, desc, cost )
154
+ # @code = code
155
+ # @name = name
156
+ # @desc = desc
157
+ # @cost = cost
158
+ #
159
+ # @features = [ ]
160
+ # end
161
+ #
162
+ # def add_feature( feature )
163
+ # @features << feature
164
+ # end
165
+ #
166
+ # # Support templating of member data.
167
+ # def get_binding
168
+ # binding
169
+ # end
170
+ #
171
+ # # ...
172
+ # end
173
+ #
174
+ # # Create template.
175
+ # template = @{
176
+ # <html>
177
+ # <head><title>Ruby Toys -- <@= @name @></title></head>
178
+ # <body>
179
+ #
180
+ # <h1><@= @name @> (<@= @code @>)</h1>
181
+ # <p><@= @desc @></p>
182
+ #
183
+ # <ul>
184
+ # <@ @features.each do |f| @>
185
+ # <li><b><@= f @></b></li>
186
+ # <@ end @>
187
+ # </ul>
188
+ #
189
+ # <p>
190
+ # <@ if @cost < 10 @>
191
+ # <b>Only <@= @cost @>!!!</b>
192
+ # <@ else @>
193
+ # Call for a price, today!
194
+ # <@ end @>
195
+ # </p>
196
+ #
197
+ # </body>
198
+ # </html>
199
+ # }.gsub(/^ /, '')
200
+ #
201
+ # rhtml = CustomERB.new(template)
202
+ #
203
+ # # Set up template data.
204
+ # toy = Product.new( "TZ-1002",
205
+ # "Rubysapien",
206
+ # "Geek's Best Friend! Responds to Ruby commands...",
207
+ # 999.95 )
208
+ # toy.add_feature("Listens for verbal commands in the Ruby language!")
209
+ # toy.add_feature("Ignores Perl, Java, and all C variants.")
210
+ # toy.add_feature("Karate-Chop Action!!!")
211
+ # toy.add_feature("Matz signature on left leg.")
212
+ # toy.add_feature("Gem studded eyes... Rubies, of course!")
213
+ #
214
+ # # Produce result.
215
+ # rhtml.run(toy.get_binding)
216
+ #
217
+ # <i>Generates (some blank lines removed):</i>
218
+ #
219
+ # <html>
220
+ # <head><title>Ruby Toys -- Rubysapien</title></head>
221
+ # <body>
222
+ #
223
+ # <h1>Rubysapien (TZ-1002)</h1>
224
+ # <p>Geek's Best Friend! Responds to Ruby commands...</p>
225
+ #
226
+ # <ul>
227
+ # <li><b>Listens for verbal commands in the Ruby language!</b></li>
228
+ # <li><b>Ignores Perl, Java, and all C variants.</b></li>
229
+ # <li><b>Karate-Chop Action!!!</b></li>
230
+ # <li><b>Matz signature on left leg.</b></li>
231
+ # <li><b>Gem studded eyes... Rubies, of course!</b></li>
232
+ # </ul>
233
+ #
234
+ # <p>
235
+ # Call for a price, today!
236
+ # </p>
237
+ #
238
+ # </body>
239
+ # </html>
240
+ #
241
+ #
242
+ # == Notes
243
+ #
244
+ # There are a variety of templating solutions available in various Ruby projects:
245
+ # * CustomERB's big brother, eRuby, works the same but is written in C for speed;
246
+ # * Amrita (smart at producing HTML/XML);
247
+ # * cs/Template (written in C for speed);
248
+ # * RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
249
+ # * and others; search the RAA.
250
+ #
251
+ # Rails, the web application framework, uses CustomERB to create views.
252
+ #
253
+ class CustomERB
254
+ Revision = '$Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $' #'
255
+
256
+ # Returns revision information for the erb.rb module.
257
+ def self.version
258
+ "erb.rb [2.0.4 #{CustomERB::Revision.split[1]}]"
259
+ end
260
+ end
261
+
262
+ #--
263
+ # CustomERB::Compiler
264
+ class CustomERB
265
+ class Compiler # :nodoc:
266
+ class PercentLine # :nodoc:
267
+ def initialize(str)
268
+ @value = str
269
+ end
270
+ attr_reader :value
271
+ alias :to_s :value
272
+ end
273
+
274
+ class Scanner # :nodoc:
275
+ SplitRegexp = /(<@@)|(@@>)|(<@=)|(<@#)|(<@)|(@>)|(\n)/
276
+
277
+ @scanner_map = {}
278
+ def self.regist_scanner(klass, trim_mode, percent)
279
+ @scanner_map[[trim_mode, percent]] = klass
280
+ end
281
+
282
+ def self.default_scanner=(klass)
283
+ @default_scanner = klass
284
+ end
285
+
286
+ def self.make_scanner(src, trim_mode, percent)
287
+ klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
288
+ klass.new(src, trim_mode, percent)
289
+ end
290
+
291
+ def initialize(src, trim_mode, percent)
292
+ @src = src
293
+ @stag = nil
294
+ end
295
+ attr_accessor :stag
296
+
297
+ def scan; end
298
+ end
299
+
300
+ class TrimScanner < Scanner # :nodoc:
301
+ TrimSplitRegexp = /(<@@)|(@@>)|(<@=)|(<@#)|(<@)|(@>\n)|(@>)|(\n)/
302
+
303
+ def initialize(src, trim_mode, percent)
304
+ super
305
+ @trim_mode = trim_mode
306
+ @percent = percent
307
+ if @trim_mode == '>'
308
+ @scan_line = self.method(:trim_line1)
309
+ elsif @trim_mode == '<>'
310
+ @scan_line = self.method(:trim_line2)
311
+ elsif @trim_mode == '-'
312
+ @scan_line = self.method(:explicit_trim_line)
313
+ else
314
+ @scan_line = self.method(:scan_line)
315
+ end
316
+ end
317
+ attr_accessor :stag
318
+
319
+ def scan(&block)
320
+ @stag = nil
321
+ if @percent
322
+ @src.each do |line|
323
+ percent_line(line, &block)
324
+ end
325
+ else
326
+ @src.each do |line|
327
+ @scan_line.call(line, &block)
328
+ end
329
+ end
330
+ nil
331
+ end
332
+
333
+ def percent_line(line, &block)
334
+ if @stag || line[0] != ?@
335
+ return @scan_line.call(line, &block)
336
+ end
337
+
338
+ line[0] = ''
339
+ if line[0] == ?@
340
+ @scan_line.call(line, &block)
341
+ else
342
+ yield(PercentLine.new(line.chomp))
343
+ end
344
+ end
345
+
346
+ def scan_line(line)
347
+ line.split(SplitRegexp).each do |token|
348
+ next if token.empty?
349
+ yield(token)
350
+ end
351
+ end
352
+
353
+ def trim_line1(line)
354
+ line.split(TrimSplitRegexp).each do |token|
355
+ next if token.empty?
356
+ if token == "@>\n"
357
+ yield('@>')
358
+ yield(:cr)
359
+ break
360
+ end
361
+ yield(token)
362
+ end
363
+ end
364
+
365
+ def trim_line2(line)
366
+ head = nil
367
+ line.split(TrimSplitRegexp).each do |token|
368
+ next if token.empty?
369
+ head = token unless head
370
+ if token == "@>\n"
371
+ yield('@>')
372
+ if is_erb_stag?(head)
373
+ yield(:cr)
374
+ else
375
+ yield("\n")
376
+ end
377
+ break
378
+ end
379
+ yield(token)
380
+ end
381
+ end
382
+
383
+ ExplicitTrimRegexp = /(^[ \t]*<@-)|(-@>\n?\z)|(<@-)|(-@>)|(<@@)|(@@>)|(<@=)|(<@#)|(<@)|(@>)|(\n)/
384
+ def explicit_trim_line(line)
385
+ line.split(ExplicitTrimRegexp).each do |token|
386
+ next if token.empty?
387
+ if @stag.nil? && /[ \t]*<@-/ =~ token
388
+ yield('<@')
389
+ elsif @stag && /-@>\n/ =~ token
390
+ yield('@>')
391
+ yield(:cr)
392
+ elsif @stag && token == '-@>'
393
+ yield('@>')
394
+ else
395
+ yield(token)
396
+ end
397
+ end
398
+ end
399
+
400
+ CustomERB_STAG = %w(<@= <@# <@)
401
+ def is_erb_stag?(s)
402
+ CustomERB_STAG.member?(s)
403
+ end
404
+ end
405
+
406
+ Scanner.default_scanner = TrimScanner
407
+
408
+ class SimpleScanner < Scanner # :nodoc:
409
+ def scan
410
+ @src.each do |line|
411
+ line.split(SplitRegexp).each do |token|
412
+ next if token.empty?
413
+ yield(token)
414
+ end
415
+ end
416
+ end
417
+ end
418
+
419
+ Scanner.regist_scanner(SimpleScanner, nil, false)
420
+
421
+ begin
422
+ require 'strscan'
423
+ class SimpleScanner2 < Scanner # :nodoc:
424
+ def scan
425
+ stag_reg = /(.*?)(<@@|<@=|<@#|<@|\n|\z)/
426
+ etag_reg = /(.*?)(@@>|@>|\n|\z)/
427
+ scanner = StringScanner.new(@src)
428
+ while ! scanner.eos?
429
+ scanner.scan(@stag ? etag_reg : stag_reg)
430
+ text = scanner[1]
431
+ elem = scanner[2]
432
+ yield(text) unless text.empty?
433
+ yield(elem) unless elem.empty?
434
+ end
435
+ end
436
+ end
437
+ Scanner.regist_scanner(SimpleScanner2, nil, false)
438
+
439
+ class PercentScanner < Scanner # :nodoc:
440
+ def scan
441
+ new_line = true
442
+ stag_reg = /(.*?)(<@@|<@=|<@#|<@|\n|\z)/
443
+ etag_reg = /(.*?)(@@>|@>|\n|\z)/
444
+ scanner = StringScanner.new(@src)
445
+ while ! scanner.eos?
446
+ if new_line && @stag.nil?
447
+ if scanner.scan(/@@/)
448
+ yield('@')
449
+ new_line = false
450
+ next
451
+ elsif scanner.scan(/@/)
452
+ yield(PercentLine.new(scanner.scan(/.*?(\n|\z)/).chomp))
453
+ next
454
+ end
455
+ end
456
+ scanner.scan(@stag ? etag_reg : stag_reg)
457
+ text = scanner[1]
458
+ elem = scanner[2]
459
+ yield(text) unless text.empty?
460
+ yield(elem) unless elem.empty?
461
+ new_line = (elem == "\n")
462
+ end
463
+ end
464
+ end
465
+ Scanner.regist_scanner(PercentScanner, nil, true)
466
+
467
+ class ExplicitScanner < Scanner # :nodoc:
468
+ def scan
469
+ new_line = true
470
+ stag_reg = /(.*?)(<@@|<@=|<@#|<@-|<@|\n|\z)/
471
+ etag_reg = /(.*?)(@@>|-@>|@>|\n|\z)/
472
+ scanner = StringScanner.new(@src)
473
+ while ! scanner.eos?
474
+ if new_line && @stag.nil? && scanner.scan(/[ \t]*<@-/)
475
+ yield('<@')
476
+ new_line = false
477
+ next
478
+ end
479
+ scanner.scan(@stag ? etag_reg : stag_reg)
480
+ text = scanner[1]
481
+ elem = scanner[2]
482
+ new_line = (elem == "\n")
483
+ yield(text) unless text.empty?
484
+ if elem == '-@>'
485
+ yield('@>')
486
+ if scanner.scan(/(\n|\z)/)
487
+ yield(:cr)
488
+ new_line = true
489
+ end
490
+ elsif elem == '<@-'
491
+ yield('<@')
492
+ else
493
+ yield(elem) unless elem.empty?
494
+ end
495
+ end
496
+ end
497
+ end
498
+ Scanner.regist_scanner(ExplicitScanner, '-', false)
499
+
500
+ rescue LoadError
501
+ end
502
+
503
+ class Buffer # :nodoc:
504
+ def initialize(compiler)
505
+ @compiler = compiler
506
+ @line = []
507
+ @script = ""
508
+ @compiler.pre_cmd.each do |x|
509
+ push(x)
510
+ end
511
+ end
512
+ attr_reader :script
513
+
514
+ def push(cmd)
515
+ @line << cmd
516
+ end
517
+
518
+ def cr
519
+ @script << (@line.join('; '))
520
+ @line = []
521
+ @script << "\n"
522
+ end
523
+
524
+ def close
525
+ return unless @line
526
+ @compiler.post_cmd.each do |x|
527
+ push(x)
528
+ end
529
+ @script << (@line.join('; '))
530
+ @line = nil
531
+ end
532
+ end
533
+
534
+ def compile(s)
535
+ out = Buffer.new(self)
536
+
537
+ content = ''
538
+ scanner = make_scanner(s)
539
+ scanner.scan do |token|
540
+ if scanner.stag.nil?
541
+ case token
542
+ when PercentLine
543
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
544
+ content = ''
545
+ out.push(token.to_s)
546
+ out.cr
547
+ when :cr
548
+ out.cr
549
+ when '<@', '<@=', '<@#'
550
+ scanner.stag = token
551
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
552
+ content = ''
553
+ when "\n"
554
+ content << "\n"
555
+ out.push("#{@put_cmd} #{content.dump}")
556
+ out.cr
557
+ content = ''
558
+ when '<@@'
559
+ content << '<@'
560
+ else
561
+ content << token
562
+ end
563
+ else
564
+ case token
565
+ when '@>'
566
+ case scanner.stag
567
+ when '<@'
568
+ if content[-1] == ?\n
569
+ content.chop!
570
+ out.push(content)
571
+ out.cr
572
+ else
573
+ out.push(content)
574
+ end
575
+ when '<@='
576
+ out.push("#{@insert_cmd}((#{content}).to_s)")
577
+ when '<@#'
578
+ # out.push("# #{content.dump}")
579
+ end
580
+ scanner.stag = nil
581
+ content = ''
582
+ when '@@>'
583
+ content << '@>'
584
+ else
585
+ content << token
586
+ end
587
+ end
588
+ end
589
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
590
+ out.close
591
+ out.script
592
+ end
593
+
594
+ def prepare_trim_mode(mode)
595
+ case mode
596
+ when 1
597
+ return [false, '>']
598
+ when 2
599
+ return [false, '<>']
600
+ when 0
601
+ return [false, nil]
602
+ when String
603
+ perc = mode.include?('@')
604
+ if mode.include?('-')
605
+ return [perc, '-']
606
+ elsif mode.include?('<>')
607
+ return [perc, '<>']
608
+ elsif mode.include?('>')
609
+ return [perc, '>']
610
+ else
611
+ [perc, nil]
612
+ end
613
+ else
614
+ return [false, nil]
615
+ end
616
+ end
617
+
618
+ def make_scanner(src)
619
+ Scanner.make_scanner(src, @trim_mode, @percent)
620
+ end
621
+
622
+ def initialize(trim_mode)
623
+ @percent, @trim_mode = prepare_trim_mode(trim_mode)
624
+ @put_cmd = 'print'
625
+ @insert_cmd = @put_cmd
626
+ @pre_cmd = []
627
+ @post_cmd = []
628
+ end
629
+ attr_reader :percent, :trim_mode
630
+ attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
631
+ end
632
+ end
633
+
634
+ #--
635
+ # CustomERB
636
+ class CustomERB
637
+ #
638
+ # Constructs a new CustomERB object with the template specified in _str_.
639
+ #
640
+ # An CustomERB object works by building a chunk of Ruby code that will output
641
+ # the completed template when run. If _safe_level_ is set to a non-nil value,
642
+ # CustomERB code will be run in a separate thread with <b>$SAFE</b> set to the
643
+ # provided level.
644
+ #
645
+ # If _trim_mode_ is passed a String containing one or more of the following
646
+ # modifiers, CustomERB will adjust its code generation as listed:
647
+ #
648
+ # @ enables Ruby code processing for lines beginning with @
649
+ # <> omit newline for lines starting with <@ and ending in @>
650
+ # > omit newline for lines ending in @>
651
+ #
652
+ # _eoutvar_ can be used to set the name of the variable CustomERB will build up
653
+ # its output in. This is useful when you need to run multiple CustomERB
654
+ # templates through the same binding and/or when you want to control where
655
+ # output ends up. Pass the name of the variable to be used inside a String.
656
+ #
657
+ # === Example
658
+ #
659
+ # require "erb"
660
+ #
661
+ # # build data class
662
+ # class Listings
663
+ # PRODUCT = { :name => "Chicken Fried Steak",
664
+ # :desc => "A well messages pattie, breaded and fried.",
665
+ # :cost => 9.95 }
666
+ #
667
+ # attr_reader :product, :price
668
+ #
669
+ # def initialize( product = "", price = "" )
670
+ # @product = product
671
+ # @price = price
672
+ # end
673
+ #
674
+ # def build
675
+ # b = binding
676
+ # # create and run templates, filling member data variebles
677
+ # CustomERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b
678
+ # <@= PRODUCT[:name] @>
679
+ # <@= PRODUCT[:desc] @>
680
+ # END_PRODUCT
681
+ # CustomERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b
682
+ # <@= PRODUCT[:name] @> -- <@= PRODUCT[:cost] @>
683
+ # <@= PRODUCT[:desc] @>
684
+ # END_PRICE
685
+ # end
686
+ # end
687
+ #
688
+ # # setup template data
689
+ # listings = Listings.new
690
+ # listings.build
691
+ #
692
+ # puts listings.product + "\n" + listings.price
693
+ #
694
+ # _Generates_
695
+ #
696
+ # Chicken Fried Steak
697
+ # A well messages pattie, breaded and fried.
698
+ #
699
+ # Chicken Fried Steak -- 9.95
700
+ # A well messages pattie, breaded and fried.
701
+ #
702
+ def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
703
+ @safe_level = safe_level
704
+ compiler = CustomERB::Compiler.new(trim_mode)
705
+ set_eoutvar(compiler, eoutvar)
706
+ @src = compiler.compile(str)
707
+ @filename = nil
708
+ end
709
+
710
+ # The Ruby code generated by CustomERB
711
+ attr_reader :src
712
+
713
+ # The optional _filename_ argument passed to Kernel#eval when the CustomERB code
714
+ # is run
715
+ attr_accessor :filename
716
+
717
+ #
718
+ # Can be used to set _eoutvar_ as described in CustomERB#new. It's probably easier
719
+ # to just use the constructor though, since calling this method requires the
720
+ # setup of an CustomERB _compiler_ object.
721
+ #
722
+ def set_eoutvar(compiler, eoutvar = '_erbout')
723
+ compiler.put_cmd = "#{eoutvar}.concat"
724
+ compiler.insert_cmd = "#{eoutvar}.concat"
725
+
726
+ cmd = []
727
+ cmd.push "#{eoutvar} = ''"
728
+
729
+ compiler.pre_cmd = cmd
730
+
731
+ cmd = []
732
+ cmd.push(eoutvar)
733
+
734
+ compiler.post_cmd = cmd
735
+ end
736
+
737
+ # Generate results and print them. (see CustomERB#result)
738
+ def run(b=TOPLEVEL_BINDING)
739
+ print self.result(b)
740
+ end
741
+
742
+ #
743
+ # Executes the generated CustomERB code to produce a completed template, returning
744
+ # the results of that code. (See CustomERB#new for details on how this process can
745
+ # be affected by _safe_level_.)
746
+ #
747
+ # _b_ accepts a Binding or Proc object which is used to set the context of
748
+ # code evaluation.
749
+ #
750
+ def result(b=TOPLEVEL_BINDING)
751
+ if @safe_level
752
+ th = Thread.start {
753
+ $SAFE = @safe_level
754
+ eval(@src, b, (@filename || '(erb)'), 1)
755
+ }
756
+ return th.value
757
+ else
758
+ return eval(@src, b, (@filename || '(erb)'), 1)
759
+ end
760
+ end
761
+
762
+ def def_method(mod, methodname, fname='(CustomERB)') # :nodoc:
763
+ mod.module_eval("def #{methodname}\n" + self.src + "\nend\n", fname, 0)
764
+ end
765
+
766
+ def def_module(methodname='erb') # :nodoc:
767
+ mod = Module.new
768
+ def_method(mod, methodname)
769
+ mod
770
+ end
771
+
772
+ def def_class(superklass=Object, methodname='result') # :nodoc:
773
+ cls = Class.new(superklass)
774
+ def_method(cls, methodname)
775
+ cls
776
+ end
777
+ end
778
+
779
+ #--
780
+ # CustomERB::Util
781
+ class CustomERB
782
+ # A utility module for conversion routines, often handy in HTML generation.
783
+ module Util
784
+ public
785
+ #
786
+ # A utility method for escaping HTML tag characters in _s_.
787
+ #
788
+ # require "erb"
789
+ # include CustomERB::Util
790
+ #
791
+ # puts html_escape("is a > 0 & a < 10?")
792
+ #
793
+ # _Generates_
794
+ #
795
+ # is a &gt; 0 &amp; a &lt; 10?
796
+ #
797
+ def html_escape(s)
798
+ s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
799
+ end
800
+ alias h html_escape
801
+ module_function :h
802
+ module_function :html_escape
803
+
804
+ #
805
+ # A utility method for encoding the String _s_ as a URL.
806
+ #
807
+ # require "erb"
808
+ # include CustomERB::Util
809
+ #
810
+ # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
811
+ #
812
+ # _Generates_
813
+ #
814
+ # Programming@20Ruby@3A@20@20The@20Pragmatic@20Programmer@27s@20Guide
815
+ #
816
+ def url_encode(s)
817
+ s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("@@@02X", $&.unpack("C")[0]) }
818
+ end
819
+ alias u url_encode
820
+ module_function :u
821
+ module_function :url_encode
822
+ end
823
+ end
824
+
825
+ #--
826
+ # CustomERB::DefMethod
827
+ class CustomERB
828
+ module DefMethod # :nodoc:
829
+ public
830
+ def def_erb_method(methodname, erb)
831
+ if erb.kind_of? String
832
+ fname = erb
833
+ File.open(fname) {|f| erb = CustomERB.new(f.read) }
834
+ erb.def_method(self, methodname, fname)
835
+ else
836
+ erb.def_method(self, methodname)
837
+ end
838
+ end
839
+ module_function :def_erb_method
840
+ end
841
+ end
842
+