dy 1.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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/dy +3 -0
  3. data/lib/dy.rb +152 -0
  4. metadata +47 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f03a6c8fb8d9dc78ca173d8a953b02368ab8492a
4
+ data.tar.gz: 4e4a3c83926c6793ea35caf6ac04d011a2664528
5
+ SHA512:
6
+ metadata.gz: 880f5fa1a973ef334251a8d2a696d549c3639e5f3da8a21ae1f3d90b7f07e82608842d06d3931b235b5e5cc8ef68ded3b558f0ba607debad5c01413c9a7afa4b
7
+ data.tar.gz: 83125b2af46c635efa4d589e52f9e72037f485435ca4464ffc5a62932d22cf1563bb20f607dda38d95751082b801336635532d71829fc1655ce60c009eda4cb9
data/bin/dy ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dy.rb'
@@ -0,0 +1,152 @@
1
+ require 'erb'
2
+ require 'optparse'
3
+ require 'ostruct'
4
+ require 'yaml'
5
+
6
+ NO_CHANGE = Object.new
7
+
8
+ class Splice
9
+ attr_accessor :array
10
+
11
+ def initialize(array)
12
+ self.array = array
13
+ end
14
+ end
15
+
16
+ class Processor
17
+ attr_writer :file_content
18
+ attr_accessor :source_file
19
+
20
+ def initialize(source_file:, file_content: nil)
21
+ self.source_file = source_file
22
+ self.file_content = file_content
23
+ end
24
+
25
+ def hash
26
+ hash = file_content
27
+ process! hash
28
+ hash
29
+ end
30
+
31
+ private
32
+
33
+ def file_content
34
+ @file_content ||= YAML.load_file(source_file)
35
+ end
36
+
37
+ def relative_path(path)
38
+ File.expand_path(path, File.dirname(source_file))
39
+ end
40
+
41
+ def maybe_processed!(o)
42
+ data = process!(o)
43
+ if data == NO_CHANGE
44
+ [o, false]
45
+ else
46
+ [data, true]
47
+ end
48
+ end
49
+
50
+ def process!(o)
51
+ if o.is_a?(Hash)
52
+ if o.has_key?("__dy__")
53
+ process_dy!(o)
54
+ else
55
+ process_hash!(o)
56
+ end
57
+ elsif o.is_a?(Array)
58
+ process_array!(o)
59
+ else
60
+ NO_CHANGE
61
+ end
62
+ end
63
+
64
+ def process_dy!(dy)
65
+ case dy["__dy__"]
66
+ when "escape" then o["value"]
67
+ when "text_file"
68
+ read_file(relative_path(dy["file"]), erb: dy["erb"], args: dy["args"])
69
+ when "data_file"
70
+ file = relative_path(dy["file"])
71
+ content = read_file(file, erb: dy["erb"], args: dy["args"])
72
+ data = YAML.load(content)
73
+ data = Processor.new(source_file: file).hash
74
+ dy["splice"] ? Splice.new(data) : data
75
+ else
76
+ raise "Unknown __dy__ #{dy["__dy__"].inspect}"
77
+ end
78
+ end
79
+
80
+ def process_hash!(hash)
81
+ changed = false
82
+ hash.each do |key, value|
83
+ hash[key], processed = maybe_processed!(value)
84
+ changed ||= processed
85
+ end
86
+ changed ? hash : NO_CHANGE
87
+ end
88
+
89
+ def process_array!(array)
90
+ any_splice = false
91
+ changed = false
92
+ array.each_with_index do |value, index|
93
+ array[index], processed = maybe_processed!(value)
94
+ any_splice ||= array[index].is_a?(Splice)
95
+ changed ||= processed
96
+ end
97
+
98
+ splice_array!(array) if any_splice
99
+
100
+ changed ? array : NO_CHANGE
101
+ end
102
+ end
103
+
104
+ def splice_array!(array)
105
+ index = 0
106
+ while index < array.length do
107
+ value = array[index]
108
+ if value.is_a?(Splice)
109
+ raise "Cannot splice except arrays" unless value.array.is_a?(Array)
110
+ array[index, 1] = value.array
111
+ index += value.array.length
112
+ else
113
+ index += 1
114
+ end
115
+ end
116
+ end
117
+
118
+ def read_file(filename, erb: false, args: {})
119
+ content = File.read(filename)
120
+ if erb
121
+ renderer = ERB.new(content)
122
+ renderer.result(OpenStruct.new(args).instance_eval { binding })
123
+ else
124
+ content
125
+ end
126
+ end
127
+
128
+ def read_arguments
129
+ options = {}
130
+ OptionParser.new do |opts|
131
+ opts.banner = "Usage: test.rb [options]"
132
+
133
+ opts.on("-pPREFIX", "--prefix=PREFIX", "Prefix for the yaml output") do |v|
134
+ options[:prefix] = v
135
+ end
136
+ end.parse!
137
+
138
+ src, dst, *more = ARGV
139
+ if src.nil? || dst.nil? || !more.empty?
140
+ raise "Need two arguments"
141
+ end
142
+
143
+ [src, dst, options]
144
+ end
145
+
146
+ def main
147
+ src, dst, options = read_arguments
148
+ hash = Processor.new(source_file: src).hash
149
+ File.write(dst, "#{options[:prefix] + "\n" if options[:prefix]}#{hash.to_yaml}")
150
+ end
151
+
152
+ main
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Marco Monteiro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Extends yaml semantics to allow transforming one yaml file into another
14
+ one extended with external data
15
+ email: marco@neniu.org
16
+ executables:
17
+ - dy
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/dy
22
+ - lib/dy.rb
23
+ homepage: http://rubygems.org/gems/dy
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.5.1
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: Yaml assembler
47
+ test_files: []