rbcli 0.1.7 → 0.1.8

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +3 -1
  3. data/README.md +50 -6
  4. data/exe/rbcli +81 -32
  5. data/lib/rbcli/configuration/config.rb +6 -6
  6. data/lib/rbcli/configuration/configurate.rb +1 -1
  7. data/lib/rbcli/engine/load_project.rb +19 -0
  8. data/lib/rbcli/engine/parser.rb +2 -2
  9. data/lib/rbcli/logging/logging.rb +7 -4
  10. data/lib/rbcli/stateful_systems/state_storage.rb +4 -0
  11. data/lib/rbcli/version.rb +1 -1
  12. data/lib/rbcli-tool/erb_renderer.rb +43 -0
  13. data/lib/rbcli-tool/mdless_fix.rb +386 -0
  14. data/lib/rbcli-tool/project.rb +87 -0
  15. data/lib/rbcli-tool.rb +16 -0
  16. data/lib/rbcli.rb +11 -10
  17. data/rbcli.gemspec +1 -0
  18. data/skeletons/micro/executable +123 -0
  19. data/skeletons/mini/executable +241 -0
  20. data/skeletons/project/.gitignore +11 -0
  21. data/skeletons/project/.rbcli +0 -0
  22. data/skeletons/project/.rspec +3 -0
  23. data/skeletons/project/CODE_OF_CONDUCT.md +74 -0
  24. data/skeletons/project/Gemfile +6 -0
  25. data/skeletons/project/README.md +31 -0
  26. data/skeletons/project/Rakefile +6 -0
  27. data/skeletons/project/application/commands/command.rb +31 -0
  28. data/skeletons/project/application/commands/scripts/script.sh +23 -0
  29. data/skeletons/project/application/options.rb +30 -0
  30. data/skeletons/project/config/autoupdate.rb +32 -0
  31. data/skeletons/project/config/logging.rb +19 -0
  32. data/skeletons/project/config/storage.rb +34 -0
  33. data/skeletons/project/config/userspace.rb +28 -0
  34. data/skeletons/project/config/version.rb +3 -0
  35. data/skeletons/project/default_user_configs/user_defaults.yml +6 -0
  36. data/skeletons/project/exe/executable +54 -0
  37. data/skeletons/project/hooks/default_action.rb +16 -0
  38. data/skeletons/project/hooks/first_run.rb +16 -0
  39. data/skeletons/project/hooks/post_execution.rb +14 -0
  40. data/skeletons/project/hooks/pre_execution.rb +14 -0
  41. data/skeletons/project/spec/spec_helper.rb +14 -0
  42. data/skeletons/project/spec/untitled_spec.rb +9 -0
  43. data/skeletons/project/untitled.gemspec +40 -0
  44. metadata +47 -2
@@ -0,0 +1,386 @@
1
+ require 'mdless'
2
+
3
+ def class_exists?(class_name)
4
+ klass = Module.const_get(class_name)
5
+ return klass.is_a?(Class)
6
+ rescue NameError
7
+ return false
8
+ end
9
+
10
+ if class_exists? 'Encoding'
11
+ Encoding.default_external = Encoding::UTF_8 if Encoding.respond_to?('default_external')
12
+ Encoding.default_internal = Encoding::UTF_8 if Encoding.respond_to?('default_internal')
13
+ end
14
+
15
+ module CLIMarkdown
16
+ class Converter
17
+ def convert_markdown(input)
18
+ @headers = get_headers(input)
19
+ # yaml/MMD headers
20
+ in_yaml = false
21
+ if input.split("\n")[0] =~ /(?i-m)^---[ \t]*?(\n|$)/
22
+ @log.info("Found YAML")
23
+ # YAML
24
+ in_yaml = true
25
+ input.sub!(/(?i-m)^---[ \t]*\n([\s\S]*?)\n[\-.]{3}[ \t]*\n/) do |yaml|
26
+ m = Regexp.last_match
27
+
28
+ @log.warn("Processing YAML Header")
29
+ m[0].split(/\n/).map {|line|
30
+ if line =~ /^[\-.]{3}\s*$/
31
+ line = c([:d,:black,:on_black]) + "% " + c([:d,:black,:on_black]) + line
32
+ else
33
+ line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
34
+ line = c([:d,:black,:on_black]) + "% " + c([:d,:white]) + line
35
+ end
36
+ if @cols - line.uncolor.size > 0
37
+ line += " "*(@cols-line.uncolor.size)
38
+ end
39
+ }.join("\n") + "#{xc}\n"
40
+ end
41
+ end
42
+
43
+ if !in_yaml && input.gsub(/\n/,' ') =~ /(?i-m)^\w.+:\s+\S+ /
44
+ @log.info("Found MMD Headers")
45
+ input.sub!(/(?i-m)^([\S ]+:[\s\S]*?)+(?=\n\n)/) do |mmd|
46
+ puts mmd
47
+ mmd.split(/\n/).map {|line|
48
+ line.sub!(/^(.*?:)[ \t]+(\S)/, '\1 \2')
49
+ line = c([:d,:black,:on_black]) + "% " + c([:d,:white,:on_black]) + line
50
+ if @cols - line.uncolor.size > 0
51
+ line += " "*(@cols - line.uncolor.size)
52
+ end
53
+ }.join("\n") + " "*@cols + "#{xc}\n"
54
+ end
55
+
56
+ end
57
+
58
+
59
+ # Gather reference links
60
+ input.gsub!(/^\s{,3}(?<![\e*])\[\b(.+)\b\]: +(.+)/) do |m|
61
+ match = Regexp.last_match
62
+ @ref_links[match[1]] = match[2]
63
+ ''
64
+ end
65
+
66
+ # Gather footnotes (non-inline)
67
+ input.gsub!(/^ {,3}(?<!\*)(?:\e\[[\d;]+m)*\[(?:\e\[[\d;]+m)*\^(?:\e\[[\d;]+m)*\b(.+)\b(?:\e\[[\d;]+m)*\]: *(.*?)\n/) do |m|
68
+ match = Regexp.last_match
69
+ @footnotes[match[1].uncolor] = match[2].uncolor
70
+ ''
71
+ end
72
+
73
+ if @options[:section]
74
+ in_section = false
75
+ top_level = 1
76
+ new_content = []
77
+
78
+ input.split(/\n/).each {|graf|
79
+ if graf =~ /^(#+) *(.*?)( *#+)?$/
80
+ level = $1.length
81
+ title = $2
82
+
83
+ if in_section
84
+ if level >= top_level
85
+ new_content.push(graf)
86
+ else
87
+ in_section = false
88
+ break
89
+ end
90
+ elsif title.downcase == "#{@headers[@options[:section] - 1][1].downcase}"
91
+ in_section = true
92
+ top_level = level + 1
93
+ new_content.push(graf)
94
+ else
95
+ next
96
+ end
97
+ elsif in_section
98
+ new_content.push(graf)
99
+ end
100
+ }
101
+
102
+ input = new_content.join("\n")
103
+ end
104
+
105
+ h_adjust = highest_header(input) - 1
106
+ input.gsub!(/^(#+)/) do |m|
107
+ match = Regexp.last_match
108
+ "#" * (match[1].length - h_adjust)
109
+ end
110
+
111
+ input.gsub!(/(?i-m)([`~]{3,})([\s\S]*?)\n([\s\S]*?)\1/ ) do |cb|
112
+ m = Regexp.last_match
113
+ leader = m[2] ? m[2].upcase + ":" : 'CODE:'
114
+ leader += xc
115
+
116
+ if exec_available('pygmentize')
117
+ lexer = m[2].nil? ? '-g' : "-l #{m[2]}"
118
+ begin
119
+ hilite, s = Open3.capture2(%Q{pygmentize #{lexer} 2> /dev/null}, :stdin_data=>m[3])
120
+
121
+ if s.success?
122
+ hilite = hilite.split(/\n/).map{|l| "#{c([:x,:black])}~ #{xc}" + l}.join("\n")
123
+ end
124
+ rescue => e
125
+ @log.error(e)
126
+ hilite = m[0]
127
+ end
128
+
129
+ else
130
+
131
+ hilite = m[3].split(/\n/).map{|l|
132
+ new_code_line = l.gsub(/\t/,' ')
133
+ orig_length = new_code_line.size + 3
134
+ new_code_line.gsub!(/ /,"#{c([:x,:white,:on_black])} ")
135
+ "#{c([:x,:black])}~ #{c([:x,:white,:on_black])} " + new_code_line + c([:x,:white,:on_black]) + xc
136
+ }.join("\n")
137
+ end
138
+ "#{c([:x,:magenta])}#{leader}\n#{hilite}#{xc}"
139
+ end
140
+
141
+ # remove empty links
142
+ input.gsub!(/\[(.*?)\]\(\s*?\)/, '\1')
143
+ input.gsub!(/\[(.*?)\]\[\]/, '[\1][\1]')
144
+
145
+ lines = input.split(/\n/)
146
+
147
+ # previous_indent = 0
148
+
149
+ lines.map!.with_index do |aLine, i|
150
+ line = aLine.dup
151
+ clean_line = line.dup.uncolor
152
+
153
+
154
+ if clean_line.uncolor =~ /(^[%~])/ # || clean_line.uncolor =~ /^( {4,}|\t+)/
155
+ ## TODO: find indented code blocks and prevent highlighting
156
+ ## Needs to miss block indented 1 level in lists
157
+ ## Needs to catch lists in code
158
+ ## Needs to avoid within fenced code blocks
159
+ # if line =~ /^([ \t]+)([^*-+]+)/
160
+ # indent = $1.gsub(/\t/, " ").size
161
+ # if indent >= previous_indent
162
+ # line = "~" + line
163
+ # end
164
+ # p [indent, previous_indent]
165
+ # previous_indent = indent
166
+ # end
167
+ else
168
+ # Headlines
169
+ line.gsub!(/^(#+) *(.*?)(\s*#+)?\s*$/) do |match|
170
+ m = Regexp.last_match
171
+ pad = ""
172
+ ansi = ''
173
+ case m[1].length
174
+ when 1
175
+ ansi = c([:b, :black, :on_intense_white])
176
+ pad = c([:b,:white])
177
+ pad += m[2].length + 2 > @cols ? "*"*m[2].length : "*"*(@cols - (m[2].length + 2))
178
+ when 2
179
+ ansi = c([:b, :green, :on_black])
180
+ pad = c([:b,:black])
181
+ pad += m[2].length + 2 > @cols ? "-"*m[2].length : "-"*(@cols - (m[2].length + 2))
182
+ when 3
183
+ ansi = c([:u, :b, :yellow])
184
+ when 4
185
+ ansi = c([:x, :u, :yellow])
186
+ else
187
+ ansi = c([:b, :white])
188
+ end
189
+
190
+ "\n#{xc}#{ansi}#{m[2]} #{pad}#{xc}\n"
191
+ end
192
+
193
+ # place footnotes under paragraphs that reference them
194
+ if line =~ /\[(?:\e\[[\d;]+m)*\^(?:\e\[[\d;]+m)*(\S+)(?:\e\[[\d;]+m)*\]/
195
+ key = $1.uncolor
196
+ if @footnotes.key? key
197
+ line += "\n\n#{c([:b,:black,:on_black])}[#{c([:b,:cyan,:on_black])}^#{c([:x,:yellow,:on_black])}#{key}#{c([:b,:black,:on_black])}]: #{c([:u,:white,:on_black])}#{@footnotes[key]}#{xc}"
198
+ @footnotes.delete(key)
199
+ end
200
+ end
201
+
202
+ # color footnote references
203
+ line.gsub!(/\[\^(\S+)\]/) do |m|
204
+ match = Regexp.last_match
205
+ last = find_color(match.pre_match, true)
206
+ counter = i
207
+ while last.nil? && counter > 0
208
+ counter -= 1
209
+ find_color(lines[counter])
210
+ end
211
+ "#{c([:b,:black])}[#{c([:b,:yellow])}^#{c([:x,:yellow])}#{match[1]}#{c([:b,:black])}]" + (last ? last : xc)
212
+ end
213
+
214
+ # blockquotes
215
+ line.gsub!(/^(\s*>)+( .*?)?$/) do |m|
216
+ match = Regexp.last_match
217
+ last = find_color(match.pre_match, true)
218
+ counter = i
219
+ while last.nil? && counter > 0
220
+ counter -= 1
221
+ find_color(lines[counter])
222
+ end
223
+ "#{c([:b,:black])}#{match[1]}#{c([:x,:magenta])} #{match[2]}" + (last ? last : xc)
224
+ end
225
+
226
+ # make reference links inline
227
+ line.gsub!(/(?<![\e*])\[(\b.*?\b)?\]\[(\b.+?\b)?\]/) do |m|
228
+ match = Regexp.last_match
229
+ title = match[2] || ''
230
+ text = match[1] || ''
231
+ if match[2] && @ref_links.key?(title.downcase)
232
+ "[#{text}](#{@ref_links[title]})"
233
+ elsif match[1] && @ref_links.key?(text.downcase)
234
+ "[#{text}](#{@ref_links[text]})"
235
+ else
236
+ if input.match(/^#+\s*#{Regexp.escape(text)}/i)
237
+ "[#{text}](##{text})"
238
+ else
239
+ match[1]
240
+ end
241
+ end
242
+ end
243
+
244
+ # color inline links
245
+ line.gsub!(/(?<![\e*!])\[(\S.*?\S)\]\((\S.+?\S)\)/) do |m|
246
+ match = Regexp.last_match
247
+ color_link(match.pre_match, match[1], match[2])
248
+ end
249
+
250
+
251
+
252
+ # inline code
253
+ line.gsub!(/`(.*?)`/) do |m|
254
+ match = Regexp.last_match
255
+ last = find_color(match.pre_match, true)
256
+ "#{c([:b,:black])}`#{c([:b,:white])}#{match[1]}#{c([:b,:black])}`" + (last ? last : xc)
257
+ end
258
+
259
+ # horizontal rules
260
+ line.gsub!(/^ {,3}([\-*] ?){3,}$/) do |m|
261
+ c([:x,:black]) + '_'*@cols + xc
262
+ end
263
+
264
+ # bold, bold/italic
265
+ line.gsub!(/(^|\s)[\*_]{2,3}([^\*_\s][^\*_]+?[^\*_\s])[\*_]{2,3}/) do |m|
266
+ match = Regexp.last_match
267
+ last = find_color(match.pre_match, true)
268
+ counter = i
269
+ while last.nil? && counter > 0
270
+ counter -= 1
271
+ find_color(lines[counter])
272
+ end
273
+ "#{match[1]}#{c([:b])}#{match[2]}" + (last ? last : xc)
274
+ end
275
+
276
+ # italic
277
+ line.gsub!(/(^|\s)[\*_]([^\*_\s][^\*_]+?[^\*_\s])[\*_]/) do |m|
278
+ match = Regexp.last_match
279
+ last = find_color(match.pre_match, true)
280
+ counter = i
281
+ while last.nil? && counter > 0
282
+ counter -= 1
283
+ find_color(lines[counter])
284
+ end
285
+ "#{match[1]}#{c([:u])}#{match[2]}" + (last ? last : xc)
286
+ end
287
+
288
+ # equations
289
+ line.gsub!(/((\\\\\[)(.*?)(\\\\\])|(\\\\\()(.*?)(\\\\\)))/) do |m|
290
+ match = Regexp.last_match
291
+ last = find_color(match.pre_match)
292
+ if match[2]
293
+ brackets = [match[2], match[4]]
294
+ equat = match[3]
295
+ else
296
+ brackets = [match[5], match[7]]
297
+ equat = match[6]
298
+ end
299
+ "#{c([:b, :black])}#{brackets[0]}#{xc}#{c([:b,:blue])}#{equat}#{c([:b, :black])}#{brackets[1]}" + (last ? last : xc)
300
+ end
301
+
302
+ # list items
303
+ # TODO: Fix ordered list numbering, pad numbers based on total number of list items
304
+ line.gsub!(/^(\s*)([*\-+]|\d+\.) /) do |m|
305
+ match = Regexp.last_match
306
+ last = find_color(match.pre_match)
307
+ indent = match[1] || ''
308
+ "#{indent}#{c([:d, :red])}#{match[2]} " + (last ? last : xc)
309
+ end
310
+
311
+ # definition lists
312
+ line.gsub!(/^(:\s*)(.*?)/) do |m|
313
+ match = Regexp.last_match
314
+ "#{c([:d, :red])}#{match[1]} #{c([:b, :white])}#{match[2]}#{xc}"
315
+ end
316
+
317
+ # misc html
318
+ line.gsub!(/<br\/?>/, "\n")
319
+ line.gsub!(/(?i-m)((<\/?)(\w+[\s\S]*?)(>))/) do |tag|
320
+ match = Regexp.last_match
321
+ last = find_color(match.pre_match)
322
+ "#{c([:d,:black])}#{match[2]}#{c([:b,:black])}#{match[3]}#{c([:d,:black])}#{match[4]}" + (last ? last : xc)
323
+ end
324
+ end
325
+
326
+ line
327
+ end
328
+
329
+ input = lines.join("\n")
330
+
331
+ # images
332
+ input.gsub!(/^(.*?)!\[(.*)?\]\((.*?\.(?:png|gif|jpg))( +.*)?\)/) do |m|
333
+ match = Regexp.last_match
334
+ if match[1].uncolor =~ /^( {4,}|\t)+/
335
+ match[0]
336
+ else
337
+ tail = match[4].nil? ? '' : " "+match[4].strip
338
+ result = nil
339
+ if exec_available('imgcat') && @options[:local_images]
340
+ if match[3]
341
+ img_path = match[3]
342
+ if img_path =~ /^http/ && @options[:remote_images]
343
+ begin
344
+ res, s = Open3.capture2(%Q{curl -sS "#{img_path}" 2> /dev/null | imgcat})
345
+
346
+ if s.success?
347
+ pre = match[2].size > 0 ? " #{c([:d,:blue])}[#{match[2].strip}]\n" : ''
348
+ post = tail.size > 0 ? "\n #{c([:b,:blue])}-- #{tail} --" : ''
349
+ result = pre + res + post
350
+ end
351
+ rescue => e
352
+ @log.error(e)
353
+ end
354
+ else
355
+ if img_path =~ /^[~\/]/
356
+ img_path = File.expand_path(img_path)
357
+ elsif @file
358
+ base = File.expand_path(File.dirname(@file))
359
+ img_path = File.join(base,img_path)
360
+ end
361
+ if File.exists?(img_path)
362
+ pre = match[2].size > 0 ? " #{c([:d,:blue])}[#{match[2].strip}]\n" : ''
363
+ post = tail.size > 0 ? "\n #{c([:b,:blue])}-- #{tail} --" : ''
364
+ img = %x{imgcat "#{img_path}"}
365
+ result = pre + img + post
366
+ end
367
+ end
368
+ end
369
+ end
370
+ if result.nil?
371
+ match[1] + color_image(match.pre_match, match[2], match[3] + tail) + xc
372
+ else
373
+ match[1] + result + xc
374
+ end
375
+ end
376
+ end
377
+
378
+ @footnotes.each {|t, v|
379
+ input += "\n\n#{c([:b,:black,:on_black])}[#{c([:b,:yellow,:on_black])}^#{c([:x,:yellow,:on_black])}#{t}#{c([:b,:black,:on_black])}]: #{c([:u,:white,:on_black])}#{v}#{xc}"
380
+ }
381
+
382
+ @output += input
383
+
384
+ end
385
+ end
386
+ end
@@ -0,0 +1,87 @@
1
+ module RBCliTool
2
+ class Project
3
+
4
+ def initialize path, template_vars = {}
5
+ @skelpath = "#{File.dirname(__FILE__)}/../../skeletons/project"
6
+ @minipath = "#{File.dirname(__FILE__)}/../../skeletons/mini/executable"
7
+ @micropath = "#{File.dirname(__FILE__)}/../../skeletons/micro/executable"
8
+
9
+ @dest = path
10
+ @template_vars = template_vars
11
+ end
12
+
13
+ def create force = false
14
+ return false if project_exists? and not force
15
+ src = @skelpath
16
+
17
+ # Create Top Level Folder (TLF)
18
+ FileUtils.mkdir_p @dest
19
+
20
+ # Create project structure
21
+ %w(
22
+ application/commands
23
+ application/commands/scripts
24
+ config
25
+ default_user_configs
26
+ exe
27
+ hooks
28
+ spec
29
+ ).each do |folder|
30
+ FileUtils.mkdir_p "#{@dest}/#{folder}"
31
+ FileUtils.touch "#{@dest}/#{folder}/.keep"
32
+ end
33
+
34
+ # Create executable
35
+ RBCliTool.cp_file "#{src}/exe/executable", "#{@dest}/exe/#{@template_vars[:cmdname]}", @template_vars
36
+
37
+ # Create files for Gem package
38
+ Dir.entries(src).each do |file|
39
+ next if File.directory? "#{src}/#{file}"
40
+ RBCliTool.cp_file "#{src}/#{file}", "#{@dest}/", @template_vars
41
+ end
42
+
43
+ # Create default config
44
+ Dir.glob "#{src}/config/*.rb" do |file|
45
+ RBCliTool.cp_file file, "#{@dest}/config/", @template_vars
46
+ end
47
+
48
+ # Create application options
49
+ RBCliTool.cp_file "#{src}/application/options.rb", "#{@dest}/application/options.rb", @template_vars
50
+
51
+ true
52
+ end
53
+
54
+ def create_mini force = false
55
+ return false if project_exists? and not force
56
+ RBCliTool.cp_file @minipath, @dest, @template_vars
57
+ end
58
+
59
+ def create_micro force = false
60
+ return false if project_exists? and not force
61
+ RBCliTool.cp_file @micropath, @dest, @template_vars
62
+ end
63
+
64
+ def exists?
65
+ project_exists?
66
+ end
67
+
68
+ private
69
+
70
+ def project_exists?
71
+ # If the specified file already exists...
72
+ return true if File.exists? @dest
73
+
74
+ # Or if the .rbcli file exists anywhere in the tree...
75
+ searchpath = @dest
76
+ while !searchpath.empty?
77
+ return searchpath if File.directory? searchpath and File.exists? "#{searchpath}/.rbcli"
78
+ spath = searchpath.split('/')
79
+ searchpath = (spath.length == 2) ? '/' : spath[0..-2].join('/')
80
+ end
81
+
82
+ # Otherwise we say the project does not exist
83
+ false
84
+ end
85
+ end
86
+
87
+ end
data/lib/rbcli-tool.rb ADDED
@@ -0,0 +1,16 @@
1
+ ###########
2
+ ## RBCLI ##
3
+ ###########
4
+ #
5
+ # This file loads the Rbcli CLI Tool components.
6
+ #
7
+ ###########
8
+
9
+ lib = File.expand_path('../../lib', __FILE__)
10
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
11
+
12
+ module RBCliTool end
13
+
14
+ require 'rbcli-tool/mdless_fix'
15
+ require 'rbcli-tool/erb_renderer'
16
+ require 'rbcli-tool/project'
data/lib/rbcli.rb CHANGED
@@ -12,7 +12,7 @@ lib = File.expand_path('../../lib', __FILE__)
12
12
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
13
13
 
14
14
  module Rbcli end # Empty module declaration required to declare submodules freely
15
- require "rbcli/version"
15
+ require 'rbcli/version'
16
16
 
17
17
  # UTILS
18
18
  require 'rbcli/util/hash_deep_symbolize'
@@ -26,22 +26,23 @@ require 'rbcli/logging/logging'
26
26
 
27
27
 
28
28
  # STATE TOOLS
29
- require "rbcli/stateful_systems/configuratestorage"
30
- require "rbcli/stateful_systems/state_storage"
31
- require "rbcli/stateful_systems/storagetypes/localstate"
32
- require "rbcli/stateful_systems/storagetypes/remotestate_dynamodb"
29
+ require 'rbcli/stateful_systems/configuratestorage'
30
+ require 'rbcli/stateful_systems/state_storage'
31
+ require 'rbcli/stateful_systems/storagetypes/localstate'
32
+ require 'rbcli/stateful_systems/storagetypes/remotestate_dynamodb'
33
33
  # END STATE TOOLS
34
34
 
35
35
  # AUTOUPDATE
36
- require "rbcli/autoupdate/autoupdate"
36
+ require 'rbcli/autoupdate/autoupdate'
37
37
  # END AUTOUPDATE
38
38
 
39
39
  # SCRIPT WRAPPER
40
- require "rbcli/scriptwrapping/scriptwrapper"
40
+ require 'rbcli/scriptwrapping/scriptwrapper'
41
41
  # END SCRIPT WRAPPER
42
42
 
43
43
  # CORE
44
- require "rbcli/configuration/configurate"
45
- require "rbcli/engine/command"
46
- require "rbcli/engine/parser"
44
+ require 'rbcli/configuration/configurate'
45
+ require 'rbcli/engine/load_project'
46
+ require 'rbcli/engine/command'
47
+ require 'rbcli/engine/parser'
47
48
  # END CORE
data/rbcli.gemspec CHANGED
@@ -44,6 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_dependency 'macaddr', '~> 1.7'
45
45
  spec.add_dependency 'rufus-scheduler', '~> 3.5'
46
46
  spec.add_dependency 'octokit', '~> 4.9'
47
+ spec.add_dependency 'mdless', '~> 0.0'
47
48
 
48
49
  #spec.add_dependency 'trollop', '~> 2.1'
49
50
  end
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #########################################################
4
+ ### <%= @vars[:cmdname] %>
5
+ #######
6
+ ## This is the main executable for <%= @vars[:cmdname] %>.
7
+ ## It's job is to load and execute the application.
8
+ #########################################################
9
+
10
+ require 'rbcli'
11
+
12
+ #########################
13
+ ## Configuration Block ##
14
+ #########################
15
+ Rbcli::Configurate.me do
16
+ ## Script Name -- (Required) -- This line identifies the tool's executable on the command line.
17
+ scriptname __FILE__.split('/')[-1]
18
+
19
+ ## Version Number -- (Required)
20
+ version '0.1.0'
21
+
22
+ ## Description -- (Requierd) -- A description that will appear when the user looks at the help with -h. This can be as long as needed.
23
+ description %q{<%= @vars[:description] %>}
24
+
25
+
26
+ ## Log Target -- (Optional) -- Set the target for logs.
27
+ log_target nil
28
+
29
+ ## Log Level -- (Optional) -- Set the default log_level for users.
30
+ log_level nil
31
+
32
+
33
+ ## Config Userfile -- (Optional) -- Set location of user's config file.
34
+ config_userfile '~/.<%= @vars[:cmdname] %>', merge_defaults: true, required: false
35
+
36
+ ## Config Defaults -- (Optional, Multiple) -- Load a YAML file as part of the default config.
37
+ #config_defaults 'defaults.yml'
38
+
39
+ ## Config Default -- (Optional, Multiple) -- Specify an individual configuration parameter and set a default value.
40
+ config_default :myopt, description: 'Testing this', default: true
41
+
42
+
43
+ ## Autoupdate, Github -- (Optional) -- Check for updates to this application at a GitHub repo.
44
+ #autoupdate github_repo: '<your_user>/<your_repo>', access_token: nil, enterprise_hostname: nil, force_update: false
45
+
46
+ ## Autoupdate, Rubygems.org -- (Optional) -- Check for updates to this application on Rubygems.org
47
+ #autoupdate gem: '<your_gem>', force_update: false
48
+
49
+
50
+ ## Option -- (Optional, Multiple) -- Add a global CLI Option
51
+ option :name, 'Give me your name', type: :string, default: 'Foo', required: false, permitted: ['Jack', 'Jill']
52
+
53
+
54
+ ## Default Action -- (Optional) -- The default code to execute when no subcommand is given.
55
+ default_action do |opts|
56
+ puts "Hello, #{opts[:name]}."
57
+ puts "To see the help, use -h"
58
+ end
59
+
60
+ ## Pre-Execution Hook -- (Optional) -- Allows providing a block of code that runs _before_ all commands
61
+ # pre_hook do |opts|
62
+ # puts 'This is a pre-command hook. It executes before the command.'
63
+ # end
64
+
65
+ ## Post-Execution Hook -- (Optional) -- Allows providing a block of code that runs _after_ all commands
66
+ # post_hook do |opts|
67
+ # puts 'This is a post-command hook. It executes after the command.'
68
+ # end
69
+
70
+ ## First-Run Hook -- (Optional) -- Allows providing a block of code that executes the first time that the application is run on a given system.
71
+ # first_run halt_after_running: false do
72
+ # puts "This is the first time the mytool command is run! Don't forget to generate a config file with the `-g` option before continuing."
73
+ # end
74
+ end
75
+
76
+ ###############################
77
+ ## State Configuration Block ##
78
+ ###############################
79
+ Rbcli::Configurate.storage do
80
+ ###
81
+ # Local State Storage
82
+ ###
83
+
84
+ ## Local State -- (Optional) -- Creates a hash that is automatically saved to a file locally for state persistance. It is accessible to all commands at Rbcli.localstate[:yourkeyhere]
85
+ #local_state '/var/mytool/localstate', force_creation: true, halt_on_error: true
86
+
87
+
88
+ ## Remote State -- (Optional) -- Creates a hash that is automatically saved to a DynamoDB table. It is recommended to keep halt_on_error=true when using a shared state. Locking can be one of (:manual :auto :none).
89
+ #remote_state_dynamodb table_name: 'mytable', region: 'us-east-1', force_creation: true, halt_on_error: true, locking: :auto
90
+ end
91
+
92
+ #########################
93
+ ## Command Declaration ##
94
+ #########################
95
+ class Test < Rbcli::Command # Declare a new command by subclassing Rbcli::Command
96
+ description 'This is a short description.' # (Required) Short description for the global help
97
+ usage 'This is some really long usage text description!' # (Required) Long description for the command-specific help
98
+ parameter :force, 'Force testing', type: :boolean, default: false, required: false # (Optional, Multiple) Add a command-specific CLI parameter. Can be called multiple times
99
+
100
+ config_defaults 'defaults.yml' # (Optional, Multiple) Load a YAML file as part of the default config. This can be called multiple times, and the YAML files will be merged. User config is generated from these
101
+ config_default :myopt2, description: 'Testing this again', default: true # (Optional, Multiple) Specify an individual configuration parameter and set a default value. These will also be included in generated user config
102
+
103
+ extern path: 'env | grep "^__PARAMS\|^__ARGS\|^__GLOBAL\|^__CONFIG"', envvars: {MYVAR: 'some_value'} # (Required unless `action` defined) Runs a given application, with optional environment variables, when the user runs the command.
104
+ extern envvars: {MY_OTHER_VAR: 'another_value'} do |params, args, global_opts, config| # Alternate usage. Supplying a block instead of a path allows us to modify the command based on the arguments and configuration supplied by the user.
105
+ "echo #{params[:force].to_s}__YESSS!!!"
106
+ end
107
+
108
+ action do |params, args, global_opts, config| # (Required unless `extern` defined) Block to execute if the command is called.
109
+ Rbcli::log.info { 'These logs can go to STDERR, STDOUT, or a file' } # Example log. Interface is identical to Ruby's logger
110
+ puts "\nArgs:\n#{args}" # Arguments that came after the command on the CLI (i.e.: `mytool test bar baz` will yield args=['bar', 'baz'])
111
+ puts "Params:\n#{params}" # Parameters, as described through the option statements above
112
+ puts "Global opts:\n#{global_opts}" # Global Parameters, as descirbed in the Configurate section
113
+ puts "Config:\n#{config}" # Config file values
114
+ puts "LocalState:\n#{Rbcli.local_state}" # Local persistent state storage (when available) -- if unsure use Rbcli.local_state.nil?
115
+ puts "RemoteState:\n#{Rbcli.remote_state}" # Remote persistent state storage (when available) -- if unsure use Rbcli.remote_state.nil?
116
+ puts "\nDone!!!"
117
+ end
118
+ end
119
+
120
+ #####################
121
+ ## Parse Statement ##
122
+ #####################
123
+ Rbcli.parse # Parse CLI and execute