k_builder 0.0.60 → 0.0.68
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 +1 -0
- data/Sample-original.xml +103 -0
- data/Sample.drawio +103 -0
- data/Sample.xml +103 -0
- data/bin/k +1 -1
- data/hooks/pre-commit +2 -0
- data/k_builder.gemspec +2 -1
- data/lib/k_builder/assets/a.html +235 -0
- data/lib/k_builder/assets/b.html +109 -0
- data/lib/k_builder/assets/highlight.min.js +1120 -0
- data/lib/k_builder/assets/highlight_css +1 -0
- data/lib/k_builder/assets/ruby.min.js +7 -0
- data/lib/k_builder/base_builder.rb +226 -22
- data/lib/k_builder/commands/base_command.rb +36 -0
- data/lib/k_builder/commands/code_syntax_highlighter_command.rb +71 -0
- data/lib/k_builder/commands/rubo_cop_command.rb +112 -0
- data/lib/k_builder/configuration.rb +22 -12
- data/lib/k_builder/version.rb +1 -1
- data/lib/k_builder.rb +7 -0
- metadata +28 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/Users/davidcruwys/dev/slides-addons/highlight_css
|
|
@@ -1,21 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module KBuilder
|
|
4
|
+
# TODO: Why is this called BaseBuilder, why not just builder
|
|
5
|
+
# TODO: Is this really the builder pattern, it could be the class used by a director
|
|
6
|
+
# but it is not really storing information for builder purposes.
|
|
7
|
+
#
|
|
4
8
|
# Base builder defines builder methods, build method and configuration
|
|
5
9
|
#
|
|
6
10
|
# Convention: Setter methods (are Fluent) and use the prefix set_
|
|
7
11
|
# Getter methods (are NOT fluent) and return the stored value
|
|
8
12
|
# Setter methods (are NOT fluent) can be created as needed
|
|
9
13
|
# these methods would not be prefixed with the set_
|
|
14
|
+
|
|
15
|
+
# process_any_content(content: 'abc')
|
|
16
|
+
# process_any_content(content_file: 'abc.txt')
|
|
17
|
+
# process_any_content(template: 'abc {{name}}', name: 'sean')
|
|
18
|
+
# process_any_content(template_file: 'abc.txt', name: 'sean')
|
|
19
|
+
|
|
20
|
+
# process_any_content(content_gist: 'https://gist.github.com/klueless-io/8d4b6d199dbe4a5d40807a47fff8ed1c')
|
|
21
|
+
# process_any_content(template_gist: 'https://gist.github.com/klueless-io/8d4b6d199dbe4a5d40807a47fff8ed1c', name: 'sean')
|
|
22
|
+
|
|
10
23
|
class BaseBuilder
|
|
11
24
|
include KLog::Logging
|
|
12
25
|
|
|
13
26
|
attr_reader :configuration
|
|
14
27
|
|
|
15
28
|
attr_accessor :target_folders
|
|
16
|
-
|
|
17
29
|
attr_accessor :template_folders
|
|
18
30
|
|
|
31
|
+
attr_accessor :last_output_file
|
|
32
|
+
attr_accessor :last_output_folder
|
|
33
|
+
# attr_accessor :last_template
|
|
34
|
+
attr_accessor :last_template_file
|
|
35
|
+
|
|
19
36
|
# Factory method that provides a builder for a specified structure
|
|
20
37
|
# runs through a configuration block and then builds the final structure
|
|
21
38
|
#
|
|
@@ -59,6 +76,7 @@ module KBuilder
|
|
|
59
76
|
}
|
|
60
77
|
end
|
|
61
78
|
|
|
79
|
+
# rubocop:disable Metrics/AbcSize
|
|
62
80
|
def debug
|
|
63
81
|
log.subheading 'kbuilder'
|
|
64
82
|
|
|
@@ -69,8 +87,16 @@ module KBuilder
|
|
|
69
87
|
log.info ''
|
|
70
88
|
|
|
71
89
|
template_folders.debug(title: 'template folders (search order)')
|
|
90
|
+
|
|
91
|
+
log.info ''
|
|
92
|
+
log.kv 'last output file' , last_output_file
|
|
93
|
+
log.kv 'last output folder' , last_output_folder
|
|
94
|
+
# log.kv 'last template' , last_template
|
|
95
|
+
log.kv 'last template file' , last_template_file
|
|
96
|
+
|
|
72
97
|
''
|
|
73
98
|
end
|
|
99
|
+
# rubocop:enable Metrics/AbcSize
|
|
74
100
|
|
|
75
101
|
# ----------------------------------------------------------------------
|
|
76
102
|
# Fluent interface
|
|
@@ -95,31 +121,92 @@ module KBuilder
|
|
|
95
121
|
# Extra options will be used as data for templates, e.g
|
|
96
122
|
# @option opts [String] :to Recipient email
|
|
97
123
|
# @option opts [String] :body The email's body
|
|
124
|
+
def add_file_command(file, **opts)
|
|
125
|
+
{
|
|
126
|
+
action: :add_file,
|
|
127
|
+
file: file,
|
|
128
|
+
opts: opts
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
98
133
|
def add_file(file, **opts)
|
|
99
134
|
# move to command
|
|
100
|
-
full_file = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
|
|
135
|
+
full_file = target_file(file, **opts) # opts.key?(:folder_key) || opts.key?(:folder) ? target_file(file, folder: opts[:folder], folder_key: opts[:folder_key]) : target_file(file)
|
|
101
136
|
|
|
102
137
|
# Need logging options that can log these internal details
|
|
103
|
-
|
|
138
|
+
mkdir_p(File.dirname(full_file))
|
|
104
139
|
|
|
105
140
|
content = process_any_content(**opts)
|
|
106
141
|
|
|
107
|
-
|
|
142
|
+
file_write(full_file, content, on_exist: opts[:on_exist])
|
|
108
143
|
|
|
109
144
|
# Prettier needs to work with the original file name
|
|
110
|
-
run_prettier file
|
|
145
|
+
run_prettier file if opts.key?(:pretty)
|
|
146
|
+
# TODO: Add test
|
|
147
|
+
run_cop(full_file, fix_safe: true) if opts.key?(:cop) || opts.key?(:ruby_cop)
|
|
148
|
+
|
|
111
149
|
# Need support for rubocop -a
|
|
150
|
+
open_file(last_output_file) if opts.key?(:open)
|
|
151
|
+
open_file(last_template_file) if opts.key?(:open_template)
|
|
152
|
+
browse_file(last_output_file) if opts.key?(:browse)
|
|
153
|
+
pause(opts[:pause]) if opts[:pause]
|
|
112
154
|
|
|
113
155
|
self
|
|
114
156
|
end
|
|
157
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
158
|
+
|
|
159
|
+
def replay_commands(commands)
|
|
160
|
+
commands.each do |command|
|
|
161
|
+
case command[:action]
|
|
162
|
+
when :add_file
|
|
163
|
+
add_file(command[:file], command[:opts])
|
|
164
|
+
when :delete_file
|
|
165
|
+
delete_file(command[:file], command[:opts])
|
|
166
|
+
else
|
|
167
|
+
log.error "Unknown command: #{command[:action]}"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
115
172
|
alias touch add_file # it is expected that you would not supply any options, just a file name
|
|
116
173
|
|
|
174
|
+
def delete_file_command(file, **opts)
|
|
175
|
+
{
|
|
176
|
+
action: :delete_file,
|
|
177
|
+
file: file,
|
|
178
|
+
opts: opts
|
|
179
|
+
}
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def delete_file(file, **opts)
|
|
183
|
+
full_file = target_file(file, **opts) # = opts.key?(:folder_key) ? target_file(file, folder: opts[:folder_key]) : target_file(file)
|
|
184
|
+
|
|
185
|
+
File.delete(full_file) if File.exist?(full_file)
|
|
186
|
+
|
|
187
|
+
self
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def file_exist?(file, **opts)
|
|
191
|
+
# full_file = opts.key?(:folder_key) ? target_file(file, folder_key: opts[:folder_key]) : target_file(file)
|
|
192
|
+
full_file = target_file(file, **opts)
|
|
193
|
+
|
|
194
|
+
File.exist?(full_file)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# ToDo
|
|
198
|
+
# def delete_folder(file)
|
|
199
|
+
# FileUtils.remove_dir(path_to_directory) if File.directory?(path_to_directory)
|
|
200
|
+
|
|
201
|
+
# self
|
|
202
|
+
# end
|
|
203
|
+
|
|
117
204
|
def make_folder(folder_key = nil, sub_path: nil)
|
|
118
205
|
folder_key = current_folder_key if folder_key.nil?
|
|
119
206
|
folder = target_folder(folder_key)
|
|
120
207
|
folder = File.join(folder, sub_path) unless sub_path.nil?
|
|
121
208
|
|
|
122
|
-
|
|
209
|
+
mkdir_p(folder)
|
|
123
210
|
|
|
124
211
|
self
|
|
125
212
|
end
|
|
@@ -140,6 +227,8 @@ module KBuilder
|
|
|
140
227
|
|
|
141
228
|
begin
|
|
142
229
|
IO.popen('pbcopy', 'w') { |f| f << content }
|
|
230
|
+
|
|
231
|
+
open_file(last_template_file) if opts.key?(:open_template)
|
|
143
232
|
rescue Errno::ENOENT => e
|
|
144
233
|
if e.message == 'No such file or directory - pbcopy'
|
|
145
234
|
# May want to use this GEM in the future
|
|
@@ -152,15 +241,82 @@ module KBuilder
|
|
|
152
241
|
end
|
|
153
242
|
alias clipboard_copy add_clipboard
|
|
154
243
|
|
|
155
|
-
def
|
|
244
|
+
def vscode_command(*file_parts, folder_key: current_folder_key, file: nil)
|
|
245
|
+
{
|
|
246
|
+
action: :vscode,
|
|
247
|
+
file_parts: file_parts,
|
|
248
|
+
opts: { folder_key: folder_key, file: file }
|
|
249
|
+
}
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def vscode(*file_parts, folder_key: current_folder_key, file: nil)
|
|
156
253
|
# move to command
|
|
157
|
-
file = target_file(*file_parts,
|
|
254
|
+
file = target_file(*file_parts, folder_key: folder_key) if file.nil?
|
|
158
255
|
|
|
159
256
|
rc "code #{file}"
|
|
160
257
|
|
|
161
258
|
self
|
|
162
259
|
end
|
|
163
260
|
|
|
261
|
+
def browse_command(*file_parts, folder_key: current_folder_key, file: nil)
|
|
262
|
+
{
|
|
263
|
+
action: :browse,
|
|
264
|
+
file_parts: file_parts,
|
|
265
|
+
opts: { folder_key: folder_key, file: file }
|
|
266
|
+
}
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def browse(*file_parts, folder_key: current_folder_key, file: nil)
|
|
270
|
+
# move to command
|
|
271
|
+
file = target_file(*file_parts, folder_key: folder_key) if file.nil?
|
|
272
|
+
|
|
273
|
+
rc "open -a \"Google Chrome\" #{file}"
|
|
274
|
+
|
|
275
|
+
self
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def open
|
|
279
|
+
open_file(last_output_file)
|
|
280
|
+
|
|
281
|
+
self
|
|
282
|
+
end
|
|
283
|
+
alias o open
|
|
284
|
+
|
|
285
|
+
def open_template
|
|
286
|
+
open_file(last_template_file)
|
|
287
|
+
|
|
288
|
+
self
|
|
289
|
+
end
|
|
290
|
+
alias ot open_template
|
|
291
|
+
|
|
292
|
+
def open_file(file)
|
|
293
|
+
if file.nil?
|
|
294
|
+
log.warn('open_file will not open when file is nil')
|
|
295
|
+
return self
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
vscode(file: file)
|
|
299
|
+
|
|
300
|
+
self
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def browse_file(file)
|
|
304
|
+
if file.nil?
|
|
305
|
+
log.warn('browse_file will not browse when file is nil')
|
|
306
|
+
return self
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
browse(file: file)
|
|
310
|
+
|
|
311
|
+
self
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def pause(seconds = 1)
|
|
315
|
+
sleep(seconds)
|
|
316
|
+
|
|
317
|
+
self
|
|
318
|
+
end
|
|
319
|
+
|
|
164
320
|
# ----------------------------------------------------------------------
|
|
165
321
|
# Attributes: Think getter/setter
|
|
166
322
|
#
|
|
@@ -216,12 +372,18 @@ module KBuilder
|
|
|
216
372
|
# target_file('/abc.txt')
|
|
217
373
|
# target_file('/xyz/abc.txt')
|
|
218
374
|
# target_file('/xyz', 'abc.txt')
|
|
219
|
-
def target_file(*file_parts, folder:
|
|
375
|
+
def target_file(*file_parts, folder_key: current_folder_key, folder: nil, **)
|
|
376
|
+
# TODO: Mismatch (sometimes called folder, sometimes called folder_key:)
|
|
377
|
+
if folder
|
|
378
|
+
log.error("Change folder: to folder_key: for #{folder} - #{file_parts}")
|
|
379
|
+
return
|
|
380
|
+
end
|
|
381
|
+
|
|
220
382
|
# Absolute path
|
|
221
383
|
return File.join(*file_parts) if Pathname.new(file_parts.first).absolute?
|
|
222
384
|
|
|
223
|
-
# Relative to :
|
|
224
|
-
File.join(target_folder(
|
|
385
|
+
# Relative to :folder_key
|
|
386
|
+
File.join(target_folder(folder_key), *file_parts)
|
|
225
387
|
end
|
|
226
388
|
|
|
227
389
|
# Template folder & Files
|
|
@@ -242,7 +404,8 @@ module KBuilder
|
|
|
242
404
|
# Gets a template_file relative to the template folder, looks first in
|
|
243
405
|
# local template folder and if not found, looks in global template folder
|
|
244
406
|
def find_template_file(file_parts)
|
|
245
|
-
template_folders.find_file(file_parts)
|
|
407
|
+
self.last_template_file = template_folders.find_file(file_parts)
|
|
408
|
+
last_template_file
|
|
246
409
|
end
|
|
247
410
|
|
|
248
411
|
# Building content from templates
|
|
@@ -268,15 +431,6 @@ module KBuilder
|
|
|
268
431
|
|
|
269
432
|
return "content not found: #{opts[:content_file]}" if cf.nil?
|
|
270
433
|
|
|
271
|
-
# cf = opts[:content_file]
|
|
272
|
-
|
|
273
|
-
# unless File.exist?(cf)
|
|
274
|
-
# cf_from_template_folders = find_template_file(cf)
|
|
275
|
-
# return "Content not found: #{File.expand_path(cf)}" unless File.exist?(cf_from_template_folders)
|
|
276
|
-
|
|
277
|
-
# cf = cf_from_template_folders
|
|
278
|
-
# end
|
|
279
|
-
|
|
280
434
|
File.read(cf)
|
|
281
435
|
end
|
|
282
436
|
|
|
@@ -320,6 +474,15 @@ module KBuilder
|
|
|
320
474
|
Handlebars::Helpers::Template.render(template_content, opts) unless template_content.nil?
|
|
321
475
|
end
|
|
322
476
|
|
|
477
|
+
def run_cop(file, **opts)
|
|
478
|
+
command = Commands::RuboCopCommand.new(file, builder: self, **opts)
|
|
479
|
+
command.execute
|
|
480
|
+
|
|
481
|
+
self
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
# Need to handle absolute files, see
|
|
485
|
+
# /Users/davidcruwys/dev/printspeak/reference_application/printspeak-domain/.builders/presentation/presentation_builder/commands/copy_ruby_resource_command.rb
|
|
323
486
|
def run_prettier(file, log_level: :log)
|
|
324
487
|
# command = "prettier --check #{file} --write #{file}"
|
|
325
488
|
command = "npx prettier --loglevel #{log_level} --write #{file}"
|
|
@@ -331,7 +494,7 @@ module KBuilder
|
|
|
331
494
|
# Deep path create if needed
|
|
332
495
|
tf = target_folder
|
|
333
496
|
|
|
334
|
-
|
|
497
|
+
mkdir_p(tf)
|
|
335
498
|
|
|
336
499
|
build_command = "cd #{tf} && #{command}"
|
|
337
500
|
|
|
@@ -342,5 +505,46 @@ module KBuilder
|
|
|
342
505
|
system(build_command)
|
|
343
506
|
end
|
|
344
507
|
alias rc run_command
|
|
508
|
+
|
|
509
|
+
def file_write(file, content, on_exist: :skip)
|
|
510
|
+
self.last_output_file = file # if file not found, we still want to record this as the last_output_file
|
|
511
|
+
|
|
512
|
+
not_found = !File.exist?(file)
|
|
513
|
+
|
|
514
|
+
if not_found
|
|
515
|
+
File.write(file, content)
|
|
516
|
+
return
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
return if %i[skip ignore].include?(on_exist)
|
|
520
|
+
|
|
521
|
+
if %i[overwrite write].include?(on_exist)
|
|
522
|
+
File.write(file, content)
|
|
523
|
+
return
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
return unless on_exist == :compare
|
|
527
|
+
|
|
528
|
+
vscompare(file, content)
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
def vscompare(file, content)
|
|
532
|
+
# need to use some sort of caching folder for this
|
|
533
|
+
ext = File.extname(file)
|
|
534
|
+
fn = File.basename(file, ext)
|
|
535
|
+
temp_file = Tempfile.new([fn, ext])
|
|
536
|
+
|
|
537
|
+
temp_file.write(content)
|
|
538
|
+
temp_file.close
|
|
539
|
+
|
|
540
|
+
return if File.read(file) == content
|
|
541
|
+
|
|
542
|
+
system("code -d #{file} #{temp_file.path}")
|
|
543
|
+
sleep 2
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def mkdir_p(folder)
|
|
547
|
+
@last_output_folder = FileUtils.mkdir_p(folder).first
|
|
548
|
+
end
|
|
345
549
|
end
|
|
346
550
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBuilder
|
|
4
|
+
module Commands
|
|
5
|
+
# Base command for single responsibility actions that can be fired
|
|
6
|
+
# from methods in the builder.
|
|
7
|
+
#
|
|
8
|
+
# Uses the command pattern
|
|
9
|
+
class BaseCommand
|
|
10
|
+
include KLog::Logging
|
|
11
|
+
|
|
12
|
+
attr_accessor :builder
|
|
13
|
+
attr_accessor :valid
|
|
14
|
+
|
|
15
|
+
def initialize(**opts)
|
|
16
|
+
@builder = opts[:builder]
|
|
17
|
+
@valid = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def guard(message)
|
|
21
|
+
# THIS SHOULD ONLY LOG IF DEBUGGING IS TURNED ON
|
|
22
|
+
log.error(message)
|
|
23
|
+
@valid = false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def valid?
|
|
27
|
+
@valid
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def debug(title: nil)
|
|
31
|
+
log.section_heading(title) if title
|
|
32
|
+
debug_values if respond_to?(:debug_values)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBuilder
|
|
4
|
+
module Commands
|
|
5
|
+
# Run CodeSyntaxHighlighter against source code and produce a styled HTML representation
|
|
6
|
+
#
|
|
7
|
+
# Alternatives to Highlighter-js could be carbon-now and ray.so
|
|
8
|
+
class CodeSyntaxHighlighterCommand < BaseCommand
|
|
9
|
+
attr_reader :source_code
|
|
10
|
+
attr_reader :formatted_code
|
|
11
|
+
|
|
12
|
+
def initialize(source_code, **opts)
|
|
13
|
+
super(**opts)
|
|
14
|
+
|
|
15
|
+
self.source_code = source_code
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def execute
|
|
19
|
+
return unless valid?
|
|
20
|
+
|
|
21
|
+
run
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def source_code=(value)
|
|
27
|
+
@source_code = value
|
|
28
|
+
|
|
29
|
+
guard('Source code is required for formatting') if value.nil? || value.empty?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def run
|
|
33
|
+
# @formatted_code = ExecJS.eval("'red yellow blue'.split(' ')")
|
|
34
|
+
|
|
35
|
+
# # highlight_source = 'lib/k_builder/assets/a.js'
|
|
36
|
+
# highlight_source = 'lib/k_builder/assets/highlight.min.js'
|
|
37
|
+
|
|
38
|
+
# log.error ExecJS.runtime.name
|
|
39
|
+
|
|
40
|
+
# a = File.read(highlight_source)
|
|
41
|
+
# # context = ExecJS.compile(a)
|
|
42
|
+
# context = ExecJS.compile(highlight_source)
|
|
43
|
+
# context.call("html = hljs.highlightAuto('<h1>Hello World!</h1>').value")
|
|
44
|
+
|
|
45
|
+
# get_js_asset('highlight')
|
|
46
|
+
# get_js_asset('ruby')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/highlight.min.js
|
|
50
|
+
# https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/languages/ruby.min.js
|
|
51
|
+
|
|
52
|
+
def get_js_asset(name)
|
|
53
|
+
url = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/#{name}.min.js"
|
|
54
|
+
target_folder = 'lib/k_builder/assets'
|
|
55
|
+
file = "#{name}.min.js"
|
|
56
|
+
|
|
57
|
+
get_asset(url, target_folder, file)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_asset(url, target_folder, file)
|
|
61
|
+
local_asset_file = File.join(target_folder, file)
|
|
62
|
+
|
|
63
|
+
return if File.exist?(local_asset_file)
|
|
64
|
+
|
|
65
|
+
content = Net::HTTP.get(URI.parse(url))
|
|
66
|
+
|
|
67
|
+
File.write(local_asset_file, content)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module KBuilder
|
|
4
|
+
module Commands
|
|
5
|
+
# Run RuboCop against a file
|
|
6
|
+
class RuboCopCommand < BaseCommand
|
|
7
|
+
attr_reader :file_pattern
|
|
8
|
+
attr_reader :fix_safe
|
|
9
|
+
attr_reader :fix_unsafe
|
|
10
|
+
attr_reader :rubo_config_file
|
|
11
|
+
attr_reader :show_console
|
|
12
|
+
|
|
13
|
+
attr_reader :cop_options
|
|
14
|
+
attr_reader :cop_opt_values
|
|
15
|
+
|
|
16
|
+
# Initialize RuboCop command
|
|
17
|
+
#
|
|
18
|
+
# @param [String] file_pattern File name or file pattern
|
|
19
|
+
# @param [Hash] **opts The options
|
|
20
|
+
# @option opts [Boolean] :fix_safe RuboCop -a option will fix simple and safe issues
|
|
21
|
+
# @option opts [Boolean] :fix_unsafe RuboCop -A option will fix simple but potentially unsafe issues
|
|
22
|
+
# @option opts [Boolean] :show_console This will show in console, or if false set --out ~/last_cop.txt so that console is redirected to file
|
|
23
|
+
# @option opts [String] :rubo_config_file YAML file with RuboCop configuration options
|
|
24
|
+
#
|
|
25
|
+
# @example Cop for single file with auto fix turned on for simple issues
|
|
26
|
+
#
|
|
27
|
+
# RubCopCommand.new('abc.rb', fix_safe: true)
|
|
28
|
+
#
|
|
29
|
+
# @example Cop for all spec files to auto simple and unsafe issues
|
|
30
|
+
#
|
|
31
|
+
# RubCopCommand.new('spec/**/*.rb', fix_unsafe: true)
|
|
32
|
+
def initialize(file_pattern, **opts)
|
|
33
|
+
super(**opts)
|
|
34
|
+
|
|
35
|
+
@valid = true
|
|
36
|
+
|
|
37
|
+
self.file_pattern = file_pattern
|
|
38
|
+
|
|
39
|
+
self.fix_safe = opts[:fix_safe]
|
|
40
|
+
self.fix_unsafe = opts[:fix_unsafe]
|
|
41
|
+
self.show_console = opts[:show_console]
|
|
42
|
+
self.rubo_config_file = opts[:rubo_config_file]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def execute
|
|
46
|
+
return unless valid?
|
|
47
|
+
|
|
48
|
+
cop_run
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def cli_options
|
|
52
|
+
cli_options = []
|
|
53
|
+
# quite is the same as simple, except you will see nothing if no offenses
|
|
54
|
+
cli_options << '--format' << 'quiet' # 'simple'
|
|
55
|
+
cli_options << '-a' if fix_safe
|
|
56
|
+
cli_options << '-A' if fix_unsafe
|
|
57
|
+
cli_options << '--config' << rubo_config_file if rubo_config_file
|
|
58
|
+
cli_options << '--out' << File.expand_path('~/last_cop.txt') unless show_console
|
|
59
|
+
cli_options << file_pattern
|
|
60
|
+
cli_options
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def debug_values
|
|
64
|
+
log.kv 'rubocop target', file_pattern
|
|
65
|
+
log.kv '-a', 'automatic fix for safe issues' if fix_safe
|
|
66
|
+
log.kv '-A', 'automatic fix for potentially unsafe issues' if fix_unsafe
|
|
67
|
+
log.kv '-config', rubo_config_file if rubo_config_file
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def file_pattern=(value)
|
|
73
|
+
@file_pattern = value
|
|
74
|
+
|
|
75
|
+
if value.nil? || value.empty?
|
|
76
|
+
guard 'file_pattern is required'
|
|
77
|
+
elsif Pathname.glob(value).length.zero?
|
|
78
|
+
guard 'file_pattern does not reference an existing file'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def fix_safe=(value)
|
|
83
|
+
@fix_safe = value || false
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def fix_unsafe=(value)
|
|
87
|
+
@fix_unsafe = value || false
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def show_console=(value)
|
|
91
|
+
@show_console = value || false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def rubo_config_file=(value)
|
|
95
|
+
@rubo_config_file = value
|
|
96
|
+
|
|
97
|
+
return if value.nil? || value.empty?
|
|
98
|
+
|
|
99
|
+
guard("Unknown RuboCop config file: #{value}") unless File.exist?(value)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def cop_run
|
|
103
|
+
cli = RuboCop::CLI.new
|
|
104
|
+
|
|
105
|
+
# log.section_heading('CLI OPTIONS')
|
|
106
|
+
# log.block cli_options
|
|
107
|
+
|
|
108
|
+
cli.run(cli_options)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -5,18 +5,24 @@ module KBuilder
|
|
|
5
5
|
# Configuration for webpack5/builder
|
|
6
6
|
class << self
|
|
7
7
|
attr_writer :configuration
|
|
8
|
-
end
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
def configuration(name = :default)
|
|
10
|
+
@configuration ||= Hash.new do |h, key|
|
|
11
|
+
h[key] = KBuilder::Configuration.new
|
|
12
|
+
end
|
|
13
|
+
@configuration[name]
|
|
14
|
+
end
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
def reset(name = :default)
|
|
17
|
+
@configuration ||= Hash.new do |h, key|
|
|
18
|
+
h[key] = KBuilder::Configuration.new
|
|
19
|
+
end
|
|
20
|
+
@configuration[name] = KBuilder::Configuration.new
|
|
21
|
+
end
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
def configure(name = :default)
|
|
24
|
+
yield(configuration(name))
|
|
25
|
+
end
|
|
20
26
|
end
|
|
21
27
|
|
|
22
28
|
# Does this class need to move out into k_types?
|
|
@@ -48,12 +54,16 @@ module KBuilder
|
|
|
48
54
|
@template_folders = orig.template_folders.clone
|
|
49
55
|
end
|
|
50
56
|
|
|
51
|
-
def debug
|
|
52
|
-
log.
|
|
57
|
+
def debug(heading: 'kbuilder base configuration')
|
|
58
|
+
log.section_heading 'kbuilder base configuration' if heading
|
|
59
|
+
|
|
60
|
+
# TODO: Add name to configuration object
|
|
61
|
+
# Don't have support for name on the configuration object yet
|
|
62
|
+
# log.kv 'config name', name
|
|
53
63
|
|
|
54
64
|
target_folders.debug(title: 'target_folders')
|
|
55
65
|
|
|
56
|
-
log.info ''
|
|
66
|
+
# log.info ''
|
|
57
67
|
|
|
58
68
|
template_folders.debug(title: 'template folders (search order)')
|
|
59
69
|
''
|
data/lib/k_builder/version.rb
CHANGED
data/lib/k_builder.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'rubocop'
|
|
4
|
+
|
|
3
5
|
require 'k_log'
|
|
4
6
|
require 'k_util'
|
|
5
7
|
require 'k_type'
|
|
@@ -9,6 +11,11 @@ require 'k_builder/base_configuration'
|
|
|
9
11
|
require 'k_builder/configuration'
|
|
10
12
|
require 'k_builder/file_segments'
|
|
11
13
|
|
|
14
|
+
# should commands be in their own gem?
|
|
15
|
+
require 'k_builder/commands/base_command'
|
|
16
|
+
require 'k_builder/commands/rubo_cop_command'
|
|
17
|
+
require 'k_builder/commands/code_syntax_highlighter_command'
|
|
18
|
+
|
|
12
19
|
require 'handlebars/helpers/template'
|
|
13
20
|
|
|
14
21
|
module KBuilder
|