ecg 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +87 -1
- data/lib/ecg/command.rb +6 -4
- data/lib/ecg/context.rb +42 -0
- data/lib/ecg/option_parser.rb +67 -30
- data/lib/ecg/store.rb +18 -12
- data/lib/ecg/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d22e44c0a03b9a540006d7c0502e8c3c73101f7c446c9c05393ba5319bdc57ae
|
4
|
+
data.tar.gz: 03e5ed33aacd6ef40dfb7d7c0da2533d572259f444ce08e57d6a077bf4a64436
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6177f797de5728e5daf1f30b2178cb4f25c6281dc1cf2c9452afa88c9d1f5de54eabd3aa5afb12a40a05512e819a551bc052a92d7bbbeb17f3b35b008c37272
|
7
|
+
data.tar.gz: 59e1caa2a49b47af62ce27ee6b7b008ad3c8df286d7e84a77d0224892b9dd14dc9226d3586a50f637efe13e55e6869055797ec9b78673172168bd6fbbe506c74
|
data/README.md
CHANGED
@@ -14,7 +14,10 @@ Ruby: 2.4 or higher
|
|
14
14
|
gem install ecg
|
15
15
|
```
|
16
16
|
|
17
|
-
##
|
17
|
+
## Usage
|
18
|
+
See also `ecg --help`
|
19
|
+
|
20
|
+
### Simple example
|
18
21
|
```sh
|
19
22
|
ecg --values name=epaew --values email="epaew.333@gmail.com" < template.json.erb
|
20
23
|
{
|
@@ -47,5 +50,88 @@ with
|
|
47
50
|
email: epaew.333@gmail.com
|
48
51
|
```
|
49
52
|
|
53
|
+
### Using nested keys
|
54
|
+
```sh
|
55
|
+
ecg --values user.name=epaew --values user.email="epaew.333@gmail.com" < template.json.erb
|
56
|
+
{
|
57
|
+
"user": {
|
58
|
+
"name": "epaew",
|
59
|
+
"email": "epaew.333@gmail.com"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
```
|
63
|
+
or
|
64
|
+
```sh
|
65
|
+
ecg config.yml < template.json.erb
|
66
|
+
{
|
67
|
+
"user": {
|
68
|
+
"name": "epaew",
|
69
|
+
"email": "epaew.333@gmail.com"
|
70
|
+
}
|
71
|
+
}
|
72
|
+
```
|
73
|
+
with
|
74
|
+
* template.json.erb
|
75
|
+
```json
|
76
|
+
{
|
77
|
+
"user": {
|
78
|
+
"name": "<%= user.name %>",
|
79
|
+
"email": "<%= user.email %>"
|
80
|
+
}
|
81
|
+
}
|
82
|
+
```
|
83
|
+
* config.yml
|
84
|
+
```yaml
|
85
|
+
user:
|
86
|
+
name: epaew
|
87
|
+
email: epaew.333@gmail.com
|
88
|
+
```
|
89
|
+
|
90
|
+
### Using array (JSON and YAML only)
|
91
|
+
```sh
|
92
|
+
ecg config.yml < template.json.erb
|
93
|
+
{
|
94
|
+
"user": [
|
95
|
+
{
|
96
|
+
"name": "Kurimu"
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"name": "Chizuru"
|
100
|
+
},
|
101
|
+
{
|
102
|
+
"name": "Minatsu"
|
103
|
+
},
|
104
|
+
{
|
105
|
+
"name": "Mahuyu"
|
106
|
+
}
|
107
|
+
]
|
108
|
+
}
|
109
|
+
```
|
110
|
+
with
|
111
|
+
* template.json.erb
|
112
|
+
```json
|
113
|
+
{
|
114
|
+
"user": [
|
115
|
+
<% users.each_with_index do |user, i| %>
|
116
|
+
{
|
117
|
+
"name": "<%= user.name %>"
|
118
|
+
<% unless i == users.count - 1 %>
|
119
|
+
},
|
120
|
+
<% else %>
|
121
|
+
}
|
122
|
+
<% end %>
|
123
|
+
<% end %>
|
124
|
+
]
|
125
|
+
}
|
126
|
+
```
|
127
|
+
* config.yml
|
128
|
+
```yaml
|
129
|
+
users:
|
130
|
+
- name: Kurimu
|
131
|
+
- name: Chizuru
|
132
|
+
- name: Minatsu
|
133
|
+
- name: Mahuyu
|
134
|
+
```
|
135
|
+
|
50
136
|
## License
|
51
137
|
[MIT](LICENSE)
|
data/lib/ecg/command.rb
CHANGED
@@ -2,17 +2,19 @@
|
|
2
2
|
|
3
3
|
require 'erb'
|
4
4
|
require_relative 'option_parser'
|
5
|
-
require_relative 'store'
|
6
5
|
|
7
6
|
module ECG
|
8
7
|
class Command
|
9
8
|
def initialize(args)
|
10
|
-
parser = OptionParser.new(args)
|
11
|
-
@store = parser.parse!
|
9
|
+
@parser = OptionParser.new(args)
|
12
10
|
end
|
13
11
|
|
14
12
|
def execute(input = $stdin, output = $stdout)
|
15
|
-
|
13
|
+
context = @parser.context
|
14
|
+
# NOTE: ERB.new's non-keyword arguments are deprecated in 2.6
|
15
|
+
# erb = ERB.new(input.read, trim_mode: context.trim_mode)
|
16
|
+
erb = ERB.new(input.read, nil, context.trim_mode)
|
17
|
+
output.puts erb.result(context.values.binding)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
data/lib/ecg/context.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'store'
|
4
|
+
|
5
|
+
module ECG
|
6
|
+
class Context
|
7
|
+
attr_reader :trim_mode
|
8
|
+
|
9
|
+
def initialize(filepath:, trim_mode:, values:)
|
10
|
+
@trim_mode = trim_mode
|
11
|
+
@values_file = filepath
|
12
|
+
@values_option = values
|
13
|
+
end
|
14
|
+
|
15
|
+
def values
|
16
|
+
Store.new(merged_hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def load_file(path)
|
22
|
+
case File.extname(path)
|
23
|
+
when '.json'
|
24
|
+
require 'json'
|
25
|
+
File.open(path) { |f| JSON.parse(f.read) }
|
26
|
+
when /\A\.ya?ml\z/
|
27
|
+
require 'yaml'
|
28
|
+
# NOTE: YAML.safe_load's non-keyword arguments are deprecated in 2.6
|
29
|
+
# File.open(path) { |f| YAML.safe_load(f.read, aliases: true) }
|
30
|
+
File.open(path) { |f| YAML.safe_load(f.read, [], [], true) }
|
31
|
+
else
|
32
|
+
raise ArgumentError,
|
33
|
+
"Cannot load file `#{path}`. Only JSON/YAML are allowed."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def merged_hash
|
38
|
+
hash = @values_file.nil? ? {} : load_file(@values_file)
|
39
|
+
hash.merge(@values_option)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/ecg/option_parser.rb
CHANGED
@@ -1,26 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'optparse'
|
4
|
-
require_relative '
|
4
|
+
require_relative 'context'
|
5
|
+
require_relative 'version'
|
5
6
|
|
6
7
|
module ECG
|
7
|
-
class LoadError < ::StandardError; end
|
8
|
-
|
9
8
|
class OptionParser
|
10
|
-
attr_reader :args, :option
|
11
|
-
|
12
9
|
def initialize(args = [])
|
13
10
|
@args = args
|
14
|
-
@
|
11
|
+
@options = { filepath: nil, trim_mode: '<>', values: {} }
|
15
12
|
end
|
16
13
|
|
17
|
-
def
|
18
|
-
|
14
|
+
def context
|
15
|
+
return @context if instance_variable_defined?(:@context)
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Store.new(hash)
|
17
|
+
parse!
|
18
|
+
@context = Context.new(@options)
|
24
19
|
end
|
25
20
|
|
26
21
|
private
|
@@ -31,39 +26,46 @@ module ECG
|
|
31
26
|
__BANNER__
|
32
27
|
end
|
33
28
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
hash.merge(@option)
|
38
|
-
end
|
29
|
+
def filepath
|
30
|
+
print_help(false) if @args.length > 1
|
31
|
+
return nil if @args.empty?
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
require 'json'
|
44
|
-
File.open(path) { |f| JSON.parse(f.read) }
|
45
|
-
when /\A\.ya?ml\z/
|
46
|
-
require 'yaml'
|
47
|
-
File.open(path) { |f| YAML.safe_load(f.read, [], [], true) }
|
48
|
-
else
|
33
|
+
path = @args.first
|
34
|
+
extname = File.extname(path)
|
35
|
+
if %w[.json .yml .yaml].none? { |ext| ext == extname }
|
49
36
|
raise ArgumentError,
|
50
37
|
"Cannot load file `#{path}`. Only JSON/YAML are allowed."
|
51
38
|
end
|
39
|
+
|
40
|
+
path
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse!
|
44
|
+
print_help(false) if @args.empty?
|
45
|
+
|
46
|
+
parser.parse!(@args)
|
47
|
+
@options[:filepath] = filepath
|
48
|
+
self
|
52
49
|
end
|
53
50
|
|
54
|
-
def parser
|
51
|
+
def parser # rubocop:disable Style/MethodLength
|
55
52
|
::OptionParser.new do |opt|
|
56
53
|
opt.banner = banner
|
54
|
+
opt.version = VERSION
|
57
55
|
|
58
56
|
opt.on('-v', '--values Key=Value', <<~__DESC__) do |str|
|
59
57
|
Set the key-value mapping to be embedded in the template.
|
60
58
|
__DESC__
|
61
59
|
|
62
|
-
|
63
|
-
|
60
|
+
set_option_value(*str.split('=', 2))
|
61
|
+
end
|
62
|
+
opt.on('-t', '--trim-mode MODE', <<~__DESC__) do |v|
|
63
|
+
Set ERB's trim_mode. Default is "<>".
|
64
|
+
__DESC__
|
65
|
+
@options[:trim_mode] = v
|
64
66
|
end
|
65
67
|
opt.on('-V', '--version', 'Print version information') do
|
66
|
-
puts
|
68
|
+
puts opt.ver
|
67
69
|
exit
|
68
70
|
end
|
69
71
|
opt.on('-h', '--help', 'Print this help message', &method(:print_help))
|
@@ -74,5 +76,40 @@ module ECG
|
|
74
76
|
warn parser.help
|
75
77
|
exit bool
|
76
78
|
end
|
79
|
+
|
80
|
+
def set_option_value(key, value)
|
81
|
+
keys = key.split('.').map(&:to_sym)
|
82
|
+
if keys.count == 1
|
83
|
+
set_single_option_value(keys.first, value)
|
84
|
+
else
|
85
|
+
set_nested_option_value(keys, value)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_single_option_value(key, value)
|
90
|
+
values = @options[:values]
|
91
|
+
if values[key].is_a? Hash
|
92
|
+
raise ArgumentError, 'Reaf keys cannot have own value.'
|
93
|
+
end
|
94
|
+
|
95
|
+
values[key] = value
|
96
|
+
values
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_nested_option_value(keys, value)
|
100
|
+
values = @options[:values]
|
101
|
+
last_key = keys.pop
|
102
|
+
|
103
|
+
nested = keys.inject(values) do |result, key|
|
104
|
+
result[key] ||= {}
|
105
|
+
unless result[key].is_a? Hash
|
106
|
+
raise ArgumentError, 'Reaf keys cannot have own value.'
|
107
|
+
end
|
108
|
+
|
109
|
+
result[key]
|
110
|
+
end
|
111
|
+
nested[last_key] = value
|
112
|
+
values
|
113
|
+
end
|
77
114
|
end
|
78
115
|
end
|
data/lib/ecg/store.rb
CHANGED
@@ -40,18 +40,7 @@ module ECG
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def to_h
|
43
|
-
@store.transform_values
|
44
|
-
case value
|
45
|
-
when self.class
|
46
|
-
value.to_h
|
47
|
-
when Array
|
48
|
-
value.map do |element|
|
49
|
-
element.respond_to?(:to_h) ? element.to_h : element
|
50
|
-
end
|
51
|
-
else
|
52
|
-
value
|
53
|
-
end
|
54
|
-
end
|
43
|
+
@store.transform_values(&method(:intransform_value))
|
55
44
|
end
|
56
45
|
|
57
46
|
def to_json(*args)
|
@@ -59,8 +48,25 @@ module ECG
|
|
59
48
|
to_h.to_json(args)
|
60
49
|
end
|
61
50
|
|
51
|
+
def ==(other)
|
52
|
+
return false unless other.is_a?(self.class)
|
53
|
+
|
54
|
+
to_h == other.to_h
|
55
|
+
end
|
56
|
+
|
62
57
|
private
|
63
58
|
|
59
|
+
def intransform_value(value)
|
60
|
+
case value
|
61
|
+
when self.class
|
62
|
+
value.to_h
|
63
|
+
when Array
|
64
|
+
value.map(&method(:intransform_value))
|
65
|
+
else
|
66
|
+
value
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
64
70
|
def transform_value(value)
|
65
71
|
case value
|
66
72
|
when Hash
|
data/lib/ecg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- epaew
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,7 @@ files:
|
|
136
136
|
- bin/ecg
|
137
137
|
- lib/ecg.rb
|
138
138
|
- lib/ecg/command.rb
|
139
|
+
- lib/ecg/context.rb
|
139
140
|
- lib/ecg/option_parser.rb
|
140
141
|
- lib/ecg/store.rb
|
141
142
|
- lib/ecg/version.rb
|
@@ -159,7 +160,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
160
|
- !ruby/object:Gem::Version
|
160
161
|
version: '0'
|
161
162
|
requirements: []
|
162
|
-
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 2.7.6.2
|
163
165
|
signing_key:
|
164
166
|
specification_version: 4
|
165
167
|
summary: ecg is an ERB(eRuby) based, simple and powerful configration file generator
|