planter-cli 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/bin/plant ADDED
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $VERBOSE = true
5
+
6
+ require 'optparse'
7
+ require_relative '../lib/planter'
8
+
9
+ options = {
10
+ help: false,
11
+ debug: false,
12
+ version: false
13
+ }
14
+
15
+ # Variable definition
16
+ # variables:
17
+ # - key: var
18
+ # prompt: Variable
19
+ # type: [string,float,integer,number,date]
20
+ # value: (for date type can be today, time, now, etc.)
21
+ # default: Untitled
22
+ # min: 1
23
+ # max: 5
24
+ Planter.variables = {}
25
+ Planter::Color.coloring = $stdout.isatty
26
+
27
+ opts = OptionParser.new
28
+ opts.banner = 'Usage: planter [options] TEMPLATE'
29
+
30
+ Planter.accept_defaults = false
31
+ opts.on('--defaults', 'Accept default values for all variables') do
32
+ Planter.accept_defaults = true
33
+ end
34
+
35
+ Planter.target = Dir.pwd
36
+ opts.on('-i', '--in TARGET', 'Plant in TARGET instead of current directory') do |opt|
37
+ target = File.expand_path(opt)
38
+ FileUtils.mkdir_p(target) unless File.exist?(target)
39
+ Planter.target = target
40
+ end
41
+
42
+ opts.on('-k', '--var=KEY:VALUE,KEY:VALUE...', Array,
43
+ 'Pass a variable on the command line as KEY:VALUE pairs. Can be used multiple times.') do |opt|
44
+ opt.each do |o|
45
+ parts = o.split(/:/)
46
+ key = parts.shift
47
+ value = parts.join(':')
48
+ Planter.variables[key.to_var] = value
49
+ end
50
+ end
51
+
52
+ opts.on('-o', '--overwrite', 'Overwrite existing files') do
53
+ Planter.overwrite = true
54
+ end
55
+
56
+ opts.on_tail('-d', '--debug', 'Display version number') do
57
+ Planter.debug = true
58
+ end
59
+
60
+ opts.on_tail('-h', '--help', 'Display this screen, or list variables for template argument') do
61
+ options[:help] = true
62
+ end
63
+
64
+ opts.on_tail('-v', '--version', 'Display version number') do
65
+ options[:version] = true
66
+ end
67
+
68
+ opts.parse!
69
+
70
+ ##
71
+ ## List variables for a template
72
+ ##
73
+ ## @param template [String] The template
74
+ ##
75
+ def list_vars(template)
76
+ puts "#{template} variables:"
77
+ Planter.config = template
78
+ Planter.config[:variables].sort_by { |v| v[:key].to_var }.each do |var|
79
+ title = var[:prompt] || var[:key]
80
+ var_type = var[:type].normalize_type || :string
81
+ default = var[:value] || var[:default]
82
+ default = default ? ", default: #{default.coerce(var_type)}" : ''
83
+ puts "#{title}:"
84
+ puts " [#{var[:key].to_var}] (type: #{var_type}#{default})"
85
+ end
86
+ end
87
+
88
+ if options[:version]
89
+ puts "planter v#{Planter::VERSION}"
90
+ Process.exit 0
91
+ elsif options[:help]
92
+ if ARGV.count.zero?
93
+ puts opts
94
+ else
95
+ list_vars(ARGV[0])
96
+ end
97
+ Process.exit 0
98
+ elsif ARGV.count.zero?
99
+ raise Planter::Errors::ArgumentError.new 'Template argument required'
100
+ end
101
+
102
+ ARGV.each do |template|
103
+ Planter.config = template
104
+ app = Planter::Plant.new
105
+ app.plant
106
+ end
data/debug.log ADDED
File without changes
data/docker/Dockerfile ADDED
@@ -0,0 +1,12 @@
1
+ FROM ruby:3.0.1
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
3
+ RUN mkdir /planter
4
+ WORKDIR /planter
5
+
6
+ RUN gem install bundler:2.2.29
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less vim
9
+ COPY ./docker/inputrc /root/.inputrc
10
+ COPY ./docker/bash_profile /root/.bash_profile
11
+ RUN mkdir -p /root/.config/planter/templates/test
12
+ CMD ["/planter/scripts/runtests.sh"]
@@ -0,0 +1,12 @@
1
+ FROM ruby:2.6
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
3
+ RUN mkdir /howzit
4
+ WORKDIR /howzit
5
+ # COPY ./ /howzit/
6
+ RUN gem install bundler:2.2.29
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less vim
9
+ COPY ./docker/inputrc /root/.inputrc
10
+ COPY ./docker/bash_profile /root/.bash_profile
11
+ RUN mkdir -p /root/.config/planter/templates/test
12
+ CMD ["/planter/scripts/runtests.sh"]
@@ -0,0 +1,12 @@
1
+ FROM ruby:2.7
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
3
+ RUN mkdir /howzit
4
+ WORKDIR /howzit
5
+ # COPY ./ /howzit/
6
+ RUN gem install bundler:2.2.29
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less vim
9
+ COPY ./docker/inputrc /root/.inputrc
10
+ COPY ./docker/bash_profile /root/.bash_profile
11
+ RUN mkdir -p /root/.config/planter/templates/test
12
+ CMD ["/planter/scripts/runtests.sh"]
@@ -0,0 +1,11 @@
1
+ FROM ruby:3.0.0
2
+ # RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
3
+ RUN mkdir /howzit
4
+ WORKDIR /howzit
5
+ # COPY ./ /howzit/
6
+ RUN gem install bundler:2.2.29
7
+ RUN apt-get update -y
8
+ RUN apt-get install -y less vim
9
+ COPY ./docker/inputrc /root/.inputrc
10
+ COPY ./docker/bash_profile /root/.bash_profile
11
+ CMD ["/planter/scripts/runtests.sh"]
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+ export GLI_DEBUG=true
3
+ export EDITOR="/usr/bin/vim"
4
+ alias b="bundle exec bin/plant"
5
+ alias quit="exit"
6
+
7
+ shopt -s nocaseglob
8
+ shopt -s histappend
9
+ shopt -s histreedit
10
+ shopt -s histverify
11
+ shopt -s cmdhist
12
+
13
+ cd /planter
14
+ bundle install
15
+ gem install pkg/*.gem
data/docker/inputrc ADDED
@@ -0,0 +1,57 @@
1
+ "\e[3~": delete-char
2
+ "\ex": 'cd !$ \015ls\015'
3
+ "\ez": 'cd -\015'
4
+ "\e\C-m": '\C-a "$(\C-e|fzf)"\C-a'
5
+ "\e/": '"$(!!|fzf)"\C-a \C-m\C-m'
6
+ # these allow you to use alt+left/right arrow keys
7
+ # to jump the cursor over words
8
+ "\e[1;5C": forward-word
9
+ "\e[1;5D": backward-word
10
+ # "\e[D": backward-word
11
+ # "\e[C": forward-word
12
+ "\ea": menu-complete
13
+ # TAB: menu-complete
14
+ # "\e[Z": "\e-1\C-i"
15
+
16
+ "\e\C-l": history-and-alias-expand-line
17
+
18
+ # these allow you to start typing a command and
19
+ # use the up/down arrow to auto complete from
20
+ # commands in your history
21
+ "\e[B": history-search-forward
22
+ "\e[A": history-search-backward
23
+ "\ew": history-search-backward
24
+ "\es": history-search-forward
25
+ # this lets you hit tab to auto-complete a file or
26
+ # directory name ignoring case
27
+ set completion-ignore-case On
28
+ set mark-symlinked-directories On
29
+ set completion-prefix-display-length 2
30
+ set bell-style none
31
+ # set bell-style visible
32
+ set meta-flag on
33
+ set convert-meta off
34
+ set input-meta on
35
+ set output-meta on
36
+ set show-all-if-ambiguous on
37
+ set show-all-if-unmodified on
38
+ set completion-map-case on
39
+ set visible-stats on
40
+
41
+ # Do history expansion when space entered?
42
+ $if bash
43
+ Space: magic-space
44
+ $endif
45
+
46
+ # Show extra file information when completing, like `ls -F` does
47
+ set visible-stats on
48
+
49
+ # Be more intelligent when autocompleting by also looking at the text after
50
+ # the cursor. For example, when the current line is "cd ~/src/mozil", and
51
+ # the cursor is on the "z", pressing Tab will not autocomplete it to "cd
52
+ # ~/src/mozillail", but to "cd ~/src/mozilla". (This is supported by the
53
+ # Readline used by Bash 4.)
54
+ set skip-completed-text on
55
+
56
+ # Use Alt/Meta + Delete to delete the preceding word
57
+ "\e[3;3~": kill-word
data/lib/.rubocop.yml ADDED
@@ -0,0 +1 @@
1
+ inherit_from: ../.rubocop.yml
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Planter
4
+ # Array helpers
5
+ class ::Array
6
+ ##
7
+ ## Convert an array of "(c)hoices" to abbrevation. If a default character is
8
+ ## provided it will be highlighted. Output is a color template, unprocessed.
9
+ ##
10
+ ## @example ["(c)hoice", "(o)ther"].abbr_choices #=> "[c/o]"
11
+ ##
12
+ ## @param default [String] The color templated output string
13
+ ##
14
+ def abbr_choices(default: nil)
15
+ chars = join(' ').scan(/\((.)\)/).map { |c| c[0] }
16
+ out = String.new
17
+ out << '{xdw}['
18
+ out << chars.map do |c|
19
+ if default && c.downcase == default.downcase
20
+ "{xbc}#{c}"
21
+ else
22
+ "{xbw}#{c}"
23
+ end
24
+ end.join('{dw}/')
25
+ out << '{dw}]{x}'
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,370 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Planter
4
+ # Cribbed from <https://github.com/flori/term-ansicolor>
5
+ # Terminal output color functions.
6
+ module Color
7
+ # Regexp to match excape sequences
8
+ ESCAPE_REGEX = /(?<=\[)(?:(?:(?:[349]|10)[0-9]|[0-9])?;?)+(?=m)/
9
+
10
+ # All available color names. Available as methods and string extensions.
11
+ #
12
+ # @example Use a color as a method. Color reset will be added to end of string.
13
+ # Color.yellow('This text is yellow') => "\e[33mThis text is yellow\e[0m"
14
+ #
15
+ # @example Use a color as a string extension. Color reset added automatically.
16
+ # 'This text is green'.green => "\e[1;32mThis text is green\e[0m"
17
+ #
18
+ # @example Send a text string as a color
19
+ # Color.send('red') => "\e[31m"
20
+ ATTRIBUTES = [
21
+ [:clear, 0], # String#clear is already used to empty string in Ruby 1.9
22
+ [:reset, 0], # synonym for :clear
23
+ [:bold, 1],
24
+ [:dark, 2],
25
+ [:italic, 3], # not widely implemented
26
+ [:underline, 4],
27
+ [:underscore, 4], # synonym for :underline
28
+ [:blink, 5],
29
+ [:rapid_blink, 6], # not widely implemented
30
+ [:negative, 7], # no reverse because of String#reverse
31
+ [:concealed, 8],
32
+ [:strikethrough, 9], # not widely implemented
33
+ [:strike, 9], # not widely implemented
34
+ [:black, 30],
35
+ [:red, 31],
36
+ [:green, 32],
37
+ [:yellow, 33],
38
+ [:blue, 34],
39
+ [:magenta, 35],
40
+ [:purple, 35],
41
+ [:cyan, 36],
42
+ [:white, 37],
43
+ [:bgblack, 40],
44
+ [:bgred, 41],
45
+ [:bggreen, 42],
46
+ [:bgyellow, 43],
47
+ [:bgblue, 44],
48
+ [:bgmagenta, 45],
49
+ [:bgpurple, 45],
50
+ [:bgcyan, 46],
51
+ [:bgwhite, 47],
52
+ [:boldblack, 90],
53
+ [:boldred, 91],
54
+ [:boldgreen, 92],
55
+ [:boldyellow, 93],
56
+ [:boldblue, 94],
57
+ [:boldmagenta, 95],
58
+ [:boldpurple, 95],
59
+ [:boldcyan, 96],
60
+ [:boldwhite, 97],
61
+ [:boldbgblack, 100],
62
+ [:boldbgred, 101],
63
+ [:boldbggreen, 102],
64
+ [:boldbgyellow, 103],
65
+ [:boldbgblue, 104],
66
+ [:boldbgmagenta, 105],
67
+ [:boldbgpurple, 105],
68
+ [:boldbgcyan, 106],
69
+ [:boldbgwhite, 107],
70
+ [:softpurple, '0;35;40'],
71
+ [:hotpants, '7;34;40'],
72
+ [:knightrider, '7;30;40'],
73
+ [:flamingo, '7;31;47'],
74
+ [:yeller, '1;37;43'],
75
+ [:whiteboard, '1;30;47'],
76
+ [:chalkboard, '1;37;40'],
77
+ [:led, '0;32;40'],
78
+ [:redacted, '0;30;40'],
79
+ [:alert, '1;31;43'],
80
+ [:error, '1;37;41'],
81
+ [:default, '0;39']
82
+ ].map(&:freeze).freeze
83
+
84
+ # Array of attribute keys only
85
+ ATTRIBUTE_NAMES = ATTRIBUTES.transpose.first
86
+
87
+ # Returns true if Color supports the +feature+.
88
+ #
89
+ # The feature :clear, that is mixing the clear color attribute into String,
90
+ # is only supported on ruby implementations, that do *not* already
91
+ # implement the String#clear method. It's better to use the reset color
92
+ # attribute instead.
93
+ def support?(feature)
94
+ case feature
95
+ when :clear
96
+ !String.instance_methods(false).map(&:to_sym).include?(:clear)
97
+ end
98
+ end
99
+
100
+ # Template coloring
101
+ class ::String
102
+ ##
103
+ ## Shortcut for #template
104
+ ##
105
+ ## @return [String] colorized string
106
+ ##
107
+ def x
108
+ Color.template(self)
109
+ end
110
+
111
+ ##
112
+ ## Extract the longest valid %color name from a string.
113
+ ##
114
+ ## Allows %colors to bleed into other text and still
115
+ ## be recognized, e.g. %greensomething still finds
116
+ ## %green.
117
+ ##
118
+ ## @return [String] a valid color name
119
+ ##
120
+ def validate_color
121
+ valid_color = nil
122
+ compiled = ''
123
+ normalize_color.chars.each do |char|
124
+ compiled += char
125
+ if Color.attributes.include?(compiled.to_sym) || compiled =~ /^([fb]g?)?#([a-f0-9]{6})$/i
126
+ valid_color = compiled
127
+ end
128
+ end
129
+
130
+ valid_color
131
+ end
132
+
133
+ ##
134
+ ## Normalize a color name, removing underscores,
135
+ ## replacing "bright" with "bold", and converting
136
+ ## bgbold to boldbg
137
+ ##
138
+ ## @return [String] Normalized color name
139
+ ##
140
+ def normalize_color
141
+ delete('_').sub(/bright/i, 'bold').sub(/bgbold/, 'boldbg')
142
+ end
143
+
144
+ # Get the calculated ANSI color at the end of the
145
+ # string
146
+ #
147
+ # @return ANSI escape sequence to match color
148
+ #
149
+ def last_color_code
150
+ m = scan(ESCAPE_REGEX)
151
+
152
+ em = ['0']
153
+ fg = nil
154
+ bg = nil
155
+ rgbf = nil
156
+ rgbb = nil
157
+
158
+ m.each do |c|
159
+ case c
160
+ when '0'
161
+ em = ['0']
162
+ fg, bg, rgbf, rgbb = nil
163
+ when /^[34]8/
164
+ case c
165
+ when /^3/
166
+ fg = nil
167
+ rgbf = c
168
+ when /^4/
169
+ bg = nil
170
+ rgbb = c
171
+ end
172
+ else
173
+ c.split(';').each do |i|
174
+ x = i.to_i
175
+ if x <= 9
176
+ em << x
177
+ elsif x >= 30 && x <= 39
178
+ rgbf = nil
179
+ fg = x
180
+ elsif x >= 40 && x <= 49
181
+ rgbb = nil
182
+ bg = x
183
+ elsif x >= 90 && x <= 97
184
+ rgbf = nil
185
+ fg = x
186
+ elsif x >= 100 && x <= 107
187
+ rgbb = nil
188
+ bg = x
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ escape = "\e[#{em.join(';')}m"
195
+ escape += "\e[#{rgbb}m" if rgbb
196
+ escape += "\e[#{rgbf}m" if rgbf
197
+ escape + "\e[#{[fg, bg].delete_if(&:nil?).join(';')}m"
198
+ end
199
+ end
200
+
201
+ class << self
202
+ # Returns true if the coloring function of this module
203
+ # is switched on, false otherwise.
204
+ def coloring?
205
+ @coloring
206
+ end
207
+
208
+ attr_writer :coloring
209
+
210
+ ##
211
+ ## Enables colored output
212
+ ##
213
+ ## @example Turn color on or off based on TTY
214
+ ## Color.coloring = STDOUT.isatty
215
+ def coloring
216
+ @coloring ||= true
217
+ end
218
+
219
+ ##
220
+ ## Convert a template string to a colored string.
221
+ ## Colors are specified with single letters inside
222
+ ## curly braces. Uppercase changes background color.
223
+ ##
224
+ ## w: white, k: black, g: green, l: blue, y: yellow, c: cyan,
225
+ ## m: magenta, r: red, b: bold, u: underline, i: italic,
226
+ ## x: reset (remove background, color, emphasis)
227
+ ##
228
+ ## Also accepts {(#)RGB} and {(#)RRGGBB} strings. Put a b before
229
+ ## the hash to make it a background color
230
+ ##
231
+ ## @example Convert a templated string
232
+ ## Color.template('{Rwb}Warning:{x} {w}you look a little {g}ill{x}')
233
+ ##
234
+ ## @example Convert using RGB colors
235
+ ## Color.template('{#f0a}This is an RGB color')
236
+ ##
237
+ ## @param input [String, Array] The template
238
+ ## string. If this is an array, the
239
+ ## elements will be joined with a
240
+ ## space.
241
+ ##
242
+ ## @return [String] Colorized string
243
+ ##
244
+ def template(input)
245
+ input = input.join(' ') if input.is_a? Array
246
+ return input.gsub(/(?<!\\)\{(\w+)\}/i, '') unless Color.coloring?
247
+
248
+ input = input.gsub(/(?<!\\)\{((?:[fb]g?)?#[a-f0-9]{3,6})\}/i) do
249
+ hex = Regexp.last_match(1)
250
+ rgb(hex)
251
+ end
252
+
253
+ fmt = input.gsub(/%/, '%%')
254
+ fmt = fmt.gsub(/(?<!\\)\{(\w+)\}/i) do
255
+ Regexp.last_match(1).chars.map { |c| "%<#{c}>s" }.join('')
256
+ end
257
+
258
+ colors = { w: white, k: black, g: green, l: blue,
259
+ y: yellow, c: cyan, m: magenta, r: red,
260
+ W: bgwhite, K: bgblack, G: bggreen, L: bgblue,
261
+ Y: bgyellow, C: bgcyan, M: bgmagenta, R: bgred,
262
+ d: dark, b: bold, u: underline, i: italic, x: reset }
263
+
264
+ format(fmt, colors)
265
+ end
266
+ end
267
+
268
+ ATTRIBUTES.each do |c, v|
269
+ new_method = <<-EOSCRIPT
270
+ # Color string as #{c}
271
+ def #{c}(string = nil)
272
+ result = ''
273
+ result << "\e[#{v}m" if Color.coloring?
274
+ if block_given?
275
+ result << yield
276
+ elsif string.respond_to?(:to_str)
277
+ result << string.to_str
278
+ elsif respond_to?(:to_str)
279
+ result << to_str
280
+ else
281
+ return result #only switch on
282
+ end
283
+ result << "\e[0m" if Color.coloring?
284
+ result
285
+ end
286
+ EOSCRIPT
287
+
288
+ module_eval(new_method)
289
+
290
+ next unless /bold/.match?(c)
291
+
292
+ # Accept brightwhite in addition to boldwhite
293
+ new_method = <<-EOSCRIPT
294
+ # color string as #{c}
295
+ def #{c.to_s.sub(/bold/, 'bright')}(string = nil)
296
+ result = ''
297
+ result << "\e[#{v}m" if Color.coloring?
298
+ if block_given?
299
+ result << yield
300
+ elsif string.respond_to?(:to_str)
301
+ result << string.to_str
302
+ elsif respond_to?(:to_str)
303
+ result << to_str
304
+ else
305
+ return result #only switch on
306
+ end
307
+ result << "\e[0m" if Color.coloring?
308
+ result
309
+ end
310
+ EOSCRIPT
311
+
312
+ module_eval(new_method)
313
+ end
314
+
315
+ ##
316
+ ## Generate escape codes for hex colors
317
+ ##
318
+ ## @param hex [String] The hexadecimal color code
319
+ ##
320
+ ## @return [String] ANSI escape string
321
+ ##
322
+ def rgb(hex)
323
+ is_bg = /^bg?#/.match?(hex)
324
+ hex_string = hex.sub(/^([fb]g?)?#/, '')
325
+
326
+ if hex_string.length == 3
327
+ parts = hex_string.match(/(?<r>.)(?<g>.)(?<b>.)/)
328
+
329
+ t = []
330
+ %w[r g b].each do |e|
331
+ t << parts[e]
332
+ t << parts[e]
333
+ end
334
+ hex_string = t.join('')
335
+ end
336
+
337
+ parts = hex_string.match(/(?<r>..)(?<g>..)(?<b>..)/)
338
+ t = []
339
+ %w[r g b].each do |e|
340
+ t << parts[e].hex
341
+ end
342
+
343
+ "\e[#{is_bg ? '48' : '38'};2;#{t.join(';')}m"
344
+ end
345
+
346
+ # Regular expression that is used to scan for ANSI-sequences while
347
+ # uncoloring strings.
348
+ COLORED_REGEXP = /\e\[(?:(?:(?:[349]|10)[0-9]|[0-9])?;?)+m/
349
+
350
+ # Returns an uncolored version of the string, that is all
351
+ # ANSI-sequences are stripped from the string.
352
+ def uncolor(string = nil) # :yields:
353
+ if block_given?
354
+ yield.to_str.gsub(COLORED_REGEXP, '')
355
+ elsif string.respond_to?(:to_str)
356
+ string.to_str.gsub(COLORED_REGEXP, '')
357
+ elsif respond_to?(:to_str)
358
+ to_str.gsub(COLORED_REGEXP, '')
359
+ else
360
+ ''
361
+ end
362
+ end
363
+
364
+ # Returns an array of all Color attributes as symbols.
365
+ def attributes
366
+ ATTRIBUTE_NAMES
367
+ end
368
+ extend self
369
+ end
370
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Planter
4
+ ## Error handlers
5
+ module Errors
6
+ ## Exit codes
7
+ EXIT_CODES = {
8
+ argument: 12,
9
+ canceled: 1,
10
+ config: 127,
11
+ git: 129
12
+ }.deep_freeze
13
+
14
+ ## Argument error class
15
+ class InputError < StandardError
16
+ def initialize(msg = nil)
17
+ msg = msg ? "Input: #{msg}" : 'Canceled'
18
+
19
+ Planter.notify(msg, :error, exit_code: EXIT_CODES[:canceled])
20
+
21
+ super(msg)
22
+ end
23
+ end
24
+
25
+ ## Argument error class
26
+ class ArgumentError < StandardError
27
+ def initialize(msg = nil)
28
+ msg = msg ? "Argument error: #{msg}" : 'Argument error'
29
+
30
+ Planter.notify(msg, :error, exit_code: EXIT_CODES[:argument])
31
+
32
+ super(msg)
33
+ end
34
+ end
35
+
36
+ ## Git error class
37
+ class GitError < StandardError
38
+ def initialize(msg = nil)
39
+ msg = msg ? "Git: #{msg}" : 'Git error'
40
+
41
+ Planter.spinner.error('(Error)')
42
+ Planter.notify(msg, :error, exit_code: EXIT_CODES[:git])
43
+
44
+ super(msg)
45
+ end
46
+ end
47
+
48
+ # Configuration error class
49
+ class ConfigError < StandardError
50
+ def initialize(msg = nil)
51
+ msg = msg ? "Config: #{msg}" : 'Configuration error'
52
+ Planter.spinner.error('(Error)')
53
+ Planter.notify(msg, :error, exit_code: EXIT_CODES[:config])
54
+
55
+ super(msg)
56
+ end
57
+ end
58
+ end
59
+ end