k_builder 0.0.37 → 0.0.55
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/.rubocop.yml +3 -0
- data/Rakefile +14 -0
- data/STORIES.md +22 -2
- data/USAGE.md +24 -24
- data/k_builder.gemspec +3 -0
- data/lib/k_builder.rb +10 -4
- data/lib/k_builder/base_builder.rb +70 -81
- data/lib/k_builder/base_configuration.rb +1 -1
- data/lib/k_builder/configuration.rb +14 -9
- data/lib/k_builder/file_segments.rb +32 -0
- data/lib/k_builder/version.rb +1 -1
- metadata +45 -5
- data/lib/k_builder/data_helper.rb +0 -66
- data/lib/k_builder/layered_folders.rb +0 -104
- data/lib/k_builder/named_folders.rb +0 -100
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f0600bab4a6de1743b8be1d7f14f4cc20e997edc60201e920fd3102086472bf
|
4
|
+
data.tar.gz: ad10a064ebf45d8e73aac310b7c6725193f3cf36bacc847f0fe2e312919c0b1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3c82683757bf60d630b3e9e6827b57abbaca1bbd83b132e7dd1433961f8946acd651beb5eebf8614cbcd5ad544ea7aa8b7bfd7a7c48feadf87a3e0d8c651acf
|
7
|
+
data.tar.gz: d8c7778a7501ccf7a76611bf15aae7d3824658e48e5249c2a1f7879fad7b18ae354323fe92794171737b1ddd386e38ab254f9f399895acd8af86014f3688e98c
|
data/.rubocop.yml
CHANGED
data/Rakefile
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
GEM_NAME = 'k_builder'
|
4
|
+
|
3
5
|
require 'bundler/gem_tasks'
|
4
6
|
require 'rspec/core/rake_task'
|
7
|
+
require 'k_builder/version'
|
5
8
|
|
6
9
|
RSpec::Core::RakeTask.new(:spec)
|
7
10
|
|
@@ -14,4 +17,15 @@ Rake::ExtensionTask.new('k_builder') do |ext|
|
|
14
17
|
ext.lib_dir = 'lib/k_builder'
|
15
18
|
end
|
16
19
|
|
20
|
+
desc 'Publish the gem to RubyGems.org'
|
21
|
+
task :publish do
|
22
|
+
system 'gem build'
|
23
|
+
system "gem push #{GEM_NAME}-#{KBuilder::VERSION}.gem"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Remove old *.gem files'
|
27
|
+
task :clean do
|
28
|
+
system 'rm *.gem'
|
29
|
+
end
|
30
|
+
|
17
31
|
task default: %i[clobber compile spec]
|
data/STORIES.md
CHANGED
@@ -10,14 +10,34 @@ As a Polyglot Developer, I want to be up and running in any development language
|
|
10
10
|
|
11
11
|
As a Polyglot Developer, I want to be up and running in any development language with consistency, so I am productive and using best practices [EPIC]
|
12
12
|
|
13
|
-
|
13
|
+
As a Developer, I need builders to be easier to use, so I am more efficient
|
14
14
|
|
15
|
-
|
15
|
+
- Logging needs to be more informative
|
16
|
+
- Template errors need to log the template and the filename
|
17
|
+
- add_file with template_file: needs to support optional filename that is the same as the template_file (or use a token, eg. $TF_PATH$, $TF_NAME$, $TF_FILE$
|
18
|
+
- add_file, the files being generated are not being logged
|
16
19
|
|
17
20
|
## Stories and tasks
|
18
21
|
|
22
|
+
### Stories - completed
|
23
|
+
|
24
|
+
As a Developer, I want have multiple template, so I can group my templates by area of specialty
|
25
|
+
|
26
|
+
- Refactor global and app templates to a layered folder array using (First In, Last Out) priority
|
27
|
+
- Support subfolders of any template folder (maybe)
|
28
|
+
|
29
|
+
As a Developer, I want have multiple output folders, so I can write to multiple locations
|
30
|
+
|
31
|
+
- Refactor output folder so that there are multiple named output folders, with :default working the same way as the existing system
|
32
|
+
- Support subfolders of any output folder
|
33
|
+
- Support output folder change of focus
|
34
|
+
|
19
35
|
### Tasks - completed
|
20
36
|
|
37
|
+
WatchBuilder - Build Watcher (as a builder) - [k_builder-watch](https://github.com/klueless-io/k_builder-watch)
|
38
|
+
|
39
|
+
Refactor BaseBuilder
|
40
|
+
|
21
41
|
Setup RubyGems and RubyDoc
|
22
42
|
|
23
43
|
- Build and deploy gem to [rubygems.org](https://rubygems.org/gems/k_builder)
|
data/USAGE.md
CHANGED
@@ -55,26 +55,26 @@ TEXT
|
|
55
55
|
|
56
56
|
builder = KBuilder::Builder.init
|
57
57
|
|
58
|
-
builder
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
58
|
+
builder.add_file('main.rb', template_file: 'class.rb', name: 'main').add_file(
|
59
|
+
'person.rb',
|
60
|
+
template_file: 'model.rb', name: 'person', fields: %i[first_name last_name]
|
61
|
+
).add_file(
|
62
|
+
'address.rb',
|
63
|
+
template_file: 'model.rb',
|
64
|
+
name: 'address',
|
65
|
+
fields: %i[street1 street2 post_code state]
|
66
|
+
).add_file(
|
67
|
+
'configuration.log.txt',
|
68
|
+
template: template,
|
69
|
+
a: builder.template_folder,
|
70
|
+
b: builder.global_template_folder,
|
71
|
+
c: builder.target_folder
|
72
|
+
).add_file(
|
73
|
+
'css/index.css',
|
74
|
+
template: '{{#each colors}} .{{.}} { color: {{.}} } {{/each}}',
|
75
|
+
colors: %w[red blue green],
|
76
|
+
pretty: true
|
77
|
+
)
|
78
78
|
```
|
79
79
|
|
80
80
|
#### Folder Structure (after)
|
@@ -85,7 +85,7 @@ Folder structure after running the builder
|
|
85
85
|
|
86
86
|
#### main.rb
|
87
87
|
|
88
|
-

|
89
89
|
|
90
90
|
#### person.rb
|
91
91
|
|
@@ -93,12 +93,12 @@ Folder structure after running the builder
|
|
93
93
|
|
94
94
|
#### address.rb
|
95
95
|
|
96
|
-

|
97
97
|
|
98
98
|
#### configuration.log.txt
|
99
99
|
|
100
|
-

|
101
101
|
|
102
102
|
#### css/index.css
|
103
103
|
|
104
|
-

|
data/k_builder.gemspec
CHANGED
@@ -39,6 +39,9 @@ Gem::Specification.new do |spec|
|
|
39
39
|
# spec.extensions = ['ext/k_builder/extconf.rb']
|
40
40
|
|
41
41
|
spec.add_dependency 'handlebars-helpers', '~> 0'
|
42
|
+
spec.add_dependency 'k_log', '~> 0'
|
43
|
+
spec.add_dependency 'k_type', '~> 0'
|
44
|
+
spec.add_dependency 'k_util', '~> 0'
|
42
45
|
# spec.add_dependency "anyway_config" , ">= 2.0.0"
|
43
46
|
# spec.add_dependency "config" , ">= 3.0.0"
|
44
47
|
end
|
data/lib/k_builder.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'k_log'
|
4
|
+
require 'k_util'
|
5
|
+
require 'k_type'
|
3
6
|
require 'k_builder/version'
|
4
7
|
require 'k_builder/base_builder'
|
5
8
|
require 'k_builder/base_configuration'
|
6
9
|
require 'k_builder/configuration'
|
7
|
-
require 'k_builder/
|
8
|
-
require 'k_builder/named_folders'
|
9
|
-
require 'k_builder/layered_folders'
|
10
|
+
require 'k_builder/file_segments'
|
10
11
|
|
11
12
|
require 'handlebars/helpers/template'
|
12
13
|
|
13
14
|
module KBuilder
|
14
15
|
# raise KBuilder::Error, 'Sample message'
|
15
16
|
class Error < StandardError; end
|
17
|
+
end
|
16
18
|
|
17
|
-
|
19
|
+
if ENV['KLUE_DEBUG']&.to_s&.downcase == 'true'
|
20
|
+
namespace = 'KBuilder::Version'
|
21
|
+
file_path = $LOADED_FEATURES.find { |f| f.include?('k_builder/version') }
|
22
|
+
version = KBuilder::VERSION.ljust(9)
|
23
|
+
puts "#{namespace.ljust(40)} : #{version.ljust(9)} : #{file_path}"
|
18
24
|
end
|
@@ -41,16 +41,6 @@ module KBuilder
|
|
41
41
|
|
42
42
|
@target_folders = configuration.target_folders.clone
|
43
43
|
@template_folders = configuration.template_folders.clone
|
44
|
-
|
45
|
-
define_builder_setter_methods
|
46
|
-
end
|
47
|
-
|
48
|
-
# Return an array of symbols to represent the fluent
|
49
|
-
# setter methods that you want on your builder.
|
50
|
-
#
|
51
|
-
# Abstract method
|
52
|
-
def builder_setter_methods
|
53
|
-
[]
|
54
44
|
end
|
55
45
|
|
56
46
|
# @return [Hash/StrongType] Returns data object, can be a hash
|
@@ -91,8 +81,9 @@ module KBuilder
|
|
91
81
|
# @option opts [String] :to Recipient email
|
92
82
|
# @option opts [String] :body The email's body
|
93
83
|
def add_file(file, **opts)
|
94
|
-
full_file = target_file(file)
|
84
|
+
full_file = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
|
95
85
|
|
86
|
+
# Need logging options that can log these internal details
|
96
87
|
FileUtils.mkdir_p(File.dirname(full_file))
|
97
88
|
|
98
89
|
content = process_any_content(**opts)
|
@@ -104,6 +95,42 @@ module KBuilder
|
|
104
95
|
|
105
96
|
self
|
106
97
|
end
|
98
|
+
alias touch add_file # it is expected that you would not supply any options, just a file name
|
99
|
+
|
100
|
+
# Add content to the clipboard
|
101
|
+
#
|
102
|
+
# @option opts [String] :content Supply the content that you want to write to the file
|
103
|
+
# @option opts [String] :template Supply the template that you want to write to the file, template will be processed ('nobody') From address
|
104
|
+
# @option opts [String] :content_file File with content, file location is based on where the program is running
|
105
|
+
# @option opts [String] :template_file File with handlebars templated content that will be transformed, file location is based on the configured template_path
|
106
|
+
#
|
107
|
+
# Extra options will be used as data for templates, e.g
|
108
|
+
# @option opts [String] :to Recipient email
|
109
|
+
# @option opts [String] :body The email's body
|
110
|
+
def add_clipboard(**opts)
|
111
|
+
content = process_any_content(**opts)
|
112
|
+
|
113
|
+
begin
|
114
|
+
IO.popen('pbcopy', 'w') { |f| f << content }
|
115
|
+
rescue Errno::ENOENT => e
|
116
|
+
if e.message == 'No such file or directory - pbcopy'
|
117
|
+
# May want to use this GEM in the future
|
118
|
+
# https://github.com/janlelis/clipboard
|
119
|
+
puts 'Clipboard paste is currently only supported on MAC'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
self
|
124
|
+
end
|
125
|
+
alias clipboard_copy add_clipboard
|
126
|
+
|
127
|
+
def vscode(*file_parts, folder: current_folder_key)
|
128
|
+
file = target_file(*file_parts, folder: folder)
|
129
|
+
|
130
|
+
rc "code #{file}"
|
131
|
+
|
132
|
+
self
|
133
|
+
end
|
107
134
|
|
108
135
|
# ----------------------------------------------------------------------
|
109
136
|
# Attributes: Think getter/setter
|
@@ -125,10 +152,6 @@ module KBuilder
|
|
125
152
|
end
|
126
153
|
alias cd set_current_folder
|
127
154
|
|
128
|
-
def current_folder_key
|
129
|
-
target_folders.current
|
130
|
-
end
|
131
|
-
|
132
155
|
# Fluent adder for target folder (KBuilder::NamedFolders)
|
133
156
|
def add_target_folder(folder_key, value)
|
134
157
|
target_folders.add(folder_key, value)
|
@@ -136,16 +159,40 @@ module KBuilder
|
|
136
159
|
self
|
137
160
|
end
|
138
161
|
|
139
|
-
|
162
|
+
def current_folder_key
|
163
|
+
target_folders.current
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get target folder by folder_key
|
140
167
|
#
|
141
|
-
#
|
142
|
-
def
|
168
|
+
# If folder_key not supplied then get the current target folder
|
169
|
+
def target_folder(folder_key = current_folder_key)
|
143
170
|
target_folders.get(folder_key)
|
144
171
|
end
|
145
172
|
|
146
173
|
# Get target file
|
147
|
-
|
148
|
-
|
174
|
+
#
|
175
|
+
# If you provide a relative folder, then it will be relative to the :folder parameter
|
176
|
+
#
|
177
|
+
# If the :folder is not set, then it will be relative to the current folder
|
178
|
+
#
|
179
|
+
# @examples
|
180
|
+
# target_file('abc.txt')
|
181
|
+
# target_file('xyz/abc.txt')
|
182
|
+
# target_file('xyz', 'abc.txt')
|
183
|
+
#
|
184
|
+
# If you provide an absolute folder, then it will ignore the :folder parameter
|
185
|
+
#
|
186
|
+
# @examples
|
187
|
+
# target_file('/abc.txt')
|
188
|
+
# target_file('/xyz/abc.txt')
|
189
|
+
# target_file('/xyz', 'abc.txt')
|
190
|
+
def target_file(*file_parts, folder: current_folder_key)
|
191
|
+
# Absolute path
|
192
|
+
return File.join(*file_parts) if Pathname.new(file_parts.first).absolute?
|
193
|
+
|
194
|
+
# Relative to :folder
|
195
|
+
File.join(target_folder(folder), *file_parts)
|
149
196
|
end
|
150
197
|
|
151
198
|
# Template folder & Files
|
@@ -243,74 +290,16 @@ module KBuilder
|
|
243
290
|
|
244
291
|
def run_command(command)
|
245
292
|
# Deep path create if needed
|
246
|
-
|
293
|
+
tf = target_folder
|
247
294
|
|
248
|
-
FileUtils.mkdir_p(
|
295
|
+
FileUtils.mkdir_p(tf)
|
249
296
|
|
250
|
-
build_command = "cd #{
|
297
|
+
build_command = "cd #{tf} && #{command}"
|
251
298
|
|
252
299
|
puts build_command
|
253
300
|
|
254
301
|
system(build_command)
|
255
302
|
end
|
256
303
|
alias rc run_command
|
257
|
-
|
258
|
-
# TODO
|
259
|
-
# Support Nesting
|
260
|
-
# Support Generation fo the following
|
261
|
-
# - fluent set_
|
262
|
-
# - Support setter (non-fluent)
|
263
|
-
# - Support getter (non-fluent)
|
264
|
-
|
265
|
-
# # builds a nested structure by either builder block or hash
|
266
|
-
# # @param data_structure [type=DataStructure]
|
267
|
-
# # @param builder [type=Builder]
|
268
|
-
# # @param attributes [type=Hash|DataStructure instance]
|
269
|
-
# # @param &block
|
270
|
-
# #
|
271
|
-
# # @return [type=Hash]
|
272
|
-
# def build_nested(data_structure, builder, attributes = {}, &block)
|
273
|
-
# if block_given?
|
274
|
-
# builder.build(&block).to_h
|
275
|
-
# else
|
276
|
-
# build_hash(data_structure, attributes)
|
277
|
-
# end
|
278
|
-
# end
|
279
|
-
|
280
|
-
private
|
281
|
-
|
282
|
-
# #
|
283
|
-
# # @param data_structure [type=DataStructure]
|
284
|
-
# # @param attributes [type=Hash, DataStructure]
|
285
|
-
# #
|
286
|
-
# # @return [type=Hash]
|
287
|
-
# def build_hash(data_structure, attributes)
|
288
|
-
# if attributes.is_a?(data_structure)
|
289
|
-
# attributes.to_h
|
290
|
-
# else
|
291
|
-
# data_structure.new(attributes).to_h
|
292
|
-
# end
|
293
|
-
# end
|
294
|
-
|
295
|
-
# Defines all of the necessary builder setter methods
|
296
|
-
#
|
297
|
-
# @return [Builder] Returns the builder via fluent interface
|
298
|
-
def define_builder_setter_methods
|
299
|
-
builder_setter_methods.each { |method| define_builder_method(method) }
|
300
|
-
self
|
301
|
-
end
|
302
|
-
|
303
|
-
# Defines a method using the convention set_[method_name]
|
304
|
-
#
|
305
|
-
# Convention: Setter methods (are Fluent) and use the prefix set_
|
306
|
-
# Getter methods (are NOT fluent) and return the stored value
|
307
|
-
#
|
308
|
-
# @return [Builder] Returns the builder via fluent interface
|
309
|
-
def define_builder_method(method_name)
|
310
|
-
self.class.send(:define_method, "set_#{method_name}") do |value|
|
311
|
-
@hash[method_name.to_s] = value
|
312
|
-
self
|
313
|
-
end
|
314
|
-
end
|
315
304
|
end
|
316
305
|
end
|
@@ -22,7 +22,7 @@ module KBuilder
|
|
22
22
|
instance_variables.each do |var|
|
23
23
|
value = instance_variable_get(var)
|
24
24
|
|
25
|
-
value =
|
25
|
+
value = KUtil.data.to_hash(value) if complex_type?(value)
|
26
26
|
|
27
27
|
hash[var.to_s.delete('@')] = value
|
28
28
|
end
|
@@ -21,6 +21,8 @@ module KBuilder
|
|
21
21
|
|
22
22
|
# Configuration class
|
23
23
|
class Configuration < BaseConfiguration
|
24
|
+
include KLog::Logging
|
25
|
+
|
24
26
|
attr_accessor :target_folders
|
25
27
|
attr_accessor :template_folders
|
26
28
|
|
@@ -29,8 +31,8 @@ module KBuilder
|
|
29
31
|
# @target_folder = Dir.getwd
|
30
32
|
# @template_folder = File.join(Dir.getwd, '.templates')
|
31
33
|
# @global_template_folder = nil
|
32
|
-
@target_folders = NamedFolders.new
|
33
|
-
@template_folders = LayeredFolders.new
|
34
|
+
@target_folders = KType::NamedFolders.new
|
35
|
+
@template_folders = KType::LayeredFolders.new
|
34
36
|
end
|
35
37
|
|
36
38
|
def initialize_copy(orig)
|
@@ -42,19 +44,22 @@ module KBuilder
|
|
42
44
|
|
43
45
|
# rubocop:disable Metrics/AbcSize
|
44
46
|
def debug
|
45
|
-
|
46
|
-
puts 'kbuilder base configuration'
|
47
|
+
log.subheading 'kbuilder base configuration'
|
47
48
|
|
48
|
-
|
49
|
+
log.section_heading 'target_folders'
|
49
50
|
target_folders.folders.each_key do |key|
|
50
51
|
folder = target_folders.folders[key]
|
51
|
-
kv key.to_s, folder
|
52
|
+
log.kv key.to_s, folder
|
52
53
|
end
|
54
|
+
log.info ''
|
55
|
+
|
56
|
+
log.section_heading 'template folders (search order)'
|
53
57
|
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
template_folders.ordered_keys.each do |key|
|
59
|
+
folder = template_folders.folders[key]
|
60
|
+
log.kv key.to_s, folder
|
57
61
|
end
|
62
|
+
''
|
58
63
|
end
|
59
64
|
# rubocop:enable Metrics/AbcSize
|
60
65
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KBuilder
|
4
|
+
# Splits a file into its base parts (file, path, file_name, extension and file_name_only)
|
5
|
+
#
|
6
|
+
# Provides the interpolate helper to rebuild a different filename using those segments
|
7
|
+
class FileSegments
|
8
|
+
attr_reader :file
|
9
|
+
attr_reader :path
|
10
|
+
attr_reader :file_name
|
11
|
+
attr_reader :ext
|
12
|
+
attr_reader :file_name_only
|
13
|
+
|
14
|
+
def initialize(file)
|
15
|
+
@file = file
|
16
|
+
@path = File.dirname(file)
|
17
|
+
@file_name = File.basename(file)
|
18
|
+
@ext = File.extname(file)
|
19
|
+
@file_name_only = File.basename(file, @ext)
|
20
|
+
end
|
21
|
+
|
22
|
+
def interpolate(target_file)
|
23
|
+
# p str.gsub( /#{var}/, 'foo' ) # => "a test foo"
|
24
|
+
target_file
|
25
|
+
.gsub(/\$T_FILE\$/i, file)
|
26
|
+
.gsub(/\$T_PATH\$/i, path)
|
27
|
+
.gsub(/\$T_FILE_NAME\$/i, file_name)
|
28
|
+
.gsub(/\$T_EXT\$/i, ext)
|
29
|
+
.gsub(/\$T_FILE_NAME_ONLY\$/i, file_name_only)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/k_builder/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: k_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.55
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Cruwys
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: handlebars-helpers
|
@@ -24,6 +24,48 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: k_log
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: k_type
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: k_util
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
27
69
|
description: " K Builder provides various fluent builders for initializing applications
|
28
70
|
with different language requirements\n"
|
29
71
|
email:
|
@@ -56,9 +98,7 @@ files:
|
|
56
98
|
- lib/k_builder/base_builder.rb
|
57
99
|
- lib/k_builder/base_configuration.rb
|
58
100
|
- lib/k_builder/configuration.rb
|
59
|
-
- lib/k_builder/
|
60
|
-
- lib/k_builder/layered_folders.rb
|
61
|
-
- lib/k_builder/named_folders.rb
|
101
|
+
- lib/k_builder/file_segments.rb
|
62
102
|
- lib/k_builder/version.rb
|
63
103
|
- usage/_out1.png
|
64
104
|
- usage/_out2.png
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Attach data helper to the KBuilder module
|
4
|
-
module KBuilder
|
5
|
-
# Data helpers/utils for Kbuilder
|
6
|
-
class << self
|
7
|
-
attr_writer :data
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.data
|
11
|
-
@data ||= DataHelper.new
|
12
|
-
end
|
13
|
-
|
14
|
-
# Helper methods attached to the namespace for working with Data
|
15
|
-
#
|
16
|
-
# Usage: KBuilder.data.to_struct(data)
|
17
|
-
class DataHelper
|
18
|
-
# Convert a hash into a deep OpenStruct or array an array
|
19
|
-
# of objects into an array of OpenStruct
|
20
|
-
def to_struct(data)
|
21
|
-
case data
|
22
|
-
when Hash
|
23
|
-
OpenStruct.new(data.transform_values { |v| to_struct(v) })
|
24
|
-
|
25
|
-
when Array
|
26
|
-
data.map { |o| to_struct(o) }
|
27
|
-
|
28
|
-
else
|
29
|
-
# Some primitave type: String, True/False, Symbol or an ObjectStruct
|
30
|
-
data
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
35
|
-
def struct_to_hash(data)
|
36
|
-
# No test yet
|
37
|
-
if data.is_a?(Array)
|
38
|
-
return data.map { |v| v.is_a?(OpenStruct) ? struct_to_hash(v) : v }
|
39
|
-
end
|
40
|
-
|
41
|
-
return struct_to_hash(data.to_h) if !data.is_a?(Hash) && data.respond_to?(:to_h)
|
42
|
-
|
43
|
-
data.each_pair.with_object({}) do |(key, value), hash|
|
44
|
-
case value
|
45
|
-
when OpenStruct, Struct, Hash
|
46
|
-
hash[key] = struct_to_hash(value)
|
47
|
-
when Array
|
48
|
-
# No test yet
|
49
|
-
values = value.map do |v|
|
50
|
-
v.is_a?(OpenStruct) || v.is_a?(Struct) || v.is_a?(Hash) ? struct_to_hash(v) : v
|
51
|
-
end
|
52
|
-
hash[key] = values
|
53
|
-
else
|
54
|
-
hash[key] = value
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
59
|
-
|
60
|
-
def clean_symbol(value)
|
61
|
-
return value if value.nil?
|
62
|
-
|
63
|
-
value.is_a?(Symbol) ? value.to_s : value
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module KBuilder
|
4
|
-
#
|
5
|
-
# Named folders makes sense for generated/output folders because you may want
|
6
|
-
# more than one type of location to generate output.
|
7
|
-
#
|
8
|
-
# Don't confuse multiple named output folders with sub-paths, when you want to
|
9
|
-
# build up a file name in a child folder, you can do that as part of building
|
10
|
-
# the filename.
|
11
|
-
#
|
12
|
-
# The idea behind named folders is for when you have two or more totally different
|
13
|
-
# outputs that (may live in the a similar location) or live in different locations.
|
14
|
-
|
15
|
-
# Layered folders allow files to be found in any of the searchable folders
|
16
|
-
#
|
17
|
-
# They derive from and thus work just like named folders in that they allow folders
|
18
|
-
# to be stored with easy to remember names/alias's.
|
19
|
-
#
|
20
|
-
# Where they differ is that they are retrieved in preferential search order that is
|
21
|
-
# by default (First In, Last Out) priority aka a Stack (Last In, First Out) or
|
22
|
-
# optionally over ridden via the search_order method
|
23
|
-
#
|
24
|
-
# Layered folders makes sense for use with template files and source data/model
|
25
|
-
# where you can have specific usage files available and if they are not found then
|
26
|
-
# you can use fall-back files in other folders.
|
27
|
-
#
|
28
|
-
# example:
|
29
|
-
# folders = LayeredFolders.new
|
30
|
-
# folders.add(:global , '~/global_templates')
|
31
|
-
# folders.add(:domain , '/my-project/domain_templates')
|
32
|
-
# folders.add(:app , '/my-project/my-app/.templates')
|
33
|
-
#
|
34
|
-
# # Find a file and folder will in folders in this order
|
35
|
-
# # app_templates, then domain_templates and then finally global templates
|
36
|
-
# # ['/my-project/my-app/.templates', '/my-project/domain_templates', '~/global_templates']
|
37
|
-
# #
|
38
|
-
# # Find a file called template1.txt and return its fully-qualified path
|
39
|
-
# folders.find_file('template1.txt')
|
40
|
-
#
|
41
|
-
# # As above, but returns the folder only, file name and sub-paths are ignored
|
42
|
-
# folders.find_file_folder('template1.txt')
|
43
|
-
# folders.find_file_folder('abc/xyz/deep-template.txt')
|
44
|
-
#
|
45
|
-
# # If an additional folder is added, say in child configuration that is designed
|
46
|
-
# # to override some of the global templates, then you can run a search_order
|
47
|
-
# # method to re-order the templates
|
48
|
-
#
|
49
|
-
# folders.add(:global_shim , '~/global_templates_shim')
|
50
|
-
# folders.search_order(:app, :domain, :global_shim, :global)
|
51
|
-
#
|
52
|
-
# class Builder < KBuilder::BaseBuilder
|
53
|
-
class LayeredFolders < KBuilder::NamedFolders
|
54
|
-
attr_reader :ordered_keys
|
55
|
-
attr_reader :ordered_folders
|
56
|
-
|
57
|
-
def initialize
|
58
|
-
super()
|
59
|
-
|
60
|
-
@ordered_keys = []
|
61
|
-
@ordered_folders = []
|
62
|
-
end
|
63
|
-
|
64
|
-
def initialize_copy(orig)
|
65
|
-
super(orig)
|
66
|
-
|
67
|
-
@ordered_keys = orig.ordered_keys.clone
|
68
|
-
@ordered_folders = orig.ordered_folders.clone
|
69
|
-
end
|
70
|
-
|
71
|
-
def add(folder_key, folder)
|
72
|
-
folder = super(folder_key, folder)
|
73
|
-
|
74
|
-
ordered_keys.prepend(folder_key)
|
75
|
-
ordered_folders.prepend(folder)
|
76
|
-
|
77
|
-
folder
|
78
|
-
end
|
79
|
-
|
80
|
-
# File name or array of sub-paths plus file
|
81
|
-
#
|
82
|
-
# Return the folder that a file is found in
|
83
|
-
def find_file(file_parts)
|
84
|
-
folder = find_file_folder(file_parts)
|
85
|
-
folder.nil? ? nil : File.join(folder, file_parts)
|
86
|
-
end
|
87
|
-
|
88
|
-
# File name or array of sub-paths plus file
|
89
|
-
#
|
90
|
-
# Return the folder that a file is found in
|
91
|
-
def find_file_folder(file_parts)
|
92
|
-
ordered_folders.find { |folder| File.exist?(File.join(folder, file_parts)) }
|
93
|
-
end
|
94
|
-
|
95
|
-
def to_h
|
96
|
-
{
|
97
|
-
ordered: {
|
98
|
-
keys: ordered_keys,
|
99
|
-
folders: ordered_folders
|
100
|
-
}
|
101
|
-
}.merge(@folders)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
@@ -1,100 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module KBuilder
|
4
|
-
# Named folders allow folders to be stored with easy to remember names/alias's
|
5
|
-
# Secondarily, you can also build up file names based on these named folders.
|
6
|
-
#
|
7
|
-
# Named folders makes sense for generated/output folders because you may want
|
8
|
-
# more than one type of location to generate output.
|
9
|
-
#
|
10
|
-
# Don't confuse multiple named output folders with sub-paths, when you want to
|
11
|
-
# build up a file name in a child folder, you can do that as part of building
|
12
|
-
# the filename.
|
13
|
-
#
|
14
|
-
# The idea behind named folders is for when you have two or more totally different
|
15
|
-
# outputs that (may live in the a similar location) or live in different locations.
|
16
|
-
# Samples:
|
17
|
-
# name: :code - generating source code into a project
|
18
|
-
# name: :slide - generating slide deck into a documentation folder
|
19
|
-
# name: :webpack - folder where you might generate webpack files, e.g. webpack.config.*.json
|
20
|
-
#
|
21
|
-
# example:
|
22
|
-
# folders = NamedFolders.new
|
23
|
-
# folders.add(:csharp , '~/dev/csharp/cool-project')
|
24
|
-
# folders.add(:package_json , :csharp)
|
25
|
-
# folders.add(:webpack , folders.join(:csharp, 'config'))
|
26
|
-
# folders.add(:builder , folders.join(:csharp, 'builder'))
|
27
|
-
# folders.add(:slides , '~/doc/csharp/cool-project')
|
28
|
-
#
|
29
|
-
# puts folders.get(:builder)
|
30
|
-
#
|
31
|
-
# puts folders.get_filename(:csharp, 'Program.cs')
|
32
|
-
# puts folders.get_filename(:csharp, 'Models/Order.cs')
|
33
|
-
# puts folders.get_filename(:csharp, 'Models', 'Order.cs')
|
34
|
-
#
|
35
|
-
# Do I need to support :default?
|
36
|
-
class NamedFolders
|
37
|
-
attr_reader :folders
|
38
|
-
|
39
|
-
attr_reader :current
|
40
|
-
|
41
|
-
def initialize
|
42
|
-
@folders = {}
|
43
|
-
@current = nil
|
44
|
-
end
|
45
|
-
|
46
|
-
def initialize_copy(orig)
|
47
|
-
super(orig)
|
48
|
-
|
49
|
-
@folders = orig.folders.clone
|
50
|
-
end
|
51
|
-
|
52
|
-
def current=(folder_key)
|
53
|
-
guard_folder_key(folder_key)
|
54
|
-
@current = folder_key
|
55
|
-
end
|
56
|
-
|
57
|
-
def add(folder_key, folder)
|
58
|
-
# get a predefined folder by symbol
|
59
|
-
if folder.is_a?(Symbol)
|
60
|
-
folder = get(folder)
|
61
|
-
elsif folder.start_with?('~')
|
62
|
-
folder = File.expand_path(folder)
|
63
|
-
end
|
64
|
-
|
65
|
-
@current = folder_key if @current.nil?
|
66
|
-
folders[folder_key] = folder
|
67
|
-
end
|
68
|
-
|
69
|
-
# Get a folder
|
70
|
-
def get(folder_key)
|
71
|
-
guard_folder_key(folder_key)
|
72
|
-
folders[folder_key]
|
73
|
-
end
|
74
|
-
|
75
|
-
# Join the lookup folder key with the subpath folder parts (optionally + filename) and return the folder or filename
|
76
|
-
#
|
77
|
-
# Return fully qualified filename
|
78
|
-
def join(folder_key, *file_folder_parts)
|
79
|
-
folder = get(folder_key)
|
80
|
-
|
81
|
-
File.join(folder, file_folder_parts)
|
82
|
-
end
|
83
|
-
# Get a file name using the lookup folder key and the file name or array of sub-paths plus filename
|
84
|
-
alias get_filename join
|
85
|
-
|
86
|
-
def folder_keys
|
87
|
-
@folders.keys
|
88
|
-
end
|
89
|
-
|
90
|
-
def to_h
|
91
|
-
@folders
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
|
96
|
-
def guard_folder_key(folder_key)
|
97
|
-
raise KBuilder::Error, "Folder not found, this folder key not found: #{folder_key}" unless folders.key?(folder_key)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|