k_builder 0.0.37 → 0.0.55

Sign up to get free protection for your applications and to get access to all the features.
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