toys-core 0.11.3 → 0.12.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -2
  3. data/README.md +1 -1
  4. data/lib/toys-core.rb +4 -1
  5. data/lib/toys/acceptor.rb +3 -3
  6. data/lib/toys/arg_parser.rb +6 -7
  7. data/lib/toys/cli.rb +44 -14
  8. data/lib/toys/compat.rb +19 -22
  9. data/lib/toys/completion.rb +3 -1
  10. data/lib/toys/context.rb +2 -2
  11. data/lib/toys/core.rb +1 -1
  12. data/lib/toys/dsl/base.rb +85 -0
  13. data/lib/toys/dsl/flag.rb +3 -3
  14. data/lib/toys/dsl/flag_group.rb +7 -7
  15. data/lib/toys/dsl/internal.rb +206 -0
  16. data/lib/toys/dsl/positional_arg.rb +3 -3
  17. data/lib/toys/dsl/tool.rb +174 -216
  18. data/lib/toys/errors.rb +1 -0
  19. data/lib/toys/flag.rb +15 -18
  20. data/lib/toys/flag_group.rb +5 -4
  21. data/lib/toys/input_file.rb +4 -4
  22. data/lib/toys/loader.rb +189 -50
  23. data/lib/toys/middleware.rb +1 -1
  24. data/lib/toys/mixin.rb +2 -2
  25. data/lib/toys/positional_arg.rb +3 -3
  26. data/lib/toys/settings.rb +900 -0
  27. data/lib/toys/source_info.rb +121 -18
  28. data/lib/toys/standard_middleware/apply_config.rb +5 -4
  29. data/lib/toys/standard_middleware/set_default_descriptions.rb +18 -18
  30. data/lib/toys/standard_middleware/show_help.rb +17 -5
  31. data/lib/toys/standard_mixins/bundler.rb +7 -2
  32. data/lib/toys/standard_mixins/exec.rb +22 -15
  33. data/lib/toys/standard_mixins/git_cache.rb +48 -0
  34. data/lib/toys/standard_mixins/xdg.rb +56 -0
  35. data/lib/toys/template.rb +2 -2
  36. data/lib/toys/{tool.rb → tool_definition.rb} +100 -41
  37. data/lib/toys/utils/exec.rb +12 -10
  38. data/lib/toys/utils/gems.rb +48 -14
  39. data/lib/toys/utils/git_cache.rb +184 -0
  40. data/lib/toys/utils/help_text.rb +90 -34
  41. data/lib/toys/utils/terminal.rb +1 -1
  42. data/lib/toys/utils/xdg.rb +293 -0
  43. metadata +15 -8
@@ -2,21 +2,27 @@
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
  ##
9
10
  # Create a SourceInfo.
10
11
  # @private
11
12
  #
12
- def initialize(parent, context_directory, source_type, source_path, source_proc,
13
- source_name, data_dir_name, lib_dir_name)
13
+ def initialize(parent, priority, context_directory, source_type, source_path, source_proc,
14
+ git_remote, git_path, git_commit, source_name, data_dir_name, lib_dir_name)
14
15
  @parent = parent
16
+ @root = parent&.root || self
17
+ @priority = priority
15
18
  @context_directory = context_directory
16
19
  @source_type = source_type
17
20
  @source = source_type == :proc ? source_proc : source_path
18
21
  @source_path = source_path
19
22
  @source_proc = source_proc
23
+ @git_remote = git_remote
24
+ @git_path = git_path
25
+ @git_commit = git_commit
20
26
  @source_name = source_name
21
27
  @data_dir_name = data_dir_name
22
28
  @lib_dir_name = lib_dir_name
@@ -32,6 +38,21 @@ module Toys
32
38
  #
33
39
  attr_reader :parent
34
40
 
41
+ ##
42
+ # The root ancestor of this SourceInfo.
43
+ #
44
+ # @return [Toys::SourceInfo] The root ancestor.
45
+ #
46
+ attr_reader :root
47
+
48
+ ##
49
+ # The priority of tools defined by this source. Higher values indicate a
50
+ # higher priority. Lower priority values could be negative.
51
+ #
52
+ # @return [Integer] The priority.
53
+ #
54
+ attr_reader :priority
55
+
35
56
  ##
36
57
  # The context directory path (normally the directory containing the
37
58
  # toplevel toys file or directory).
@@ -73,6 +94,30 @@ module Toys
73
94
  #
74
95
  attr_reader :source_proc
75
96
 
97
+ ##
98
+ # The git remote.
99
+ #
100
+ # @return [String] The git remote
101
+ # @return [nil] if this source is not fron git.
102
+ #
103
+ attr_reader :git_remote
104
+
105
+ ##
106
+ # The git path.
107
+ #
108
+ # @return [String] The git path. This could be the empty string.
109
+ # @return [nil] if this source is not fron git.
110
+ #
111
+ attr_reader :git_path
112
+
113
+ ##
114
+ # The git commit.
115
+ #
116
+ # @return [String] The git commit.
117
+ # @return [nil] if this source is not fron git.
118
+ #
119
+ attr_reader :git_commit
120
+
76
121
  ##
77
122
  # The user-visible name of this source.
78
123
  #
@@ -120,51 +165,109 @@ module Toys
120
165
  # Create a child SourceInfo relative to the parent path.
121
166
  # @private
122
167
  #
123
- def relative_child(filename)
124
- raise "relative_child is valid only on a directory source" unless source_type == :directory
168
+ def relative_child(filename, source_name: nil)
169
+ unless source_type == :directory
170
+ raise LoaderError, "relative_child is valid only on a directory source"
171
+ end
125
172
  child_path = ::File.join(source_path, filename)
126
173
  child_path, type = SourceInfo.check_path(child_path, true)
127
174
  return nil unless child_path
128
- SourceInfo.new(self, context_directory, type, child_path, nil, child_path,
129
- @data_dir_name, @lib_dir_name)
175
+ child_git_path = ::File.join(git_path, filename) if git_path
176
+ source_name ||=
177
+ if git_path
178
+ "git(remote=#{git_remote} path=#{child_git_path} commit=#{git_commit})"
179
+ else
180
+ child_path
181
+ end
182
+ SourceInfo.new(self, priority, context_directory, type, child_path, nil,
183
+ git_remote, child_git_path, git_commit,
184
+ source_name, @data_dir_name, @lib_dir_name)
130
185
  end
131
186
 
132
187
  ##
133
188
  # Create a child SourceInfo with an absolute path.
134
189
  # @private
135
190
  #
136
- def absolute_child(child_path)
191
+ def absolute_child(child_path, source_name: nil)
192
+ child_path, type = SourceInfo.check_path(child_path, false)
193
+ source_name ||= child_path
194
+ SourceInfo.new(self, priority, context_directory, type, child_path, nil, nil, nil, nil,
195
+ source_name, @data_dir_name, @lib_dir_name)
196
+ end
197
+
198
+ ##
199
+ # Create a child SourceInfo with a git source.
200
+ # @private
201
+ #
202
+ def git_child(child_git_remote, child_git_path, child_git_commit, child_path,
203
+ source_name: nil)
137
204
  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)
205
+ source_name ||=
206
+ "git(remote=#{child_git_remote} path=#{child_git_path} commit=#{child_git_commit})"
207
+ SourceInfo.new(self, priority, context_directory, type, child_path, nil,
208
+ child_git_remote, child_git_path, child_git_commit,
209
+ source_name, @data_dir_name, @lib_dir_name)
140
210
  end
141
211
 
142
212
  ##
143
213
  # Create a proc child SourceInfo
144
214
  # @private
145
215
  #
146
- def proc_child(child_proc, source_name = nil)
216
+ def proc_child(child_proc, source_name: nil)
147
217
  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)
218
+ SourceInfo.new(self, priority, context_directory, :proc, source_path, child_proc,
219
+ git_remote, git_path, git_commit,
220
+ source_name, @data_dir_name, @lib_dir_name)
150
221
  end
151
222
 
152
223
  ##
153
224
  # Create a root source info for a file path.
154
225
  # @private
155
226
  #
156
- def self.create_path_root(source_path, data_dir_name, lib_dir_name)
227
+ def self.create_path_root(source_path, priority,
228
+ context_directory: nil,
229
+ data_dir_name: nil,
230
+ lib_dir_name: nil,
231
+ source_name: nil)
232
+ source_path, type = check_path(source_path, false)
233
+ case context_directory
234
+ when :parent
235
+ context_directory = ::File.dirname(source_path)
236
+ when :path
237
+ context_directory = source_path
238
+ end
239
+ source_name ||= source_path
240
+ new(nil, priority, context_directory, type, source_path, nil, nil, nil, nil,
241
+ source_name, data_dir_name, lib_dir_name)
242
+ end
243
+
244
+ ##
245
+ # Create a root source info for a cached git repo.
246
+ # @private
247
+ #
248
+ def self.create_git_root(git_remote, git_path, git_commit, source_path, priority,
249
+ context_directory: nil,
250
+ data_dir_name: nil,
251
+ lib_dir_name: nil,
252
+ source_name: nil)
157
253
  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)
254
+ source_name ||= "git(remote=#{git_remote} path=#{git_path} commit=#{git_commit})"
255
+ new(nil, priority, context_directory, type, source_path, nil, git_remote,
256
+ git_path, git_commit, source_name, data_dir_name, lib_dir_name)
160
257
  end
161
258
 
162
259
  ##
163
260
  # Create a root source info for a proc.
164
261
  # @private
165
262
  #
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)
263
+ def self.create_proc_root(source_proc, priority,
264
+ context_directory: nil,
265
+ data_dir_name: nil,
266
+ lib_dir_name: nil,
267
+ source_name: nil)
268
+ source_name ||= "(code block #{source_proc.object_id})"
269
+ new(nil, priority, context_directory, :proc, nil, source_proc, nil, nil,
270
+ nil, source_name, data_dir_name, lib_dir_name)
168
271
  end
169
272
 
170
273
  ##
@@ -19,9 +19,9 @@ 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
@@ -30,9 +30,10 @@ module Toys
30
30
  # Appends the configuration block.
31
31
  # @private
32
32
  #
33
- def config(tool, _loader)
33
+ def config(tool, loader)
34
34
  tool_class = tool.tool_class
35
- DSL::Tool.prepare(tool_class, nil, @source_info) do
35
+ DSL::Internal.prepare(tool_class, tool.full_name, tool.priority, nil, @source_info,
36
+ loader) do
36
37
  tool_class.class_eval(&@block)
37
38
  end
38
39
  yield
@@ -115,12 +115,12 @@ module Toys
115
115
  # By default, it uses the parameters given to the middleware object.
116
116
  # Override this method to provide different logic.
117
117
  #
118
- # @param tool [Toys::Tool] The tool to document.
118
+ # @param tool [Toys::ToolDefinition] The tool to document.
119
119
  # @param data [Hash] Additional data that might be useful. Currently,
120
120
  # the {Toys::Loader} is passed with key `:loader`. Future versions
121
121
  # of Toys may provide additional information.
122
122
  # @return [String,Array<String>,Toys::WrappableString] The default
123
- # description. See {Toys::Tool#desc=} for info on the format.
123
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
124
124
  # @return [nil] if this middleware should not set the description.
125
125
  #
126
126
  def generate_tool_desc(tool, data)
@@ -141,12 +141,12 @@ module Toys
141
141
  # By default, it uses the parameters given to the middleware object.
142
142
  # Override this method to provide different logic.
143
143
  #
144
- # @param tool [Toys::Tool] The tool to document
144
+ # @param tool [Toys::ToolDefinition] The tool to document
145
145
  # @param data [Hash] Additional data that might be useful. Currently,
146
146
  # the {Toys::Loader} is passed with key `:loader`. Future versions of
147
147
  # Toys may provide additional information.
148
148
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
149
- # long description. See {Toys::Tool#long_desc=} for info on the
149
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
150
150
  # format.
151
151
  # @return [nil] if this middleware should not set the long description.
152
152
  #
@@ -166,10 +166,10 @@ module Toys
166
166
  #
167
167
  # @param flag [Toys::Flag] The flag to document
168
168
  # @param data [Hash] Additional data that might be useful. Currently,
169
- # the {Toys::Tool} is passed with key `:tool`. Future
169
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
170
170
  # versions of Toys may provide additional information.
171
171
  # @return [String,Array<String>,Toys::WrappableString] The default
172
- # description. See {Toys::Tool#desc=} for info on the format.
172
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
173
173
  # @return [nil] if this middleware should not set the description.
174
174
  #
175
175
  def generate_flag_desc(flag, data) # rubocop:disable Lint/UnusedMethodArgument
@@ -185,10 +185,10 @@ module Toys
185
185
  #
186
186
  # @param flag [Toys::Flag] The flag to document
187
187
  # @param data [Hash] Additional data that might be useful. Currently,
188
- # the {Toys::Tool} is passed with key `:tool`. Future versions of
188
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
189
189
  # versions of Toys may provide additional information.
190
190
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
191
- # long description. See {Toys::Tool#long_desc=} for info on the
191
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
192
192
  # format.
193
193
  # @return [nil] if this middleware should not set the long description.
194
194
  #
@@ -202,10 +202,10 @@ module Toys
202
202
  #
203
203
  # @param arg [Toys::PositionalArg] The arg to document
204
204
  # @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.
205
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
206
+ # versions of Toys may provide additional information.
207
207
  # @return [String,Array<String>,Toys::WrappableString] The default
208
- # description. See {Toys::Tool#desc=} for info on the format.
208
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
209
209
  # @return [nil] if this middleware should not set the description.
210
210
  #
211
211
  def generate_arg_desc(arg, data) # rubocop:disable Lint/UnusedMethodArgument
@@ -227,10 +227,10 @@ module Toys
227
227
  #
228
228
  # @param arg [Toys::PositionalArg] The arg to document
229
229
  # @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.
230
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
231
+ # versions of Toys may provide additional information.
232
232
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
233
- # long description. See {Toys::Tool#long_desc=} for info on the
233
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
234
234
  # format.
235
235
  # @return [nil] if this middleware should not set the long description.
236
236
  #
@@ -244,10 +244,10 @@ module Toys
244
244
  #
245
245
  # @param group [Toys::FlagGroup] The flag group to document
246
246
  # @param data [Hash] Additional data that might be useful. Currently,
247
- # the {Toys::Tool} is passed with key `:tool`. Future
247
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
248
248
  # versions of Toys may provide additional information.
249
249
  # @return [String,Array<String>,Toys::WrappableString] The default
250
- # description. See {Toys::Tool#desc=} for info on the format.
250
+ # description. See {Toys::DSL::Tool#desc} for info on the format.
251
251
  # @return [nil] if this middleware should not set the description.
252
252
  #
253
253
  def generate_flag_group_desc(group, data) # rubocop:disable Lint/UnusedMethodArgument
@@ -264,10 +264,10 @@ module Toys
264
264
  #
265
265
  # @param group [Toys::FlagGroup] The flag group to document
266
266
  # @param data [Hash] Additional data that might be useful. Currently,
267
- # the {Toys::Tool} is passed with key `:tool`. Future
267
+ # the {Toys::ToolDefinition} is passed with key `:tool`. Future
268
268
  # versions of Toys may provide additional information.
269
269
  # @return [Array<Toys::WrappableString,String,Array<String>>] The default
270
- # long description. See {Toys::Tool#long_desc=} for info on the
270
+ # long description. See {Toys::DSL::Tool#long_desc} for info on the
271
271
  # format.
272
272
  # @return [nil] if this middleware should not set the long description.
273
273
  #
@@ -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?
@@ -250,7 +254,9 @@ module Toys
250
254
  help_text = get_help_text(context, true)
251
255
  str = help_text.usage_string(
252
256
  recursive: context[RECURSIVE_SUBTOOLS_KEY],
253
- include_hidden: context[SHOW_ALL_SUBTOOLS_KEY], wrap_width: terminal.width
257
+ include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
258
+ separate_sources: @separate_sources,
259
+ wrap_width: terminal.width
254
260
  )
255
261
  terminal.puts(str)
256
262
  end
@@ -258,8 +264,11 @@ module Toys
258
264
  def show_list(context)
259
265
  help_text = get_help_text(context, true)
260
266
  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
267
+ recursive: context[RECURSIVE_SUBTOOLS_KEY],
268
+ search: context[SEARCH_STRING_KEY],
269
+ include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
270
+ separate_sources: @separate_sources,
271
+ wrap_width: terminal.width
263
272
  )
264
273
  terminal.puts(str)
265
274
  end
@@ -267,8 +276,11 @@ module Toys
267
276
  def show_help(context, use_extra_args)
268
277
  help_text = get_help_text(context, use_extra_args)
269
278
  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,
279
+ recursive: context[RECURSIVE_SUBTOOLS_KEY],
280
+ search: context[SEARCH_STRING_KEY],
281
+ include_hidden: context[SHOW_ALL_SUBTOOLS_KEY],
282
+ show_source_path: @show_source_path,
283
+ separate_sources: @separate_sources,
272
284
  wrap_width: terminal.width
273
285
  )
274
286
  if less_path
@@ -57,6 +57,9 @@ module Toys
57
57
  # * `:ignore` - just silently proceed without bundling again.
58
58
  # * `:warn` - print a warning and proceed without bundling again.
59
59
  #
60
+ # * `:retries` (Integer) Number of times to retry bundler operations
61
+ # (optional)
62
+ #
60
63
  # * `:terminal` (Toys::Utils::Terminal) Terminal to use (optional)
61
64
  # * `:input` (IO) Input IO (optional, defaults to STDIN)
62
65
  # * `:output` (IO) Output IO (optional, defaults to STDOUT)
@@ -100,6 +103,7 @@ module Toys
100
103
  groups: nil,
101
104
  on_missing: nil,
102
105
  on_conflict: nil,
106
+ retries: nil,
103
107
  terminal: nil,
104
108
  input: nil,
105
109
  output: nil)
@@ -111,7 +115,7 @@ module Toys
111
115
  end
112
116
  gems = ::Toys::Utils::Gems.new(on_missing: on_missing, on_conflict: on_conflict,
113
117
  terminal: terminal, input: input, output: output)
114
- gems.bundle(groups: groups, gemfile_path: gemfile_path)
118
+ gems.bundle(groups: groups, gemfile_path: gemfile_path, retries: retries)
115
119
  end
116
120
 
117
121
  # @private
@@ -155,7 +159,8 @@ module Toys
155
159
  def search_toys
156
160
  source_info = @source_info
157
161
  while source_info
158
- if source_info.source_type == :directory
162
+ if source_info.source_type == :directory &&
163
+ source_info.source_path != source_info.context_directory
159
164
  result = ::Toys::Utils::Gems.find_gemfile(source_info.source_path,
160
165
  gemfile_names: @toys_gemfile_names)
161
166
  return result if result
@@ -16,8 +16,6 @@ module Toys
16
16
  # This is a frontend for {Toys::Utils::Exec}. More information is
17
17
  # available in that class's documentation.
18
18
  #
19
- # ## Features
20
- #
21
19
  # ### Controlling processes
22
20
  #
23
21
  # A process can be started in the *foreground* or the *background*. If you
@@ -149,7 +147,7 @@ module Toys
149
147
  #
150
148
  # include :exec, exit_on_nonzero_status: true
151
149
  #
152
- # ## Configuration Options
150
+ # ### Configuration Options
153
151
  #
154
152
  # A variety of options can be used to control subprocesses. These can be
155
153
  # provided to any method that starts a subprocess. You can also set
@@ -267,7 +265,7 @@ module Toys
267
265
  # If the process is not set to run in the background, and a block is
268
266
  # provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
269
267
  #
270
- # ## Examples
268
+ # ### Examples
271
269
  #
272
270
  # Run a command without a shell, and print the exit code (0 for success):
273
271
  #
@@ -303,7 +301,7 @@ module Toys
303
301
  # If the process is not set to run in the background, and a block is
304
302
  # provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
305
303
  #
306
- # ## Example
304
+ # ### Example
307
305
  #
308
306
  # Execute a small script with warnings
309
307
  #
@@ -337,7 +335,7 @@ module Toys
337
335
  # Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows)
338
336
  # do not support this method because they do not support fork.
339
337
  #
340
- # ## Example
338
+ # ### Example
341
339
  #
342
340
  # Run a proc in a forked process.
343
341
  #
@@ -377,7 +375,7 @@ module Toys
377
375
  # Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows)
378
376
  # do not support this method because they do not support fork.
379
377
  #
380
- # ## Example
378
+ # ### Example
381
379
  #
382
380
  # Run the "system update" tool and pass it an argument.
383
381
  #
@@ -424,7 +422,7 @@ module Toys
424
422
  # run a tool that uses a different bundle. It may also be necessary on
425
423
  # environments without "fork" (such as JRuby or Ruby on Windows).
426
424
  #
427
- # ## Example
425
+ # ### Example
428
426
  #
429
427
  # Run the "system update" tool and pass it an argument.
430
428
  #
@@ -459,7 +457,7 @@ module Toys
459
457
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
460
458
  # yielded to it.
461
459
  #
462
- # ## Example
460
+ # ### Example
463
461
  #
464
462
  # Capture the output of an echo command
465
463
  #
@@ -490,7 +488,7 @@ module Toys
490
488
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
491
489
  # yielded to it.
492
490
  #
493
- # ## Example
491
+ # ### Example
494
492
  #
495
493
  # Capture the output of a ruby script.
496
494
  #
@@ -524,7 +522,7 @@ module Toys
524
522
  # Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows)
525
523
  # do not support this method because they do not support fork.
526
524
  #
527
- # ## Example
525
+ # ### Example
528
526
  #
529
527
  # Run a proc in a forked process and capture its output:
530
528
  #
@@ -564,7 +562,7 @@ module Toys
564
562
  # Beware that some Ruby environments (e.g. JRuby, and Ruby on Windows)
565
563
  # do not support this method because they do not support fork.
566
564
  #
567
- # ## Example
565
+ # ### Example
568
566
  #
569
567
  # Run the "system version" tool and capture its output.
570
568
  #
@@ -612,7 +610,7 @@ module Toys
612
610
  # run a tool that uses a different bundle. It may also be necessary on
613
611
  # environments without "fork" (such as JRuby or Ruby on Windows).
614
612
  #
615
- # ## Example
613
+ # ### Example
616
614
  #
617
615
  # Run the "system version" tool and capture its output.
618
616
  #
@@ -642,7 +640,7 @@ module Toys
642
640
  # If a block is provided, a {Toys::Utils::Exec::Controller} will be
643
641
  # yielded to it.
644
642
  #
645
- # ## Example
643
+ # ### Example
646
644
  #
647
645
  # Run a shell script
648
646
  #
@@ -708,7 +706,16 @@ module Toys
708
706
 
709
707
  ## @private
710
708
  def self._interpret_e(value, context)
711
- value ? proc { |r| context.exit(r.exit_code) if r.error? } : nil
709
+ return nil unless value
710
+ proc do |result|
711
+ if result.failed?
712
+ context.exit(127)
713
+ elsif result.signaled?
714
+ context.exit(result.signal_code + 128)
715
+ elsif result.error?
716
+ context.exit(result.exit_code)
717
+ end
718
+ end
712
719
  end
713
720
 
714
721
  ## @private