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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '094bf462c5d39f6b39aa8df40e75d4623af9c5d1f6594109cb7afb4e9e82bfb2'
4
- data.tar.gz: 4dd0400aa1a64e797c56aacc53d3af7ef4cda66c5aca9bbc32f13aeb1604e481
3
+ metadata.gz: 3f0600bab4a6de1743b8be1d7f14f4cc20e997edc60201e920fd3102086472bf
4
+ data.tar.gz: ad10a064ebf45d8e73aac310b7c6725193f3cf36bacc847f0fe2e312919c0b1b
5
5
  SHA512:
6
- metadata.gz: a6196e9716b5e86f7cbdb5dba23252a5e7c477da329e2aa8a6a9989c59b790be10316130a9286fd6c5041c49d85a10282dc206a52ef5c73ce2ddf66601ad3c72
7
- data.tar.gz: 301407050730841e77aad746a32bf046c636970346c4cda6f158699a571d125617eef1e15159a6495ba81fff19c125e25578a57f84407958a19c12f73f706dea
6
+ metadata.gz: b3c82683757bf60d630b3e9e6827b57abbaca1bbd83b132e7dd1433961f8946acd651beb5eebf8614cbcd5ad544ea7aa8b7bfd7a7c48feadf87a3e0d8c651acf
7
+ data.tar.gz: d8c7778a7501ccf7a76611bf15aae7d3824658e48e5249c2a1f7879fad7b18ae354323fe92794171737b1ddd386e38ab254f9f399895acd8af86014f3688e98c
data/.rubocop.yml CHANGED
@@ -73,6 +73,9 @@ Layout/EmptyLineBetweenDefs:
73
73
  Exclude:
74
74
  - "**/spec/**/*"
75
75
 
76
+ Style/Documentation:
77
+ Enabled: false
78
+
76
79
  Lint/AmbiguousBlockAssociation:
77
80
  Exclude:
78
81
  - "**/spec/**/*"
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
- ### Tasks next on list
13
+ As a Developer, I need builders to be easier to use, so I am more efficient
14
14
 
15
- BaseBuilder
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
- .add_file('main.rb', template_file: 'class.rb', name: 'main')
60
- .add_file('person.rb',
61
- template_file: 'model.rb',
62
- name: 'person',
63
- fields: %i[first_name last_name])
64
- .add_file('address.rb',
65
- template_file: 'model.rb',
66
- name: 'address',
67
- fields: %i[street1 street2 post_code state])
68
- .add_file('configuration.log.txt',
69
- template: template,
70
- a: builder.template_folder,
71
- b: builder.global_template_folder,
72
- c: builder.target_folder)
73
- .add_file('css/index.css',
74
- template: '{{#each colors}} .{{.}} { color: {{.}} } {{/each}}',
75
- colors: ['red', 'blue', 'green'],
76
- pretty: true)
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
- ![main.rb](usage/_out1.png)
88
+ ![](usage/_out1.png)
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
- ![person.rb](usage/_out3.png)
96
+ ![](usage/_out3.png)
97
97
 
98
98
  #### configuration.log.txt
99
99
 
100
- ![configuration.log.txt](usage/_out4.png)
100
+ ![](usage/_out4.png)
101
101
 
102
102
  #### css/index.css
103
103
 
104
- ![css/index.css](usage/_out5.png)
104
+ ![](usage/_out5.png)
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/data_helper'
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
- # Your code goes here...
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
- # Get target folder
162
+ def current_folder_key
163
+ target_folders.current
164
+ end
165
+
166
+ # Get target folder by folder_key
140
167
  #
141
- # Defaults to current_target_folder
142
- def get_target_folder(folder_key = current_folder_key)
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
- def target_file(file_parts, folder: current_folder_key)
148
- File.join(get_target_folder(folder), file_parts)
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
- target_folder = get_target_folder
293
+ tf = target_folder
247
294
 
248
- FileUtils.mkdir_p(target_folder)
295
+ FileUtils.mkdir_p(tf)
249
296
 
250
- build_command = "cd #{target_folder} && #{command}"
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 = KBuilder.data.struct_to_hash(value) if complex_type?(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
- puts '-' * 120
46
- puts 'kbuilder base configuration'
47
+ log.subheading 'kbuilder base configuration'
47
48
 
48
- puts 'target_folders'
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
- puts 'template folders (search order)'
55
- template_folders.ordered_folders.each do |folder|
56
- puts folder.to_s
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KBuilder
4
- VERSION = '0.0.37'
4
+ VERSION = '0.0.55'
5
5
  end
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.37
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-03-20 00:00:00.000000000 Z
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/data_helper.rb
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