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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c64b6f78c5e647a9466ebd60985ac716ded1bf9f
4
- data.tar.gz: ef987404e179109f39e0d70bef78b7926428b21f
3
+ metadata.gz: 1f477879c1c21aefbb14a98a5b81adbec74aa359
4
+ data.tar.gz: 5476e96fb0f8bd8a7235e7ac22d7e8386ba2cdcd
5
5
  SHA512:
6
- metadata.gz: 289d7586526bc1634e9303ddd1d9dde0b4110f1434fd270e059b1a7ab35af9c4407efef24bc14739bc598d5d13a806c79bc355cefd3f8d896cf7b36dd5333235
7
- data.tar.gz: df6f588f1eac45e2e11567812981b36e96162cc3c1b5e95cd68a4a3eeed741980d1a27250fa5fe14021a12362d42fd56fdc2925f81214088a5c2e30b3d162ef8
6
+ metadata.gz: 2c5f6158af88078c592cabbdc937287abfb40f5b34f70be01471ec571ef19b37c0b3b71223f1ac331fd74e7f6c589696d188d0a16fdba8bdf3d2cae94b03a25a
7
+ data.tar.gz: 3a7515d2f1463bff01978b09e40575a97bfecb414a3036d59d7a31df465651e1306b445a08a9c881ebb256d1ad5387dee5efc6c63eb7160c3f96ec96b3dad46f
@@ -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(args = [])
56
+ def run(argv = [])
57
+ args = argv.dup
47
58
  recipient = (command(args) || @parser)
48
59
  recipient.run(args)
49
60
  rescue InvalidCommand => e
@@ -51,21 +51,25 @@ module WIP
51
51
  end
52
52
 
53
53
  def run(argv = [])
54
- parser.run(argv) do |command, arguments, options|
55
- if command.nil?
56
- if options.help
57
- parser.help
58
- return
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 OptionParser::InvalidOption, InvalidArguments, InvalidCommand => e
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
- if parser.arguments.keys.any? { |key| arguments[key].nil? }
81
- lines = []
82
- arguments.each_pair do |key, value|
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.capitalize)
100
+ @io.say(e.message)
99
101
  @io.newline
100
102
  parser.help
101
103
  end
@@ -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 = self.class.name.split('::').last
15
- .gsub(/([A-Z])/, " \\1")
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
- class InvalidArguments < Error; end
22
- class InvalidCommand < Error; end
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
@@ -2,6 +2,18 @@ require 'ostruct'
2
2
 
3
3
  module WIP
4
4
  module Runner
5
- class Options < OpenStruct ; end
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
@@ -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, '(missing)' if command.nil?
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, details|
86
- padding = ' ' * (parser.summary_width - name.length + 1)
87
- parser.separator [parser.summary_indent, name, padding, details[:overview]].join('')
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,5 @@
1
+ module WIP::Runner::Renderer
2
+ module Handlers ; end
3
+ end
4
+
5
+ Dir[File.expand_path('../handlers/*.rb', __FILE__)].each { |f| require(f) }
@@ -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) }
@@ -1,5 +1,5 @@
1
1
  module WIP
2
2
  module Runner
3
- VERSION = "0.3.0"
3
+ VERSION = "0.3.1"
4
4
  end
5
5
  end
data/lib/wip/runner.rb CHANGED
@@ -11,7 +11,7 @@ require 'wip/runner/cli/version'
11
11
  require 'wip/runner/shell'
12
12
  require 'wip/runner/workflow'
13
13
  require 'wip/runner/commands'
14
- require 'wip/runner/renderers'
14
+ require 'wip/runner/renderer'
15
15
 
16
16
  module WIP
17
17
  module Runner ; end
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.0
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-03 00:00:00.000000000 Z
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/renderers.rb
99
- - lib/wip/runner/renderers/erb.rb
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
@@ -1,7 +0,0 @@
1
- module WIP
2
- module Runner
3
- module Renderers ; end
4
- end
5
- end
6
-
7
- Dir[File.expand_path('../renderers/*.rb', __FILE__)].each { |f| require(f) }