planter-cli 0.0.3

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.
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