planter-cli 3.0.4 → 3.0.7
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/.irbrc +2 -1
- data/.rubocop.yml +4 -3
- data/.rubocop_todo.yml +63 -0
- data/.yardopts +3 -2
- data/CHANGELOG.md +28 -0
- data/Guardfile +1 -1
- data/README.md +132 -46
- data/Rakefile +0 -3
- data/bin/plant +5 -4
- data/lib/planter/array.rb +15 -1
- data/lib/planter/color.rb +8 -4
- data/lib/planter/config.rb +185 -0
- data/lib/planter/fileentry.rb +9 -3
- data/lib/planter/filelist.rb +28 -2
- data/lib/planter/numeric.rb +39 -0
- data/lib/planter/plant.rb +24 -17
- data/lib/planter/prompt.rb +43 -11
- data/lib/planter/script.rb +3 -3
- data/lib/planter/string.rb +153 -74
- data/lib/planter/tag.rb +43 -1
- data/lib/planter/version.rb +1 -1
- data/lib/planter.rb +39 -108
- data/lib/tty-spinner/lib/tty/spinner/multi.rb +3 -3
- data/planter-cli.gemspec +3 -1
- data/spec/cli_spec.rb +12 -2
- data/spec/planter/filelist_spec.rb +2 -2
- data/spec/planter/prompt_spec.rb +71 -0
- data/spec/planter/script_spec.rb +5 -4
- data/spec/planter/string_spec.rb +26 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/templates/test/_planter.yml +2 -0
- data/spec/templates/test/_scripts/plant.sh +3 -0
- data/src/_README.md +132 -46
- metadata +11 -4
data/lib/planter/string.rb
CHANGED
@@ -138,11 +138,14 @@ module Planter
|
|
138
138
|
MOD_RX = '(?<mod>
|
139
139
|
(?::
|
140
140
|
(
|
141
|
-
l(?:ow(?:er)?)?)?|
|
142
|
-
|
141
|
+
l(?:ow(?:er(case)?)?)?)?|
|
142
|
+
d(?:own(?:case)?)?|
|
143
|
+
u(?:p(?:per(case)?)?)?|upcase|
|
143
144
|
c(?:ap(?:ital(?:ize)?)?)?|
|
144
145
|
t(?:itle)?|
|
145
146
|
snake|camel|slug|
|
147
|
+
fl|first_letter|
|
148
|
+
fw|first_word|
|
146
149
|
f(?:ile(?:name)?
|
147
150
|
)?
|
148
151
|
)*
|
@@ -172,7 +175,7 @@ module Planter
|
|
172
175
|
m['default'].apply_var_names
|
173
176
|
else
|
174
177
|
# Retrieve the default value for the variable from the configuration
|
175
|
-
vars = Planter.config
|
178
|
+
vars = Planter.config.variables.filter { |v| v[:key] == m['varname'] }
|
176
179
|
default = vars.first[:default] if vars.count.positive?
|
177
180
|
if default.nil?
|
178
181
|
m[0]
|
@@ -204,8 +207,7 @@ module Planter
|
|
204
207
|
def apply_logic(variables = nil)
|
205
208
|
variables = variables.nil? ? Planter.variables : variables
|
206
209
|
|
207
|
-
gsub(/%%if .*?%%.*?%%end(if)?%%/mi) do |construct|
|
208
|
-
res = false
|
210
|
+
gsub(/%%if .*?%%.*?%%end( ?if)?%%/mi) do |construct|
|
209
211
|
# Get the condition and the content
|
210
212
|
output = construct.match(/%%else%%(.*?)%%end/m) ? Regexp.last_match(1) : ''
|
211
213
|
|
@@ -213,72 +215,8 @@ module Planter
|
|
213
215
|
/%%(?<statement>(?:els(?:e )?)?if) (?<condition>.*?)%%(?<content>.*?)(?=%%)/mi).map do
|
214
216
|
Regexp.last_match
|
215
217
|
end
|
216
|
-
conditions.each do |condition|
|
217
|
-
variable, operator, value = condition['condition'].split(/ +/, 3)
|
218
|
-
value.strip_quotes!
|
219
|
-
variable = variable.to_var
|
220
|
-
negate = false
|
221
|
-
if operator =~ /^!/
|
222
|
-
operator = operator[1..-1]
|
223
|
-
negate = true
|
224
|
-
end
|
225
|
-
operator = case operator
|
226
|
-
when /^={1,2}/
|
227
|
-
:equal
|
228
|
-
when /^=~/
|
229
|
-
:matches_regex
|
230
|
-
when /\*=/
|
231
|
-
:contains
|
232
|
-
when /\^=/
|
233
|
-
:starts_with
|
234
|
-
when /\$=/
|
235
|
-
:ends_with
|
236
|
-
when />/
|
237
|
-
:greater_than
|
238
|
-
when /</
|
239
|
-
:less_than
|
240
|
-
when />=/
|
241
|
-
:greater_than_or_equal
|
242
|
-
when /<=/
|
243
|
-
:less_than_or_equal
|
244
|
-
else
|
245
|
-
:equal
|
246
|
-
end
|
247
|
-
|
248
|
-
comp = variables[variable.to_var].to_s
|
249
|
-
|
250
|
-
res = case operator
|
251
|
-
when :equal
|
252
|
-
comp =~ /^#{value}$/i
|
253
|
-
when :matches_regex
|
254
|
-
comp =~ Regexp.new(value.gsub(%r{^/|/$}, ''))
|
255
|
-
when :contains
|
256
|
-
comp =~ /#{value}/i
|
257
|
-
when :starts_with
|
258
|
-
comp =~ /^#{value}/i
|
259
|
-
when :ends_with
|
260
|
-
comp =~ /#{value}$/i
|
261
|
-
when :greater_than
|
262
|
-
comp > value.to_f
|
263
|
-
when :less_than
|
264
|
-
comp < value.to_f
|
265
|
-
when :greater_than_or_equal
|
266
|
-
comp >= value.to_f
|
267
|
-
when :less_than_or_equal
|
268
|
-
comp <= value.to_f
|
269
|
-
else
|
270
|
-
false
|
271
|
-
end
|
272
|
-
res = !res if negate
|
273
|
-
|
274
|
-
next unless res
|
275
|
-
|
276
|
-
Planter.notify("Condition matched: #{comp} #{negate ? 'not ' : ''}#{operator} #{value}", :debug)
|
277
|
-
output = condition['content']
|
278
|
-
break
|
279
|
-
end
|
280
218
|
|
281
|
-
output
|
219
|
+
apply_conditions(conditions, variables, output)
|
282
220
|
end
|
283
221
|
end
|
284
222
|
|
@@ -287,6 +225,121 @@ module Planter
|
|
287
225
|
replace apply_logic(variables)
|
288
226
|
end
|
289
227
|
|
228
|
+
##
|
229
|
+
## Apply operator logic to a string. Operators are defined as
|
230
|
+
## :copy, :overwrite, :ignore, or :merge. Logic can be if/else
|
231
|
+
## constructs or inline operators.
|
232
|
+
##
|
233
|
+
## @example "var = 1; if var == 1:copy; else: ignore" #=> :copy
|
234
|
+
## @example "var = 2; copy if var == 1 else ignore" #=> :ignore
|
235
|
+
##
|
236
|
+
## @param variables [Hash] Hash of variables (default: Planter.variables)
|
237
|
+
##
|
238
|
+
def apply_operator_logic(variables = nil)
|
239
|
+
variables = variables.nil? ? Planter.variables : variables
|
240
|
+
op_rx = ' *(?<content>c(?:opy)?|o(?:ver(?:write)?)?|i(?:gnore)?|m(?:erge)?)? *'
|
241
|
+
|
242
|
+
output = strip.gsub(/^if .*?(?:end(?: ?if)?|$)/mi) do |construct|
|
243
|
+
# Get the condition and the content
|
244
|
+
output = construct.match(/else:#{op_rx}/m) ? Regexp.last_match(1) : ''
|
245
|
+
|
246
|
+
conditions = construct.to_enum(:scan,
|
247
|
+
/(?<statement>(?:els(?:e )?)?if) +(?<condition>.*?):#{op_rx}(?=;|$)/mi).map do
|
248
|
+
Regexp.last_match
|
249
|
+
end
|
250
|
+
|
251
|
+
apply_conditions(conditions, variables, output)
|
252
|
+
end
|
253
|
+
output = output.gsub(/^#{op_rx} +if .*?(end( ?if)?|$)/mi) do |construct|
|
254
|
+
# Get the condition and the content
|
255
|
+
output = construct.match(/else[; ]+(#{op_rx})/m) ? Regexp.last_match(1) : :ignore
|
256
|
+
condition = construct.match(/^#{op_rx}(?<statement>if) +(?<condition>.*?)(?=;|$)/mi)
|
257
|
+
|
258
|
+
apply_conditions([condition], variables, output)
|
259
|
+
end
|
260
|
+
|
261
|
+
output.normalize_operator
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
## Apply conditions
|
266
|
+
##
|
267
|
+
## @param conditions [Array<MatchData>] Array of conditions ['statement', 'condition', 'content']
|
268
|
+
## @param variables [Hash] Hash of variables
|
269
|
+
## @param output [String] Output string
|
270
|
+
##
|
271
|
+
## @return [String] Output string
|
272
|
+
##
|
273
|
+
def apply_conditions(conditions, variables, output)
|
274
|
+
res = false
|
275
|
+
conditions.each do |condition|
|
276
|
+
variable, operator, value = condition['condition'].split(/ +/, 3)
|
277
|
+
value.strip_quotes!
|
278
|
+
variable = variable.to_var
|
279
|
+
negate = false
|
280
|
+
if operator =~ /^!/
|
281
|
+
operator = operator[1..-1]
|
282
|
+
negate = true
|
283
|
+
end
|
284
|
+
operator = case operator
|
285
|
+
when /^={1,2}/
|
286
|
+
:equal
|
287
|
+
when /^=~/
|
288
|
+
:matches_regex
|
289
|
+
when /\*=/
|
290
|
+
:contains
|
291
|
+
when /\^=/
|
292
|
+
:starts_with
|
293
|
+
when /\$=/
|
294
|
+
:ends_with
|
295
|
+
when />/
|
296
|
+
:greater_than
|
297
|
+
when /</
|
298
|
+
:less_than
|
299
|
+
when />=/
|
300
|
+
:greater_than_or_equal
|
301
|
+
when /<=/
|
302
|
+
:less_than_or_equal
|
303
|
+
else
|
304
|
+
:equal
|
305
|
+
end
|
306
|
+
|
307
|
+
comp = variables[variable.to_var].to_s
|
308
|
+
|
309
|
+
res = case operator
|
310
|
+
when :equal
|
311
|
+
comp =~ /^#{value}$/i
|
312
|
+
when :matches_regex
|
313
|
+
comp =~ Regexp.new(value.gsub(%r{^/|/$}, ''))
|
314
|
+
when :contains
|
315
|
+
comp =~ /#{value}/i
|
316
|
+
when :starts_with
|
317
|
+
comp =~ /^#{value}/i
|
318
|
+
when :ends_with
|
319
|
+
comp =~ /#{value}$/i
|
320
|
+
when :greater_than
|
321
|
+
comp > value.to_f
|
322
|
+
when :less_than
|
323
|
+
comp < value.to_f
|
324
|
+
when :greater_than_or_equal
|
325
|
+
comp >= value.to_f
|
326
|
+
when :less_than_or_equal
|
327
|
+
comp <= value.to_f
|
328
|
+
else
|
329
|
+
false
|
330
|
+
end
|
331
|
+
res = res ? true : false
|
332
|
+
res = !res if negate
|
333
|
+
|
334
|
+
next unless res
|
335
|
+
|
336
|
+
Planter.notify("Condition matched: #{comp} #{negate ? 'not ' : ''}#{operator} #{value}", :debug)
|
337
|
+
output = condition['content']
|
338
|
+
break
|
339
|
+
end
|
340
|
+
output
|
341
|
+
end
|
342
|
+
|
290
343
|
##
|
291
344
|
## Apply key/value substitutions to a string. Variables are represented as
|
292
345
|
## %%key%%, and the hash passed to the function is { key: value }
|
@@ -326,6 +379,8 @@ module Planter
|
|
326
379
|
if m['mod']
|
327
380
|
mods = m['mod']&.split(/:/)
|
328
381
|
mods&.each do |mod|
|
382
|
+
next if mod.nil? || mod.empty?
|
383
|
+
|
329
384
|
v = v.apply_mod(mod.normalize_mod)
|
330
385
|
end
|
331
386
|
end
|
@@ -369,13 +424,20 @@ module Planter
|
|
369
424
|
end
|
370
425
|
|
371
426
|
##
|
372
|
-
## Apply
|
427
|
+
## Apply all logic, variables, and regexes to a string
|
428
|
+
##
|
429
|
+
def apply_all
|
430
|
+
apply_logic.apply_variables.apply_regexes
|
431
|
+
end
|
432
|
+
|
433
|
+
##
|
434
|
+
## Apply regex replacements from Planter.config[:replacements]
|
373
435
|
##
|
374
436
|
## @return [String] string with regexes applied
|
375
437
|
##
|
376
438
|
def apply_regexes(regexes = nil)
|
377
439
|
content = dup.clean_encode
|
378
|
-
regexes = regexes.nil? && Planter.config.key?(:replacements) ? Planter.config
|
440
|
+
regexes = regexes.nil? && Planter.config.key?(:replacements) ? Planter.config.replacements : regexes
|
379
441
|
|
380
442
|
return self unless regexes
|
381
443
|
|
@@ -455,6 +517,10 @@ module Planter
|
|
455
517
|
snake_case
|
456
518
|
when :camel_case
|
457
519
|
camel_case
|
520
|
+
when :first_letter
|
521
|
+
split('')[0]
|
522
|
+
when :first_word
|
523
|
+
split(/[ !,?;:]+/)[0]
|
458
524
|
else
|
459
525
|
self
|
460
526
|
end
|
@@ -481,7 +547,7 @@ module Planter
|
|
481
547
|
##
|
482
548
|
def normalize_mod
|
483
549
|
case self
|
484
|
-
when /^(
|
550
|
+
when /^(file|slug)/
|
485
551
|
:slug
|
486
552
|
when /^cam/
|
487
553
|
:camel_case
|
@@ -489,10 +555,14 @@ module Planter
|
|
489
555
|
:snake_case
|
490
556
|
when /^u/
|
491
557
|
:uppercase
|
492
|
-
when /^
|
558
|
+
when /^[ld]/
|
493
559
|
:lowercase
|
494
560
|
when /^[ct]/
|
495
561
|
:title_case
|
562
|
+
when /^(fl|first_letter)/
|
563
|
+
:first_letter
|
564
|
+
when /^(fw|first_word)/
|
565
|
+
:first_word
|
496
566
|
end
|
497
567
|
end
|
498
568
|
|
@@ -622,5 +692,14 @@ module Planter
|
|
622
692
|
gsub(/\((.)\)/, '{dw}({xbw}\1{dw}){xw}')
|
623
693
|
end
|
624
694
|
end
|
695
|
+
|
696
|
+
#
|
697
|
+
# Test if a string has a parenthetical selector
|
698
|
+
#
|
699
|
+
# @return [Boolean] has selector
|
700
|
+
#
|
701
|
+
def selector?
|
702
|
+
self =~ /\(.\)/ ? true : false
|
703
|
+
end
|
625
704
|
end
|
626
705
|
end
|
data/lib/planter/tag.rb
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Planter
|
4
|
+
#
|
5
|
+
# File tagging module
|
6
|
+
#
|
7
|
+
# @author Brett Terpstra <me@brettterpstra.com>
|
8
|
+
#
|
4
9
|
module Tag
|
10
|
+
# File tagging class
|
5
11
|
class << self
|
12
|
+
#
|
13
|
+
# Set tags on target file.
|
14
|
+
#
|
15
|
+
# @param target [String] path to target file
|
16
|
+
# @param tags [Array] Array of tags to set
|
17
|
+
#
|
18
|
+
# @return [Boolean] success
|
19
|
+
#
|
6
20
|
def set(target, tags)
|
7
21
|
return false unless TTY::Which.exist?('xattr')
|
8
22
|
|
@@ -14,8 +28,11 @@ module Planter
|
|
14
28
|
|
15
29
|
# Add tags to a directory.
|
16
30
|
#
|
17
|
-
# @param
|
31
|
+
# @param target [String] The directory to tag.
|
18
32
|
# @param tags [Array<String>] The tags to add.
|
33
|
+
#
|
34
|
+
# @return [Boolean] Success.
|
35
|
+
#
|
19
36
|
def add(target, tags)
|
20
37
|
return false unless TTY::Which.exist?('xattr')
|
21
38
|
|
@@ -36,6 +53,13 @@ module Planter
|
|
36
53
|
res
|
37
54
|
end
|
38
55
|
|
56
|
+
#
|
57
|
+
# Get tags on target file.
|
58
|
+
#
|
59
|
+
# @param target [String] target file path
|
60
|
+
#
|
61
|
+
# @return [Array] Array of tags
|
62
|
+
#
|
39
63
|
def get(target)
|
40
64
|
return false unless TTY::Which.exist?('xattr')
|
41
65
|
|
@@ -49,6 +73,14 @@ module Planter
|
|
49
73
|
tags
|
50
74
|
end
|
51
75
|
|
76
|
+
#
|
77
|
+
# Copy tags from one file to another.
|
78
|
+
#
|
79
|
+
# @param source [String] path to source file
|
80
|
+
# @param target [String] path to target file
|
81
|
+
#
|
82
|
+
# @return [Boolean] success
|
83
|
+
#
|
52
84
|
def copy(source, target)
|
53
85
|
return false unless TTY::Which.exist?('xattr')
|
54
86
|
|
@@ -67,6 +99,16 @@ module Planter
|
|
67
99
|
|
68
100
|
private
|
69
101
|
|
102
|
+
#
|
103
|
+
# Set tags on target file.
|
104
|
+
#
|
105
|
+
# @param target [String] file path
|
106
|
+
# @param tags [Array] Array of tags
|
107
|
+
#
|
108
|
+
# @return [Boolean] success
|
109
|
+
#
|
110
|
+
# @api private
|
111
|
+
#
|
70
112
|
def set_tags(target, tags)
|
71
113
|
return false unless TTY::Which.exist?('xattr')
|
72
114
|
|
data/lib/planter/version.rb
CHANGED
data/lib/planter.rb
CHANGED
@@ -15,14 +15,15 @@ require 'tty-screen'
|
|
15
15
|
require 'tty-which'
|
16
16
|
|
17
17
|
require_relative 'tty-spinner/lib/tty-spinner'
|
18
|
+
require_relative 'planter/config'
|
18
19
|
require_relative 'planter/version'
|
19
20
|
require_relative 'planter/hash'
|
20
21
|
require_relative 'planter/array'
|
21
22
|
require_relative 'planter/symbol'
|
23
|
+
require_relative 'planter/numeric'
|
22
24
|
require_relative 'planter/file'
|
23
25
|
require_relative 'planter/tag'
|
24
26
|
require_relative 'planter/color'
|
25
|
-
require_relative 'planter/errors'
|
26
27
|
require_relative 'planter/prompt'
|
27
28
|
require_relative 'planter/string'
|
28
29
|
require_relative 'planter/filelist'
|
@@ -30,6 +31,27 @@ require_relative 'planter/fileentry'
|
|
30
31
|
require_relative 'planter/script'
|
31
32
|
require_relative 'planter/plant'
|
32
33
|
|
34
|
+
# @return [Integer] Exit codes
|
35
|
+
EXIT_CODES = {
|
36
|
+
argument: 12,
|
37
|
+
input: 13,
|
38
|
+
canceled: 1,
|
39
|
+
script: 10,
|
40
|
+
config: 127,
|
41
|
+
git: 129
|
42
|
+
}.deep_freeze
|
43
|
+
|
44
|
+
#
|
45
|
+
# Exit the program with a message
|
46
|
+
#
|
47
|
+
# @param msg [String] error message
|
48
|
+
# @param code [Integer] Exit code
|
49
|
+
#
|
50
|
+
def die(msg = 'Exited', code = :canceled)
|
51
|
+
code = EXIT_CODES.key?(code) ? code : :canceled
|
52
|
+
Planter.notify(msg, :error, above_spinner: false, exit_code: EXIT_CODES[code])
|
53
|
+
end
|
54
|
+
|
33
55
|
# Main Journal module
|
34
56
|
module Planter
|
35
57
|
# Base directory for templates
|
@@ -56,7 +78,7 @@ module Planter
|
|
56
78
|
attr_accessor :template
|
57
79
|
|
58
80
|
## Config Hash
|
59
|
-
attr_reader :config
|
81
|
+
# attr_reader :config
|
60
82
|
|
61
83
|
## Variable key/values
|
62
84
|
attr_accessor :variables
|
@@ -67,6 +89,13 @@ module Planter
|
|
67
89
|
## Accept all defaults
|
68
90
|
attr_accessor :accept_defaults
|
69
91
|
|
92
|
+
## Reader for the configuration object
|
93
|
+
##
|
94
|
+
## @return [Planter::Config] Configuration object
|
95
|
+
def config
|
96
|
+
@config ||= Config.new
|
97
|
+
end
|
98
|
+
|
70
99
|
##
|
71
100
|
## Print a message on the command line
|
72
101
|
##
|
@@ -92,11 +121,15 @@ module Planter
|
|
92
121
|
'{bw}'
|
93
122
|
end
|
94
123
|
out = "#{color}#{string}{x}"
|
95
|
-
out = out.gsub(/\[(.*?)\]/, "{by}\\1{x}#{color}")
|
124
|
+
# out = out.gsub(/\[(.*?)\]/, "{by}\\1{x}#{color}")
|
96
125
|
out = "\n#{out}" if newline
|
126
|
+
|
127
|
+
spinner.update(title: 'ERROR') if exit_code
|
128
|
+
spinner.error if notification_type == :error
|
129
|
+
|
97
130
|
above_spinner ? spinner.log(out.x) : warn(out.x)
|
98
131
|
|
99
|
-
|
132
|
+
exit(exit_code) if exit_code && $stdout.isatty && (ENV['PLANTER_RSPEC'] == 'true' || ENV['PLANTER_DEBUG'] != 'true')
|
100
133
|
|
101
134
|
true
|
102
135
|
end
|
@@ -118,56 +151,6 @@ module Planter
|
|
118
151
|
@base_dir ||= ENV['PLANTER_BASE_DIR'] || File.join(Dir.home, '.config', 'planter')
|
119
152
|
end
|
120
153
|
|
121
|
-
##
|
122
|
-
## Build a configuration from template name
|
123
|
-
##
|
124
|
-
## @param template [String] The template name
|
125
|
-
##
|
126
|
-
## @return [Hash] Configuration object
|
127
|
-
##
|
128
|
-
def config=(template)
|
129
|
-
@template = template
|
130
|
-
Planter.variables ||= {}
|
131
|
-
FileUtils.mkdir_p(Planter.base_dir) unless File.directory?(Planter.base_dir)
|
132
|
-
base_config = File.join(Planter.base_dir, 'planter.yml')
|
133
|
-
|
134
|
-
if File.exist?(base_config)
|
135
|
-
@config = YAML.load(IO.read(base_config)).symbolize_keys
|
136
|
-
else
|
137
|
-
default_base_config = {
|
138
|
-
defaults: false,
|
139
|
-
git_init: false,
|
140
|
-
files: { '_planter.yml' => 'ignore' },
|
141
|
-
color: true,
|
142
|
-
preserve_tags: true
|
143
|
-
}
|
144
|
-
begin
|
145
|
-
File.open(base_config, 'w') { |f| f.puts(YAML.dump(default_base_config.stringify_keys)) }
|
146
|
-
rescue Errno::ENOENT
|
147
|
-
Planter.notify("Unable to create #{base_config}", :error)
|
148
|
-
end
|
149
|
-
@config = default_base_config.symbolize_keys
|
150
|
-
Planter.notify("New configuration written to #{base_config}, edit as needed.", :warn)
|
151
|
-
end
|
152
|
-
|
153
|
-
base_dir = File.join(Planter.base_dir, 'templates', @template)
|
154
|
-
unless File.directory?(base_dir)
|
155
|
-
notify("Template #{@template} does not exist", :error)
|
156
|
-
res = Prompt.yn('Create template directory', default_response: false)
|
157
|
-
|
158
|
-
raise Errors::InputError.new('Canceled') unless res
|
159
|
-
|
160
|
-
FileUtils.mkdir_p(base_dir)
|
161
|
-
end
|
162
|
-
|
163
|
-
load_template_config
|
164
|
-
|
165
|
-
config_array_to_hash(:files) if @config[:files].is_a?(Array)
|
166
|
-
config_array_to_hash(:replacements) if @config[:replacements].is_a?(Array)
|
167
|
-
rescue Psych::SyntaxError => e
|
168
|
-
raise Errors::ConfigError.new "Parse error in configuration file:\n#{e.message}"
|
169
|
-
end
|
170
|
-
|
171
154
|
##
|
172
155
|
## Execute a shell command and return a Boolean success response
|
173
156
|
##
|
@@ -189,58 +172,6 @@ module Planter
|
|
189
172
|
|
190
173
|
private
|
191
174
|
|
192
|
-
##
|
193
|
-
## Load a template-specific configuration
|
194
|
-
##
|
195
|
-
## @return [Hash] updated config object
|
196
|
-
##
|
197
|
-
## @api private
|
198
|
-
##
|
199
|
-
def load_template_config
|
200
|
-
base_dir = File.join(Planter.base_dir, 'templates', @template)
|
201
|
-
config = File.join(base_dir, '_planter.yml')
|
202
|
-
|
203
|
-
unless File.exist?(config)
|
204
|
-
default_config = {
|
205
|
-
variables: [
|
206
|
-
key: 'var_key',
|
207
|
-
prompt: 'CLI Prompt',
|
208
|
-
type: '[string, float, integer, number, date]',
|
209
|
-
value: '(optional, force value, can include variables. Empty to prompt. For date type: today, now, etc.)',
|
210
|
-
default: '(optional default value, leave empty or remove key for no default)',
|
211
|
-
min: '(optional, for number type set a minimum value)',
|
212
|
-
max: '(optional, for number type set a maximum value)'
|
213
|
-
],
|
214
|
-
git_init: false,
|
215
|
-
files: {
|
216
|
-
'*.tmp' => 'ignore',
|
217
|
-
'*.bak' => 'ignore',
|
218
|
-
'.DS_Store' => 'ignore'
|
219
|
-
}
|
220
|
-
}
|
221
|
-
FileUtils.mkdir_p(base_dir)
|
222
|
-
File.open(config, 'w') { |f| f.puts(YAML.dump(default_config.stringify_keys)) }
|
223
|
-
notify("New configuration written to #{config}, please edit.", :warn)
|
224
|
-
Process.exit 0
|
225
|
-
end
|
226
|
-
@config = @config.deep_merge(YAML.load(IO.read(config)).symbolize_keys)
|
227
|
-
end
|
228
|
-
|
229
|
-
##
|
230
|
-
## Convert an errant array to a hash
|
231
|
-
##
|
232
|
-
## @param key [Symbol] The key in @config to convert
|
233
|
-
##
|
234
|
-
## @api private
|
235
|
-
##
|
236
|
-
def config_array_to_hash(key)
|
237
|
-
files = {}
|
238
|
-
@config[key].each do |k, v|
|
239
|
-
files[k] = v
|
240
|
-
end
|
241
|
-
@config[key] = files
|
242
|
-
end
|
243
|
-
|
244
175
|
##
|
245
176
|
## Process :files in config into regex pattern/operator pairs
|
246
177
|
##
|
@@ -250,9 +181,9 @@ module Planter
|
|
250
181
|
##
|
251
182
|
def process_patterns
|
252
183
|
patterns = {}
|
253
|
-
@config
|
184
|
+
@config.files.each do |file, oper|
|
254
185
|
pattern = Regexp.new(".*?/#{file.to_s.sub(%r{^/}, '').to_rx}$")
|
255
|
-
operator = oper.
|
186
|
+
operator = oper.apply_operator_logic(Planter.variables)
|
256
187
|
patterns[pattern] = operator
|
257
188
|
end
|
258
189
|
patterns
|
@@ -112,7 +112,7 @@ module TTY
|
|
112
112
|
pattern_or_spinner
|
113
113
|
else
|
114
114
|
raise ArgumentError, "Expected a pattern or spinner, " \
|
115
|
-
|
115
|
+
"got: #{pattern_or_spinner.class}"
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -259,8 +259,8 @@ module TTY
|
|
259
259
|
# @api public
|
260
260
|
def on(key, &callback)
|
261
261
|
unless @callbacks.key?(key)
|
262
|
-
raise ArgumentError, "The event #{key} does not exist.
|
263
|
-
"
|
262
|
+
raise ArgumentError, "The event #{key} does not exist. " \
|
263
|
+
"Use :spin, :success, :error, or :done instead"
|
264
264
|
end
|
265
265
|
@callbacks[key] << callback
|
266
266
|
self
|
data/planter-cli.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
lib = File.expand_path(File.join('..', 'lib'), __FILE__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
5
|
require 'planter/version'
|
@@ -23,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
23
25
|
spec.add_development_dependency 'bundler', '~> 2.2'
|
24
26
|
spec.add_development_dependency 'rake', '~> 13.0'
|
25
27
|
|
26
|
-
spec.add_development_dependency 'guard', '~> 2.
|
28
|
+
spec.add_development_dependency 'guard', '~> 2.16'
|
27
29
|
spec.add_development_dependency 'guard-rspec', '~> 4.5'
|
28
30
|
spec.add_development_dependency 'guard-rubocop', '~> 1.2'
|
29
31
|
spec.add_development_dependency 'guard-yard', '~> 2.1'
|
data/spec/cli_spec.rb
CHANGED
@@ -17,11 +17,21 @@ describe 'CLI' do
|
|
17
17
|
|
18
18
|
it 'displays help message' do
|
19
19
|
output, stderr, status = planter('--help')
|
20
|
-
expect(output).
|
20
|
+
expect(output).to match(/Usage: plant \[options\] TEMPLATE/)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'displays variables for a template' do
|
24
|
+
output, stderr, status = planter('--help', 'test')
|
25
|
+
expect(output).to match(/CLI Prompt/)
|
21
26
|
end
|
22
27
|
|
23
28
|
it 'plants a new project' do
|
24
|
-
output, stderr, status = planter(
|
29
|
+
output, stderr, status = planter("--in=#{TEST_DIR}", 'test')
|
25
30
|
expect(File.exist?(File.join(TEST_DIR, 'bollocks_and_beans.rtf'))).to be true
|
26
31
|
end
|
32
|
+
|
33
|
+
it 'plants a new file with a script' do
|
34
|
+
output, stderr, status = planter("--in=#{TEST_DIR}", 'test')
|
35
|
+
expect(File.exist?(File.join(TEST_DIR, 'planted_by_script.txt'))).to be true
|
36
|
+
end
|
27
37
|
end
|
@@ -7,8 +7,8 @@ describe Planter::FileList do
|
|
7
7
|
it 'initializes with an empty list' do
|
8
8
|
Planter.base_dir = File.expand_path('spec')
|
9
9
|
Planter.variables = { project: 'Untitled', script: 'Script', title: 'Title' }
|
10
|
-
Planter.
|
11
|
-
filelist =
|
10
|
+
Planter.template = 'test'
|
11
|
+
filelist = described_class.new
|
12
12
|
expect(filelist.files).not_to eq([])
|
13
13
|
end
|
14
14
|
end
|