cheri 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -87,7 +87,7 @@ end #self
87
87
  # Duplicating this here rather than including Cheri::AWT. (See note re: performance)
88
88
  #++
89
89
  def awt(*r,&k)
90
- if (ctx = __cheri_ctx)
90
+ if ctx = __cheri_ctx
91
91
  if k
92
92
  AWTFrame.new(ctx,*r,&k).run
93
93
  else
@@ -101,7 +101,7 @@ end #self
101
101
  # swing([*args] [, &block]) -> SwingProxy if no block given, else result of block
102
102
  #
103
103
  def swing(*r,&k)
104
- if (ctx = __cheri_ctx)
104
+ if ctx = __cheri_ctx
105
105
  if k
106
106
  if ctx.empty? && (c = ctx.client).kind_of?(RPC) || c.kind_of?(JComp)
107
107
  ctx.fsend(CheriYieldFactory,:cheri_yield,c,&k)
@@ -36,6 +36,17 @@ XmlConnecter = Cheri::Builder::TypeConnecter.new do
36
36
  connect XmlElement
37
37
  end
38
38
 
39
+ type TextElem do
40
+ connect XmlElement
41
+ connect Cheri::Builder::Content
42
+ connect Object
43
+ end
44
+
45
+ type Namespace do
46
+ connect XmlElement do |namespace,elem|
47
+ elem.ns ||= namespace.__prefix__
48
+ end
49
+ end
39
50
  end #XmlConnecter
40
51
 
41
52
  end #Xml
@@ -32,18 +32,18 @@ end #XmlElement
32
32
 
33
33
  # Included by all Cheri::Xml builders
34
34
  module XmlBuilder
35
- CE = ' />'.freeze #:nodoc:
35
+ TCE = ' />'.freeze #:nodoc:
36
36
 
37
37
  def empty_s(str='')
38
- str << CE
38
+ str << TCE
39
39
  end
40
40
 
41
41
  def empty_io(ios)
42
- ios << CE
42
+ ios << TCE
43
43
  end
44
44
 
45
45
  def esc(inp,out=nil)
46
- if @ctx[:xml_esc] && (cs = Charsets.charset(inp))
46
+ if @opt[:esc] && (cs = Charsets.charset(inp))
47
47
  cs.xlat(inp,(out ||= ''))
48
48
  out
49
49
  elsif out
@@ -58,10 +58,26 @@ class Elem
58
58
  include Cheri::Builder::MarkupBuilder
59
59
  include XmlBuilder
60
60
  include XmlElement
61
+
62
+ def initialize(ctx,*r,&k)
63
+ opt = @opt = ctx[:xml_opts] || {}
64
+ @fmt = true if opt[:format]
65
+ @amap = opt[:attr] if opt[:attr]
66
+ super
67
+ end
61
68
 
62
69
  def mod
63
70
  Cheri::Xml
64
71
  end
72
+
73
+ def margin
74
+ @mrg || @opt[:margin] || @ctx[:margin] || 0
75
+ end
76
+
77
+ def indent
78
+ @idt || @opt[:indent] || @ctx[:indent] || 0
79
+ end
80
+
65
81
  end
66
82
 
67
83
  class EmptyElem
@@ -69,40 +85,53 @@ class EmptyElem
69
85
  include XmlBuilder
70
86
  include XmlElement
71
87
 
88
+ def initialize(ctx,*r,&k)
89
+ opt = @opt = ctx[:xml_opts] || {}
90
+ @fmt = true if opt[:format]
91
+ @amap = opt[:attr] if opt[:attr]
92
+ super
93
+ end
94
+
72
95
  def mod
73
96
  Cheri::Xml
74
97
  end
75
98
 
76
- def content?(value)
99
+ def add?(value)
77
100
  raise XmlException,"content not allowed for empty element #{@sym}: #{value}"
78
101
  end
79
- end
80
102
 
103
+ def margin
104
+ @mrg || @opt[:margin] || @ctx[:margin] || 0
105
+ end
106
+
107
+ def indent
108
+ @idt || @opt[:indent] || @ctx[:indent] || 0
109
+ end
110
+
111
+ end
81
112
 
82
113
  class TextElem
83
- include Cheri::Builder::Builder
84
- include Cheri::Builder::Content
85
- include Cheri::Builder::ContentArgs
114
+ include Cheri::Builder::MarkupLikeBuilder
86
115
  include XmlBuilder
87
116
 
88
- def mod
89
- Cheri::Xml
117
+ def initialize(ctx,*r,&k)
118
+ @opt = ctx[:xml_opts] || {}
119
+ super
90
120
  end
91
121
 
92
- def object
93
- self
122
+ def set?(n,v)
123
+ raise XmlException,"attribute not allowed for text element #{@sym}: #{n}=#{v}"
94
124
  end
125
+ private :set?
95
126
 
96
- def run
97
- value = @ctx.call(self,&@blk) if @blk
98
- add(value) if String === value
99
- #add(value) if value && !(Appendable === value || BaseProxy === value)
100
- self
127
+ def mod
128
+ Cheri::Xml
101
129
  end
102
130
 
103
131
  # Appends content to +str+, or to an empty string if +str+ is omitted.
104
132
  # Returns the result.
105
133
  def to_s(str='')
134
+ return to_io(str) unless String === str
106
135
  @cont.each do |c|
107
136
  if String === c
108
137
  esc(c,str)
@@ -127,6 +156,7 @@ class TextElem
127
156
 
128
157
  end
129
158
 
159
+ # Like TextElem, but always escapes values, regardless of :esc setting
130
160
  class EscElem < TextElem
131
161
 
132
162
  def esc(inp,out=nil)
@@ -142,14 +172,54 @@ class EscElem < TextElem
142
172
 
143
173
  end
144
174
 
175
+ class CommentElem
176
+ include Cheri::Builder::CommentBuilder
177
+ include XmlBuilder
178
+ include XmlElement
179
+ # :stopdoc:
180
+ CO = '<!-- '.freeze
181
+ CC = ' -->'.freeze
182
+ CCLF = " -->\n".freeze
183
+ # :startdoc:
184
+ def initialize(ctx,*r,&k)
185
+ opt = @opt = ctx[:xml_opts] || {}
186
+ @fmt = true if opt[:format]
187
+ super
188
+ end
189
+
190
+ def set?(n,v)
191
+ raise XmlException,"attribute not allowed for comment #{@sym}: #{n}=#{v}"
192
+ end
193
+ private :set?
194
+
195
+ def mod
196
+ Cheri::Xml
197
+ end
198
+
199
+ def margin
200
+ @mrg || @opt[:margin] || @ctx[:margin] || 0
201
+ end
202
+
203
+ def indent
204
+ @idt || @opt[:indent] || @ctx[:indent] || 0
205
+ end
206
+
207
+ end #CommentElem
208
+
145
209
  # TODO: special handling for these:
146
210
 
147
211
  class XmlRoot
148
- XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".freeze #:nodoc:
149
- include Cheri::Builder::Builder
150
- include Cheri::Builder::Content
151
- include Cheri::Builder::ContentArgs
212
+ # :stopdoc:
213
+ XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>".freeze
214
+ # :startdoc:
215
+ include Cheri::Builder::MarkupBuilder
152
216
  include XmlBuilder
217
+
218
+ def initialize(ctx,*r,&k)
219
+ opt = @opt = ctx[:xml_opts] || {}
220
+ @fmt = true if opt[:format]
221
+ super
222
+ end
153
223
 
154
224
  def mod
155
225
  Cheri::Xml
@@ -167,17 +237,29 @@ class XmlRoot
167
237
  # Appends content to +str+ (or new String if +str+ is omitted). Returns the result.
168
238
  def to_s(str='')
169
239
  return to_io(str) unless String === str
240
+ str << ' ' * @opt[:margin] if @fmt && @opt[:margin]
170
241
  str << XML
242
+ str << 10 if @fmt
171
243
  cont_s(str)
172
244
  str
173
245
  end
174
246
 
175
247
  # Appends content to +ios+. Returns the result.
176
248
  def to_io(ios)
249
+ ios << ' ' * @opt[:margin] if @fmt && @opt[:margin]
177
250
  ios << XML
251
+ ios << LF if @fmt
178
252
  cont_io(ios)
179
253
  ios
180
254
  end
255
+
256
+ def format!
257
+ @fmt = true
258
+ end
259
+
260
+ def depth
261
+ -1
262
+ end
181
263
 
182
264
  end
183
265
 
@@ -185,5 +267,42 @@ end
185
267
  class ProcElem < Elem
186
268
  end
187
269
 
270
+ class Namespace
271
+ alias_method :__methods__,:methods
272
+ keep = /^(__|<|>|=)|^(class|inspect|to_s)$|(\?|!|=)$/
273
+ instance_methods.each do |m|
274
+ undef_method m unless m =~ keep
275
+ end
276
+
277
+ def initialize(ctx,prefix,uri=nil)
278
+ @ctx = ctx
279
+ @pfx = prefix.to_sym
280
+ @uri = uri if uri
281
+ end
282
+
283
+ def __prefix__
284
+ @pfx
285
+ end
286
+
287
+ def __uri__
288
+ @uri
289
+ end
290
+
291
+ def mod
292
+ Cheri::Xml
293
+ end
294
+ private :mod
295
+
296
+ def method_missing(sym,*r,&k)
297
+ @ctx.nsend(mod,@pfx,sym,*r,&k)
298
+ end
299
+ private :method_missing
300
+
301
+ def inspect
302
+ "#<#{self.class}:instance>"
303
+ end
304
+
305
+ end #Namespace
306
+
188
307
  end #Xml
189
308
  end #Cheri
@@ -41,7 +41,7 @@ class << self
41
41
 
42
42
  def connecter
43
43
  XmlConnecter
44
- end
44
+ end
45
45
 
46
46
  end #self
47
47
 
@@ -51,33 +51,170 @@ end #self
51
51
  # xml([*args] [, &block]) -> XmlProxy if no block given, else result of block
52
52
  #
53
53
  def xml(*r,&k)
54
- if (ctx = __cheri_ctx)
54
+ if ctx = __cheri_ctx
55
+ unless copts = ctx[:xml_opts]
56
+ iopts = ctx.ictx[:xml_opts] ||= XmlOptions.new
57
+ copts = ctx[:xml_opts] = XmlOptions.new(iopts)
58
+ end
55
59
  if k
56
60
  if ctx.tos(XmlBuilder)
57
61
  XmlFrame.new(ctx,*r,&k).run
58
62
  else
59
- ctx.msend(Cheri::Xml,:xml,*r,&k)
63
+ copts.ingest_args(*r) unless r.empty?
64
+ ctx.msend(Cheri::Xml,:xml,&k)
60
65
  end
61
66
  else
67
+ copts.ingest_args(*r) unless r.empty?
62
68
  ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
63
69
  end
64
70
  end
65
71
  end
66
72
  private :xml
67
-
68
-
73
+
69
74
  module XmlFactory
70
75
  def self.builder(ctx,sym,*r,&k)
76
+ opts = ctx[:xml_opts] || {}
77
+ if ((als = opts[:alias]) && (asym = als[sym])) || (asym = Aliases[sym])
78
+ sym = asym
79
+ end
71
80
  if (clazz = Types[sym])
72
81
  clazz.new(ctx,sym,*r,&k)
73
- elsif ctx[:xml_any] || ((acc = ctx[:xml_accept]) && acc[sym])
82
+ elsif :no_ns == sym || ((hns = opts[:ns]) && hns[sym])
83
+ ns = (ctx[:xml_ns] ||= {})[sym] ||= Namespace.new(ctx,sym)
84
+ NamespaceBuilder.new(ns,ctx,sym,*r,&k)
85
+ elsif opts[:any] || ((acc = opts[:accept]) && acc[sym])
74
86
  Elem.new(ctx,sym,*r,&k)
75
87
  else
76
- nil
88
+ nil
77
89
  end
78
90
  end
79
91
  end #XmlFactory
80
92
 
93
+ class XmlOptions < Cheri::Builder::BaseOptions
94
+ def validate(key,value)
95
+ raise Cheri.type_error(key,Symbol) unless Symbol === key
96
+ case key
97
+ when :any : validate_boolean_nil(value) || nil
98
+ when :esc : validate_boolean_nil(value) || nil
99
+ when :format : validate_boolean_nil(value) || nil
100
+ when :indent
101
+ unless Fixnum === value
102
+ if true == value
103
+ value = 2
104
+ elsif false == value || nil == value
105
+ value = nil
106
+ else
107
+ raise Cheri.type_error(value,Fixnum,TrueClass,FalseClass,NilClass)
108
+ end
109
+ end
110
+ store(:format,true) if value
111
+ value
112
+ when :margin
113
+ unless Fixnum === value
114
+ if false == value || nil == value
115
+ value = nil
116
+ else
117
+ raise Cheri.type_error(value,Fixnum,FalseClass,NilClass)
118
+ end
119
+ end
120
+ store(:format,true) if value
121
+ value
122
+ when :ns
123
+ value = value.to_sym if String === value
124
+ if Symbol === value
125
+ hns = self[:ns] || {}
126
+ hns[value] = true
127
+ hns
128
+ elsif Array === value
129
+ hns = self[:ns] || {}
130
+ value.each do |ns|
131
+ if String === ns
132
+ ns = ns.to_sym
133
+ else
134
+ validate_symbol(ns)
135
+ end
136
+ hns[ns] = true
137
+ end
138
+ warn "warning: empty array specified in xml :ns" if value.empty?
139
+ hns
140
+ elsif Hash === value
141
+ value.each_pair do |k,v|
142
+ validate_symbol(k)
143
+ validate_boolean_nil(v)
144
+ end
145
+ value
146
+ else
147
+ raise Cheri.type_error(value,Symbol,Array,Hash)
148
+ end
149
+ when :accept
150
+ value = value.to_sym if String === value
151
+ if Symbol === value
152
+ acc = self[:accept] || {}
153
+ acc[value] = true
154
+ acc
155
+ elsif Array === value
156
+ acc = self[:accept] || {}
157
+ value.each do |a|
158
+ if String === a
159
+ a = a.to_sym
160
+ else
161
+ validate_symbol(a)
162
+ end
163
+ acc[a] = true
164
+ end
165
+ warn "warning: empty array specified in xml :accept" if value.empty?
166
+ store(:any,false)
167
+ acc
168
+ elsif Hash === value
169
+ value.each_pair do |k,v|
170
+ validate_symbol(k)
171
+ validate_boolean_nil(v)
172
+ end
173
+ value
174
+ else
175
+ raise Cheri.type_error(value,Symbol,Array,Hash)
176
+ end
177
+ when :alias
178
+ if Array === value
179
+ raise ArgumentError,"odd number of values for :alias" if ((len = value.length) & 1) == 1
180
+ als = self[:alias] || {}
181
+ (len>>1).times do |i|
182
+ als[value[i*2].to_sym] = value[i*2+1].to_sym
183
+ end
184
+ als
185
+ elsif Hash === value
186
+ value.each_pair do |k,v|
187
+ validate_symbol(k)
188
+ validate_symbol(v)
189
+ end
190
+ value
191
+ else
192
+ raise Cheri.type_error(value,Array,Hash)
193
+ end
194
+ when :attr
195
+ if Array === value
196
+ raise ArgumentError,"odd number of values for :attr" if ((len = value.length) & 1) == 1
197
+ als = self[:attr] || {}
198
+ (len>>1).times do |i|
199
+ als[value[i*2].to_sym] = value[i*2+1].to_sym
200
+ end
201
+ als
202
+ elsif Hash === value
203
+ value.each_pair do |k,v|
204
+ validate_symbol(k)
205
+ validate_symbol(v)
206
+ end
207
+ value
208
+ else
209
+ raise Cheri.type_error(value,Array,Hash)
210
+ end
211
+ else
212
+ raise ArgumentError,"invalid xml option: #{key}"
213
+ end
214
+ end
215
+ end #XmlOptions
216
+
217
+
81
218
  class XmlProxy < Cheri::Builder::BaseProxy
82
219
 
83
220
  impl(Types.keys)
@@ -87,43 +224,62 @@ class XmlProxy < Cheri::Builder::BaseProxy
87
224
  end
88
225
  private :mod
89
226
 
90
- def [](opts)
91
- if Symbol === opts
92
- case opts
93
- when :any : @ctx[:xml_any] = true
94
- when :esc : @ctx[:xml_esc] = true
95
- else raise ArgumentError,"invalid simple xml option: :#{opts}"
96
- end
97
- elsif Hash === opts
98
- @ctx[:xml_any] = opts[:any] != false if opts[:any] != nil
99
- @ctx[:xml_esc] = opts[:esc] != false if opts[:esc] != nil
100
- if (accept = opts[:accept])
101
- raise Cheri.type_error(accept,Array) unless Array === accept
102
- acc = {}
103
- accept.each do |a|
104
- raise Cheri.type_error(a,Symbol) unless Symbol === a
105
- acc[a] = true
106
- end
107
- @ctx[:xml_accept] = acc
108
- @ctx[:xml_any] = nil
109
- end
110
- else
111
- raise Cheri.type_error(opts,Hash,Symbol)
112
- end
227
+ def [](*args)
228
+ ictx = (ctx = @ctx).ictx
229
+ iopts = ictx[:xml_opts] ||= XmlOptions.new
230
+ iopts.ingest_args(*args)
231
+ copts = ctx[:xml_opts] ||= XmlOptions.new
232
+ copts.ingest_args(*args)
113
233
  nil
114
234
  end
115
235
 
116
236
  end #XmlProxy
117
237
 
238
+ class NamespaceBuilder
239
+ include Cheri::Builder::Builder
240
+ def initialize(ns,*r,&k)
241
+ super(*r,&k)
242
+ @obj = ns
243
+ end
244
+ def child?
245
+ false
246
+ end
247
+ def parent?
248
+ false
249
+ end
250
+ def any?
251
+ true
252
+ end
253
+ def mod
254
+ Cheri::Xml
255
+ end
256
+ end #NamespaceBuilder
257
+
118
258
  class XmlFrame
119
259
  include Cheri::Builder::Frame
120
260
  def initialize(ctx,*r,&k)
121
- super
122
- @obj = ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
261
+ super(ctx,&k)
262
+ @obj = ctx[:xml_proxy] ||= XmlProxy.new(ctx,*r)
263
+ @args = r unless r.empty?
123
264
  end
124
265
  def mod
125
266
  Cheri::Xml
126
267
  end
268
+ def run
269
+ if blk = @blk
270
+ if args = @args
271
+ opts = (ctx = @ctx)[:xml_opts]
272
+ temp = XmlOptions.new(opts)
273
+ temp.ingest_args(*args)
274
+ ctx[:xml_opts] = temp
275
+ result = ctx.call(self,&blk)
276
+ ctx[:xml_opts] = opts
277
+ result
278
+ else
279
+ @ctx.call(self,&blk)
280
+ end
281
+ end
282
+ end
127
283
  end #XmlFrame
128
284
 
129
285
  end #Xml