wip-runner 0.3.0 → 0.3.1

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