ytemplate 0.0.1

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.
@@ -0,0 +1,3 @@
1
+ README.md
2
+ lib/**/*.rb
3
+ LICENSE
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format nested
2
+ --color
@@ -0,0 +1,8 @@
1
+ Changes in ytemplate
2
+ ====================
3
+
4
+ Changes in ytemplate releases are listed here.
5
+
6
+ v0.0.1
7
+ ------
8
+ - Simple YAML::Template deploy, deploy_to, and match functions
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in priehlazx.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Malo Skrylevo
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,71 @@
1
+ # YAML-шаблонъ
2
+
3
+ YAML-шаблонъ есть расширитель YAML модели шаблонами. Онъ позволяетъ расшрирять любой YAML-документъ, предоставляя пользователю развёртывать и проверять его по опредѣлённому шаблону.
4
+
5
+ ## Использованіе
6
+
7
+ ### Простая развёртка
8
+
9
+ require 'ytemplate'
10
+
11
+ SampleTemplate = <<C
12
+ ---
13
+ local=:
14
+ lkey: lvalue
15
+ key1: value
16
+ key2: %local
17
+ key3:
18
+ %local:
19
+ key4: value
20
+ C
21
+
22
+ tmpl = YAML::Template.new SampleTemplate
23
+
24
+ o = tmpl.deploy # => {"key1"=>"value", "key2"=>{"lkey"=>"lvalue"}, "key3"=>{"lkey"=>"lvalue", "key4"=>"value"}}
25
+ puts o.to_yaml
26
+ # ---
27
+ # key1: value
28
+ # key2:
29
+ # lkey: lvalue
30
+ # key3:
31
+ # lkey: lvalue
32
+ # key4: value
33
+
34
+
35
+ ### Развёртка въ иной YAML-документъ
36
+
37
+ SampleFile = <<C
38
+ ---
39
+ key1: value
40
+ key2:
41
+ lkey: lvalue
42
+ key3:
43
+ lkey: lvalue
44
+ key4: value
45
+ C
46
+
47
+ o = tmpl.deploy_to( YAML.load( SampleFile) ) # => {"key1"=>"+value", "key2"=>{"lkey"=>"+lvalue"}, "key3"=>{"lkey"=>"+lvalue", "key4"=>"+value"}}
48
+ puts o.to_yaml
49
+ # ---
50
+ # key1: +value
51
+ # key2:
52
+ # lkey: +lvalue
53
+ # key3:
54
+ # lkey: +lvalue
55
+ # key4: +value
56
+
57
+ ### Провѣрка подобности
58
+
59
+ Можно провѣрить, подобенъ ли YAML-документъ нѣкоему шаблону. Выходомъ метода 'match' будетъ Наборъ ошибокъ, представленныхъ въ видѣ текста.
60
+
61
+ file = YAML.load( SampleFile )
62
+ o = tmpl.match( file ) # => []
63
+
64
+ file['key1'] = 'novalue'
65
+ o = tmpl.match( file ) # => [":key1 => novalue =~ value"]
66
+
67
+ # Права
68
+
69
+ Авторскія и исключительныя права (а) 2011 Малъ Скрылевъ
70
+ Зри LICENSE за подробностями.
71
+
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,391 @@
1
+ #!/usr/bin/ruby -KU
2
+ # encoding: utf-8
3
+
4
+ require 'yaml'
5
+ require 'rdoba/re'
6
+ require 'rdoba/debug'
7
+ require 'rdoba/deploy'
8
+ require 'rdoba/yaml'
9
+
10
+ module YAML
11
+ class Template
12
+
13
+ # def puts(*args)
14
+ # File.open('yaml_t.log','a') do |f| f.puts(*args) end
15
+ # end
16
+
17
+ @@errors = {
18
+ :dict_unallow => 'Словарь не допустим на уровне %i',
19
+ :var_undef => 'Переменная %s не определена',
20
+ :no_tmpl_str => 'Значение строки шаблона отсутствует',
21
+ :added => 'Переменная \'%s\' добавлена',
22
+ }
23
+
24
+ private
25
+
26
+ def deploy_verility(content)
27
+ @verility_template = YAML.load( StringIO.new content.to_s ).deploy
28
+ deploy_value(@verility_template)
29
+ end
30
+
31
+ def deploy_value(value)
32
+ @levelno ? @levelno += 1 : @levelno = 0
33
+ res = case value.class.to_s
34
+ when 'Hash'
35
+ unless value.class == Hash
36
+ @levelno -= 1
37
+ raise @@errors[:dict_unallow] % @levelno
38
+ end
39
+
40
+ value.each_pair do |tkey, tvalue|
41
+ if tkey =~ /^(.*)=$/ and not @vars.keys.include? $1
42
+ dbp12 "[deploy_value]> #{@@errors[:added] % $1}"
43
+ @vars[$1] = tvalue
44
+ value.delete(tkey)
45
+ end
46
+ end
47
+
48
+ err = []
49
+ unless (value.each_pair do |tkey, tvalue|
50
+ begin
51
+ if tkey =~ /^%(.*)$/
52
+ raise @@errors[:var_undef] % $1 unless @vars.keys.include? $1
53
+ value.delete(tkey)
54
+ @vars[$1].each_pair do |k,v| value[k] = v; end
55
+ else
56
+ break false unless deploy_value(tkey)
57
+ end
58
+ break false unless deploy_value(tvalue)
59
+ rescue
60
+ $stderr.puts "Exception: #{$!}\n\t#{$@.join("\n\t")}"
61
+ err << $!.to_s
62
+ break false
63
+ end
64
+ end)
65
+ @levelno -= 1
66
+ raise err.join(',')
67
+ end
68
+
69
+ when 'Array'
70
+ err = []
71
+ unless (value.each do |tvalue|
72
+ begin
73
+ break false unless deploy_value(tvalue)
74
+ rescue
75
+ $stderr.puts "Exception: #{$!}\n\t#{$@.join("\n\t")}"
76
+ err << $!.to_s
77
+ break false
78
+ end
79
+ end)
80
+ @levelno -= 1
81
+ raise err.join(',')
82
+ end
83
+
84
+ when 'String'
85
+ if value == ''
86
+ @levelno -= 1
87
+ raise @@errors[:no_tmpl_str]
88
+ end
89
+
90
+ else
91
+ end
92
+
93
+ @levelno -= 1
94
+ true
95
+ end
96
+
97
+ def initialize(verility_template)
98
+ @levels = []
99
+ @vars = {}
100
+ deploy_verility(verility_template)
101
+ end
102
+
103
+ public
104
+
105
+ def deploy
106
+ @verility_template.clone
107
+ end
108
+
109
+ def deploy_to(inval, options = {})
110
+ # options:
111
+ # required: array - field list in hash that is required to be shewn
112
+ # use_template: true | +false
113
+ # expand_level: integer - force expand upto the specified level( or -1 to full) the hash and array
114
+ dbp11 "[deploy_to] <<< #{inval.inspect}, #{options.inspect}"
115
+ options = { :required => [], :use_template => false, :expand_level => 0 } | options
116
+ options[:expand_level] = -1 if options[:expand_level].class != Fixnum
117
+
118
+ hash = @verility_template.clone
119
+
120
+ def deploy_array_to(form, tform, options = {})
121
+ dbp11 "[deploy_array_to] <<< form = #{form.inspect}, tform = #{tform.inspect}, options = #{options.inspect}"
122
+ tidx = -tform.size
123
+ expand = options[:expand_level]
124
+ form.reverse.each do |value|
125
+ expand = true
126
+ dbp14 "[deploy_array_to]> #{value.inspect} <<< #{tform[0].inspect}"
127
+ case value.class.to_s
128
+ when 'Hash'
129
+ deploy_hash_to(value, tform[0], options)
130
+ when 'Array'
131
+ deploy_array_to(value, tform[0], options)
132
+ when 'String'
133
+ if tform[0] =~ /@.*@(.*)$/
134
+ # - matched array value /@expr@/ =~ '@.*@'
135
+ value.replace(tform[0] + value)
136
+ end
137
+ end
138
+ end
139
+
140
+ if options[:expand_level] < 0
141
+ tform.reverse.each do |tvalue|
142
+ dbp12 "[deploy_array_to]> Append: #{tvalue.inspect}"
143
+ form.push(tvalue)
144
+ end
145
+ end
146
+ dbp11 "[deploy_array_to] >>> #{form.inspect}"
147
+ end
148
+
149
+ def crop_to(level, value)
150
+ dbp14 "[crop_to] <<< level = #{level.inspect}, value = #{value.inspect}"
151
+ level -= 1 if level > 0
152
+ res = case value.class.to_sym
153
+ when :Hash
154
+ res = {}
155
+ value.each do |k,v| res[k] = level != 0 && crop_to(level, v) || nil end if level != 0
156
+ res
157
+ when :Array
158
+ res = []
159
+ value.each do |v|
160
+ res << crop_to(level, v)
161
+ end if level != 0
162
+ res
163
+ else
164
+ value
165
+ end
166
+ dbp14 "[crop_to] >>> #{res.inspect}"
167
+ res
168
+ end
169
+
170
+ def deploy_hash_to(form, tform, options = {})
171
+ dbp11 "[deploy_hash_to] <<< form = #{form.inspect}, tform = #{tform.inspect}, options = #{options.inspect}"
172
+ rplc = {}
173
+ expand = options[:expand_level] || (not (options[:required].empty? ||
174
+ options[:required].each do |x| break false if tform.key?(x) end ))
175
+ form.each_pair do |key, value|
176
+ expand = true
177
+ tform.each_pair do |tkey, tvalue|
178
+ dbp12 "[deploy_hash_to]> Check #{tkey} => #{key}"
179
+ if tkey =~ /^\/([^\/]+)/ and key =~ /#{$1}/ and key !~ /^\//
180
+ # matched hash key /(sr|...)/ =~ 'sr'
181
+ p tkey, key, options
182
+ if options[:use_template]
183
+ nkey = tkey.gsub(key,"+#{key}")
184
+ dbp12 "[deploy_hash_to]> Replace key #{key} => #{nkey}"
185
+ rplc[key] = nkey
186
+ end
187
+ key = tkey
188
+ end
189
+
190
+ if tkey == key
191
+ dbp14 "[deploy_hash_to]> Try deploy #{key}: #{value.inspect} <= #{tvalue.inspect}"
192
+ break case value.class.to_s
193
+ when 'Hash'
194
+ deploy_hash_to(value, tvalue, options)
195
+ when 'Array'
196
+ deploy_array_to(value, tvalue, options)
197
+ when 'String'
198
+ value.insert(0, '+') if tvalue == value
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ rplc.each do |key,nkey| form[nkey] = form.delete(key); end
205
+
206
+ if expand
207
+ tform.each_pair do |tkey, tvalue|
208
+ dbp14 "[deploy_hash_to]> Template pair: #{tkey.inspect} => #{tvalue.inspect}"
209
+ if form.key?(tkey)
210
+ dbp14 "[deploy_hash_to]> Form has template key: #{tkey.inspect}"
211
+ basevalue = form[tkey]
212
+ if tvalue.class == String
213
+ dbp14 "[deploy_hash_to]> Try match string: #{basevalue.inspect} to string as re: #{tvalue.inspect}"
214
+ if tvalue =~ /^\/(.*)/u and (re_s = $1) =~ /[\(\)]/ and basevalue.match(/#{re_s}/u)
215
+ # matched value /(sr|...)/ =~ 'sr'
216
+ form[tkey] = tvalue.sub(basevalue, '+' + basevalue)
217
+ elsif tvalue =~ /@.*@(.*)$/
218
+ # matched value /@expr@/ =~ '@.*@'
219
+ form[tkey] = tvalue + basevalue + $1.to_s
220
+ end
221
+ end
222
+ else
223
+ dbp14 "[deploy_hash_to]> Form has NO template key: #{tkey.inspect}"
224
+ basekey = tkey =~ /(.*)\[.*\]/
225
+ form[tkey] = if basekey and form.key?($1)
226
+ basevalue = form.delete($1)
227
+ tvalue.sub(/#{basevalue}/, '+' + basevalue)
228
+ else
229
+ if options[:expand_level]
230
+ dbp14 "[deploy_hash_to]> Expand level >>> #{options[:expand_level].inspect}"
231
+ crop_to(options[:expand_level].to_i, tvalue)
232
+ elsif tvalue.class == String
233
+ tvalue
234
+ else
235
+ tvalue.dup.clear
236
+ end if options[:expand_level].to_i != 0
237
+ end
238
+ end
239
+ end
240
+ end
241
+ end
242
+
243
+ inhash = if inval.class == String
244
+ YAML.load(StringIO.new(inval)) || {}
245
+ elsif inval.class == Hash
246
+ inval
247
+ else
248
+ raise "The class '#{inval.class}' of the input parameter is undeploable"
249
+ end
250
+
251
+ begin
252
+ deploy_hash_to(inhash, hash, options)
253
+ rescue
254
+ $stderr.puts "Error #{$!}\t#{$@.join("\n\t")}"
255
+ return {}
256
+ end
257
+
258
+ dbp18 "[deploy_to]>>> output dump: vvv\n #{inhash.inspect}"
259
+
260
+ dbp11 "[deploy_to] >>> #{inhash.to_yml}"
261
+
262
+ inval.class == String ? inval.replace(inhash.to_yml) : inval.replace(inhash)
263
+ inhash
264
+ end
265
+
266
+ def match(inval, options = {}) #TODO add path to a base value to match... ":key1:key2", to match to => key3:value
267
+ # options:
268
+ # required: array - field list in hash that is required to be shewn
269
+ # use_template: true | +false
270
+ # expand_level: integer - force expand upto the specified level( or -1 to full) the hash and array
271
+ dbp11 "[match] <<< #{inval.inspect}, #{options.inspect}"
272
+ options = { :required => [], :use_template => false, :expand_level => 0 } | options
273
+ options[:expand_level] = -1 if options[:expand_level].class != Fixnum
274
+
275
+ hash = @verility_template.clone
276
+
277
+ err = []
278
+
279
+ def crop_to(level, value)
280
+ dbp14 "[crop_to] <<< level = #{level.inspect}, value = #{value.inspect}"
281
+ level -= 1 if level > 0
282
+ res = case value.class.to_sym
283
+ when :Hash
284
+ res = {}
285
+ value.each do |k,v| res[k] = level != 0 && crop_to(level, v) || nil end if level != 0
286
+ res
287
+ when :Array
288
+ res = []
289
+ value.each do |v|
290
+ res << crop_to(level, v)
291
+ end if level != 0
292
+ res
293
+ else
294
+ value
295
+ end
296
+ dbp14 "[crop_to] >>> #{res.inspect}"
297
+ res
298
+ end
299
+
300
+ def match_string(path, value, tvalue, err, options = {})
301
+ return if tvalue =~ /@.*@(.*)$/
302
+
303
+ if value != tvalue
304
+ err << "#{path.join(':')} => #{value} =~ #{tvalue}"
305
+ end
306
+ end
307
+
308
+ def match_array(path, form, tform, err, options = {})
309
+ dbp11 "[match_array] <<< form = #{form.inspect}, tform = #{tform.inspect}, options = #{options.inspect}"
310
+ tidx = -tform.size
311
+ expand = options[:expand_level]
312
+ size = from.size
313
+ rform = form.reverse.each_index do |idx|
314
+ value = form[-idx - 1]
315
+ expand = true
316
+ dbp14 "[match_array]> #{value.inspect} <<< #{tform[0].inspect}"
317
+ npath = path.dup << size - idx - 1
318
+ case value.class.to_s
319
+ when 'Hash'
320
+ match_hash(npath, value, tform[0], err, options)
321
+ when 'Array'
322
+ match_array(npath, value, tform[0], err, options)
323
+ when 'String'
324
+ match_array(npath, value, tform[0], err, options)
325
+ end
326
+ end
327
+
328
+ dbp11 "[match_array] >>> #{form.inspect}"
329
+ end
330
+
331
+ def match_hash(path, form, tform, err, options = {})
332
+ dbp11 "[match_hash] <<< form = #{form.inspect}, tform = #{tform.inspect}, options = #{options.inspect}"
333
+ rplc = {}
334
+ expand = options[:expand_level] || (not (options[:required].empty? ||
335
+ options[:required].each do |x| break false if tform.key?(x) end ))
336
+ form.each_pair do |key, value|
337
+ expand = true
338
+ tform.each_pair do |tkey, tvalue|
339
+ dbp12 "[match_hash]> Check #{tkey} => #{key}"
340
+ if tkey =~ /^\/([^\/]+)/ and key =~ /#{$1}/
341
+ # matched hash key /(sr|...)/ =~ 'sr'
342
+ if options[:use_template]
343
+ nkey = tkey.gsub(key,"+#{key}")
344
+ dbp12 "[match_hash]> Replace key #{key} => #{nkey}"
345
+ rplc[key] = nkey
346
+ end
347
+ key = tkey
348
+ end
349
+
350
+ if tkey == key
351
+ dbp14 "[match_hash]> Try match #{key} => #{value.inspect}"
352
+ npath = path.dup << key
353
+ break case value.class.to_sym
354
+ when :Hash
355
+ match_hash(npath, value, tvalue, err, options)
356
+ when :Array
357
+ match_array(npath, value, tvalue, err, options)
358
+ when :String
359
+ match_string(npath, value, tvalue, err, options)
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+ end
366
+
367
+ inhash = if inval.class == String
368
+ YAML.load(StringIO.new(inval)) || {}
369
+ elsif inval.class == Hash
370
+ inval
371
+ else
372
+ raise "The class '#{inval.class}' of the input parameter is unmatchable"
373
+ end
374
+
375
+ begin
376
+ match_hash([''], inhash, hash, err, options)
377
+ rescue
378
+ $stderr.puts "Error #{$!}\t#{$@.join("\n\t")}"
379
+ return {}
380
+ end
381
+
382
+ dbp18 "[match]>>> output dump: vvv\n #{inhash.inspect}"
383
+
384
+ dbp11 "[match] >>> #{inhash.to_yml}"
385
+
386
+ inval.class == String ? inval.replace(inhash.to_yml) : inval.replace(inhash)
387
+ err
388
+ end
389
+ end
390
+ end
391
+
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/ruby -KU
2
+ # encoding: utf-8
3
+
4
+ require 'yaml'
5
+ require 'strscan'
6
+ require 'rdoba'
7
+
8
+ module YAML
9
+ class TemplateMisc
10
+
11
+ # def puts(*args)
12
+ # File.open('yaml_t.log','a') do |f| f.puts(*args) end
13
+ # end
14
+
15
+ @@errors = {
16
+ :unkn_class => 'Непонятный класс %s для присваиваемого ключа %s',
17
+ :dict_unallow => 'Словарь не допустим на уровне %i',
18
+ :var_undef => 'Переменная %s не определена',
19
+ :no_tmpl_str => 'Значение строки шаблона отсутствует',
20
+ :tmpl_undef => 'Не определён шаблон %s на уровне %i',
21
+ :git_unfound => 'Гит схов не найден в папке %s',
22
+ :fold_unfound => 'Папка %s для словаря не существует',
23
+ :dict_unfound => 'Словарь %s не найден во Гит схове',
24
+ :cant_save => 'Невозможно сохранить изменения лексемы %s по причине %s',
25
+ :create_ok => 'Лексема создана успешно',
26
+ :update_ok => 'Лексема обновлена успешно',
27
+ :added => 'Переменная \'%s\' добавлена',
28
+ }
29
+
30
+ def self.simply(hash, vars)
31
+ hash.keys.each do |key|
32
+ vars[$1] = hash.delete(key) if key =~ /(.*)=$/
33
+ end
34
+
35
+ hash.keys.each do |key|
36
+ value = hash[key]
37
+ if key =~ /^%(.*)/
38
+ var = vars[$1].clone
39
+ if var.class == Hash
40
+ self.simply(var, vars)
41
+ hash.replace( hash.merge(var) )
42
+ elsif var.class == String
43
+ hash[var] = nil
44
+ else
45
+ raise "Unsupported variable #{$1} value class #{var.class}"
46
+ end
47
+ hash.delete(key)
48
+ next
49
+ end
50
+
51
+ case value.class.to_s.to_sym
52
+ when :String
53
+ hash[key] = vars[$1].clone if value =~ /^%(.*)/
54
+ when :Hash
55
+ self.simply(value, vars)
56
+ end
57
+ end
58
+ end
59
+
60
+ def rule
61
+ ### dbp21 "$$$ Строка '#{invalue}' == '#{tinvalue}'"
62
+ # parse conditiones
63
+ tvalue = ''
64
+ ss = StringScanner.new(tinvalue)
65
+
66
+ while ss.scan_until(/\[(.*)\]/)
67
+ if ss[1] =~ /(.*)=(.*)/
68
+ ckey = $1
69
+ cvalue = $2
70
+ tvalue += ss.pre_match if begin
71
+ @levels[-2].class == Hash and @levels[-2].key?(ckey) and match(@levels[-2][ckey], cvalue)
72
+ rescue
73
+ false
74
+ end
75
+
76
+ ### dbp22 "$$$ Добавок в правило: #{tvalue}"
77
+ end
78
+ end
79
+
80
+ tvalue += ss.rest
81
+ ### dbp12 "$$$ Новое правило #{tvalue}"
82
+
83
+ end
84
+
85
+ def expand__(invalue, tinvalue)
86
+ @levels << invalue
87
+ res = case invalue.class.to_s
88
+ when 'Hash'
89
+ unless tinvalue.class == Hash
90
+ @levels.pop
91
+ raise "#{@levels.size}"
92
+ ### raise "Словарь не допустим на уровне #{@levels.size}"
93
+ end
94
+
95
+ tinvalue.each_pair do |tkey, tvalue|
96
+ if tkey =~ /^(.*)=$/ and not @vars.keys.include? $1
97
+ ### dbp22 "### Переменная '#{$1}' добавлена"
98
+ @vars[$1] = tvalue
99
+ tinvalue.delete(tkey)
100
+ end
101
+ end
102
+
103
+ tinvalue.each_pair do |tkey, tvalue|
104
+ if tkey =~ /^%(.*)$/
105
+ raise "#{$1}" unless @vars.keys.include? $1
106
+ ### raise "Переменная #{$1} не определена" unless @vars.keys.include? $1
107
+ tinvalue.delete(tkey)
108
+ @vars[$1].each_pair do |k,v| tinvalue[k] = v; end
109
+ end
110
+ end
111
+
112
+ when 'Array'
113
+ when 'String'
114
+ if tinvalue == ''
115
+ @levels.pop
116
+ ### raise "Значение строки шаблона отсутствует"
117
+ end
118
+
119
+ else
120
+ @levels.pop
121
+ ### raise "Неизвестный класс #{value.class}"
122
+ end
123
+
124
+ @levels.pop
125
+ true
126
+ end
127
+
128
+ def match(invalue, tinvalue)
129
+ @levels << invalue
130
+ res = case invalue.class.to_s
131
+ when 'Hash'
132
+ unless tinvalue.class == Hash
133
+ @levels.pop
134
+ raise "1 #{@levels.size}"
135
+ ### raise "Словарь не допустим на уровне #{@levels.size}"
136
+ end
137
+
138
+ tinvalue.each_pair do |tkey, tvalue|
139
+ if tkey =~ /^(.*)=$/ and not @vars.keys.include? $1
140
+ ### dbp22 "### Переменная '#{$1}' добавлена"
141
+ @vars[$1] = tvalue
142
+ tinvalue.delete(tkey)
143
+ end
144
+ end
145
+
146
+ tinvalue.each_pair do |tkey, tvalue|
147
+ if tkey =~ /^%(.*)$/
148
+ raise "#{$1}" unless @vars.keys.include? $1
149
+ ### raise "Переменная #{$1} не определена" unless @vars.keys.include? $1
150
+ tinvalue.delete(tkey)
151
+ @vars[$1].each_pair do |k,v| tinvalue[k] = v; end
152
+ end
153
+ end
154
+
155
+ invalue.each_pair do |key, value|
156
+ err = []
157
+ errup = tinvalue.each_pair do |tkey, tvalue|
158
+ begin
159
+ break false if match(key, tkey) and match(value, tvalue)
160
+ rescue
161
+ err << $!
162
+ break true
163
+ end
164
+ end
165
+ if errup
166
+ @levels.pop
167
+ key += ": #{value}" if value.class == String
168
+ ### raise "Пара с ключём '#{key}' не удовлетворяет шаблонной на уровне #{@levels.size}\n <= #{err.join(',')}\t"
169
+ end
170
+ end
171
+ true
172
+ when 'Array'
173
+ invalue.each do |value|
174
+ err = []
175
+ errup = tinvalue.each do |tvalue|
176
+ begin
177
+ break false if match(value, tvalue)
178
+ rescue
179
+ err << $!
180
+ break true
181
+ end
182
+ end
183
+ if errup
184
+ @levels.pop
185
+ ### val = " со значением #{value}" if value.class == String
186
+ ### raise "Массив#{val} не удовлетворяет шаблонному на уровне #{@levels.size}\n <= #{err.join(',')}"
187
+ end
188
+ end
189
+ true
190
+ when 'String'
191
+ if tinvalue == ''
192
+ @levels.pop
193
+ raise "2"
194
+ ### raise "Значение строки шаблона отсутствует"
195
+ end
196
+ if invalue == ''
197
+ @levels.pop
198
+ raise "3"
199
+ ### raise "Входное значение сроки отсутствует"
200
+ end
201
+
202
+ ### dbp22 "$$$ Строка '#{invalue}' == '#{tinvalue}'"
203
+ # parse conditiones
204
+ tvalue = ''
205
+ ss = StringScanner.new(tinvalue)
206
+
207
+ while ss.scan_until(/\[(.*)\]/)
208
+ if ss[1] =~ /(.*)=(.*)/
209
+ ckey = $1
210
+ cvalue = $2
211
+ tvalue += ss.pre_match if begin
212
+ @levels[-2].class == Hash and @levels[-2].key?(ckey) and match(@levels[-2][ckey], cvalue)
213
+ rescue
214
+ false
215
+ end
216
+
217
+ ### dbp22 "$$$ Добавок в правило: #{tvalue}"
218
+ end
219
+ end
220
+
221
+ tvalue += ss.rest
222
+ ### dbp22 "$$$ Новое правило #{tvalue}"
223
+
224
+ if tvalue != ''
225
+
226
+ # match
227
+ (tvalue = /#{$1}/) if tvalue =~ /^\/([^\/]+)/
228
+
229
+ ### dbp22 "$$$ Правило '#{invalue}' =~ '#{tvalue}'"
230
+
231
+ res = (invalue =~ tvalue)
232
+ ### dbp22 "$$$ Попало? #{not not res}"
233
+
234
+ res
235
+ else
236
+ false
237
+ end
238
+ else
239
+ @levels.pop
240
+ raise "333 #{value.class}"
241
+ ### raise "Неизвестный класс #{value.class}"
242
+ end
243
+
244
+ @levels.pop
245
+ res
246
+ end
247
+ end
248
+ end
249
+
@@ -0,0 +1,5 @@
1
+ module YAML
2
+ class Template
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,50 @@
1
+
2
+ require File.expand_path('../../lib/ytemplate', __FILE__)
3
+
4
+ RSpec.configure do |c|
5
+ c.mock_with :rspec
6
+ end
7
+
8
+ SampleTemplate = <<C
9
+ ---
10
+ @instance=:
11
+ ikey: ivalue
12
+ local=:
13
+ lkey: lvalue
14
+ key1: value
15
+ key2: %local
16
+ key3:
17
+ %local:
18
+ key4: value
19
+ C
20
+
21
+ SampleFile = <<C
22
+ ---
23
+ key1: value
24
+ key2:
25
+ lkey: lvalue
26
+ key3:
27
+ lkey: lvalue
28
+ key4: value
29
+ C
30
+
31
+ SampleResultTemplate = <<C
32
+ ---
33
+ key1: value
34
+ key2:
35
+ lkey: lvalue
36
+ key3:
37
+ lkey: lvalue
38
+ key4: value
39
+ C
40
+
41
+ SampleResultDocument = <<C
42
+ ---
43
+ key1: +value
44
+ key2:
45
+ lkey: +lvalue
46
+ key3:
47
+ lkey: +lvalue
48
+ key4: +value
49
+ C
50
+
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.expand_path('../spec_helper', __FILE__)
4
+
5
+ describe 'Eventer' do
6
+ it "Expand of a template" do
7
+ tmpl = YAML::Template.new SampleTemplate
8
+
9
+ o = tmpl.deploy
10
+
11
+ raise "Resulted YAML-document is wrong" if o != YAML.load( SampleResultTemplate )
12
+ end
13
+
14
+ it "Expand of a document" do
15
+ tmpl = YAML::Template.new SampleTemplate
16
+
17
+ o = tmpl.deploy_to( YAML.load( SampleFile ), :use_template => true)
18
+
19
+ raise "Resulted YAML-document is wrong" if o != YAML.load( SampleResultDocument )
20
+ end
21
+
22
+ it "Document match to the template" do
23
+ tmpl = YAML::Template.new SampleTemplate
24
+
25
+ o = tmpl.match(YAML.load( SampleFile) )
26
+
27
+ raise "Resulted YAML-document is wrong" unless o.empty?
28
+ end
29
+
30
+ it "Erroneous document match to the template" do
31
+ tmpl = YAML::Template.new SampleTemplate
32
+
33
+ file = YAML.load( SampleFile )
34
+ file['key1'] = 'novalue'
35
+
36
+ o = tmpl.match( file )
37
+
38
+ raise "Resulted YAML-document is wrong" if o.empty?
39
+ end
40
+ end
41
+
42
+
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ytemplate/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ytemplate"
7
+ s.version = YAML::Template::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = [ 'Малъ Скрылёвъ (Malo Skrylevo)' ]
10
+ s.email = [ '3aHyga@gmail.com' ]
11
+ s.homepage = 'https://github.com/3aHyga/ytemplate'
12
+ s.summary = 'YAML template deployment extension'
13
+ s.description = 'ytemplate is YAML extension allowing deployment of YAML templates'
14
+
15
+ s.rubyforge_project = "ytemplate"
16
+
17
+ s.required_rubygems_version = '>= 1.6.0'
18
+
19
+ s.add_dependency 'rdoba', ">= 0.1"
20
+
21
+ s.add_development_dependency("bundler", ">= 1.0.0")
22
+ s.add_development_dependency("rspec", "~> 2.0.1")
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
26
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
27
+ s.require_paths = ["lib"]
28
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ytemplate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Малъ Скрылёвъ (Malo Skrylevo)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-05-18 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rdoba
16
+ requirement: &69624460 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *69624460
25
+ - !ruby/object:Gem::Dependency
26
+ name: bundler
27
+ requirement: &69624230 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *69624230
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &69624000 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.0.1
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *69624000
47
+ description: ytemplate is YAML extension allowing deployment of YAML templates
48
+ email:
49
+ - 3aHyga@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .document
55
+ - .gitignore
56
+ - .rspec
57
+ - CHANGES.md
58
+ - Gemfile
59
+ - LICENSE
60
+ - README.md
61
+ - Rakefile
62
+ - lib/ytemplate.rb
63
+ - lib/ytemplate/misc.rb
64
+ - lib/ytemplate/version.rb
65
+ - spec/spec_helper.rb
66
+ - spec/ytemplate_spec.rb
67
+ - ytemplate.gemspec
68
+ homepage: https://github.com/3aHyga/ytemplate
69
+ licenses: []
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.6.0
86
+ requirements: []
87
+ rubyforge_project: ytemplate
88
+ rubygems_version: 1.7.2
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: YAML template deployment extension
92
+ test_files:
93
+ - spec/spec_helper.rb
94
+ - spec/ytemplate_spec.rb