toys 0.2.2 → 0.3.0

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.
@@ -0,0 +1,101 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ module Toys
31
+ module Utils
32
+ ##
33
+ # A helper module that provides methods to do module lookups. This is
34
+ # used to obtain named helpers, middleware, and templates from the
35
+ # respective modules.
36
+ #
37
+ # You generally do not need to use these module methods directly. Instead
38
+ # use the convenience methods {Toys::Helpers.lookup},
39
+ # {Toys::Middleware.lookup}, or {Toys::Templates.lookup}.
40
+ #
41
+ module ModuleLookup
42
+ class << self
43
+ ##
44
+ # Convert the given string to a path element. Specifically, converts
45
+ # to `lower_snake_case`.
46
+ #
47
+ # @param [String,Symbol] str String to convert.
48
+ # @return [String] Converted string
49
+ #
50
+ def to_path_name(str)
51
+ str.to_s.gsub(/([a-zA-Z])([A-Z])/) { |_m| "#{$1}_#{$2.downcase}" }.downcase
52
+ end
53
+
54
+ ##
55
+ # Convert the given string to a module name. Specifically, converts
56
+ # to `UpperCamelCase`.
57
+ #
58
+ # @param [String,Symbol] str String to convert.
59
+ # @return [String] Converted string
60
+ #
61
+ def to_module_name(str)
62
+ str.to_s.gsub(/(^|_)([a-zA-Z0-9])/) { |_m| $2.upcase }
63
+ end
64
+
65
+ ##
66
+ # Obtain a named module from the given collection. Raises an exception
67
+ # on failure.
68
+ #
69
+ # @param [String,Symbol] collection The collection to search. Typical
70
+ # values are `:helpers`, `:middleware`, and `:templates`.
71
+ # @param [String,Symbol] name The name of the module to return.
72
+ #
73
+ # @return [Module] The specified module
74
+ # @raise [LoadError] No Ruby file containing the given module could
75
+ # be found.
76
+ # @raise [NameError] The given module was not defined.
77
+ #
78
+ def lookup!(collection, name)
79
+ require "toys/#{to_path_name(collection)}/#{to_path_name(name)}"
80
+ ::Toys.const_get(to_module_name(collection)).const_get(to_module_name(name))
81
+ end
82
+
83
+ ##
84
+ # Obtain a named module from the given collection. Returns `nil` on
85
+ # failure.
86
+ #
87
+ # @param [String,Symbol] collection The collection to search. Typical
88
+ # values are `:helpers`, `:middleware`, and `:templates`.
89
+ # @param [String,Symbol] name The name of the module to return.
90
+ #
91
+ # @return [Module,nil] The specified module, or `nil` if not found.
92
+ #
93
+ def lookup(collection, name)
94
+ lookup!(collection, name)
95
+ rescue ::NameError, ::LoadError
96
+ nil
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,119 @@
1
+ # Copyright 2018 Daniel Azuma
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ # * Neither the name of the copyright holder, nor the names of any other
14
+ # contributors to this software, may be used to endorse or promote products
15
+ # derived from this software without specific prior written permission.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ # POSSIBILITY OF SUCH DAMAGE.
28
+ ;
29
+
30
+ module Toys
31
+ module Utils
32
+ ##
33
+ # Helper that generates usage text
34
+ #
35
+ class Usage
36
+ def self.from_context(context)
37
+ new(context[Context::TOOL], context[Context::BINARY_NAME], context[Context::LOADER])
38
+ end
39
+
40
+ def initialize(tool, binary_name, loader)
41
+ @tool = tool
42
+ @binary_name = binary_name
43
+ @loader = loader
44
+ end
45
+
46
+ def string(recursive: false)
47
+ optparse = ::OptionParser.new
48
+ optparse.banner = @tool.includes_executor? ? tool_banner : group_banner
49
+ unless @tool.effective_long_desc.empty?
50
+ optparse.separator("")
51
+ optparse.separator(@tool.effective_long_desc)
52
+ end
53
+ add_switches(optparse)
54
+ if @tool.includes_executor?
55
+ add_positional_arguments(optparse)
56
+ elsif !@tool.alias?
57
+ add_command_list(optparse, recursive)
58
+ end
59
+ optparse.to_s
60
+ end
61
+
62
+ private
63
+
64
+ def tool_banner
65
+ banner = ["Usage:", @binary_name] + @tool.full_name
66
+ banner << "[<options...>]" unless @tool.switches.empty?
67
+ @tool.required_args.each do |arg_info|
68
+ banner << "<#{arg_info.canonical_name}>"
69
+ end
70
+ @tool.optional_args.each do |arg_info|
71
+ banner << "[<#{arg_info.canonical_name}>]"
72
+ end
73
+ if @tool.remaining_args
74
+ banner << "[<#{@tool.remaining_args.canonical_name}...>]"
75
+ end
76
+ banner.join(" ")
77
+ end
78
+
79
+ def group_banner
80
+ (["Usage:", @binary_name] + @tool.full_name + ["<command>", "[<options...>]"]).join(" ")
81
+ end
82
+
83
+ def add_switches(optparse)
84
+ return if @tool.switches.empty?
85
+ optparse.separator("")
86
+ optparse.separator("Options:")
87
+ @tool.switches.each do |switch|
88
+ optparse.on(*switch.optparse_info)
89
+ end
90
+ end
91
+
92
+ def add_positional_arguments(optparse)
93
+ args_to_display = @tool.required_args + @tool.optional_args
94
+ args_to_display << @tool.remaining_args if @tool.remaining_args
95
+ return if args_to_display.empty?
96
+ optparse.separator("")
97
+ optparse.separator("Positional arguments:")
98
+ args_to_display.each do |arg_info|
99
+ optparse.separator(" #{arg_info.canonical_name.ljust(31)} #{arg_info.doc.first}")
100
+ (arg_info.doc[1..-1] || []).each do |d|
101
+ optparse.separator(" #{d}")
102
+ end
103
+ end
104
+ end
105
+
106
+ def add_command_list(optparse, recursive)
107
+ name_len = @tool.full_name.length
108
+ subtools = @loader.list_subtools(@tool.full_name, recursive)
109
+ return if subtools.empty?
110
+ optparse.separator("")
111
+ optparse.separator("Commands:")
112
+ subtools.each do |subtool|
113
+ tool_name = subtool.full_name.slice(name_len..-1).join(" ").ljust(31)
114
+ optparse.separator(" #{tool_name} #{subtool.effective_desc}")
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -32,5 +32,5 @@ module Toys
32
32
  # Current version of Toys
33
33
  # @return [String]
34
34
  #
35
- VERSION = "0.2.2".freeze
35
+ VERSION = "0.3.0".freeze
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-13 00:00:00.000000000 Z
11
+ date: 2018-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.10'
19
+ version: '5.11'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.10'
26
+ version: '5.11'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest-focus
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.53.0
61
+ version: 0.55.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.53.0
68
+ version: 0.55.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -88,25 +88,37 @@ executables:
88
88
  extensions: []
89
89
  extra_rdoc_files: []
90
90
  files:
91
+ - CHANGELOG.md
91
92
  - LICENSE.md
92
93
  - README.md
93
94
  - bin/toys
94
95
  - lib/toys.rb
95
96
  - lib/toys/builder.rb
97
+ - lib/toys/builtins/do.rb
96
98
  - lib/toys/builtins/system.rb
97
99
  - lib/toys/cli.rb
98
100
  - lib/toys/context.rb
99
101
  - lib/toys/errors.rb
102
+ - lib/toys/helpers.rb
100
103
  - lib/toys/helpers/exec.rb
101
104
  - lib/toys/helpers/file_utils.rb
102
- - lib/toys/lookup.rb
105
+ - lib/toys/loader.rb
106
+ - lib/toys/middleware.rb
107
+ - lib/toys/middleware/base.rb
108
+ - lib/toys/middleware/group_default.rb
109
+ - lib/toys/middleware/set_verbosity.rb
110
+ - lib/toys/middleware/show_tool_help.rb
111
+ - lib/toys/middleware/show_usage_errors.rb
103
112
  - lib/toys/template.rb
113
+ - lib/toys/templates.rb
104
114
  - lib/toys/templates/clean.rb
105
115
  - lib/toys/templates/gem_build.rb
106
116
  - lib/toys/templates/minitest.rb
107
117
  - lib/toys/templates/rubocop.rb
108
118
  - lib/toys/templates/yardoc.rb
109
119
  - lib/toys/tool.rb
120
+ - lib/toys/utils/module_lookup.rb
121
+ - lib/toys/utils/usage.rb
110
122
  - lib/toys/version.rb
111
123
  homepage: https://github.com/dazuma/toys
112
124
  licenses:
@@ -128,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
140
  version: '0'
129
141
  requirements: []
130
142
  rubyforge_project:
131
- rubygems_version: 2.6.14
143
+ rubygems_version: 2.7.6
132
144
  signing_key:
133
145
  specification_version: 4
134
146
  summary: Command line tool framework