wip-runner 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/wip/runner/cli.rb +12 -1
- data/lib/wip/runner/command.rb +21 -19
- data/lib/wip/runner/errors.rb +52 -5
- data/lib/wip/runner/options.rb +13 -1
- data/lib/wip/runner/parser/option_parser.rb +41 -0
- data/lib/wip/runner/parser.rb +7 -4
- data/lib/wip/runner/renderer/context.rb +24 -0
- data/lib/wip/runner/renderer/handlers/erb.rb +22 -0
- data/lib/wip/runner/renderer/handlers.rb +5 -0
- data/lib/wip/runner/renderer/helper.rb +26 -0
- data/lib/wip/runner/renderer.rb +33 -0
- data/lib/wip/runner/version.rb +1 -1
- data/lib/wip/runner.rb +1 -1
- metadata +8 -4
- data/lib/wip/runner/renderers/erb.rb +0 -34
- data/lib/wip/runner/renderers.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f477879c1c21aefbb14a98a5b81adbec74aa359
|
4
|
+
data.tar.gz: 5476e96fb0f8bd8a7235e7ac22d7e8386ba2cdcd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c5f6158af88078c592cabbdc937287abfb40f5b34f70be01471ec571ef19b37c0b3b71223f1ac331fd74e7f6c589696d188d0a16fdba8bdf3d2cae94b03a25a
|
7
|
+
data.tar.gz: 3a7515d2f1463bff01978b09e40575a97bfecb414a3036d59d7a31df465651e1306b445a08a9c881ebb256d1ad5387dee5efc6c63eb7160c3f96ec96b3dad46f
|
data/lib/wip/runner/cli.rb
CHANGED
@@ -10,6 +10,8 @@ module WIP
|
|
10
10
|
if File.exist?("#{extension}.rb")
|
11
11
|
$:.push(File.join(extension, 'lib'))
|
12
12
|
require extension
|
13
|
+
|
14
|
+
templates(File.join(extension, 'templates'))
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -29,6 +31,14 @@ module WIP
|
|
29
31
|
def namespace
|
30
32
|
@namespace || WIP::Runner
|
31
33
|
end
|
34
|
+
|
35
|
+
def templates(*paths)
|
36
|
+
@templates ||= []
|
37
|
+
unless paths.empty?
|
38
|
+
@templates = (@templates + paths.flatten).uniq
|
39
|
+
end
|
40
|
+
@templates
|
41
|
+
end
|
32
42
|
end
|
33
43
|
|
34
44
|
def initialize(io = HighLine.new)
|
@@ -43,7 +53,8 @@ module WIP
|
|
43
53
|
exit
|
44
54
|
end
|
45
55
|
|
46
|
-
def run(
|
56
|
+
def run(argv = [])
|
57
|
+
args = argv.dup
|
47
58
|
recipient = (command(args) || @parser)
|
48
59
|
recipient.run(args)
|
49
60
|
rescue InvalidCommand => e
|
data/lib/wip/runner/command.rb
CHANGED
@@ -51,21 +51,25 @@ module WIP
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def run(argv = [])
|
54
|
-
|
55
|
-
|
56
|
-
if
|
57
|
-
|
58
|
-
|
54
|
+
begin
|
55
|
+
parser.run(argv) do |command, arguments, options|
|
56
|
+
if command.nil?
|
57
|
+
if options.help
|
58
|
+
parser.help
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
validate!(arguments)
|
63
|
+
execute(arguments, options)
|
64
|
+
else
|
65
|
+
# TODO: add a spec for the help path.
|
66
|
+
command.match(/^-/) ? parser.help : delegate(command, argv)
|
59
67
|
end
|
60
|
-
|
61
|
-
validate!(arguments)
|
62
|
-
execute(arguments, options)
|
63
|
-
else
|
64
|
-
# TODO: add a spec for the help path.
|
65
|
-
command.match(/^-/) ? parser.help : delegate(command, argv)
|
66
68
|
end
|
69
|
+
rescue OptionParser::InvalidOption => e
|
70
|
+
raise InvalidOption, e.args.join(' ')
|
67
71
|
end
|
68
|
-
rescue
|
72
|
+
rescue InvalidArgument, InvalidArguments, InvalidCommand, InvalidOption, InvalidOptions => e
|
69
73
|
print_error(e)
|
70
74
|
end
|
71
75
|
|
@@ -77,13 +81,11 @@ module WIP
|
|
77
81
|
|
78
82
|
def validate!(arguments)
|
79
83
|
unless parser.arguments.empty? || parser.config.no_validate
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
lines << " - #{key} ... (missing)" if value.nil?
|
84
|
-
end
|
85
|
-
raise InvalidArguments, %Q{\n#{lines.join("\n")}}
|
84
|
+
missing = parser.arguments.keys.inject({}) do |memo, key|
|
85
|
+
memo[key] = nil if arguments[key].nil?
|
86
|
+
memo
|
86
87
|
end
|
88
|
+
raise InvalidArguments, missing unless missing.empty?
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
@@ -95,7 +97,7 @@ module WIP
|
|
95
97
|
end
|
96
98
|
|
97
99
|
def print_error(e)
|
98
|
-
@io.say(e.message
|
100
|
+
@io.say(e.message)
|
99
101
|
@io.newline
|
100
102
|
parser.help
|
101
103
|
end
|
data/lib/wip/runner/errors.rb
CHANGED
@@ -10,15 +10,62 @@ module WIP
|
|
10
10
|
# - OptionParser::InvalidOption
|
11
11
|
module Runner
|
12
12
|
class Error < StandardError
|
13
|
+
def initialize(message = nil)
|
14
|
+
super
|
15
|
+
@message = message
|
16
|
+
end
|
17
|
+
|
13
18
|
def message
|
14
|
-
prefix
|
15
|
-
|
19
|
+
"#{prefix.capitalize}: #{format(super)}".sub(/\s\n/, "\n")
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def format(original)
|
25
|
+
if @message.is_a?(Array)
|
26
|
+
values = @message.map(&:to_s)
|
27
|
+
width = values.sort { |a, b| b.size <=> a.size }[0].size
|
28
|
+
lines = []
|
29
|
+
values.each do |value|
|
30
|
+
lines << sprintf(" - %-#{width}s", value)
|
31
|
+
end
|
32
|
+
"\n#{lines.join("\n")}"
|
33
|
+
elsif @message.respond_to?(:each) # e.g., Hash, WIP::Runner::Options
|
34
|
+
keys = @message.keys.map(&:to_s)
|
35
|
+
width = keys.sort { |a, b| b.size <=> a.size }[0].size
|
36
|
+
lines = []
|
37
|
+
@message.each do |key, value|
|
38
|
+
lines << [
|
39
|
+
sprintf(" - %-#{width}s", key.to_s),
|
40
|
+
format_value(value)
|
41
|
+
].join(' ... ')
|
42
|
+
end
|
43
|
+
"\n#{lines.join("\n")}"
|
44
|
+
else
|
45
|
+
format_value(@message)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def format_value(value)
|
50
|
+
case value
|
51
|
+
when nil
|
52
|
+
'(missing)'
|
53
|
+
else
|
54
|
+
value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def prefix
|
59
|
+
self.class.name.split('::').last.gsub(/([A-Z])/, " \\1")
|
16
60
|
.strip
|
17
61
|
.capitalize
|
18
|
-
"#{prefix}: #{super}".sub(/\s\n/, "\n")
|
19
62
|
end
|
20
63
|
end
|
21
|
-
|
22
|
-
class
|
64
|
+
|
65
|
+
class InvalidArgument < Error ; end
|
66
|
+
class InvalidArguments < Error ; end
|
67
|
+
class InvalidCommand < Error ; end
|
68
|
+
class InvalidOption < Error ; end
|
69
|
+
class InvalidOptions < Error ; end
|
23
70
|
end
|
24
71
|
end
|
data/lib/wip/runner/options.rb
CHANGED
@@ -2,6 +2,18 @@ require 'ostruct'
|
|
2
2
|
|
3
3
|
module WIP
|
4
4
|
module Runner
|
5
|
-
class Options < OpenStruct
|
5
|
+
class Options < OpenStruct
|
6
|
+
def each(&block)
|
7
|
+
self.to_h.each(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def keys
|
11
|
+
self.to_h.keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def values
|
15
|
+
self.to_h.values
|
16
|
+
end
|
17
|
+
end
|
6
18
|
end
|
7
19
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module WIP
|
2
|
+
module Runner
|
3
|
+
class Parser
|
4
|
+
class OptionParser < ::OptionParser
|
5
|
+
def list(items, mode = :rows, option = nil, pad = true)
|
6
|
+
if (mode == :rows)
|
7
|
+
items = items.map { |item| "#{option} #{item}" } if option
|
8
|
+
items.join("\n#{pad ? padding : nil}")
|
9
|
+
else
|
10
|
+
HighLine.new.list(items, mode, option)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def wrap(text, mode = :description, line_width = 80)
|
15
|
+
indented = false
|
16
|
+
|
17
|
+
if mode == :description
|
18
|
+
line_width -= indentation
|
19
|
+
indented = true
|
20
|
+
end
|
21
|
+
|
22
|
+
wrapped = text.split("\n").collect! do |line|
|
23
|
+
line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line
|
24
|
+
end * "\n"
|
25
|
+
|
26
|
+
indented ? wrapped.split("\n").join("\n#{padding}") : wrapped
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def indentation
|
32
|
+
@indentation ||= summary_indent.length + summary_width + 1
|
33
|
+
end
|
34
|
+
|
35
|
+
def padding
|
36
|
+
@padding ||= ' ' * indentation
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/wip/runner/parser.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'wip/runner/parser/option_parser'
|
2
|
+
|
1
3
|
module WIP
|
2
4
|
module Runner
|
3
5
|
class Parser
|
@@ -12,7 +14,7 @@ module WIP
|
|
12
14
|
def run(argv)
|
13
15
|
unless commands.empty?
|
14
16
|
command = argv.shift
|
15
|
-
raise InvalidCommand
|
17
|
+
raise InvalidCommand if command.nil?
|
16
18
|
yield(command, nil, nil)
|
17
19
|
else
|
18
20
|
remaining = options.parse!(argv)
|
@@ -82,9 +84,10 @@ module WIP
|
|
82
84
|
parser.separator ''
|
83
85
|
parser.separator heading
|
84
86
|
|
85
|
-
pairs.each do |name,
|
86
|
-
padding
|
87
|
-
|
87
|
+
pairs.each do |name, definition|
|
88
|
+
padding = ' ' * (parser.summary_width - name.length + 1)
|
89
|
+
overview = definition[:overview]
|
90
|
+
parser.separator [parser.summary_indent, name, padding, overview].join('')
|
88
91
|
end
|
89
92
|
end
|
90
93
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module WIP::Runner::Renderer
|
2
|
+
class Context
|
3
|
+
class << self
|
4
|
+
def for(context = {})
|
5
|
+
self.new(context).send(:__binding__)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(context)
|
10
|
+
context.each do |key, value|
|
11
|
+
if value.is_a?(Module)
|
12
|
+
value = Helper.for(self, value)
|
13
|
+
end
|
14
|
+
self.class.send(:define_method, key.intern, Proc.new { value })
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def __binding__
|
21
|
+
binding
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module WIP::Runner::Renderer
|
4
|
+
class Handlers::ERB
|
5
|
+
def initialize(template)
|
6
|
+
@template = clean(template)
|
7
|
+
end
|
8
|
+
|
9
|
+
def render(context)
|
10
|
+
::ERB.new(@template).result(context)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def clean(string)
|
16
|
+
return if string.nil?
|
17
|
+
|
18
|
+
indent = (string.scan(/^[ \t]*(?=\S)/).min || '').size
|
19
|
+
string.gsub(/^[ \t]{#{indent}}/, '').strip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module WIP::Runner::Renderer
|
2
|
+
class Helper
|
3
|
+
def self.for(context, mod)
|
4
|
+
self.instance_eval { include mod }
|
5
|
+
self.new(context)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(context)
|
9
|
+
@context = context
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def method_missing(method_name, *args, &block)
|
15
|
+
if @context.respond_to?(method_name)
|
16
|
+
@context.send(method_name, *args, &block)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to_missing?(method_name, include_private = false)
|
23
|
+
@context.respond_to?(method_name) || super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module WIP
|
2
|
+
module Runner
|
3
|
+
module Renderer
|
4
|
+
# TODO: allow handler configuration/option
|
5
|
+
def render(content, context = {})
|
6
|
+
content = path?(content) ? template(content) : content
|
7
|
+
handler(:ERB, content).render(Context.for(context))
|
8
|
+
end
|
9
|
+
|
10
|
+
def template(path)
|
11
|
+
base_paths = WIP::Runner::CLI.templates
|
12
|
+
base_paths.each do |base|
|
13
|
+
file = File.join("#{base}/#{path}")
|
14
|
+
return File.read(file) if File.exist?(file)
|
15
|
+
end
|
16
|
+
|
17
|
+
raise WIP::Runner::InvalidArgument, "#{path} not found in:\n#{base_paths.map { |base| " - #{base}" }.join("\n")}"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def path?(content)
|
23
|
+
File.extname(content).match(/\.[a-z]+$/)
|
24
|
+
end
|
25
|
+
|
26
|
+
def handler(key, content)
|
27
|
+
Handlers::const_get(key).new(content)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Dir[File.expand_path('../renderer/*.rb', __FILE__)].each { |f| require(f) }
|
data/lib/wip/runner/version.rb
CHANGED
data/lib/wip/runner.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wip-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Corey Innis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -95,8 +95,12 @@ files:
|
|
95
95
|
- lib/wip/runner/errors.rb
|
96
96
|
- lib/wip/runner/options.rb
|
97
97
|
- lib/wip/runner/parser.rb
|
98
|
-
- lib/wip/runner/
|
99
|
-
- lib/wip/runner/
|
98
|
+
- lib/wip/runner/parser/option_parser.rb
|
99
|
+
- lib/wip/runner/renderer.rb
|
100
|
+
- lib/wip/runner/renderer/context.rb
|
101
|
+
- lib/wip/runner/renderer/handlers.rb
|
102
|
+
- lib/wip/runner/renderer/handlers/erb.rb
|
103
|
+
- lib/wip/runner/renderer/helper.rb
|
100
104
|
- lib/wip/runner/shell.rb
|
101
105
|
- lib/wip/runner/shell/handlers.rb
|
102
106
|
- lib/wip/runner/shell/handlers/base.rb
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
|
-
module WIP
|
4
|
-
module Runner
|
5
|
-
module Renderers
|
6
|
-
module ERB
|
7
|
-
def self.included(base)
|
8
|
-
base.extend(ClassMethods)
|
9
|
-
end
|
10
|
-
|
11
|
-
def render(template, context)
|
12
|
-
if (file = File.join("#{self.class.templates}/#{template}.erb")) && File.exist?(file)
|
13
|
-
template = File.read(file)
|
14
|
-
end
|
15
|
-
::ERB.new(clean(template)).result(context)
|
16
|
-
end
|
17
|
-
|
18
|
-
def clean(string)
|
19
|
-
return if string.nil?
|
20
|
-
|
21
|
-
indent = (string.scan(/^[ \t]*(?=\S)/).min || '').size
|
22
|
-
string.gsub(/^[ \t]{#{indent}}/, '').strip
|
23
|
-
end
|
24
|
-
|
25
|
-
module ClassMethods
|
26
|
-
def templates(value = nil)
|
27
|
-
@templates = value unless value.nil?
|
28
|
-
@templates
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|