sycl 1.2 → 1.3
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/lib/sycl.rb +270 -77
- metadata +4 -4
data/lib/sycl.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
-
# sycl.rb - Simple YAML Configuration Library
|
2
|
-
#
|
1
|
+
# = sycl.rb - Simple YAML Configuration Library
|
2
|
+
#
|
3
|
+
# For more details, visit the
|
4
|
+
# {Sycl GitHub page}[https://github.com/groupon/sycl/"target="_parent].
|
5
|
+
#
|
6
|
+
# == License
|
3
7
|
#
|
4
8
|
# Copyright (c) 2012, Groupon, Inc.
|
5
9
|
# All rights reserved.
|
@@ -33,20 +37,44 @@
|
|
33
37
|
|
34
38
|
require 'yaml'
|
35
39
|
|
40
|
+
# = sycl.rb - Simple YAML Configuration Library
|
41
|
+
#
|
42
|
+
# Sycl is a gem that makes using YAML[http://yaml.org/] for
|
43
|
+
# configuration files convenient and easy. Hashes and arrays made from
|
44
|
+
# parsing YAML via Sycl get helper methods that provide simple and natural
|
45
|
+
# syntax for querying and setting values. YAML output through Sycl is
|
46
|
+
# sorted, so configuration file versions can be compared consistently, and
|
47
|
+
# Sycl has hooks to add output styles, so your configuration files stay
|
48
|
+
# easy for humans to read and edit, even after being parsed and
|
49
|
+
# re-emitted.
|
50
|
+
#
|
51
|
+
# For more details, visit the
|
52
|
+
# {Sycl GitHub page}[https://github.com/groupon/sycl/"target="_parent].
|
53
|
+
|
36
54
|
module Sycl
|
37
55
|
|
38
|
-
# Sycl::load(yaml)
|
39
|
-
#
|
40
|
-
#
|
56
|
+
# Sycl::load(yaml) is the Sycl counterpart to YAML::load(yaml). It
|
57
|
+
# accepts YAML text, and returns a Sycl::Hash or Sycl::Array object
|
58
|
+
# representing the parsed YAML.
|
41
59
|
|
42
60
|
def self.load(yaml)
|
43
61
|
from_object YAML::load(yaml)
|
44
62
|
end
|
45
63
|
|
64
|
+
# Sycl::load(filename) is the Sycl counterpart to
|
65
|
+
# YAML::load_file(filename). It accepts a filename, and returns a
|
66
|
+
# Sycl::Hash or Sycl::Array object representing the parsed YAML from
|
67
|
+
# that file.
|
68
|
+
|
46
69
|
def self.load_file(filename)
|
47
70
|
from_object YAML::load_file(filename)
|
48
71
|
end
|
49
72
|
|
73
|
+
# Sycl::dump(object) is the Sycl counterpart to YAML::dump(object). It
|
74
|
+
# takes a Sycl::Hash or a Sycl::Array, and renders it as YAML. Sycl
|
75
|
+
# YAML output is always sorted in canonical order, so you can parse
|
76
|
+
# and re-emit data in a reliable way.
|
77
|
+
|
50
78
|
def self.dump(object)
|
51
79
|
if (object.is_a?(::Hash) && !object.is_a?(Sycl::Hash)) ||
|
52
80
|
(object.is_a?(::Array) && !object.is_a?(Sycl::Array))
|
@@ -70,32 +98,58 @@ module Sycl
|
|
70
98
|
end
|
71
99
|
|
72
100
|
|
73
|
-
# A Sycl::Array is like an Array, but creating one from an array
|
74
|
-
# any child Array or Hash objects into Sycl::Array or
|
101
|
+
# A Sycl::Array is like an Array, but creating one from an array
|
102
|
+
# blesses any child Array or Hash objects into Sycl::Array or
|
103
|
+
# Sycl::Hash objects. All the normal Array methods are supported,
|
104
|
+
# and automatically promote any inputs into Sycl equivalents. The
|
105
|
+
# following example illustrates this:
|
106
|
+
#
|
107
|
+
# h = { 'a' => { 'b' => 'Hello, world!' } }
|
108
|
+
# a = Sycl::Array.new
|
109
|
+
# a << h
|
110
|
+
#
|
111
|
+
# puts a.first.a.b # outputs 'Hello, world!'
|
112
|
+
#
|
113
|
+
# A Sycl::Array supports YAML preprocessing and postprocessing, and
|
114
|
+
# having individual nodes marked as being rendered in inline style.
|
115
|
+
# YAML output is always sorted, unless individual nodes are marked
|
116
|
+
# as being rendered unsorted.
|
117
|
+
#
|
118
|
+
# a = Sycl::Array.from_array %w{bravo delta charlie alpha}
|
119
|
+
# a.render_inline!
|
120
|
+
# a.yaml_preprocessor { |x| x.each { |e| e.capitalize! } }
|
121
|
+
# a.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
75
122
|
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
# output is also always sorted.
|
123
|
+
# puts a.first # outputs 'bravo'
|
124
|
+
# puts a.to_yaml # outputs '[Alpha, Bravo, Charlie, Delta]'
|
79
125
|
|
80
126
|
class Array < ::Array
|
81
|
-
def initialize(*args)
|
127
|
+
def initialize(*args) # :nodoc:
|
82
128
|
@yaml_preprocessor = nil
|
83
129
|
@yaml_postprocessor = nil
|
84
130
|
@yaml_style = nil
|
131
|
+
@render_sorted = true
|
85
132
|
super
|
86
133
|
end
|
87
134
|
|
88
|
-
def self.[](*args)
|
135
|
+
def self.[](*args) # :nodoc:
|
89
136
|
Sycl::Array.from_array super
|
90
137
|
end
|
91
138
|
|
92
|
-
|
93
|
-
|
139
|
+
# Like Sycl::load_file(), a shortcut method to create a Sycl::Array
|
140
|
+
# from loading and parsing YAML from a file.
|
141
|
+
|
142
|
+
def self.load_file(filename)
|
143
|
+
Sycl::Array.from_array YAML::load_file filename
|
94
144
|
end
|
95
145
|
|
96
|
-
|
146
|
+
# Create a Sycl::Array from a normal Array, or, really, any object
|
147
|
+
# that supports Enumerable#each(). Every child Array or Hash gets
|
148
|
+
# promoted to a Sycl::Array or Sycl::Hash.
|
149
|
+
|
150
|
+
def self.from_array(array) # :nodoc:
|
97
151
|
retval = Sycl::Array.new
|
98
|
-
|
152
|
+
array.each { |e| retval << Sycl::from_object(e) }
|
99
153
|
retval
|
100
154
|
end
|
101
155
|
|
@@ -104,7 +158,7 @@ module Sycl
|
|
104
158
|
# to their Sycl equivalents. This lets dot notation, styled YAML,
|
105
159
|
# and other Sycl goodies continue.
|
106
160
|
|
107
|
-
def []=(*args)
|
161
|
+
def []=(*args) # :nodoc:
|
108
162
|
raise ArgumentError => 'wrong number of arguments' unless args.size > 1
|
109
163
|
unless args[-1].is_a?(Sycl::Hash) || args[-1].is_a?(Sycl::Array)
|
110
164
|
args[-1] = Sycl::from_object(args[-1])
|
@@ -112,24 +166,27 @@ module Sycl
|
|
112
166
|
super
|
113
167
|
end
|
114
168
|
|
115
|
-
def <<(e)
|
169
|
+
def <<(e) # :nodoc:
|
116
170
|
unless e.is_a?(Sycl::Hash) || e.is_a?(Sycl::Array)
|
117
171
|
e = Sycl::from_object(e)
|
118
172
|
end
|
119
173
|
super
|
120
174
|
end
|
121
175
|
|
122
|
-
def collect!(&block)
|
176
|
+
def collect!(&block) # :nodoc:
|
177
|
+
super { |o| Sycl::from_object(block.call o) }
|
178
|
+
end
|
179
|
+
|
180
|
+
def map!(&block) # :nodoc:
|
123
181
|
super { |o| Sycl::from_object(block.call o) }
|
124
182
|
end
|
125
|
-
alias_method :map!, :collect!
|
126
183
|
|
127
|
-
def concat(a)
|
184
|
+
def concat(a) # :nodoc:
|
128
185
|
a = Sycl::Array.from_array(a) unless a.is_a?(Sycl::Array)
|
129
186
|
super
|
130
187
|
end
|
131
188
|
|
132
|
-
def fill(*args, &block)
|
189
|
+
def fill(*args, &block) # :nodoc:
|
133
190
|
raise ArgumentError => 'wrong number of arguments' if args.empty?
|
134
191
|
if block_given?
|
135
192
|
super { |idx| Sycl::from_object(block.call idx) }
|
@@ -141,7 +198,7 @@ module Sycl
|
|
141
198
|
end
|
142
199
|
end
|
143
200
|
|
144
|
-
def insert(i, *args)
|
201
|
+
def insert(i, *args) # :nodoc:
|
145
202
|
raise ArgumentError => 'wrong number of arguments' if args.empty?
|
146
203
|
args.collect! do |o|
|
147
204
|
unless o.is_a?(Sycl::Hash) || o.is_a?(Sycl::Array)
|
@@ -151,7 +208,7 @@ module Sycl
|
|
151
208
|
super
|
152
209
|
end
|
153
210
|
|
154
|
-
def push(*args)
|
211
|
+
def push(*args) # :nodoc:
|
155
212
|
raise ArgumentError => 'wrong number of arguments' if args.empty?
|
156
213
|
args.collect! do |o|
|
157
214
|
unless o.is_a?(Sycl::Hash) || o.is_a?(Sycl::Array)
|
@@ -161,12 +218,12 @@ module Sycl
|
|
161
218
|
super
|
162
219
|
end
|
163
220
|
|
164
|
-
def replace(a)
|
221
|
+
def replace(a) # :nodoc:
|
165
222
|
a = Sycl::Array.from_array(a) unless a.is_a?(Sycl::Array)
|
166
223
|
super
|
167
224
|
end
|
168
225
|
|
169
|
-
def unshift(*args)
|
226
|
+
def unshift(*args) # :nodoc:
|
170
227
|
raise ArgumentError => 'wrong number of arguments' if args.empty?
|
171
228
|
args.collect! do |o|
|
172
229
|
unless o.is_a?(Sycl::Hash) || o.is_a?(Sycl::Array)
|
@@ -177,13 +234,35 @@ module Sycl
|
|
177
234
|
end
|
178
235
|
|
179
236
|
|
180
|
-
# Make this array,
|
237
|
+
# Make this array, and its children, rendered in inline/flow style.
|
181
238
|
# The default is to render arrays in block (multi-line) style.
|
239
|
+
#
|
240
|
+
# Example:
|
241
|
+
#
|
242
|
+
# a = Sycl::Array::from_array %w{one two}
|
243
|
+
# a.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
244
|
+
#
|
245
|
+
# puts a.to_yaml # output: "- one\n- two"
|
246
|
+
# a.render_inline!
|
247
|
+
# puts a.to_yaml # output: '[one, two]'
|
182
248
|
|
183
249
|
def render_inline!
|
184
250
|
@yaml_style = :inline
|
185
251
|
end
|
186
252
|
|
253
|
+
# Keep rendering this array in block (multi-line) style, but, make
|
254
|
+
# this array's children rendered in inline/flow style.
|
255
|
+
#
|
256
|
+
# Example:
|
257
|
+
#
|
258
|
+
# a = Sycl::Array::from_array ['one', {'two' => ['three']}]
|
259
|
+
# a.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
260
|
+
#
|
261
|
+
# a.render_values_inline!
|
262
|
+
# puts a.to_yaml # output: "- one\n- two: [three]"
|
263
|
+
# a.render_inline!
|
264
|
+
# puts a.to_yaml # output: '[one, {two: [three]}]'
|
265
|
+
|
187
266
|
def render_values_inline!
|
188
267
|
self.each do |e|
|
189
268
|
e.render_inline! if e.respond_to?(:render_inline!)
|
@@ -191,21 +270,52 @@ module Sycl
|
|
191
270
|
end
|
192
271
|
|
193
272
|
|
194
|
-
#
|
273
|
+
# Do not sort this array when it is rendered as YAML. Usually we want
|
274
|
+
# elements sorted so that diffs are human-readable, however, there are
|
275
|
+
# certain cases where array ordering is significant (for example, a
|
276
|
+
# sorted list of queues).
|
277
|
+
|
278
|
+
def render_unsorted!
|
279
|
+
@render_sorted = false
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
# Set a preprocessor hook which runs before each time YAML is
|
284
|
+
# dumped, for example, via to_yaml() or Sycl::dump(). The hook is a
|
285
|
+
# block that gets the object itself as an argument. The hook can
|
286
|
+
# then set render_inline!() or similar style arguments, prune nil or
|
287
|
+
# empty leaf values from hashes, or do whatever other styling needs
|
288
|
+
# to be done before a Sycl object is rendered as YAML.
|
195
289
|
|
196
290
|
def yaml_preprocessor(&block)
|
197
291
|
@yaml_preprocessor = block if block_given?
|
198
292
|
end
|
199
293
|
|
294
|
+
# Set a postprocessor hook which runs after YML is dumped, for
|
295
|
+
# example, via to_yaml() or Sycl::dump(). The hook is a block that
|
296
|
+
# gets the YAML text string as an argument, and returns a new,
|
297
|
+
# possibly different, YAML text string.
|
298
|
+
#
|
299
|
+
# A common example use case is to suppress the initial document
|
300
|
+
# separator, which is just visual noise when humans are viewing or
|
301
|
+
# editing a single YAML file:
|
302
|
+
#
|
303
|
+
# a.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
304
|
+
#
|
305
|
+
# Your conventions might also prohibit trailing whitespace, which at
|
306
|
+
# least the Syck library will tack on the end of YAML hash keys:
|
307
|
+
#
|
308
|
+
# a.yaml_postprocessor { |yaml| yaml.gsub(/:\s+$/, '') }
|
309
|
+
|
200
310
|
def yaml_postprocessor(&block)
|
201
311
|
@yaml_postprocessor = block if block_given?
|
202
312
|
end
|
203
313
|
|
204
|
-
def yaml_preprocess!
|
314
|
+
def yaml_preprocess! # :nodoc:
|
205
315
|
@yaml_preprocessor.call(self) if @yaml_preprocessor
|
206
316
|
end
|
207
317
|
|
208
|
-
def yaml_postprocess(yaml)
|
318
|
+
def yaml_postprocess(yaml) # :nodoc:
|
209
319
|
@yaml_postprocessor ? @yaml_postprocessor.call(yaml) : yaml
|
210
320
|
end
|
211
321
|
|
@@ -214,50 +324,68 @@ module Sycl
|
|
214
324
|
# if to_yaml is over-ridden on a non-native type. So, we fake out
|
215
325
|
# Psych and pretend Sycl::Array is a native type.
|
216
326
|
|
217
|
-
class MockNativeType
|
327
|
+
class MockNativeType # :nodoc:
|
218
328
|
def source_location
|
219
329
|
['psych/core_ext.rb']
|
220
330
|
end
|
221
331
|
end
|
222
332
|
|
223
|
-
def method(sym)
|
333
|
+
def method(sym) # :nodoc:
|
224
334
|
sym == :to_yaml ? MockNativeType.new : super
|
225
335
|
end
|
226
336
|
|
227
337
|
|
228
|
-
# YAML rendering
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
coder.represent_seq nil, sort
|
237
|
-
end
|
238
|
-
end
|
338
|
+
# Render this object as YAML. Before rendering, run the object
|
339
|
+
# through any yaml_preprocessor() code block. After rendering,
|
340
|
+
# filter the YAML text through any yaml_postprocessor() code block.
|
341
|
+
#
|
342
|
+
# Nodes marked with render_inline!() or render_values_inline!()
|
343
|
+
# will be output in flow/inline style, all hashes and arrays will
|
344
|
+
# be sorted, and we set a long line width to more or less support
|
345
|
+
# line wrap under the Psych library.
|
239
346
|
|
240
347
|
def to_yaml(opts = {})
|
241
348
|
yaml_preprocess!
|
242
349
|
if defined?(YAML::ENGINE) && YAML::ENGINE.yamler == 'psych'
|
243
350
|
opts ||= {}
|
244
|
-
opts[:line_width] ||= 999999
|
351
|
+
opts[:line_width] ||= 999999 # Psych doesn't let you disable line wrap
|
245
352
|
yaml = super
|
246
353
|
else
|
247
354
|
yaml = YAML::quick_emit(self, opts) do |out|
|
248
|
-
|
249
|
-
|
355
|
+
if @render_sorted
|
356
|
+
out.seq(nil, @yaml_style || to_yaml_style) do |seq|
|
357
|
+
sort.each { |e| seq.add(e) }
|
358
|
+
end
|
359
|
+
else
|
360
|
+
out.seq(nil, @yaml_style || to_yaml_style) do |seq|
|
361
|
+
each { |e| seq.add(e) }
|
362
|
+
end
|
250
363
|
end
|
251
364
|
end
|
252
365
|
end
|
253
366
|
yaml_postprocess yaml
|
254
367
|
end
|
255
368
|
|
369
|
+
if defined?(YAML::ENGINE) && YAML::ENGINE.yamler == 'psych'
|
370
|
+
def encode_with(coder) # :nodoc:
|
371
|
+
coder.style = Psych::Nodes::Sequence::FLOW if @yaml_style == :inline
|
372
|
+
coder.represent_seq nil, sort
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
256
376
|
end
|
257
377
|
|
258
378
|
|
259
379
|
# A Sycl::Hash is like a Hash, but creating one from an hash blesses
|
260
|
-
# any child Array or Hash objects into Sycl::Array or Sycl::Hash
|
380
|
+
# any child Array or Hash objects into Sycl::Array or Sycl::Hash
|
381
|
+
# objects. All the normal Hash methods are supported, and
|
382
|
+
# automatically promote any inputs into Sycl equivalents. The
|
383
|
+
# following example illustrates this:
|
384
|
+
#
|
385
|
+
# h = Sycl::Hash.new
|
386
|
+
# h['a'] = { 'b' => { 'c' => 'Hello, world!' } }
|
387
|
+
#
|
388
|
+
# puts h.a.b.c # outputs 'Hello, world!'
|
261
389
|
#
|
262
390
|
# Hash contents can be accessed via "dot notation" (h.foo.bar means
|
263
391
|
# the same as h['foo']['bar']). However, h.foo.bar dies if h['foo']
|
@@ -266,27 +394,42 @@ module Sycl
|
|
266
394
|
# There is also a convenient deep_merge() that is like Hash#merge(),
|
267
395
|
# but also descends into and merges child nodes of the new hash.
|
268
396
|
#
|
269
|
-
# Sycl::
|
270
|
-
# individual nodes marked as being rendered in inline style.
|
271
|
-
# output is also always sorted by key.
|
397
|
+
# A Sycl::Hash supports YAML preprocessing and postprocessing, and
|
398
|
+
# having individual nodes marked as being rendered in inline style.
|
399
|
+
# YAML output is also always sorted by key.
|
400
|
+
#
|
401
|
+
# h = Sycl::Hash.from_hash({'b' => 'bravo', 'a' => 'alpha'})
|
402
|
+
# h.render_inline!
|
403
|
+
# h.yaml_preprocessor { |x| x.values.each { |e| e.capitalize! } }
|
404
|
+
# h.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
405
|
+
#
|
406
|
+
# puts h['a'] # outputs 'alpha'
|
407
|
+
# puts h.keys.first # outputs 'a' or 'b' depending on Hash order
|
408
|
+
# puts h.to_yaml # outputs '{a: Alpha, b: Bravo}'
|
272
409
|
|
273
410
|
class Hash < ::Hash
|
274
411
|
|
275
|
-
def initialize(*args)
|
412
|
+
def initialize(*args) # :nodoc:
|
276
413
|
@yaml_preprocessor = nil
|
277
414
|
@yaml_postprocessor = nil
|
278
415
|
@yaml_style = nil
|
279
416
|
super
|
280
417
|
end
|
281
418
|
|
282
|
-
def self.[](*args)
|
419
|
+
def self.[](*args) # :nodoc:
|
283
420
|
Sycl::Hash.from_hash super
|
284
421
|
end
|
285
422
|
|
423
|
+
# Like Sycl::load_file(), a shortcut method to create a Sycl::Hash
|
424
|
+
# from loading and parsing YAML from a file.
|
425
|
+
|
286
426
|
def self.load_file(f)
|
287
427
|
Sycl::Hash.from_hash YAML::load_file f
|
288
428
|
end
|
289
429
|
|
430
|
+
# Create a Sycl::Array from a normal Hash or Hash-like object. Every
|
431
|
+
# child Array or Hash gets promoted to a Sycl::Array or Sycl::Hash.
|
432
|
+
|
290
433
|
def self.from_hash(h)
|
291
434
|
retval = Sycl::Hash.new
|
292
435
|
h.each { |k, v| retval[k] = Sycl::from_object(v) }
|
@@ -298,19 +441,29 @@ module Sycl
|
|
298
441
|
# to their Sycl equivalents. This lets dot notation, styled YAML,
|
299
442
|
# and other Sycl goodies continue.
|
300
443
|
|
301
|
-
def []=(k, v)
|
444
|
+
def []=(k, v) # :nodoc:
|
302
445
|
unless v.is_a?(Sycl::Hash) || v.is_a?(Sycl::Array)
|
303
446
|
v = Sycl::from_object(v)
|
304
447
|
end
|
305
448
|
super
|
306
449
|
end
|
307
|
-
alias_method :store, :[]=
|
308
450
|
|
309
|
-
def
|
451
|
+
def store(k, v) # :nodoc:
|
452
|
+
unless v.is_a?(Sycl::Hash) || v.is_a?(Sycl::Array)
|
453
|
+
v = Sycl::from_object(v)
|
454
|
+
end
|
455
|
+
super
|
456
|
+
end
|
457
|
+
|
458
|
+
def merge!(h) # :nodoc:
|
459
|
+
h = Sycl::Hash.from_hash(h) unless h.is_a?(Sycl::Hash)
|
460
|
+
super
|
461
|
+
end
|
462
|
+
|
463
|
+
def update(h) # :nodoc:
|
310
464
|
h = Sycl::Hash.from_hash(h) unless h.is_a?(Sycl::Hash)
|
311
465
|
super
|
312
466
|
end
|
313
|
-
alias_method :update, :merge!
|
314
467
|
|
315
468
|
|
316
469
|
# Allow method call syntax: h.foo.bar.baz == h['foo']['bar']['baz'].
|
@@ -394,22 +547,37 @@ module Sycl
|
|
394
547
|
|
395
548
|
include Comparable
|
396
549
|
|
397
|
-
def <=>(another)
|
550
|
+
def <=>(another) # :nodoc:
|
398
551
|
self.to_str <=> another.to_str
|
399
552
|
end
|
400
553
|
|
401
|
-
def to_str
|
554
|
+
def to_str # :nodoc:
|
402
555
|
self.keys.sort.first
|
403
556
|
end
|
404
557
|
|
405
558
|
|
406
|
-
# Make this hash,
|
407
|
-
# The default is to render
|
559
|
+
# Make this hash, and its children, rendered in inline/flow style.
|
560
|
+
# The default is to render arrays in block (multi-line) style.
|
408
561
|
|
409
562
|
def render_inline!
|
410
563
|
@yaml_style = :inline
|
411
564
|
end
|
412
565
|
|
566
|
+
# Keep rendering this hash in block (multi-line) style, but, make
|
567
|
+
# this array's children rendered in inline/flow style.
|
568
|
+
#
|
569
|
+
# Example:
|
570
|
+
#
|
571
|
+
# h = Sycl::Hash.new
|
572
|
+
# h['one'] = 'two'
|
573
|
+
# h['three'] = %w{four five}
|
574
|
+
# h.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
575
|
+
#
|
576
|
+
# h.render_values_inline!
|
577
|
+
# puts h.to_yaml # output: "one: two\nthree: [five four]"
|
578
|
+
# h.render_inline!
|
579
|
+
# puts h.to_yaml # output: '{one: two, three: [five four]}'
|
580
|
+
|
413
581
|
def render_values_inline!
|
414
582
|
self.values.each do |v|
|
415
583
|
v.render_inline! if v.respond_to?(:render_inline!)
|
@@ -417,21 +585,42 @@ module Sycl
|
|
417
585
|
end
|
418
586
|
|
419
587
|
|
420
|
-
#
|
588
|
+
# Set a preprocessor hook which runs before each time YAML is
|
589
|
+
# dumped, for example, via to_yaml() or Sycl::dump(). The hook is a
|
590
|
+
# block that gets the object itself as an argument. The hook can
|
591
|
+
# then set render_inline!() or similar style arguments, prune nil or
|
592
|
+
# empty leaf values from hashes, or do whatever other styling needs
|
593
|
+
# to be done before a Sycl object is rendered as YAML.
|
421
594
|
|
422
595
|
def yaml_preprocessor(&block)
|
423
596
|
@yaml_preprocessor = block if block_given?
|
424
597
|
end
|
425
598
|
|
599
|
+
# Set a postprocessor hook which runs after YML is dumped, for
|
600
|
+
# example, via to_yaml() or Sycl::dump(). The hook is a block that
|
601
|
+
# gets the YAML text string as an argument, and returns a new,
|
602
|
+
# possibly different, YAML text string.
|
603
|
+
#
|
604
|
+
# A common example use case is to suppress the initial document
|
605
|
+
# separator, which is just visual noise when humans are viewing or
|
606
|
+
# editing a single YAML file:
|
607
|
+
#
|
608
|
+
# a.yaml_postprocessor { |yaml| yaml.sub(/\A---\s+/, '') }
|
609
|
+
#
|
610
|
+
# Your conventions might also prohibit trailing whitespace, which at
|
611
|
+
# least the Syck library will tack on the end of YAML hash keys:
|
612
|
+
#
|
613
|
+
# a.yaml_postprocessor { |yaml| yaml.gsub(/:\s+$/, '') }
|
614
|
+
|
426
615
|
def yaml_postprocessor(&block)
|
427
616
|
@yaml_postprocessor = block if block_given?
|
428
617
|
end
|
429
618
|
|
430
|
-
def yaml_preprocess!
|
619
|
+
def yaml_preprocess! # :nodoc:
|
431
620
|
@yaml_preprocessor.call(self) if @yaml_preprocessor
|
432
621
|
end
|
433
622
|
|
434
|
-
def yaml_postprocess(yaml)
|
623
|
+
def yaml_postprocess(yaml) # :nodoc:
|
435
624
|
@yaml_postprocessor ? @yaml_postprocessor.call(yaml) : yaml
|
436
625
|
end
|
437
626
|
|
@@ -440,34 +629,31 @@ module Sycl
|
|
440
629
|
# if to_yaml is over-ridden on a non-native type. So, we fake out
|
441
630
|
# Psych and pretend Sycl::Hash is a native type.
|
442
631
|
|
443
|
-
class MockNativeType
|
632
|
+
class MockNativeType # :nodoc:
|
444
633
|
def source_location
|
445
634
|
['psych/core_ext.rb']
|
446
635
|
end
|
447
636
|
end
|
448
637
|
|
449
|
-
def method(sym)
|
638
|
+
def method(sym) # :nodoc:
|
450
639
|
sym == :to_yaml ? MockNativeType.new : super
|
451
640
|
end
|
452
641
|
|
453
642
|
|
454
|
-
# YAML rendering
|
455
|
-
#
|
456
|
-
#
|
457
|
-
#
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
coder.represent_map nil, sort
|
463
|
-
end
|
464
|
-
end
|
643
|
+
# Render this object as YAML. Before rendering, run the object
|
644
|
+
# through any yaml_preprocessor() code block. After rendering,
|
645
|
+
# filter the YAML text through any yaml_postprocessor() code block.
|
646
|
+
#
|
647
|
+
# Nodes marked with render_inline!() or render_values_inline!()
|
648
|
+
# will be output in flow/inline style, all hashes and arrays will
|
649
|
+
# be sorted, and we set a long line width to more or less support
|
650
|
+
# line wrap under the Psych library.
|
465
651
|
|
466
652
|
def to_yaml(opts = {})
|
467
653
|
yaml_preprocess!
|
468
654
|
if defined?(YAML::ENGINE) && YAML::ENGINE.yamler == 'psych'
|
469
655
|
opts ||= {}
|
470
|
-
opts[:line_width] ||= 999999
|
656
|
+
opts[:line_width] ||= 999999 # Psych doesn't let you disable line wrap
|
471
657
|
yaml = super
|
472
658
|
else
|
473
659
|
yaml = YAML::quick_emit(self, opts) do |out|
|
@@ -479,5 +665,12 @@ module Sycl
|
|
479
665
|
yaml_postprocess yaml
|
480
666
|
end
|
481
667
|
|
668
|
+
if defined?(YAML::ENGINE) && YAML::ENGINE.yamler == 'psych'
|
669
|
+
def encode_with(coder) # :nodoc:
|
670
|
+
coder.style = Psych::Nodes::Mapping::FLOW if @yaml_style == :inline
|
671
|
+
coder.represent_map nil, sort
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
482
675
|
end
|
483
676
|
end
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sycl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: "1.
|
8
|
+
- 3
|
9
|
+
version: "1.3"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Andrew Ho
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-
|
17
|
+
date: 2012-10-15 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|