ytemplate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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