aws-cfn-dsl 0.6.0 → 0.7.0
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.
- checksums.yaml +5 -13
- data/Gemfile +0 -2
- data/aws-cfn-dsl.gemspec +3 -2
- data/lib/aws/cfn/dsl/base.rb +55 -443
- data/lib/aws/cfn/dsl/main.rb +2 -17
- data/lib/aws/cfn/dsl/mixins/dsl.rb +52 -0
- data/lib/aws/cfn/dsl/mixins/maintainer.rb +42 -0
- data/lib/aws/cfn/dsl/mixins/options.rb +126 -0
- data/lib/aws/cfn/dsl/mixins/output.rb +53 -0
- data/lib/aws/cfn/dsl/mixins/prettyprint.rb +296 -0
- data/lib/aws/cfn/dsl/mixins/simplify.rb +59 -0
- data/lib/aws/cfn/dsl/template.rb +0 -164
- data/lib/aws/cfn/dsl/version.rb +1 -1
- metadata +51 -25
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
NTdkNGVhNWQ5NzRhMTVmNjA3ZTA4Y2QzOGZhOWM3N2IxYTc3ODk1OA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b9ba230058f9ce82bf26b89f880d91fe995fe42f
|
4
|
+
data.tar.gz: f2e68182943d453d15ff62e516fe6afdc74a3f7b
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZTc2ZTBhZjc4MTU3OGY3ODlkYzMzOWMzYmMwM2U1Yjc1MGZlZmVhYTVmN2Vm
|
11
|
-
MTMxYTI3MWM3MDMzYWVkYjllNTRkZWEyOGQ4MjRjMGQ5MWEzYTk=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NzFjZjgyNmJlNzcxOTMwNzUwZTk4NmMyZTg3NDRiM2JiNjQ3ZmQzNDM3MmEz
|
14
|
-
NGJmNWYyZWI0NDhiYjBmZGJiOGY5NDMyMTE0YTNlNmQ1MjNlODZmMTU0YTBm
|
15
|
-
NWMxMDMwYTQ3MmQ5NGY0ZmViOGUwZDZjODdhMTJiMDcwMzYwYTY=
|
6
|
+
metadata.gz: 3bd00bf073fe8842760c5727baf1828660df3699ca5c4be19bdf23ca9715ab74de6cd2b3e9031bf26a08e5d9fb8b7198f3e41c1b6acf1a8136b766b0c8b79768
|
7
|
+
data.tar.gz: 0e0e5bd09a2bfdc3218a91a3e2a9929882581837b92fad3861e8f333abc336a642169aa80c614916b760ecab6598095d82c6657574f5548f9ec391dc0353640f
|
data/Gemfile
CHANGED
@@ -12,8 +12,6 @@ gem 'aws-cfn-compiler', :path => '../aws-cfn-compiler', :group => :development
|
|
12
12
|
gem 'aws-cfn-yats', :path => '../aws-cfn-yats', :group => :development
|
13
13
|
gem 'aws-cfn-stacker', :path => '../aws-cfn-stacker', :group => :development
|
14
14
|
|
15
|
-
gem 'slop', :group => :development
|
16
|
-
|
17
15
|
gem 'json_pure', :group => :development
|
18
16
|
gem 'bundler', '~> 1.5', :group => :development
|
19
17
|
gem 'rake', :group => :development
|
data/aws-cfn-dsl.gemspec
CHANGED
@@ -18,9 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency 'awesome_print'
|
21
|
+
spec.add_dependency 'awesome_print', '~> 1.2', '>= 1.2.0'
|
22
|
+
spec.add_dependency 'psych'
|
22
23
|
spec.add_dependency 'json'
|
24
|
+
spec.add_dependency 'slop'
|
23
25
|
spec.add_dependency 'cloudformation-ruby-dsl', '~> 0.4', '>= 0.4.3'
|
24
|
-
spec.add_dependency "slop"
|
25
26
|
|
26
27
|
end
|
data/lib/aws/cfn/dsl/base.rb
CHANGED
@@ -7,7 +7,7 @@ module Aws
|
|
7
7
|
module Dsl
|
8
8
|
class Base
|
9
9
|
attr_accessor :items
|
10
|
-
attr_reader :
|
10
|
+
attr_reader :template
|
11
11
|
|
12
12
|
require 'dldinternet/mixlib/logging'
|
13
13
|
include DLDInternet::Mixlib::Logging
|
@@ -17,30 +17,42 @@ module Aws
|
|
17
17
|
@output = []
|
18
18
|
@config ||= {}
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
:pattern => "%#{mlll}l: %m %C\n",
|
37
|
-
:date_pattern => '%Y-%m-%d %H:%M:%S',
|
38
|
-
:color_scheme => 'compiler'
|
20
|
+
# noinspection RubyStringKeysInHashInspection
|
21
|
+
@formats = {
|
22
|
+
'yaml' => 'yaml',
|
23
|
+
'yml' => 'yaml',
|
24
|
+
'yts' => 'yaml',
|
25
|
+
'ytf' => 'yaml',
|
26
|
+
'ytp' => 'yaml',
|
27
|
+
'json' => 'json',
|
28
|
+
'jml' => 'json',
|
29
|
+
'jts' => 'json',
|
30
|
+
'jtf' => 'json',
|
31
|
+
'jtp' => 'json',
|
32
|
+
'tpl' => 'json',
|
33
|
+
'template' => 'json',
|
34
|
+
'ruby' => 'ruby',
|
35
|
+
'rb' => 'ruby',
|
39
36
|
}
|
40
|
-
}
|
41
|
-
@config[:log_level] = :info
|
42
|
-
@logger = getLogger(@config)
|
43
37
|
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def ext2format(ext)
|
42
|
+
@formats.has_key? ext ? @formats[ext] : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def format2exts(format)
|
46
|
+
exts = @formats.select{ |_,v| v == format }
|
47
|
+
if exts.size > 0
|
48
|
+
exts.keys
|
49
|
+
else
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def formats_compatible?(format, match)
|
55
|
+
@formats[match] == @formats[format]
|
44
56
|
end
|
45
57
|
|
46
58
|
def save_dsl(path=nil,parts=@items)
|
@@ -50,11 +62,13 @@ module Aws
|
|
50
62
|
|
51
63
|
def load_template(file=nil)
|
52
64
|
if file
|
53
|
-
|
65
|
+
filn = File.join(File.dirname(file), file)
|
66
|
+
filn = File.expand_path(file) if @config[:expandedpaths]
|
67
|
+
logStep "Loading #{filn}"
|
54
68
|
begin
|
55
69
|
abs = File.absolute_path(File.expand_path(file))
|
56
|
-
unless File.exists?(abs) or @
|
57
|
-
abs = File.absolute_path(File.expand_path(File.join(@
|
70
|
+
unless File.exists?(abs) or @config[:directory].nil?
|
71
|
+
abs = File.absolute_path(File.expand_path(File.join(@config[:directory],file)))
|
58
72
|
end
|
59
73
|
rescue
|
60
74
|
# pass
|
@@ -71,78 +85,13 @@ module Aws
|
|
71
85
|
else
|
72
86
|
abort! "Unable to open template: #{abs}"
|
73
87
|
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
protected
|
78
|
-
|
79
|
-
def simplify(val,start=false)
|
80
|
-
logStep "Simplify a block ..." if start
|
81
|
-
if val.is_a?(Hash)
|
82
|
-
val = Hash[val.map { |k,v| [k, simplify(v)] }]
|
83
|
-
if val.length != 1
|
84
|
-
val
|
85
|
-
else
|
86
|
-
k, v = val.entries[0]
|
87
|
-
case @opts[:functions]
|
88
|
-
when /1|on|set|enable|yes|true/ then
|
89
|
-
case
|
90
|
-
# CloudFormation functions
|
91
|
-
when k == 'Fn::Base64'
|
92
|
-
FnCall.new 'base64', [v], true
|
93
|
-
when k == 'Fn::FindInMap'
|
94
|
-
FnCall.new 'find_in_map', v
|
95
|
-
when k == 'Fn::GetAtt'
|
96
|
-
FnCall.new 'get_att', v
|
97
|
-
when k == 'Fn::GetAZs'
|
98
|
-
FnCall.new 'get_azs', v != '' ? [v] : []
|
99
|
-
when k == 'Fn::Join'
|
100
|
-
FnCall.new 'join', [v[0]] + v[1], true
|
101
|
-
when k == 'Fn::Select'
|
102
|
-
FnCall.new 'select', v
|
103
|
-
when k == 'Ref' && v == 'AWS::Region'
|
104
|
-
FnCall.new 'aws_region', []
|
105
|
-
when k == 'Ref' && v == 'AWS::StackName'
|
106
|
-
FnCall.new 'aws_stack_name', []
|
107
|
-
# CloudFormation internal references
|
108
|
-
when k == 'Ref'
|
109
|
-
FnCall.new 'ref', [v]
|
110
|
-
else
|
111
|
-
val
|
112
|
-
end
|
113
|
-
else
|
114
|
-
val
|
115
|
-
end
|
116
|
-
end
|
117
|
-
elsif val.is_a?(Array)
|
118
|
-
val.map { |v| simplify(v) }
|
88
|
+
@items
|
119
89
|
else
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def pprint(val)
|
125
|
-
logStep "Pretty print ..."
|
126
|
-
case detect_type(val)
|
127
|
-
when :template
|
128
|
-
pprint_cfn_template(val)
|
129
|
-
when :parameter
|
130
|
-
pprint_cfn_section 'parameter', 'TODO', val, 'Parameters'
|
131
|
-
when :resource
|
132
|
-
pprint_cfn_resource 'TODO', val
|
133
|
-
when :parameters
|
134
|
-
val.each { |k, v| pprint_cfn_section 'parameter', k, v, 'Parameters' }
|
135
|
-
when :resources
|
136
|
-
val.each { |k, v| pprint_cfn_resource k, v }
|
137
|
-
else
|
138
|
-
pprint_value(val, '')
|
90
|
+
nil
|
139
91
|
end
|
140
92
|
end
|
141
93
|
|
142
|
-
|
143
|
-
name = self.class.to_s.split("::")
|
144
|
-
name[0..parts-1].join('::')
|
145
|
-
end
|
94
|
+
protected
|
146
95
|
|
147
96
|
def abort!(msg=nil,rc=1)
|
148
97
|
@logger.error msg if msg
|
@@ -150,361 +99,24 @@ module Aws
|
|
150
99
|
exit rc
|
151
100
|
end
|
152
101
|
|
153
|
-
|
154
|
-
|
155
|
-
s = s.join('')
|
156
|
-
end
|
157
|
-
if @output.size > 0
|
158
|
-
@output[0].write s
|
159
|
-
else
|
160
|
-
print s
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def writeln(s='')
|
165
|
-
if @output.size > 0
|
166
|
-
@output[0].puts s
|
167
|
-
else
|
168
|
-
puts s
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# Attempt to figure out what fragment of the template we have. This is imprecise and can't
|
173
|
-
# detect Mappings and Outputs sections reliably, so it doesn't attempt to.
|
174
|
-
def detect_type(val)
|
175
|
-
if val.is_a?(Hash) && val['AWSTemplateFormatVersion']
|
176
|
-
:template
|
177
|
-
elsif val.is_a?(Hash) && /^(String|Number)$/ =~ val['Type']
|
178
|
-
:parameter
|
179
|
-
elsif val.is_a?(Hash) && val['Type']
|
180
|
-
:resource
|
181
|
-
elsif val.is_a?(Hash) && val.values.all? { |v| detect_type(v) == :parameter }
|
182
|
-
:parameters
|
183
|
-
elsif val.is_a?(Hash) && val.values.all? { |v| detect_type(v) == :resource }
|
184
|
-
:resources
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
def pprint_cfn_template(tpl)
|
189
|
-
file = File.basename(@opts[:template]).gsub(%r'\.(json|yaml|js|yaml)$'i, '.rb')
|
190
|
-
# noinspection RubyParenthesesAroundConditionInspection
|
191
|
-
if (iam = open_output('', file.gsub(%r'\.(json|yaml|js|yml|rb)'i, '')))
|
192
|
-
logStep "Saving #{file}"
|
193
|
-
writeln "#!/usr/bin/env ruby"
|
194
|
-
print_maintainer('')
|
195
|
-
writeln
|
196
|
-
if @opts[:output]
|
197
|
-
writeln "$:.unshift(File.dirname(__FILE__))"
|
198
|
-
# noinspection RubyExpressionInStringInspection
|
199
|
-
writeln '$:.unshift File.absolute_path("#{File.dirname(__FILE__)}/../lib")'
|
200
|
-
end
|
201
|
-
writeln "require 'bundler/setup'"
|
202
|
-
writeln "require 'aws/cfn/dsl/template'"
|
203
|
-
#writeln "require 'cloudformation-ruby-dsl/spotprice'"
|
204
|
-
#writeln "require 'cloudformation-ruby-dsl/table'"
|
205
|
-
writeln
|
206
|
-
writeln "template do"
|
207
|
-
writeln
|
208
|
-
tpl.each do |section, v|
|
209
|
-
case section
|
210
|
-
when 'Parameters'
|
211
|
-
when 'Mappings'
|
212
|
-
when 'Resources'
|
213
|
-
when 'Outputs'
|
214
|
-
else
|
215
|
-
write " value #{fmt_key(section)} => "
|
216
|
-
pprint_value v, ' '
|
217
|
-
writeln
|
218
|
-
writeln
|
219
|
-
end
|
220
|
-
end
|
221
|
-
else
|
222
|
-
@logger.warn "Not overwriting template: '#{file}'"
|
223
|
-
end
|
224
|
-
%w(Mappings Parameters Resources Outputs).each do |section|
|
225
|
-
writeln " # #{section}" if iam
|
226
|
-
v = tpl[section]
|
227
|
-
case section
|
228
|
-
when 'Parameters'
|
229
|
-
v.each { |name, options| pprint_cfn_section 'parameter', name, options, 'Parameters', iam }
|
230
|
-
when 'Mappings'
|
231
|
-
v.each { |name, options| pprint_cfn_section 'mapping', name, options, 'Mappings', iam }
|
232
|
-
when 'Resources'
|
233
|
-
v.each { |name, options| pprint_cfn_resource name, options, iam }
|
234
|
-
when 'Outputs'
|
235
|
-
v.each { |name, options| pprint_cfn_section 'output', name, options, 'Outputs', iam }
|
236
|
-
else
|
237
|
-
abort! "Internal Error: Unexpected section '#{section}'"
|
238
|
-
end
|
239
|
-
writeln if iam
|
240
|
-
end
|
241
|
-
writeln "end.exec!" if iam
|
242
|
-
end
|
243
|
-
|
244
|
-
def open_output(subdir,name)
|
245
|
-
if @opts[:output]
|
246
|
-
file = rb_file(subdir, name)
|
247
|
-
if i_am_maintainer(file)
|
248
|
-
@output.unshift File.open(file, 'w')
|
249
|
-
true
|
250
|
-
else
|
251
|
-
false
|
252
|
-
end
|
253
|
-
else
|
254
|
-
true
|
255
|
-
end
|
256
|
-
end
|
102
|
+
require "aws/cfn/dsl/mixins/options"
|
103
|
+
include Aws::Cfn::Dsl::Options
|
257
104
|
|
258
|
-
|
259
|
-
|
260
|
-
#file = rb_file(subdir, name).gsub(%r'^#{@opts[:output]}/','')
|
261
|
-
#writeln " file '#{file}'"
|
262
|
-
s = subdir.downcase.gsub(%r's$','')
|
263
|
-
writeln " #{s} '#{name}'"
|
264
|
-
end
|
265
|
-
end
|
105
|
+
require "aws/cfn/dsl/mixins/maintainer"
|
106
|
+
include Aws::Cfn::Dsl::Maintainer
|
266
107
|
|
267
|
-
|
268
|
-
|
269
|
-
unless File.directory? path
|
270
|
-
Dir.mkdir path
|
271
|
-
end
|
272
|
-
file = File.join(path, "#{name}.rb")
|
273
|
-
end
|
108
|
+
require "aws/cfn/dsl/mixins/simplify"
|
109
|
+
include Aws::Cfn::Dsl::Simplify
|
274
110
|
|
275
|
-
|
276
|
-
|
277
|
-
fp = @output.shift
|
278
|
-
fp.close
|
279
|
-
end
|
280
|
-
end
|
111
|
+
require "aws/cfn/dsl/mixins/prettyprint"
|
112
|
+
include Aws::Cfn::Dsl::PrettyPrint
|
281
113
|
|
282
|
-
|
283
|
-
|
284
|
-
end
|
114
|
+
require "aws/cfn/dsl/mixins/output"
|
115
|
+
include Aws::Cfn::Dsl::Output
|
285
116
|
|
286
|
-
|
287
|
-
|
288
|
-
"#{indent}# Remove this message and/or set the 'maintainer: <author name>' when you need your changes to survive.\n" +
|
289
|
-
"#{indent}# Abscence of the 'maintainer: ' will be considered conscent to overwrite.\n" +
|
290
|
-
"#{indent}# #{maintainer 3}\n" +
|
291
|
-
"#\n"
|
292
|
-
end
|
117
|
+
require "aws/cfn/dsl/mixins/dsl"
|
118
|
+
include Aws::Cfn::Dsl::DSL
|
293
119
|
|
294
|
-
def print_maintainer(indent=' ')
|
295
|
-
writeln maintainer_comment(indent)
|
296
|
-
end
|
297
|
-
|
298
|
-
def i_am_maintainer(file)
|
299
|
-
# mod = module_name 2
|
300
|
-
if File.exists?(file)
|
301
|
-
src = IO.read(file)
|
302
|
-
mtc = src.match(%r'#{maintainer 2}')
|
303
|
-
iam = (not mtc.nil? or src.match(%r'#\s*maintainer:').nil?)
|
304
|
-
ovr = @config[:overwrite]
|
305
|
-
iam or ovr
|
306
|
-
else
|
307
|
-
true
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
def prelude_code(indent=' ')
|
312
|
-
"scope = Aws::Cfn::Compiler.binding[File.basename(File.dirname(__FILE__))][File.basename(__FILE__, '.rb')]\n"+
|
313
|
-
"template = scope[:template]\n"+
|
314
|
-
"\n"+
|
315
|
-
"# noinspection RubyStringKeysInHashInspection\n"+
|
316
|
-
"template." +
|
317
|
-
""
|
318
|
-
end
|
319
|
-
|
320
|
-
def print_with_wrapper(code,indent=' ')
|
321
|
-
write prelude_code(indent)+code.gsub(%r'^\s+','')
|
322
|
-
end
|
323
|
-
|
324
|
-
def pprint_cfn_section(section, name, options, subdir, brick=true)
|
325
|
-
if open_output(subdir,name)
|
326
|
-
@logger.info "Pretty print #{section} '#{name}' to '#{rb_file(subdir, name)}'"
|
327
|
-
print_maintainer ''
|
328
|
-
print_with_wrapper "#{section} #{fmt_string(name)}"
|
329
|
-
indent = ' ' + (' ' * section.length) + ' '
|
330
|
-
hang = true
|
331
|
-
options.each do |k, v|
|
332
|
-
if hang
|
333
|
-
writeln ','
|
334
|
-
hang = false
|
335
|
-
end
|
336
|
-
write indent, fmt_key(k), " => "
|
337
|
-
pprint_value v, indent
|
338
|
-
hang = true
|
339
|
-
end
|
340
|
-
writeln
|
341
|
-
writeln
|
342
|
-
close_output
|
343
|
-
add_brick(subdir,name) if brick
|
344
|
-
else
|
345
|
-
@logger.warn "NOT overwriting existing source file '#{rb_file(subdir, name)}'"
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
|
-
def pprint_cfn_resource(name, options, brick=true)
|
350
|
-
subdir = 'Resources'
|
351
|
-
if open_output(subdir,name)
|
352
|
-
@logger.info "Pretty print resource '#{name}' to '#{rb_file(subdir, name)}'"
|
353
|
-
print_maintainer ''
|
354
|
-
print_with_wrapper "resource #{fmt_string(name)}"
|
355
|
-
indent = ' '
|
356
|
-
hang = true
|
357
|
-
options.each do |k, v|
|
358
|
-
if hang
|
359
|
-
writeln ','
|
360
|
-
hang = false
|
361
|
-
end
|
362
|
-
|
363
|
-
case k
|
364
|
-
when /^(Metadata|Properties)$/
|
365
|
-
write "#{indent}#{fmt_key(k)} => "
|
366
|
-
pprint_value options[k], indent
|
367
|
-
hang = true
|
368
|
-
else
|
369
|
-
write "#{indent}#{fmt_key(k)} => "
|
370
|
-
write "#{fmt(v)}"
|
371
|
-
hang = true
|
372
|
-
end
|
373
|
-
end
|
374
|
-
writeln
|
375
|
-
close_output
|
376
|
-
add_brick(subdir,name) if brick
|
377
|
-
else
|
378
|
-
@logger.warn "NOT overwriting existing source file '#{rb_file(subdir, name)}'"
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
|
-
def pprint_value(val, indent)
|
383
|
-
# Prefer to write the value on a single line if it's reasonable to do so
|
384
|
-
single_line = is_single_line(val) || is_single_line_hack(val)
|
385
|
-
if single_line && !is_multi_line_hack(val)
|
386
|
-
s = fmt(val)
|
387
|
-
if s.length < 120 || is_single_line_hack(val)
|
388
|
-
write s
|
389
|
-
return
|
390
|
-
end
|
391
|
-
end
|
392
|
-
|
393
|
-
# Print the value across multiple lines
|
394
|
-
if val.is_a?(Hash)
|
395
|
-
writeln "{"
|
396
|
-
val.each do |k, v|
|
397
|
-
write "#{indent} #{fmt_key(k)} => "
|
398
|
-
pprint_value v, indent + ' '
|
399
|
-
writeln ","
|
400
|
-
end
|
401
|
-
write "#{indent}}"
|
402
|
-
|
403
|
-
elsif val.is_a?(Array)
|
404
|
-
writeln "["
|
405
|
-
val.each do |v|
|
406
|
-
write "#{indent} "
|
407
|
-
pprint_value v, indent + ' '
|
408
|
-
writeln ","
|
409
|
-
end
|
410
|
-
write "#{indent}]"
|
411
|
-
|
412
|
-
elsif val.is_a?(FnCall) && val.multiline && @opts[:functions] != 'raw'
|
413
|
-
write val.name, "("
|
414
|
-
args = val.arguments
|
415
|
-
sep = ''
|
416
|
-
sub_indent = indent + ' '
|
417
|
-
if val.name == 'join' && args.length > 1
|
418
|
-
pprint_value args[0], indent + ' '
|
419
|
-
args = args[1..-1]
|
420
|
-
sep = ','
|
421
|
-
sub_indent = indent + ' '
|
422
|
-
end
|
423
|
-
unless args.empty?
|
424
|
-
args.each do |v|
|
425
|
-
writeln sep
|
426
|
-
write sub_indent
|
427
|
-
pprint_value v, sub_indent
|
428
|
-
sep = ','
|
429
|
-
end
|
430
|
-
if val.name == 'join' && args.length > 1
|
431
|
-
write ","
|
432
|
-
end
|
433
|
-
writeln
|
434
|
-
write indent
|
435
|
-
end
|
436
|
-
write ")"
|
437
|
-
|
438
|
-
else
|
439
|
-
write fmt(val)
|
440
|
-
end
|
441
|
-
end
|
442
|
-
|
443
|
-
def is_single_line(val)
|
444
|
-
if val.is_a?(Hash)
|
445
|
-
is_single_line(val.values)
|
446
|
-
elsif val.is_a?(Array)
|
447
|
-
val.empty? ||
|
448
|
-
(val.length == 1 && is_single_line(val[0]) && !val[0].is_a?(Hash)) ||
|
449
|
-
val.all? { |v| v.is_a?(String) }
|
450
|
-
else
|
451
|
-
true
|
452
|
-
end
|
453
|
-
end
|
454
|
-
|
455
|
-
# Emo-specific hacks to force the desired output formatting
|
456
|
-
def is_single_line_hack(val)
|
457
|
-
is_array_of_strings_hack(val)
|
458
|
-
end
|
459
|
-
|
460
|
-
# Emo-specific hacks to force the desired output formatting
|
461
|
-
def is_multi_line_hack(val)
|
462
|
-
val.is_a?(Hash) && val['email']
|
463
|
-
end
|
464
|
-
|
465
|
-
# Emo-specific hacks to force the desired output formatting
|
466
|
-
def is_array_of_strings_hack(val)
|
467
|
-
val.is_a?(Array) && val.all? { |v| v.is_a?(String) } && val.grep(/\s/).empty? && (
|
468
|
-
val.include?('autoscaling:EC2_INSTANCE_LAUNCH') ||
|
469
|
-
val.include?('m1.small')
|
470
|
-
)
|
471
|
-
end
|
472
|
-
|
473
|
-
def fmt(val)
|
474
|
-
if val == {}
|
475
|
-
'{}'
|
476
|
-
elsif val == []
|
477
|
-
'[]'
|
478
|
-
elsif val.is_a?(Hash)
|
479
|
-
'{ ' + (val.map { |k,v| fmt_key(k) + ' => ' + fmt(v) }).join(', ') + ' }'
|
480
|
-
elsif val.is_a?(Array) && is_array_of_strings_hack(val)
|
481
|
-
'%w(' + val.join(' ') + ')'
|
482
|
-
elsif val.is_a?(Array)
|
483
|
-
'[ ' + (val.map { |v| fmt(v) }).join(', ') + ' ]'
|
484
|
-
elsif val.is_a?(FnCall) && val.arguments.empty?
|
485
|
-
val.name
|
486
|
-
elsif val.is_a?(FnCall)
|
487
|
-
val.name + '(' + (val.arguments.map { |v| fmt(v) }).join(', ') + ')'
|
488
|
-
elsif val.is_a?(String)
|
489
|
-
fmt_string(val)
|
490
|
-
elsif val == nil
|
491
|
-
'null'
|
492
|
-
else
|
493
|
-
val.to_s # number, boolean
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
def fmt_key(s)
|
498
|
-
':' + (/^[a-zA-Z_]\w+$/ =~ s ? s : fmt_string(s)) # returns a symbol like :Foo or :'us-east-1'
|
499
|
-
end
|
500
|
-
|
501
|
-
def fmt_string(s)
|
502
|
-
if /[^ -~]/ =~ s
|
503
|
-
s.dump # contains, non-ascii or control char, return double-quoted string
|
504
|
-
else
|
505
|
-
'\'' + s.gsub(/([\\'])/, '\\\\\1') + '\'' # return single-quoted string, escape \ and '
|
506
|
-
end
|
507
|
-
end
|
508
120
|
|
509
121
|
end
|
510
122
|
end
|