kojo 0.2.1 → 0.2.2
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 +34 -14
- data/bin/kojo +1 -1
- data/lib/kojo.rb +1 -1
- data/lib/kojo/cli.rb +2 -0
- data/lib/kojo/collection.rb +38 -0
- data/lib/kojo/commands/config.rb +10 -4
- data/lib/kojo/commands/dir.rb +21 -20
- data/lib/kojo/commands/file.rb +8 -3
- data/lib/kojo/config.rb +66 -0
- data/lib/kojo/exceptions.rb +5 -0
- data/lib/kojo/extensions/array.rb +1 -0
- data/lib/kojo/extensions/string.rb +3 -2
- data/lib/kojo/template.rb +35 -12
- data/lib/kojo/version.rb +1 -1
- metadata +4 -2
- data/lib/kojo/generator.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60d550cda8b281a7ecbac40c236b6446fbe6a4d0b2ed7cb261ec47abeb654cbc
|
4
|
+
data.tar.gz: a991496e62aa272ad939b5c663cec543ed5e49aa9dedff5f3505c579d50de8d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa51aa1c425c7af70bd8fd12bed004c0472d290e96cfdb172e3222f76d994a671eba764b45baae57f1287ebb4f7ba27fa94f0fbf725edc714095740653c9507a
|
7
|
+
data.tar.gz: 58802308a1134db6abd3265b0f7ccacd854fe4cdef6468f6c15217799f75eaf03aae0e9761a2b990201ae6c50cb680f2bb026f1f8869be86930bbff4dce36779
|
data/README.md
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|

|
4
4
|
|
5
|
-
Kojo
|
5
|
+
Kojo Configuration Ninja
|
6
6
|
==================================================
|
7
7
|
|
8
8
|
[](https://badge.fury.io/rb/kojo)
|
9
9
|
[](https://travis-ci.com/DannyBen/kojo)
|
10
10
|
[](https://codeclimate.com/github/DannyBen/kojo/maintainability)
|
11
|
-
|
11
|
+
[](https://codeclimate.com/github/DannyBen/kojo/test_coverage)
|
12
12
|
|
13
13
|
Kojo helps you generate configuration files from templates, using variables
|
14
14
|
and definition files.
|
@@ -25,8 +25,8 @@ Table of Contents
|
|
25
25
|
- [Usage](#usage)
|
26
26
|
- [Variables](#variables)
|
27
27
|
- [Import](#import)
|
28
|
-
- [One to Many Generation](#one-to-many-generation)
|
29
28
|
- [Compile an Entire Folder](#compile-an-entire-folder)
|
29
|
+
- [One to Many Generation](#one-to-many-generation)
|
30
30
|
- [Conditions and Loops with ERB](#conditions-and-loops-with-erb)
|
31
31
|
|
32
32
|
---
|
@@ -41,7 +41,7 @@ Installation
|
|
41
41
|
Usage
|
42
42
|
--------------------------------------------------
|
43
43
|
|
44
|
-
If you prefer to learn by example, see the [examples](examples) folder for
|
44
|
+
If you prefer to learn by example, see the [examples](examples#examples) folder for
|
45
45
|
several use cases. Each example subfolder contains the command to run, the
|
46
46
|
relevant files, and the expected output.
|
47
47
|
|
@@ -85,15 +85,28 @@ The space after `filename` is optional.
|
|
85
85
|
|
86
86
|
|
87
87
|
|
88
|
+
### Compile an Entire Folder
|
89
|
+
|
90
|
+

|
91
|
+
|
92
|
+
Process a folder containing templates and `@imports`, and generate a mirror
|
93
|
+
output folder, with all the variables and `@imports` evaluated.
|
94
|
+
|
95
|
+
|
96
|
+
|
88
97
|
### One to Many Generation
|
89
98
|
|
90
99
|

|
91
100
|
|
92
|
-
|
93
|
-
|
101
|
+
Using the `kojo config` command together with a simple definitions file, you
|
102
|
+
can:
|
103
|
+
|
104
|
+
1. Generate multiple output files based on a single template file
|
105
|
+
2. Generate multiple output directories, based on a single source directory.
|
106
|
+
|
107
|
+
To achieve this, you need to:
|
94
108
|
|
95
|
-
1. Create the configuration template
|
96
|
-
where appropriate.
|
109
|
+
1. Create the configuration template or directory of templates.
|
97
110
|
2. Create a configuration YAML file using this syntax:
|
98
111
|
|
99
112
|
```yaml
|
@@ -109,15 +122,22 @@ output:
|
|
109
122
|
argument2: value
|
110
123
|
```
|
111
124
|
|
125
|
+
When using a folder as input, simply provide the folder name in the `input`
|
126
|
+
property, and instead of providing desired output filenames in the `output`
|
127
|
+
property, provide desired output directories:
|
112
128
|
|
129
|
+
```yaml
|
130
|
+
input: base
|
113
131
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
Process a folder containing templates and `@imports`, and generate a mirror
|
119
|
-
output folder, with all the variables and `@imports` evaluated.
|
132
|
+
output:
|
133
|
+
app1:
|
134
|
+
argument1: value
|
135
|
+
argument2: value
|
120
136
|
|
137
|
+
app2:
|
138
|
+
argument1: value
|
139
|
+
argument2: value
|
140
|
+
```
|
121
141
|
|
122
142
|
|
123
143
|
### Conditions and Loops with ERB
|
data/bin/kojo
CHANGED
data/lib/kojo.rb
CHANGED
data/lib/kojo/cli.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Kojo
|
2
|
+
# The Collection class is a wrapper around the {Template} object. It
|
3
|
+
# provides a mechanism for processing an entire directory of templates.
|
4
|
+
class Collection
|
5
|
+
attr_reader :dir
|
6
|
+
attr_accessor :import_base
|
7
|
+
|
8
|
+
def initialize(dir)
|
9
|
+
@dir = dir
|
10
|
+
@import_base = dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(args={}, &block)
|
14
|
+
files.each do |file|
|
15
|
+
handle file, args, &block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def handle(file, args={})
|
22
|
+
template = Template.new file
|
23
|
+
template.import_base = import_base
|
24
|
+
|
25
|
+
path = file.sub(/#{dir}\//, '')
|
26
|
+
|
27
|
+
yield path, template.render(args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def files
|
31
|
+
return @files if @files
|
32
|
+
raise Kojo::NotFoundError, "Directory not found: #{dir}" unless Dir.exist? dir
|
33
|
+
raise Kojo::NotFoundError, "Directory is empty: #{dir}" if Dir.empty? dir
|
34
|
+
|
35
|
+
@files = Dir["#{dir}/**/*"].reject { |f| File.directory? f }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/kojo/commands/config.rb
CHANGED
@@ -2,15 +2,17 @@ require 'fileutils'
|
|
2
2
|
require 'mister_bin'
|
3
3
|
|
4
4
|
module Kojo::Commands
|
5
|
+
# Handle calls to the +kojo config+ command
|
5
6
|
class ConfigCmd < MisterBin::Command
|
6
|
-
attr_reader :gen, :outdir, :opts
|
7
|
+
attr_reader :gen, :outdir, :opts, :import_base, :config_file
|
7
8
|
|
8
9
|
help "Generate based on instructions from a config file"
|
9
10
|
|
10
|
-
usage "kojo config CONFIG [--save DIR --args FILE] [ARGS...]"
|
11
|
+
usage "kojo config CONFIG [--save DIR --imports DIR --args FILE] [ARGS...]"
|
11
12
|
usage "kojo config (-h|--help)"
|
12
13
|
|
13
14
|
option "-s --save DIR", "Save output to directory instead of printing"
|
15
|
+
option "-i --imports DIR", "Specify base directory for @import directives"
|
14
16
|
option "-a --args FILE", "Load arguments from YAML file"
|
15
17
|
|
16
18
|
param "ARGS", "Optional key=value pairs"
|
@@ -21,9 +23,10 @@ module Kojo::Commands
|
|
21
23
|
example "kojo config config.yml -s output --args args.yml"
|
22
24
|
|
23
25
|
def run(args)
|
24
|
-
@
|
26
|
+
@config_file = args['CONFIG']
|
25
27
|
@outdir = args['--save']
|
26
28
|
@opts = args['ARGS'].args_to_hash
|
29
|
+
@import_base = args['--imports']
|
27
30
|
argfile = args['--args']
|
28
31
|
|
29
32
|
if argfile
|
@@ -35,7 +38,10 @@ module Kojo::Commands
|
|
35
38
|
end
|
36
39
|
|
37
40
|
def run!
|
38
|
-
|
41
|
+
config = Kojo::Config.new config_file
|
42
|
+
config.import_base = import_base if import_base
|
43
|
+
|
44
|
+
config.generate opts do |file, output|
|
39
45
|
handle file, output
|
40
46
|
end
|
41
47
|
end
|
data/lib/kojo/commands/dir.rb
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
require 'mister_bin'
|
2
2
|
|
3
3
|
module Kojo::Commands
|
4
|
+
# Handle calls to the +kojo dir+ command
|
4
5
|
class DirCmd < MisterBin::Command
|
5
6
|
attr_reader :opts, :indir, :outdir, :import_base
|
6
7
|
|
7
8
|
help "Compile a folder of templates to a similar output folder"
|
8
9
|
|
9
|
-
usage "kojo dir INDIR [--save DIR --
|
10
|
+
usage "kojo dir INDIR [--save DIR --imports DIR --args FILE] [ARGS...]"
|
10
11
|
usage "kojo dir (-h|--help)"
|
11
12
|
|
12
13
|
option "-s --save DIR", "Save output to directory instead of printing"
|
13
|
-
option "-i --
|
14
|
+
option "-i --imports DIR", "Specify base directory for @import directives"
|
14
15
|
option "-a --args FILE", "Load arguments from YAML file"
|
15
16
|
|
16
17
|
param "ARGS", "Optional key=value pairs"
|
17
18
|
|
18
19
|
example "kojo dir indir"
|
19
20
|
example "kojo dir in --save out env=production"
|
20
|
-
example "kojo dir in --save out --
|
21
|
+
example "kojo dir in --save out --imports snippets env=production"
|
21
22
|
example "kojo dir in -s out -i snippets -a args.yml"
|
22
23
|
|
23
24
|
def run(args)
|
24
25
|
@opts = args['ARGS'].args_to_hash
|
25
26
|
@indir = args['INDIR']
|
26
27
|
@outdir = args['--save']
|
27
|
-
@import_base = args['--
|
28
|
+
@import_base = args['--imports']
|
28
29
|
argfile = args['--args']
|
29
30
|
|
30
31
|
if argfile
|
@@ -37,32 +38,32 @@ module Kojo::Commands
|
|
37
38
|
|
38
39
|
private
|
39
40
|
|
40
|
-
def files
|
41
|
-
@files ||= Dir["#{indir}/**/*"].reject { |file| File.directory? file }
|
42
|
-
end
|
43
|
-
|
44
41
|
def run!
|
45
|
-
|
46
|
-
|
42
|
+
collection = Kojo::Collection.new @indir
|
43
|
+
collection.import_base = import_base if import_base
|
44
|
+
|
45
|
+
if outdir
|
46
|
+
write collection
|
47
|
+
else
|
48
|
+
show collection
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
def show(collection)
|
53
|
+
collection.render @opts do |file, output|
|
54
|
+
say "\n!txtgrn!# #{file}"
|
55
|
+
say output
|
56
|
+
end
|
57
|
+
end
|
54
58
|
|
55
|
-
|
59
|
+
def write(collection)
|
60
|
+
collection.render @opts do |file, output|
|
56
61
|
save file, output
|
57
|
-
else
|
58
|
-
outpath = file.sub(/#{indir}/, '')
|
59
|
-
say "\n!txtgrn!# #{outpath}"
|
60
|
-
say output
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
65
|
def save(file, output)
|
65
|
-
outpath =
|
66
|
+
outpath = "#{outdir}/#{file}"
|
66
67
|
dir = File.dirname outpath
|
67
68
|
FileUtils.mkdir_p dir unless Dir.exist? dir
|
68
69
|
File.write outpath, output
|
data/lib/kojo/commands/file.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'mister_bin'
|
2
2
|
|
3
3
|
module Kojo::Commands
|
4
|
+
# Handle calls to the +kojo file+ command
|
4
5
|
class FileCmd < MisterBin::Command
|
5
|
-
attr_reader :opts, :outfile, :infile
|
6
|
+
attr_reader :opts, :outfile, :infile, :import_base
|
6
7
|
|
7
8
|
help "Compile a file from a template"
|
8
9
|
|
9
|
-
usage "kojo file INFILE [--save FILE --args FILE] [ARGS...]"
|
10
|
+
usage "kojo file INFILE [--save FILE --imports DIR --args FILE] [ARGS...]"
|
10
11
|
usage "kojo file (-h|--help)"
|
11
12
|
|
12
13
|
option "-s --save FILE", "Save to file instead of printing"
|
14
|
+
option "-i --imports DIR", "Specify base directory for @import directives"
|
13
15
|
option "-a --args FILE", "Load arguments from YAML file"
|
14
16
|
|
15
17
|
param "ARGS", "Optional key=value pairs"
|
@@ -23,6 +25,7 @@ module Kojo::Commands
|
|
23
25
|
@opts = args['ARGS'].args_to_hash
|
24
26
|
@outfile = args['--save']
|
25
27
|
@infile = args['INFILE']
|
28
|
+
@import_base = args['--imports']
|
26
29
|
argfile = args['--args']
|
27
30
|
|
28
31
|
if argfile
|
@@ -34,7 +37,9 @@ module Kojo::Commands
|
|
34
37
|
end
|
35
38
|
|
36
39
|
def run!
|
37
|
-
|
40
|
+
template = Kojo::Template.new infile
|
41
|
+
template.import_base = import_base if import_base
|
42
|
+
output = template.render(opts)
|
38
43
|
|
39
44
|
if outfile
|
40
45
|
File.write outfile, output
|
data/lib/kojo/config.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Kojo
|
4
|
+
# The Config class handles multiple template generation from a
|
5
|
+
# definitions YAML file.
|
6
|
+
class Config
|
7
|
+
attr_reader :config_file, :outdir
|
8
|
+
attr_accessor :import_base
|
9
|
+
|
10
|
+
def initialize(config_file)
|
11
|
+
@config_file = config_file
|
12
|
+
@import_base = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate(opts={}, &block)
|
16
|
+
if directory_mode?
|
17
|
+
generate_from_dir opts, &block
|
18
|
+
else
|
19
|
+
generate_from_file opts, &block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def generate_from_file(opts)
|
26
|
+
config['output'].each do |target, config_opts|
|
27
|
+
local_opts = opts.merge config_opts.symbolize_keys
|
28
|
+
|
29
|
+
template = Template.new source
|
30
|
+
template.import_base = import_base if import_base
|
31
|
+
|
32
|
+
yield target, template.render(local_opts)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_from_dir(opts)
|
37
|
+
config['output'].each do |dir, config_opts|
|
38
|
+
local_opts = opts.merge config_opts.symbolize_keys
|
39
|
+
|
40
|
+
collection = Collection.new source
|
41
|
+
collection.import_base = import_base if import_base
|
42
|
+
|
43
|
+
collection.render(local_opts) do |file, output|
|
44
|
+
yield "#{dir}/#{file}", output
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def base_dir
|
50
|
+
@base_dir ||= File.dirname config_file
|
51
|
+
end
|
52
|
+
|
53
|
+
def directory_mode?
|
54
|
+
File.directory? source
|
55
|
+
end
|
56
|
+
|
57
|
+
def source
|
58
|
+
"#{base_dir}/#{config['input']}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def config
|
62
|
+
@config ||= YAML.load_file config_file
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class String
|
2
|
+
# Convert a string to the most appropriate type
|
2
3
|
def to_typed
|
3
4
|
if self =~ /\A[+-]?\d+\Z/
|
4
5
|
self.to_i
|
@@ -6,8 +7,8 @@ class String
|
|
6
7
|
elsif self =~ /\A[+-]?\d+\.\d+\Z/
|
7
8
|
self.to_f
|
8
9
|
|
9
|
-
elsif %w[yes no true false].include?
|
10
|
-
%w[yes true].include?
|
10
|
+
elsif %w[yes no true false].include? downcase
|
11
|
+
%w[yes true].include? downcase
|
11
12
|
|
12
13
|
else
|
13
14
|
self
|
data/lib/kojo/template.rb
CHANGED
@@ -2,30 +2,53 @@ require 'erb'
|
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
4
|
module Kojo
|
5
|
+
# The Template class handles a single template file, and processes it for:
|
6
|
+
# - Variables (using +%{var}+ syntax)
|
7
|
+
# - ERB
|
8
|
+
# - +@import+ statements
|
5
9
|
class Template
|
6
|
-
attr_reader :file, :extension, :
|
10
|
+
attr_reader :file, :extension, :dir, :args
|
7
11
|
attr_accessor :import_base
|
8
12
|
|
9
|
-
def initialize(file
|
13
|
+
def initialize(file)
|
10
14
|
@file = file
|
11
|
-
@
|
12
|
-
@extension = file[/(\..*)$/]
|
15
|
+
@extension = File.extname file
|
13
16
|
@dir = File.dirname file
|
14
17
|
@import_base = dir
|
15
18
|
end
|
16
19
|
|
17
|
-
def render
|
18
|
-
|
20
|
+
def render(args={})
|
21
|
+
@args = args
|
22
|
+
evaluate file
|
19
23
|
end
|
20
24
|
|
21
25
|
private
|
22
26
|
|
23
|
-
def evaluate(file
|
24
|
-
content =
|
27
|
+
def evaluate(file)
|
28
|
+
content = read_file file
|
29
|
+
content = eval_erb content
|
30
|
+
content = eval_vars content
|
31
|
+
content = eval_imports content
|
32
|
+
content
|
33
|
+
end
|
34
|
+
|
35
|
+
def read_file(file)
|
36
|
+
raise Kojo::NotFoundError, "File not found: #{file}" unless File.exist? file
|
37
|
+
File.read file
|
38
|
+
end
|
39
|
+
|
40
|
+
def eval_vars(content)
|
41
|
+
content % args
|
42
|
+
rescue ArgumentError, KeyError => e
|
43
|
+
raise Kojo::TemplateError, "#{e.message}\nin: #{file}"
|
44
|
+
end
|
25
45
|
|
26
|
-
|
27
|
-
|
28
|
-
|
46
|
+
def eval_erb(content)
|
47
|
+
erb content, args
|
48
|
+
rescue RuntimeError => e
|
49
|
+
raise Kojo::TemplateError, "Invalid Ruby code #{e.message}\nin: #{file}"
|
50
|
+
rescue SyntaxError => e
|
51
|
+
raise Kojo::TemplateError, "#{e.message}\nin: #{file}"
|
29
52
|
end
|
30
53
|
|
31
54
|
def eval_imports(content)
|
@@ -52,7 +75,7 @@ module Kojo
|
|
52
75
|
def import(file, import_args={})
|
53
76
|
filename = File.expand_path "#{file}#{extension}", import_base
|
54
77
|
all_args = args.merge import_args
|
55
|
-
self.class.new(filename
|
78
|
+
self.class.new(filename).render(all_args)
|
56
79
|
end
|
57
80
|
|
58
81
|
def erb(template, vars)
|
data/lib/kojo/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kojo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Ben Shitrit
|
@@ -134,13 +134,15 @@ files:
|
|
134
134
|
- bin/kojo
|
135
135
|
- lib/kojo.rb
|
136
136
|
- lib/kojo/cli.rb
|
137
|
+
- lib/kojo/collection.rb
|
137
138
|
- lib/kojo/commands/config.rb
|
138
139
|
- lib/kojo/commands/dir.rb
|
139
140
|
- lib/kojo/commands/file.rb
|
141
|
+
- lib/kojo/config.rb
|
142
|
+
- lib/kojo/exceptions.rb
|
140
143
|
- lib/kojo/extensions/array.rb
|
141
144
|
- lib/kojo/extensions/hash.rb
|
142
145
|
- lib/kojo/extensions/string.rb
|
143
|
-
- lib/kojo/generator.rb
|
144
146
|
- lib/kojo/template.rb
|
145
147
|
- lib/kojo/version.rb
|
146
148
|
homepage: https://github.com/dannyben/kojo
|
data/lib/kojo/generator.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
module Kojo
|
4
|
-
class Generator
|
5
|
-
attr_reader :config_file, :outdir
|
6
|
-
|
7
|
-
def initialize(config_file)
|
8
|
-
@config_file = config_file
|
9
|
-
end
|
10
|
-
|
11
|
-
def generate(opts={})
|
12
|
-
base_dir = File.dirname config_file
|
13
|
-
infile = "#{base_dir}/#{config['input']}"
|
14
|
-
|
15
|
-
config['output'].each do |outfile, config_opts|
|
16
|
-
local_opts = opts.merge config_opts.symbolize_keys
|
17
|
-
output = render infile, local_opts
|
18
|
-
yield outfile, output
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def config
|
25
|
-
@config ||= YAML.load_file config_file
|
26
|
-
end
|
27
|
-
|
28
|
-
def render(infile, opts={})
|
29
|
-
Template.new(infile, opts).render
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|