ecg 0.1.2 → 0.2.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 +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
|