toys-core 0.14.1 → 0.14.3

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
  SHA256:
3
- metadata.gz: 49f6342ac835f193218570f20cc534fc7f1d4fab14742602df3a7174cfc8a554
4
- data.tar.gz: 27b8298897b5c8fd08319fffec33540c057675ed8655700280b4837f413cc635
3
+ metadata.gz: 73e5d0f680fb70c244e6808947e471a201bc69834c15cfaaaeabf33bb17b3a15
4
+ data.tar.gz: 05702f110b55db481633b0eb56569a98002eff8aec6cfd49db78388867c9fa1c
5
5
  SHA512:
6
- metadata.gz: 55dc00e57b5c6b3212ed24d45bb3a595dae8b5b6fd076ddefdbe4835d621dfeb70d58b8551ae69a8190dc3884a66968e78b800d93b07eed6b61d42eef70faea7
7
- data.tar.gz: eb6b5c306c815947290a8fb99834a4a809052edf7e6c781f1b562c61217cf49c63a9609beb168b0e06c5e09ace51083bbb7da15ad58746e72fc5017e04f9546d
6
+ metadata.gz: b417c3f249b1d4ca13fe0a14a09771a9a172f3cee72e8e158d8a0fcdbcdf853b8f937e1d61b161f1d2ebafbcecb91fdfe0c0b143d3e22f003405697e6c78bc79
7
+ data.tar.gz: 1c323e979f9829623dd9c7048af3aaee23a3b692845c7c19e0af68972245b62411b3daf48653beab7378655910e14ffa0859665b25bfedbb054624edf36f3306
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Release History
2
2
 
3
+ ### v0.14.3 / 2022-12-29
4
+
5
+ * FIXED: Exit with a code -1 if a non-integer exit code is thrown
6
+ * FIXED: The sh command in the Exec utility returns -1 if the exit code cannot be determined
7
+ * FIXED: Update Bundler integration to support Bundler 2.4 and Ruby 3.2
8
+ * FIXED: Fix for installing bundler on older Rubies
9
+ * FIXED: Fixed XDG defaults on JRuby 9.4
10
+
11
+ ### v0.14.2 / 2022-10-09
12
+
13
+ * ADDED: The tool directive supports the delegate_relative argument, as a preferred alternative over alias_tool.
14
+ * FIXED: The toys file reference now properly appears in error messages on Ruby 3.1.
15
+ * FIXED: Error messages show the correct toys file line number on TruffleRuby.
16
+ * FIXED: Inspect strings for tool classes are less opaque and include the tool name.
17
+ * FIXED: The presence of an acceptor forces an ambiguous flag to take a value rather than erroring.
18
+
3
19
  ### v0.14.1 / 2022-10-03
4
20
 
5
21
  * (No significant changes)
data/lib/toys/context.rb CHANGED
@@ -309,7 +309,7 @@ module Toys
309
309
  # @return [void]
310
310
  #
311
311
  def exit(code = 0)
312
- throw :result, code
312
+ Context.exit(code)
313
313
  end
314
314
 
315
315
  ##
@@ -321,6 +321,7 @@ module Toys
321
321
  # @return [void]
322
322
  #
323
323
  def self.exit(code = 0)
324
+ code = -1 unless code.is_a?(::Integer)
324
325
  throw :result, code
325
326
  end
326
327
 
@@ -338,12 +339,15 @@ module Toys
338
339
  end
339
340
 
340
341
  ##
342
+ # Include the tool name in the object inspection dump.
343
+ #
341
344
  # @private
342
345
  #
343
346
  def inspect
344
- name = Array(@__data[Key::TOOL_NAME]).join(" ")
347
+ words = Array(@__data[Key::TOOL_NAME])
348
+ name = words.empty? ? "(root)" : words.join(" ").inspect
345
349
  id = object_id.to_s(16)
346
- "#<Toys::Context id=0x#{id} #{name}>"
350
+ "#<Toys::Context id=0x#{id} tool=#{name}>"
347
351
  end
348
352
  end
349
353
  end
data/lib/toys/core.rb CHANGED
@@ -9,7 +9,7 @@ module Toys
9
9
  # Current version of Toys core.
10
10
  # @return [String]
11
11
  #
12
- VERSION = "0.14.1"
12
+ VERSION = "0.14.3"
13
13
  end
14
14
 
15
15
  ##
@@ -68,6 +68,24 @@ module Toys
68
68
  end
69
69
  end
70
70
 
71
+ ##
72
+ # Called by the DSL implementation to analyze the name of a new tool
73
+ # definition in context.
74
+ #
75
+ # @private
76
+ #
77
+ def analyze_name(tool_class, words)
78
+ loader = tool_class.instance_variable_get(:@__loader)
79
+ subtool_words = tool_class.instance_variable_get(:@__words).dup
80
+ next_remaining = tool_class.instance_variable_get(:@__remaining_words)
81
+ loader.split_path(words).each do |word|
82
+ word = word.to_s
83
+ subtool_words << word
84
+ next_remaining = Loader.next_remaining_words(next_remaining, word)
85
+ end
86
+ [subtool_words, next_remaining]
87
+ end
88
+
71
89
  ##
72
90
  # Called by the DSL implementation to add a getter to the tool class.
73
91
  #
data/lib/toys/dsl/tool.rb CHANGED
@@ -273,7 +273,8 @@ module Toys
273
273
  # end
274
274
  # end
275
275
  #
276
- # The following example defines a tool that runs one of its subtools.
276
+ # The following example uses `delegate_to` to define a tool that runs one
277
+ # of its subtools.
277
278
  #
278
279
  # tool "test", delegate_to: ["test", "unit"] do
279
280
  # tool "unit" do
@@ -294,17 +295,14 @@ module Toys
294
295
  # delegate to another tool, specified by the full path. This path may
295
296
  # be given as an array of strings, or a single string possibly
296
297
  # delimited by path separators.
298
+ # @param delegate_relative [String,Array<String>] Optional. Similar to
299
+ # delegate_to, but takes a delegate name relative to the context in
300
+ # which this tool is being defined.
297
301
  # @param block [Proc] Defines the subtool.
298
302
  # @return [self]
299
303
  #
300
- def tool(words, if_defined: :combine, delegate_to: nil, &block)
301
- subtool_words = @__words.dup
302
- next_remaining = @__remaining_words
303
- @__loader.split_path(words).each do |word|
304
- word = word.to_s
305
- subtool_words << word
306
- next_remaining = Loader.next_remaining_words(next_remaining, word)
307
- end
304
+ def tool(words, if_defined: :combine, delegate_to: nil, delegate_relative: nil, &block)
305
+ subtool_words, next_remaining = DSL::Internal.analyze_name(self, words)
308
306
  subtool = @__loader.get_tool(subtool_words, @__priority)
309
307
  if subtool.includes_definition?
310
308
  case if_defined
@@ -314,9 +312,14 @@ module Toys
314
312
  subtool.reset_definition
315
313
  end
316
314
  end
317
- if delegate_to
318
- delegator = proc { self.delegate_to(delegate_to) }
319
- @__loader.load_block(source_info, delegator, subtool_words, next_remaining, @__priority)
315
+ if delegate_to || delegate_relative
316
+ delegate_to2 = @__words + @__loader.split_path(delegate_relative) if delegate_relative
317
+ orig_block = block
318
+ block = proc do
319
+ self.delegate_to(delegate_to) if delegate_to
320
+ self.delegate_to(delegate_to2) if delegate_to2
321
+ instance_eval(&orig_block) if orig_block
322
+ end
320
323
  end
321
324
  if block
322
325
  @__loader.load_block(source_info, block, subtool_words, next_remaining, @__priority)
@@ -327,9 +330,9 @@ module Toys
327
330
  ##
328
331
  # Create an alias, representing an "alternate name" for a tool.
329
332
  #
330
- # This is functionally equivalent to creating a subtool with the
331
- # `delegate_to` option, except that `alias_tool` takes a _relative_ name
332
- # for the delegate.
333
+ # Note: This is functionally equivalent to creating a tool with the
334
+ # `:delegate_relative` option. As such, `alias_tool` is considered
335
+ # deprecated.
333
336
  #
334
337
  # ### Example
335
338
  #
@@ -342,21 +345,25 @@ module Toys
342
345
  # end
343
346
  # end
344
347
  # alias_tool "t", "test"
348
+ # # Note: the following is preferred over alias_tool:
349
+ # # tool "t", delegate_relative: "test"
345
350
  #
346
351
  # @param word [String] The name of the alias
347
352
  # @param target [String,Array<String>] Relative path to the target of the
348
353
  # alias. This path may be given as an array of strings, or a single
349
354
  # string possibly delimited by path separators.
350
355
  # @return [self]
356
+ # @deprecated Use {#tool} and pass `:delegate_relative` instead
351
357
  #
352
358
  def alias_tool(word, target)
353
- tool(word, delegate_to: @__words + @__loader.split_path(target))
359
+ tool(word, delegate_relative: target)
354
360
  self
355
361
  end
356
362
 
357
363
  ##
358
- # Causes the current tool to delegate to another tool. When run, it
359
- # simply invokes the target tool with the same arguments.
364
+ # Causes the current tool to delegate to another tool, specified by the
365
+ # full tool name. When run, it simply invokes the target tool with the
366
+ # same arguments.
360
367
  #
361
368
  # ### Example
362
369
  #
@@ -1721,6 +1728,18 @@ module Toys
1721
1728
  super
1722
1729
  DSL::Internal.current_tool(self, true)&.check_definition_state(is_method: true)
1723
1730
  end
1731
+
1732
+ ##
1733
+ # Include the tool name in the class inspection dump.
1734
+ #
1735
+ # @private
1736
+ #
1737
+ def inspect
1738
+ return super unless defined? @__words
1739
+ name = @__words.empty? ? "(root)" : @__words.join(" ").inspect
1740
+ id = object_id.to_s(16)
1741
+ "#<Class id=0x#{id} tool=#{name}>"
1742
+ end
1724
1743
  end
1725
1744
  end
1726
1745
  end
data/lib/toys/errors.rb CHANGED
@@ -172,7 +172,9 @@ module Toys
172
172
 
173
173
  def add_config_path_if_missing(error, path)
174
174
  if error.config_path.nil? && error.config_line.nil?
175
- l = (error.cause.backtrace_locations || []).find { |b| b.absolute_path == path }
175
+ l = (error.cause.backtrace_locations || []).find do |b|
176
+ b.absolute_path == path || b.path == path
177
+ end
176
178
  if l
177
179
  error.config_path = path
178
180
  error.config_line = l.lineno
data/lib/toys/flag.rb CHANGED
@@ -774,12 +774,15 @@ module Toys
774
774
  long_flag_syntax.reverse_each do |flag|
775
775
  analyze_flag_syntax(flag)
776
776
  end
777
- @flag_type ||= :boolean
778
777
  if @flag_type == :boolean && @explicit_acceptor
779
778
  raise ToolDefinitionError,
780
779
  "Flag #{key.inspect} cannot have an acceptor because it does not take a value."
781
780
  end
782
- @value_type ||= :required if @flag_type == :value
781
+ @flag_type ||= (@explicit_acceptor ? :value : :boolean)
782
+ if @flag_type == :value
783
+ @value_type ||= :required
784
+ @value_label ||= "VALUE"
785
+ end
783
786
  flag_syntax.each do |flag|
784
787
  flag.configure_canonical(@flag_type, @value_type, @value_label, @value_delim)
785
788
  end
@@ -23,7 +23,7 @@ module Toys::InputFile # rubocop:disable Style/ClassAndModuleChildren
23
23
  ::Toys::DSL::Internal.prepare(tool_class, words, priority, remaining_words, source, loader) do
24
24
  ::Toys::ContextualError.capture_path("Error while loading Toys config!", path) do
25
25
  # rubocop:disable Security/Eval
26
- eval(str, __binding, path, -2)
26
+ eval(str, __binding, path)
27
27
  # rubocop:enable Security/Eval
28
28
  end
29
29
  end
@@ -43,11 +43,9 @@ module Toys::InputFile # rubocop:disable Style/ClassAndModuleChildren
43
43
  def self.build_eval_string(module_name, string)
44
44
  index = string.index(/^\s*[^#\s]/)
45
45
  return nil if index.nil?
46
- "#{string[0, index]}\n" \
47
- "module #{module_name}\n" \
48
- "@__tool_class.class_eval do\n" \
46
+ "#{string[0, index]}" \
47
+ "module #{module_name}; @__tool_class.class_eval do; " \
49
48
  "#{string[index..-1]}\n" \
50
- "end\n" \
51
- "end\n"
49
+ "end; end\n"
52
50
  end
53
51
  end
@@ -1254,9 +1254,10 @@ module Toys
1254
1254
  #
1255
1255
  def delegate_to(target)
1256
1256
  if @delegate_target
1257
+ return self if target == @delegate_target
1257
1258
  raise ToolDefinitionError,
1258
- "Cannot delegate tool #{display_name.inspect} because" \
1259
- " it already delegates to \"#{@delegate_target.join(' ')}\"."
1259
+ "Cannot delegate tool #{display_name.inspect} to #{target.join(' ')} because it" \
1260
+ " already delegates to \"#{@delegate_target.join(' ')}\"."
1260
1261
  end
1261
1262
  if includes_arguments?
1262
1263
  raise ToolDefinitionError,
@@ -427,7 +427,7 @@ module Toys
427
427
  #
428
428
  def sh(cmd, **opts, &block)
429
429
  opts = opts.merge(background: false)
430
- exec(cmd, **opts, &block).exit_code
430
+ exec(cmd, **opts, &block).exit_code || -1
431
431
  end
432
432
 
433
433
  ##
@@ -188,7 +188,7 @@ module Toys
188
188
  gemfile_path = ::File.absolute_path(gemfile_path)
189
189
  Gems.synchronize do
190
190
  if configure_gemfile(gemfile_path)
191
- activate("bundler", "~> 2.2")
191
+ activate("bundler", *bundler_version_requirements)
192
192
  require "bundler"
193
193
  setup_bundle(gemfile_path, groups: groups, retries: retries)
194
194
  end
@@ -309,7 +309,7 @@ module Toys
309
309
  modified_gemfile_path = create_modified_gemfile(gemfile_path)
310
310
  begin
311
311
  attempt_setup_bundle(modified_gemfile_path, groups)
312
- rescue ::Bundler::GemNotFound, ::Bundler::VersionConflict
312
+ rescue *bundler_exceptions
313
313
  ::Bundler.reset!
314
314
  restore_toys_libs
315
315
  install_bundle(modified_gemfile_path, retries: retries)
@@ -321,6 +321,25 @@ module Toys
321
321
  restore_toys_libs
322
322
  end
323
323
 
324
+ def bundler_exceptions
325
+ @bundler_exceptions ||= begin
326
+ exceptions = [::Bundler::GemNotFound]
327
+ exceptions << ::Bundler::VersionConflict if ::Bundler.const_defined?(:VersionConflict)
328
+ exceptions << ::Bundler::SolveFailure if ::Bundler.const_defined?(:SolveFailure)
329
+ exceptions
330
+ end
331
+ end
332
+
333
+ def bundler_version_requirements
334
+ if ::RUBY_VERSION < "2.6"
335
+ [">= 2.2", "< 2.4"]
336
+ elsif ::RUBY_VERSION < "3"
337
+ [">= 2.2", "< 2.5"]
338
+ else
339
+ ["~> 2.2"]
340
+ end
341
+ end
342
+
324
343
  def attempt_setup_bundle(modified_gemfile_path, groups)
325
344
  ::ENV["BUNDLE_GEMFILE"] = modified_gemfile_path
326
345
  ::Bundler.configure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.14.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-03 00:00:00.000000000 Z
11
+ date: 2022-12-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Toys-Core is the command line tool framework underlying Toys. It can
14
14
  be used to create command line executables using the Toys DSL and classes.
@@ -78,10 +78,10 @@ homepage: https://github.com/dazuma/toys
78
78
  licenses:
79
79
  - MIT
80
80
  metadata:
81
- changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.14.1/file.CHANGELOG.html
81
+ changelog_uri: https://dazuma.github.io/toys/gems/toys-core/v0.14.3/file.CHANGELOG.html
82
82
  source_code_uri: https://github.com/dazuma/toys/tree/main/toys-core
83
83
  bug_tracker_uri: https://github.com/dazuma/toys/issues
84
- documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.14.1
84
+ documentation_uri: https://dazuma.github.io/toys/gems/toys-core/v0.14.3
85
85
  post_install_message:
86
86
  rdoc_options: []
87
87
  require_paths: