cheri 0.0.5 → 0.0.6

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.
@@ -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