toys-core 0.11.5 → 0.13.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +5 -2
  5. data/docs/guide.md +1 -1
  6. data/lib/toys/acceptor.rb +13 -4
  7. data/lib/toys/arg_parser.rb +7 -7
  8. data/lib/toys/cli.rb +170 -120
  9. data/lib/toys/compat.rb +71 -23
  10. data/lib/toys/completion.rb +18 -6
  11. data/lib/toys/context.rb +24 -15
  12. data/lib/toys/core.rb +6 -2
  13. data/lib/toys/dsl/base.rb +87 -0
  14. data/lib/toys/dsl/flag.rb +26 -20
  15. data/lib/toys/dsl/flag_group.rb +18 -14
  16. data/lib/toys/dsl/internal.rb +206 -0
  17. data/lib/toys/dsl/positional_arg.rb +26 -16
  18. data/lib/toys/dsl/tool.rb +180 -218
  19. data/lib/toys/errors.rb +64 -8
  20. data/lib/toys/flag.rb +662 -656
  21. data/lib/toys/flag_group.rb +24 -10
  22. data/lib/toys/input_file.rb +13 -7
  23. data/lib/toys/loader.rb +293 -140
  24. data/lib/toys/middleware.rb +46 -22
  25. data/lib/toys/mixin.rb +10 -8
  26. data/lib/toys/positional_arg.rb +21 -20
  27. data/lib/toys/settings.rb +914 -0
  28. data/lib/toys/source_info.rb +147 -35
  29. data/lib/toys/standard_middleware/add_verbosity_flags.rb +2 -0
  30. data/lib/toys/standard_middleware/apply_config.rb +6 -4
  31. data/lib/toys/standard_middleware/handle_usage_errors.rb +1 -0
  32. data/lib/toys/standard_middleware/set_default_descriptions.rb +19 -18
  33. data/lib/toys/standard_middleware/show_help.rb +19 -5
  34. data/lib/toys/standard_middleware/show_root_version.rb +2 -0
  35. data/lib/toys/standard_mixins/bundler.rb +24 -15
  36. data/lib/toys/standard_mixins/exec.rb +43 -34
  37. data/lib/toys/standard_mixins/fileutils.rb +3 -1
  38. data/lib/toys/standard_mixins/gems.rb +21 -17
  39. data/lib/toys/standard_mixins/git_cache.rb +46 -0
  40. data/lib/toys/standard_mixins/highline.rb +8 -8
  41. data/lib/toys/standard_mixins/terminal.rb +5 -5
  42. data/lib/toys/standard_mixins/xdg.rb +56 -0
  43. data/lib/toys/template.rb +11 -9
  44. data/lib/toys/{tool.rb → tool_definition.rb} +292 -226
  45. data/lib/toys/utils/completion_engine.rb +7 -2
  46. data/lib/toys/utils/exec.rb +162 -132
  47. data/lib/toys/utils/gems.rb +85 -60
  48. data/lib/toys/utils/git_cache.rb +813 -0
  49. data/lib/toys/utils/help_text.rb +117 -37
  50. data/lib/toys/utils/terminal.rb +11 -3
  51. data/lib/toys/utils/xdg.rb +293 -0
  52. data/lib/toys/wrappable_string.rb +9 -2
  53. data/lib/toys-core.rb +18 -6
  54. metadata +14 -7
@@ -2,28 +2,10 @@
2
2
 
3
3
  module Toys
4
4
  ##
5
- # Information about source toys directories and files.
5
+ # Information about the source of a tool, such as the file, git repository,
6
+ # or block that defined it.
6
7
  #
7
8
  class SourceInfo
8
- ##
9
- # Create a SourceInfo.
10
- # @private
11
- #
12
- def initialize(parent, context_directory, source_type, source_path, source_proc,
13
- source_name, data_dir_name, lib_dir_name)
14
- @parent = parent
15
- @context_directory = context_directory
16
- @source_type = source_type
17
- @source = source_type == :proc ? source_proc : source_path
18
- @source_path = source_path
19
- @source_proc = source_proc
20
- @source_name = source_name
21
- @data_dir_name = data_dir_name
22
- @lib_dir_name = lib_dir_name
23
- @data_dir = find_special_dir(data_dir_name)
24
- @lib_dir = find_special_dir(lib_dir_name)
25
- end
26
-
27
9
  ##
28
10
  # The parent of this SourceInfo.
29
11
  #
@@ -32,6 +14,21 @@ module Toys
32
14
  #
33
15
  attr_reader :parent
34
16
 
17
+ ##
18
+ # The root ancestor of this SourceInfo.
19
+ #
20
+ # @return [Toys::SourceInfo] The root ancestor.
21
+ #
22
+ attr_reader :root
23
+
24
+ ##
25
+ # The priority of tools defined by this source. Higher values indicate a
26
+ # higher priority. Lower priority values could be negative.
27
+ #
28
+ # @return [Integer] The priority.
29
+ #
30
+ attr_reader :priority
31
+
35
32
  ##
36
33
  # The context directory path (normally the directory containing the
37
34
  # toplevel toys file or directory).
@@ -73,6 +70,30 @@ module Toys
73
70
  #
74
71
  attr_reader :source_proc
75
72
 
73
+ ##
74
+ # The git remote.
75
+ #
76
+ # @return [String] The git remote
77
+ # @return [nil] if this source is not fron git.
78
+ #
79
+ attr_reader :git_remote
80
+
81
+ ##
82
+ # The git path.
83
+ #
84
+ # @return [String] The git path. This could be the empty string.
85
+ # @return [nil] if this source is not fron git.
86
+ #
87
+ attr_reader :git_path
88
+
89
+ ##
90
+ # The git commit.
91
+ #
92
+ # @return [String] The git commit.
93
+ # @return [nil] if this source is not fron git.
94
+ #
95
+ attr_reader :git_commit
96
+
76
97
  ##
77
98
  # The user-visible name of this source.
78
99
  #
@@ -116,59 +137,150 @@ module Toys
116
137
  self
117
138
  end
118
139
 
140
+ ##
141
+ # Create a SourceInfo.
142
+ #
143
+ # @private
144
+ #
145
+ def initialize(parent, priority, context_directory, source_type, source_path, source_proc,
146
+ git_remote, git_path, git_commit, source_name, data_dir_name, lib_dir_name)
147
+ @parent = parent
148
+ @root = parent&.root || self
149
+ @priority = priority
150
+ @context_directory = context_directory
151
+ @source_type = source_type
152
+ @source = source_type == :proc ? source_proc : source_path
153
+ @source_path = source_path
154
+ @source_proc = source_proc
155
+ @git_remote = git_remote
156
+ @git_path = git_path
157
+ @git_commit = git_commit
158
+ @source_name = source_name
159
+ @data_dir_name = data_dir_name
160
+ @lib_dir_name = lib_dir_name
161
+ @data_dir = find_special_dir(data_dir_name)
162
+ @lib_dir = find_special_dir(lib_dir_name)
163
+ end
164
+
119
165
  ##
120
166
  # Create a child SourceInfo relative to the parent path.
167
+ #
121
168
  # @private
122
169
  #
123
- def relative_child(filename)
124
- raise "relative_child is valid only on a directory source" unless source_type == :directory
170
+ def relative_child(filename, source_name: nil)
171
+ unless source_type == :directory
172
+ raise LoaderError, "relative_child is valid only on a directory source"
173
+ end
125
174
  child_path = ::File.join(source_path, filename)
126
175
  child_path, type = SourceInfo.check_path(child_path, true)
127
176
  return nil unless child_path
128
- SourceInfo.new(self, context_directory, type, child_path, nil, child_path,
129
- @data_dir_name, @lib_dir_name)
177
+ child_git_path = ::File.join(git_path, filename) if git_path
178
+ source_name ||=
179
+ if git_path
180
+ "git(remote=#{git_remote} path=#{child_git_path} commit=#{git_commit})"
181
+ else
182
+ child_path
183
+ end
184
+ SourceInfo.new(self, priority, context_directory, type, child_path, nil,
185
+ git_remote, child_git_path, git_commit,
186
+ source_name, @data_dir_name, @lib_dir_name)
130
187
  end
131
188
 
132
189
  ##
133
190
  # Create a child SourceInfo with an absolute path.
191
+ #
134
192
  # @private
135
193
  #
136
- def absolute_child(child_path)
194
+ def absolute_child(child_path, source_name: nil)
137
195
  child_path, type = SourceInfo.check_path(child_path, false)
138
- SourceInfo.new(self, context_directory, type, child_path, nil, child_path,
139
- @data_dir_name, @lib_dir_name)
196
+ source_name ||= child_path
197
+ SourceInfo.new(self, priority, context_directory, type, child_path, nil, nil, nil, nil,
198
+ source_name, @data_dir_name, @lib_dir_name)
199
+ end
200
+
201
+ ##
202
+ # Create a child SourceInfo with a git source.
203
+ #
204
+ # @private
205
+ #
206
+ def git_child(child_git_remote, child_git_path, child_git_commit, child_path,
207
+ source_name: nil)
208
+ child_path, type = SourceInfo.check_path(child_path, false)
209
+ source_name ||=
210
+ "git(remote=#{child_git_remote} path=#{child_git_path} commit=#{child_git_commit})"
211
+ SourceInfo.new(self, priority, context_directory, type, child_path, nil,
212
+ child_git_remote, child_git_path, child_git_commit,
213
+ source_name, @data_dir_name, @lib_dir_name)
140
214
  end
141
215
 
142
216
  ##
143
217
  # Create a proc child SourceInfo
218
+ #
144
219
  # @private
145
220
  #
146
- def proc_child(child_proc, source_name = nil)
221
+ def proc_child(child_proc, source_name: nil)
147
222
  source_name ||= self.source_name
148
- SourceInfo.new(self, context_directory, :proc, source_path, child_proc, source_name,
149
- @data_dir_name, @lib_dir_name)
223
+ SourceInfo.new(self, priority, context_directory, :proc, source_path, child_proc,
224
+ git_remote, git_path, git_commit,
225
+ source_name, @data_dir_name, @lib_dir_name)
150
226
  end
151
227
 
152
228
  ##
153
229
  # Create a root source info for a file path.
230
+ #
154
231
  # @private
155
232
  #
156
- def self.create_path_root(source_path, data_dir_name, lib_dir_name)
233
+ def self.create_path_root(source_path, priority,
234
+ context_directory: nil,
235
+ data_dir_name: nil,
236
+ lib_dir_name: nil,
237
+ source_name: nil)
157
238
  source_path, type = check_path(source_path, false)
158
- context_directory = ::File.dirname(source_path)
159
- new(nil, context_directory, type, source_path, nil, source_path, data_dir_name, lib_dir_name)
239
+ case context_directory
240
+ when :parent
241
+ context_directory = ::File.dirname(source_path)
242
+ when :path
243
+ context_directory = source_path
244
+ end
245
+ source_name ||= source_path
246
+ new(nil, priority, context_directory, type, source_path, nil, nil, nil, nil,
247
+ source_name, data_dir_name, lib_dir_name)
248
+ end
249
+
250
+ ##
251
+ # Create a root source info for a cached git repo.
252
+ #
253
+ # @private
254
+ #
255
+ def self.create_git_root(git_remote, git_path, git_commit, source_path, priority,
256
+ context_directory: nil,
257
+ data_dir_name: nil,
258
+ lib_dir_name: nil,
259
+ source_name: nil)
260
+ source_path, type = check_path(source_path, false)
261
+ source_name ||= "git(remote=#{git_remote} path=#{git_path} commit=#{git_commit})"
262
+ new(nil, priority, context_directory, type, source_path, nil, git_remote,
263
+ git_path, git_commit, source_name, data_dir_name, lib_dir_name)
160
264
  end
161
265
 
162
266
  ##
163
267
  # Create a root source info for a proc.
268
+ #
164
269
  # @private
165
270
  #
166
- def self.create_proc_root(source_proc, source_name, data_dir_name, lib_dir_name)
167
- new(nil, nil, :proc, nil, source_proc, source_name, data_dir_name, lib_dir_name)
271
+ def self.create_proc_root(source_proc, priority,
272
+ context_directory: nil,
273
+ data_dir_name: nil,
274
+ lib_dir_name: nil,
275
+ source_name: nil)
276
+ source_name ||= "(code block #{source_proc.object_id})"
277
+ new(nil, priority, context_directory, :proc, nil, source_proc, nil, nil,
278
+ nil, source_name, data_dir_name, lib_dir_name)
168
279
  end
169
280
 
170
281
  ##
171
282
  # Check a path and determine the canonical path and type.
283
+ #
172
284
  # @private
173
285
  #
174
286
  def self.check_path(path, lenient)
@@ -48,6 +48,7 @@ module Toys
48
48
 
49
49
  ##
50
50
  # Configure the tool flags.
51
+ #
51
52
  # @private
52
53
  #
53
54
  def config(tool, _loader)
@@ -63,6 +64,7 @@ module Toys
63
64
 
64
65
  INCREMENT_HANDLER = ->(_val, cur) { cur.to_i + 1 }
65
66
  DECREMENT_HANDLER = ->(_val, cur) { cur.to_i - 1 }
67
+ private_constant :INCREMENT_HANDLER, :DECREMENT_HANDLER
66
68
 
67
69
  def add_verbose_flags(tool)
68
70
  verbose_flags = resolve_flags_spec(@verbose_flags, tool, DEFAULT_VERBOSE_FLAGS)
@@ -19,20 +19,22 @@ module Toys
19
19
  def initialize(parent_source: nil, source_name: nil, &block)
20
20
  @source_info =
21
21
  if parent_source
22
- parent_source.proc_child(block, source_name)
22
+ parent_source.proc_child(block, source_name: source_name)
23
23
  else
24
- SourceInfo.create_proc_root(block, source_name)
24
+ SourceInfo.create_proc_root(block, source_name: source_name)
25
25
  end
26
26
  @block = block
27
27
  end
28
28
 
29
29
  ##
30
30
  # Appends the configuration block.
31
+ #
31
32
  # @private
32
33
  #
33
- def config(tool, _loader)
34
+ def config(tool, loader)
34
35
  tool_class = tool.tool_class
35
- DSL::Tool.prepare(tool_class, nil, @source_info) do
36
+ DSL::Internal.prepare(tool_class, tool.full_name, tool.priority, nil, @source_info,
37
+ loader) do
36
38
  tool_class.class_eval(&@block)
37
39
  end
38
40
  yield
@@ -33,6 +33,7 @@ module Toys
33
33
 
34
34
  ##
35
35
  # Intercept and handle usage errors during execution.
36
+ #
36
37
  # @private
37
38
  #
38
39
  def run(context)
@@ -90,6 +90,7 @@ module Toys
90
90
 
91
91
  ##
92
92
  # Add default description text to tools.
93
+ #
93
94
  # @private
94
95
  #
95
96
  def config(tool, loader)
@@ -115,12 +116,12 @@ module Toys
115
116
  # By default, it uses the parameters given to the middleware object.
116
117
  # Override this method to provide different logic.
117
118
  #
118
- # @param tool [Toys::Tool] The tool to document.
119
+ # @param tool [Toys::ToolDefinition] The tool to document.
119
120
  # @param data [Hash] Additional data that might be useful. Currently,
120
121
  # the {Toys::Loader} is passed with key `:loader`. Future versions
121
122
  # of Toys may provide additional information.
122
123
  # @return [String,Array<String>,Toys::WrappableString] The default
123
- # description. See {Toys::Tool#desc=} for info on the format.
124
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
124
125
  # @return [nil] if this middleware should not set the description.
125
126
  #
126
127
  def generate_tool_desc(tool, data)
@@ -141,12 +142,12 @@ module Toys
141
142
  # By default, it uses the parameters given to the middleware object.
142
143
  # Override this method to provide different logic.
143
144
  #
144
- # @param tool [Toys::Tool] The tool to document
145
+ # @param tool [Toys::ToolDefinition] The tool to document
145
146
  # @param data [Hash] Additional data that might be useful. Currently,
146
147
  # the {Toys::Loader} is passed with key `:loader`. Future versions of
147
148
  # Toys may provide additional information.
148
149
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
149
- # long description. See {Toys::Tool#long_desc=} for info on the
150
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
150
151
  # format.
151
152
  # @return [nil] if this middleware should not set the long description.
152
153
  #
@@ -166,10 +167,10 @@ module Toys
166
167
  #
167
168
  # @param flag [Toys::Flag] The flag to document
168
169
  # @param data [Hash] Additional data that might be useful. Currently,
169
- # the {Toys::Tool} is passed with key `:tool`. Future
170
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
170
171
  # versions of Toys may provide additional information.
171
172
  # @return [String,Array<String>,Toys::WrappableString] The default
172
- # description. See {Toys::Tool#desc=} for info on the format.
173
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
173
174
  # @return [nil] if this middleware should not set the description.
174
175
  #
175
176
  def generate_flag_desc(flag, data) # rubocop:disable Lint/UnusedMethodArgument
@@ -185,10 +186,10 @@ module Toys
185
186
  #
186
187
  # @param flag [Toys::Flag] The flag to document
187
188
  # @param data [Hash] Additional data that might be useful. Currently,
188
- # the {Toys::Tool} is passed with key `:tool`. Future versions of
189
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
189
190
  # versions of Toys may provide additional information.
190
191
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
191
- # long description. See {Toys::Tool#long_desc=} for info on the
192
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
192
193
  # format.
193
194
  # @return [nil] if this middleware should not set the long description.
194
195
  #
@@ -202,10 +203,10 @@ module Toys
202
203
  #
203
204
  # @param arg [Toys::PositionalArg] The arg to document
204
205
  # @param data [Hash] Additional data that might be useful. Currently,
205
- # the {Toys::Tool} is passed with key `:tool`. Future versions of
206
- # Toys may provide additional information.
206
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
207
+ # versions of Toys may provide additional information.
207
208
  # @return [String,Array<String>,Toys::WrappableString] The default
208
- # description. See {Toys::Tool#desc=} for info on the format.
209
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
209
210
  # @return [nil] if this middleware should not set the description.
210
211
  #
211
212
  def generate_arg_desc(arg, data) # rubocop:disable Lint/UnusedMethodArgument
@@ -227,10 +228,10 @@ module Toys
227
228
  #
228
229
  # @param arg [Toys::PositionalArg] The arg to document
229
230
  # @param data [Hash] Additional data that might be useful. Currently,
230
- # the {Toys::Tool} is passed with key `:tool`. Future versions of
231
- # Toys may provide additional information.
231
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
232
+ # versions of Toys may provide additional information.
232
233
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
233
- # long description. See {Toys::Tool#long_desc=} for info on the
234
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
234
235
  # format.
235
236
  # @return [nil] if this middleware should not set the long description.
236
237
  #
@@ -244,10 +245,10 @@ module Toys
244
245
  #
245
246
  # @param group [Toys::FlagGroup] The flag group to document
246
247
  # @param data [Hash] Additional data that might be useful. Currently,
247
- # the {Toys::Tool} is passed with key `:tool`. Future
248
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
248
249
  # versions of Toys may provide additional information.
249
250
  # @return [String,Array<String>,Toys::WrappableString] The default
250
- # description. See {Toys::Tool#desc=} for info on the format.
251
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
251
252
  # @return [nil] if this middleware should not set the description.
252
253
  #
253
254
  def generate_flag_group_desc(group, data) # rubocop:disable Lint/UnusedMethodArgument
@@ -264,10 +265,10 @@ module Toys
264
265
  #
265
266
  # @param group [Toys::FlagGroup] The flag group to document
266
267
  # @param data [Hash] Additional data that might be useful. Currently,
267
- # the {Toys::Tool} is passed with key `:tool`. Future
268
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
268
269
  # versions of Toys may provide additional information.
269
270
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
270
- # long description. See {Toys::Tool#long_desc=} for info on the
271
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
271
272
  # format.
272
273
  # @return [nil] if this middleware should not set the long description.
273
274
  #
@@ -159,6 +159,8 @@ module Toys
159
159
  # that tool.
160
160
  # @param show_source_path [Boolean] Show the source path section. Default
161
161
  # is `false`.
162
+ # @param separate_sources [Boolean] Split up tool list by source root.
163
+ # Defaults to false.
162
164
  # @param use_less [Boolean] If the `less` tool is available, and the
163
165
  # output stream is a tty, then use `less` to display help text.
164
166
  # @param stream [IO] Output stream to write to. Default is stdout.
@@ -177,6 +179,7 @@ module Toys
177
179
  fallback_execution: false,
178
180
  allow_root_args: false,
179
181
  show_source_path: false,
182
+ separate_sources: false,
180
183
  use_less: false,
181
184
  stream: $stdout,
182
185
  styled_output: nil)
@@ -191,6 +194,7 @@ module Toys
191
194
  @fallback_execution = fallback_execution
192
195
  @allow_root_args = allow_root_args
193
196
  @show_source_path = show_source_path
197
+ @separate_sources = separate_sources
194
198
  @stream = stream
195
199
  @styled_output = styled_output
196
200
  @use_less = use_less && !Compat.jruby?
@@ -198,6 +202,7 @@ module Toys
198
202
 
199
203
  ##
200
204
  # Configure flags and default data.
205
+ #
201
206
  # @private
202
207
  #
203
208
  def config(tool, loader)
@@ -220,6 +225,7 @@ module Toys
220
225
 
221
226
  ##
222
227
  # Display help text if requested.
228
+ #
223
229
  # @private
224
230
  #
225
231
  def run(context)
@@ -250,7 +256,9 @@ module Toys
250
256
  help_text = get_help_text(context, true)
251
257
  str = help_text.usage_string(
252
258
  recursive: context[RECURSIVE_SUBTOOLS_KEY],
253
- include_hidden: context[SHOW_ALL_SUBTOOLS_KEY], wrap_width: terminal.width
259
+ include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
260
+ separate_sources: @separate_sources,
261
+ wrap_width: terminal.width
254
262
  )
255
263
  terminal.puts(str)
256
264
  end
@@ -258,8 +266,11 @@ module Toys
258
266
  def show_list(context)
259
267
  help_text = get_help_text(context, true)
260
268
  str = help_text.list_string(
261
- recursive: context[RECURSIVE_SUBTOOLS_KEY], search: context[SEARCH_STRING_KEY],
262
- include_hidden: context[SHOW_ALL_SUBTOOLS_KEY], wrap_width: terminal.width
269
+ recursive: context[RECURSIVE_SUBTOOLS_KEY],
270
+ search: context[SEARCH_STRING_KEY],
271
+ include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
272
+ separate_sources: @separate_sources,
273
+ wrap_width: terminal.width
263
274
  )
264
275
  terminal.puts(str)
265
276
  end
@@ -267,8 +278,11 @@ module Toys
267
278
  def show_help(context, use_extra_args)
268
279
  help_text = get_help_text(context, use_extra_args)
269
280
  str = help_text.help_string(
270
- recursive: context[RECURSIVE_SUBTOOLS_KEY], search: context[SEARCH_STRING_KEY],
271
- include_hidden: context[SHOW_ALL_SUBTOOLS_KEY], show_source_path: @show_source_path,
281
+ recursive: context[RECURSIVE_SUBTOOLS_KEY],
282
+ search: context[SEARCH_STRING_KEY],
283
+ include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
284
+ show_source_path: @show_source_path,
285
+ separate_sources: @separate_sources,
272
286
  wrap_width: terminal.width
273
287
  )
274
288
  if less_path
@@ -46,6 +46,7 @@ module Toys
46
46
 
47
47
  ##
48
48
  # Adds the version flag if requested.
49
+ #
49
50
  # @private
50
51
  #
51
52
  def config(tool, _loader)
@@ -58,6 +59,7 @@ module Toys
58
59
 
59
60
  ##
60
61
  # This middleware displays the version.
62
+ #
61
63
  # @private
62
64
  #
63
65
  def run(context)
@@ -67,20 +67,6 @@ module Toys
67
67
  module Bundler
68
68
  include Mixin
69
69
 
70
- on_initialize do |static: false, **kwargs|
71
- unless static
72
- context_directory = self[::Toys::Context::Key::CONTEXT_DIRECTORY]
73
- source_info = self[::Toys::Context::Key::TOOL_SOURCE]
74
- ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
75
- end
76
- end
77
-
78
- on_include do |static: false, **kwargs|
79
- if static
80
- ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
81
- end
82
- end
83
-
84
70
  ##
85
71
  # Default search directories for Gemfiles.
86
72
  # @return [Array<String,Symbol>]
@@ -93,7 +79,9 @@ module Toys
93
79
  #
94
80
  DEFAULT_TOYS_GEMFILE_NAMES = [".gems.rb", "Gemfile"].freeze
95
81
 
82
+ ##
96
83
  # @private
84
+ #
97
85
  def self.setup_bundle(context_directory,
98
86
  source_info,
99
87
  gemfile_path: nil,
@@ -118,9 +106,27 @@ module Toys
118
106
  gems.bundle(groups: groups, gemfile_path: gemfile_path, retries: retries)
119
107
  end
120
108
 
109
+ on_initialize do |static: false, **kwargs|
110
+ unless static
111
+ context_directory = self[::Toys::Context::Key::CONTEXT_DIRECTORY]
112
+ source_info = self[::Toys::Context::Key::TOOL_SOURCE]
113
+ ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
114
+ end
115
+ end
116
+
117
+ on_include do |static: false, **kwargs|
118
+ if static
119
+ ::Toys::StandardMixins::Bundler.setup_bundle(context_directory, source_info, **kwargs)
120
+ end
121
+ end
122
+
123
+ ##
121
124
  # @private
125
+ #
122
126
  class GemfileFinder
127
+ ##
123
128
  # @private
129
+ #
124
130
  def initialize(context_directory, source_info, gemfile_names, toys_gemfile_names)
125
131
  @context_directory = context_directory
126
132
  @source_info = source_info
@@ -128,7 +134,9 @@ module Toys
128
134
  @toys_gemfile_names = toys_gemfile_names || DEFAULT_TOYS_GEMFILE_NAMES
129
135
  end
130
136
 
137
+ ##
131
138
  # @private
139
+ #
132
140
  def search(search_dir)
133
141
  case search_dir
134
142
  when ::Array
@@ -159,7 +167,8 @@ module Toys
159
167
  def search_toys
160
168
  source_info = @source_info
161
169
  while source_info
162
- if source_info.source_type == :directory
170
+ if source_info.source_type == :directory &&
171
+ source_info.source_path != source_info.context_directory
163
172
  result = ::Toys::Utils::Gems.find_gemfile(source_info.source_path,
164
173
  gemfile_names: @toys_gemfile_names)
165
174
  return result if result