rbcli 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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