toys 0.11.5 → 0.12.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +1 -1
- data/builtins/system/bash-completion.rb +89 -0
- data/builtins/system/test.rb +96 -0
- data/builtins/system/update.rb +48 -0
- data/docs/guide.md +91 -3
- data/lib/toys/standard_cli.rb +2 -5
- data/lib/toys/templates/clean.rb +17 -1
- data/lib/toys/templates/gem_build.rb +22 -4
- data/lib/toys/templates/minitest.rb +17 -1
- data/lib/toys/templates/rake.rb +18 -2
- data/lib/toys/templates/rdoc.rb +22 -3
- data/lib/toys/templates/rspec.rb +17 -1
- data/lib/toys/templates/rubocop.rb +22 -3
- data/lib/toys/templates/yardoc.rb +30 -10
- data/lib/toys/testing.rb +197 -0
- data/lib/toys/version.rb +1 -1
- metadata +12 -9
- data/builtins/system.rb +0 -152
data/lib/toys/testing.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Toys
|
4
|
+
##
|
5
|
+
# Helpers for writing tool tests.
|
6
|
+
#
|
7
|
+
# EXPERIMENTAL: Interfaces are subject to change.
|
8
|
+
#
|
9
|
+
module Testing
|
10
|
+
##
|
11
|
+
# Returns the Toys CLI for this test class. By default, a single CLI and
|
12
|
+
# Loader are shared by all tests in a given class (or _describe_ block).
|
13
|
+
#
|
14
|
+
# @return [Toys::CLI]
|
15
|
+
#
|
16
|
+
def toys_cli
|
17
|
+
self.class.toys_cli
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Runs the tool corresponding to the given command line, provided as an
|
22
|
+
# array of arguments, and returns a {Toys::Exec::Result}.
|
23
|
+
#
|
24
|
+
# By default, a single CLI is shared among the tests in each test class or
|
25
|
+
# _describe_ block. Thus, tools are loaded only once, and the loader is
|
26
|
+
# shared across the tests. If you need to isolate loading for a test,
|
27
|
+
# create a separate CLI and pass it in using the `:cli` keyword argument.
|
28
|
+
#
|
29
|
+
# All other keyword arguments are the same as those defined by the
|
30
|
+
# `Toys::Utils::Exec` class. If a block is given, a
|
31
|
+
# `Toys::Utils::Exec::Controller` is yielded to it. For more info, see the
|
32
|
+
# documentation for `Toys::Utils::Exec#exec`.
|
33
|
+
#
|
34
|
+
# This method uses "fork" to isolate the run of the tool. On an environment
|
35
|
+
# without "fork" support, such as JRuby or Ruby on Windows, consider
|
36
|
+
# {#exec_separate_tool}.
|
37
|
+
#
|
38
|
+
# @param cmd [String,Array<String>] The command to execute.
|
39
|
+
# @param opts [keywords] The command options.
|
40
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
41
|
+
# for the subprocess streams.
|
42
|
+
#
|
43
|
+
# @return [Toys::Utils::Exec::Controller] The subprocess controller, if
|
44
|
+
# the process is running in the background.
|
45
|
+
# @return [Toys::Utils::Exec::Result] The result, if the process ran in
|
46
|
+
# the foreground.
|
47
|
+
#
|
48
|
+
def exec_tool(cmd, **opts, &block)
|
49
|
+
cli = opts.delete(:cli) || toys_cli
|
50
|
+
cmd = ::Shellwords.split(cmd) if cmd.is_a?(::String)
|
51
|
+
cli.loader.lookup(cmd)
|
52
|
+
tool_caller = proc { ::Kernel.exit(cli.run(*cmd)) }
|
53
|
+
self.class.toys_exec.exec_proc(tool_caller, **opts, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Runs the tool corresponding to the given command line, provided as an
|
58
|
+
# array of arguments, in a separately spawned process, and returns a
|
59
|
+
# {Toys::Exec::Result}.
|
60
|
+
#
|
61
|
+
# Unlike {#exec_tool}, this method does not use the shared CLI, but instead
|
62
|
+
# spawns a completely new Toys process for each run. It is thus slower than
|
63
|
+
# {#exec_tool}, but compatible with environments without "fork" support,
|
64
|
+
# such as JRuby or Ruby on Windows.
|
65
|
+
#
|
66
|
+
# Supported keyword arguments are the same as those defined by the
|
67
|
+
# `Toys::Utils::Exec` class. If a block is given, a
|
68
|
+
# `Toys::Utils::Exec::Controller` is yielded to it. For more info, see the
|
69
|
+
# documentation for `Toys::Utils::Exec#exec`.
|
70
|
+
#
|
71
|
+
# @param cmd [String,Array<String>] The command to execute.
|
72
|
+
# @param opts [keywords] The command options.
|
73
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
74
|
+
# for the subprocess streams.
|
75
|
+
#
|
76
|
+
# @return [Toys::Utils::Exec::Controller] The subprocess controller, if
|
77
|
+
# the process is running in the background.
|
78
|
+
# @return [Toys::Utils::Exec::Result] The result, if the process ran in
|
79
|
+
# the foreground.
|
80
|
+
#
|
81
|
+
def exec_separate_tool(cmd, **opts, &block)
|
82
|
+
cmd = ::Shellwords.split(cmd) if cmd.is_a?(::String)
|
83
|
+
cmd = [::RbConfig.ruby, "--disable=gems", ::Toys.executable_path] + cmd
|
84
|
+
self.class.toys_exec.exec(cmd, **opts, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Runs the tool corresponding to the given command line, and returns the
|
89
|
+
# data written to `STDOUT`. This is equivalent to calling {#exec_tool}
|
90
|
+
# with the keyword arguments `out: :capture, background: false`, and
|
91
|
+
# calling `#captured_out` on the result.
|
92
|
+
#
|
93
|
+
# Note: this method uses "fork" to execute the tool. If you are using an
|
94
|
+
# environment without "fork" support, such as JRuby oor Ruby on Windows,
|
95
|
+
# consider {#capture_separate_tool}.
|
96
|
+
#
|
97
|
+
# @param cmd [String,Array<String>] The command to execute.
|
98
|
+
# @param opts [keywords] The command options.
|
99
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
100
|
+
# for the subprocess streams.
|
101
|
+
#
|
102
|
+
# @return [Toys::Utils::Exec::Controller] The subprocess controller, if
|
103
|
+
# the process is running in the background.
|
104
|
+
# @return [Toys::Utils::Exec::Result] The result, if the process ran in
|
105
|
+
# the foreground.
|
106
|
+
#
|
107
|
+
def capture_tool(cmd, **opts, &block)
|
108
|
+
opts = opts.merge(out: :capture, background: false)
|
109
|
+
exec_tool(cmd, **opts, &block).captured_out
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Runs the tool corresponding to the given command line, and returns the
|
114
|
+
# data written to `STDOUT`. This is equivalent to calling
|
115
|
+
# {#exec_separate_tool} with the keyword arguments
|
116
|
+
# `out: :capture, background: false`, and calling `#captured_out` on the
|
117
|
+
# result.
|
118
|
+
#
|
119
|
+
# Unlike {#capture_tool}, this method does not use "fork", and thus can be
|
120
|
+
# called in an environment such as JRuby or Ruby on Windows.
|
121
|
+
#
|
122
|
+
# @param cmd [String,Array<String>] The command to execute.
|
123
|
+
# @param opts [keywords] The command options.
|
124
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
125
|
+
# for the subprocess streams.
|
126
|
+
#
|
127
|
+
# @return [Toys::Utils::Exec::Controller] The subprocess controller, if
|
128
|
+
# the process is running in the background.
|
129
|
+
# @return [Toys::Utils::Exec::Result] The result, if the process ran in
|
130
|
+
# the foreground.
|
131
|
+
#
|
132
|
+
def capture_separate_tool(cmd, **opts, &block)
|
133
|
+
opts = opts.merge(out: :capture, background: false)
|
134
|
+
exec_separate_tool(cmd, **opts, &block).captured_out
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Runs the tool corresponding to the given command line, managing streams
|
139
|
+
# using a controller. This is equivalent to calling {#exec_tool} with the
|
140
|
+
# keyword arguments:
|
141
|
+
#
|
142
|
+
# out: :controller,
|
143
|
+
# err: :controller,
|
144
|
+
# in: :controller,
|
145
|
+
# background: block.nil?
|
146
|
+
#
|
147
|
+
# If a block is given, the command is run in the foreground, the
|
148
|
+
# controller is passed to the block during the run, and a result object is
|
149
|
+
# returned. If no block is given, the command is run in the background, and
|
150
|
+
# the controller object is returned.
|
151
|
+
#
|
152
|
+
# @param cmd [String,Array<String>] The command to execute.
|
153
|
+
# @param opts [keywords] The command options.
|
154
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
155
|
+
# for the subprocess streams.
|
156
|
+
#
|
157
|
+
# @return [Toys::Utils::Exec::Controller] The subprocess controller, if
|
158
|
+
# the process is running in the background.
|
159
|
+
# @return [Toys::Utils::Exec::Result] The result, if the process ran in
|
160
|
+
# the foreground.
|
161
|
+
#
|
162
|
+
def control_tool(cmd, **opts, &block)
|
163
|
+
opts = opts.merge(out: :controller, err: :controller, in: :controller, background: block.nil?)
|
164
|
+
exec_tool(cmd, **opts, &block)
|
165
|
+
end
|
166
|
+
|
167
|
+
@toys_mutex = ::Mutex.new
|
168
|
+
|
169
|
+
# @private
|
170
|
+
def self.included(klass)
|
171
|
+
klass.extend(ClassMethods)
|
172
|
+
end
|
173
|
+
|
174
|
+
# @private
|
175
|
+
def self.toys_mutex
|
176
|
+
@toys_mutex
|
177
|
+
end
|
178
|
+
|
179
|
+
# @private
|
180
|
+
module ClassMethods
|
181
|
+
# @private
|
182
|
+
def toys_cli
|
183
|
+
Testing.toys_mutex.synchronize do
|
184
|
+
@toys_cli ||= StandardCLI.new
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# @private
|
189
|
+
def toys_exec
|
190
|
+
Testing.toys_mutex.synchronize do
|
191
|
+
require "toys/utils/exec"
|
192
|
+
@toys_exec ||= Utils::Exec.new
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
data/lib/toys/version.rb
CHANGED
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.
|
4
|
+
version: 0.12.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: 2021-
|
11
|
+
date: 2021-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: toys-core
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.12.0
|
20
20
|
type: :runtime
|
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: 0.
|
26
|
+
version: 0.12.0
|
27
27
|
description: Toys is a configurable command line tool. Write commands in Ruby using
|
28
28
|
a simple DSL, and Toys will provide the command line executable and take care of
|
29
29
|
all the details such as argument parsing, online help, and error reporting. Toys
|
@@ -44,7 +44,9 @@ files:
|
|
44
44
|
- README.md
|
45
45
|
- bin/toys
|
46
46
|
- builtins/do.rb
|
47
|
-
- builtins/system.rb
|
47
|
+
- builtins/system/bash-completion.rb
|
48
|
+
- builtins/system/test.rb
|
49
|
+
- builtins/system/update.rb
|
48
50
|
- docs/guide.md
|
49
51
|
- lib/toys.rb
|
50
52
|
- lib/toys/standard_cli.rb
|
@@ -56,6 +58,7 @@ files:
|
|
56
58
|
- lib/toys/templates/rspec.rb
|
57
59
|
- lib/toys/templates/rubocop.rb
|
58
60
|
- lib/toys/templates/yardoc.rb
|
61
|
+
- lib/toys/testing.rb
|
59
62
|
- lib/toys/version.rb
|
60
63
|
- share/bash-completion-remove.sh
|
61
64
|
- share/bash-completion.sh
|
@@ -63,10 +66,10 @@ homepage: https://github.com/dazuma/toys
|
|
63
66
|
licenses:
|
64
67
|
- MIT
|
65
68
|
metadata:
|
66
|
-
changelog_uri: https://dazuma.github.io/toys/gems/toys/v0.
|
69
|
+
changelog_uri: https://dazuma.github.io/toys/gems/toys/v0.12.0/file.CHANGELOG.html
|
67
70
|
source_code_uri: https://github.com/dazuma/toys/tree/main/toys
|
68
71
|
bug_tracker_uri: https://github.com/dazuma/toys/issues
|
69
|
-
documentation_uri: https://dazuma.github.io/toys/gems/toys/v0.
|
72
|
+
documentation_uri: https://dazuma.github.io/toys/gems/toys/v0.12.0
|
70
73
|
post_install_message:
|
71
74
|
rdoc_options: []
|
72
75
|
require_paths:
|
@@ -75,14 +78,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
78
|
requirements:
|
76
79
|
- - ">="
|
77
80
|
- !ruby/object:Gem::Version
|
78
|
-
version: 2.
|
81
|
+
version: 2.4.0
|
79
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
83
|
requirements:
|
81
84
|
- - ">="
|
82
85
|
- !ruby/object:Gem::Version
|
83
86
|
version: '0'
|
84
87
|
requirements: []
|
85
|
-
rubygems_version: 3.1.
|
88
|
+
rubygems_version: 3.1.6
|
86
89
|
signing_key:
|
87
90
|
specification_version: 4
|
88
91
|
summary: A configurable command line tool
|
data/builtins/system.rb
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
desc "A set of system commands for Toys"
|
4
|
-
|
5
|
-
long_desc "Contains tools that inspect, configure, and update Toys itself."
|
6
|
-
|
7
|
-
tool "version" do
|
8
|
-
desc "Print the current Toys version"
|
9
|
-
|
10
|
-
def run
|
11
|
-
puts ::Toys::VERSION
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
tool "update" do
|
16
|
-
desc "Update Toys if a newer version is available"
|
17
|
-
|
18
|
-
long_desc "Checks rubygems for a newer version of Toys. If one is available, downloads" \
|
19
|
-
" and installs it."
|
20
|
-
|
21
|
-
flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
|
22
|
-
|
23
|
-
include :exec
|
24
|
-
include :terminal
|
25
|
-
|
26
|
-
def run
|
27
|
-
require "rubygems"
|
28
|
-
configure_exec(exit_on_nonzero_status: true)
|
29
|
-
version_info = spinner(leading_text: "Checking rubygems for the latest release... ",
|
30
|
-
final_text: "Done.\n") do
|
31
|
-
capture(["gem", "list", "-q", "-r", "-e", "toys"])
|
32
|
-
end
|
33
|
-
if version_info =~ /toys\s\((.+)\)/
|
34
|
-
latest_version = ::Gem::Version.new(::Regexp.last_match(1))
|
35
|
-
cur_version = ::Gem::Version.new(::Toys::VERSION)
|
36
|
-
if latest_version > cur_version
|
37
|
-
prompt = "Update Toys from #{cur_version} to #{latest_version}? "
|
38
|
-
exit(1) unless yes || confirm(prompt, default: true)
|
39
|
-
result = spinner(leading_text: "Installing Toys version #{latest_version}... ",
|
40
|
-
final_text: "Done.\n") do
|
41
|
-
exec(["gem", "install", "toys", "--version", latest_version.to_s],
|
42
|
-
out: :capture, err: :capture)
|
43
|
-
end
|
44
|
-
if result.error?
|
45
|
-
puts(result.captured_out + result.captured_err)
|
46
|
-
puts("Toys failed to install version #{latest_version}", :red, :bold)
|
47
|
-
exit(1)
|
48
|
-
end
|
49
|
-
puts("Toys successfully installed version #{latest_version}", :green, :bold)
|
50
|
-
elsif latest_version < cur_version
|
51
|
-
puts("Toys is already at experimental version #{cur_version}, which is later than" \
|
52
|
-
" the latest released version #{latest_version}",
|
53
|
-
:yellow, :bold)
|
54
|
-
else
|
55
|
-
puts("Toys is already at the latest version: #{latest_version}", :green, :bold)
|
56
|
-
end
|
57
|
-
else
|
58
|
-
puts("Could not get latest Toys version", :red, :bold)
|
59
|
-
exit(1)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
tool "bash-completion" do
|
65
|
-
desc "Bash tab completion for Toys"
|
66
|
-
|
67
|
-
long_desc \
|
68
|
-
"Tools that manage tab completion for Toys in the bash shell.",
|
69
|
-
"",
|
70
|
-
"To install tab completion for Toys, execute the following line in a bash shell, or" \
|
71
|
-
" include it in an init file such as your .bashrc:",
|
72
|
-
[" $(toys system bash-completion install)"],
|
73
|
-
"",
|
74
|
-
"To remove tab completion, execute:",
|
75
|
-
[" $(toys system bash-completion remove)"],
|
76
|
-
"",
|
77
|
-
"It is also possible to install completions for different executable names if you have" \
|
78
|
-
" aliases for Toys. See the help for the \"install\" and \"remove\" tools for details.",
|
79
|
-
"",
|
80
|
-
"The \"eval\" tool is the actual completion command invoked by bash when it needs to" \
|
81
|
-
" complete a toys command line. You shouldn't need to invoke it directly."
|
82
|
-
|
83
|
-
tool "eval" do
|
84
|
-
desc "Tab completion command (executed by bash)"
|
85
|
-
|
86
|
-
long_desc \
|
87
|
-
"Completion command invoked by bash to compete a toys command line. Generally you do not" \
|
88
|
-
" need to invoke this directly. It reads the command line context from the COMP_LINE" \
|
89
|
-
" and COMP_POINT environment variables, and outputs completion candidates to stdout."
|
90
|
-
|
91
|
-
disable_argument_parsing
|
92
|
-
|
93
|
-
def run
|
94
|
-
require "toys/utils/completion_engine"
|
95
|
-
result = ::Toys::Utils::CompletionEngine::Bash.new(cli).run
|
96
|
-
if result > 1
|
97
|
-
logger.fatal("This tool must be invoked as a bash completion command.")
|
98
|
-
end
|
99
|
-
exit(result)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
tool "install" do
|
104
|
-
desc "Install bash tab completion"
|
105
|
-
|
106
|
-
long_desc \
|
107
|
-
"Outputs a command to set up Toys tab completion in the current bash shell.",
|
108
|
-
"",
|
109
|
-
"To use, execute the following line in a bash shell, or include it in an init file" \
|
110
|
-
" such as your .bashrc:",
|
111
|
-
[" $(toys system bash-completion install)"],
|
112
|
-
"",
|
113
|
-
"This will associate the toys tab completion logic with the `toys` executable by default." \
|
114
|
-
" If you have aliases for the toys executable, pass them as arguments. e.g.",
|
115
|
-
[" $(toys system bash-completion install my-toys-alias another-alias)"]
|
116
|
-
|
117
|
-
remaining_args :executable_names,
|
118
|
-
desc: "Names of executables for which to set up tab completion" \
|
119
|
-
" (default: #{::Toys::StandardCLI::EXECUTABLE_NAME})"
|
120
|
-
|
121
|
-
def run
|
122
|
-
require "shellwords"
|
123
|
-
path = ::File.join(::File.dirname(__dir__), "share", "bash-completion.sh")
|
124
|
-
exes = executable_names.empty? ? [::Toys::StandardCLI::EXECUTABLE_NAME] : executable_names
|
125
|
-
puts Shellwords.join(["source", path] + exes)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
tool "remove" do
|
130
|
-
desc "Remove bash tab completion"
|
131
|
-
|
132
|
-
long_desc \
|
133
|
-
"Outputs a command to remove Toys tab completion from the current bash shell.",
|
134
|
-
"",
|
135
|
-
"To use, execute the following line in a bash shell:",
|
136
|
-
[" $(toys system bash-completion remove)"],
|
137
|
-
"",
|
138
|
-
"If you have other names or aliases for the toys executable, pass them as arguments. e.g.",
|
139
|
-
[" $(toys system bash-completion remove my-toys-alias another-alias)"]
|
140
|
-
|
141
|
-
remaining_args :executable_names,
|
142
|
-
desc: "Names of executables for which to set up tab completion" \
|
143
|
-
" (default: #{::Toys::StandardCLI::EXECUTABLE_NAME})"
|
144
|
-
|
145
|
-
def run
|
146
|
-
require "shellwords"
|
147
|
-
path = ::File.join(::File.dirname(__dir__), "share", "bash-completion-remove.sh")
|
148
|
-
exes = executable_names.empty? ? [::Toys::StandardCLI::EXECUTABLE_NAME] : executable_names
|
149
|
-
puts Shellwords.join(["source", path] + exes)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|