toys-core 0.3.11 → 0.4.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 +12 -0
- data/README.md +7 -16
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/definition/tool.rb +1 -1
- data/lib/toys/dsl/tool.rb +5 -13
- data/lib/toys/input_file.rb +20 -12
- data/lib/toys/mixin.rb +35 -12
- data/lib/toys/runner.rb +1 -1
- data/lib/toys/standard_mixins/gems.rb +88 -0
- data/lib/toys/standard_mixins/highline.rb +1 -1
- data/lib/toys/standard_mixins/terminal.rb +1 -1
- data/lib/toys/tool.rb +0 -11
- data/lib/toys/utils/gems.rb +59 -42
- data/lib/toys/utils/terminal.rb +19 -7
- metadata +21 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95766b26892b0fab477c7f05a8eddf8aa0f30a9e98075b41881791ca1d446389
|
4
|
+
data.tar.gz: 03af27a0411ed093f1b0b27edb4aafd2562cc3b92f9176dfdd10e26be090d8f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc6e36460d0849a153a4fe8ac376bfc120f93e19f2931bfc892dbf0fda67af82e4aa0bd73c138e9950c5559fca8cc1bc6f056195bdaad5f935e7203a48cf3411
|
7
|
+
data.tar.gz: 458da8a2896163512994018fbce12ee6392ae69e63383b232d9c86577bdd02a5069bbbda52c79786d7d2e09f880ccea7bca2b0845979ef12c73a545a68303c28
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.4.0 / 2018-07-03
|
4
|
+
|
5
|
+
Now declaring this alpha quality. Backward-incompatible changes are still
|
6
|
+
possible from this point, but I'll try to avoid them.
|
7
|
+
|
8
|
+
* CHANGED: Utils::Terminal#confirm default is now unset by default
|
9
|
+
* CHANGED: Moved gem install/activation methods into a mixin
|
10
|
+
* IMPROVED: Toys::Utils::Gems can suppress the confirmation prompt
|
11
|
+
* IMPROVED: Magic comments are now honored in toys files.
|
12
|
+
* IMPROVED: Utils::Gems installation is now much faster.
|
13
|
+
* FIXED: Utils::Gems didn't reset the specifications on Ruby 2.3.
|
14
|
+
|
3
15
|
### 0.3.11 / 2018-07-02
|
4
16
|
|
5
17
|
* CHANGED: Require Ruby 2.3 or later
|
data/README.md
CHANGED
@@ -1,26 +1,15 @@
|
|
1
1
|
# Toys
|
2
2
|
|
3
|
-
Toys is a command line
|
4
|
-
|
5
|
-
|
6
|
-
for software developers, IT specialists, and other power users who want to
|
7
|
-
write and organize scripts to automate their workflows.
|
3
|
+
Toys is a configurable command line tool. Write commands in config files using
|
4
|
+
a simple DSL, and Toys will provide the command line binary and take care of
|
5
|
+
all the details such as argument parsing, online help, and error reporting.
|
8
6
|
|
9
7
|
Toys-Core is the command line tool framework underlying Toys. It can be used
|
10
|
-
to create command line binaries using the internal Toys APIs.
|
8
|
+
to create your own command line binaries using the internal Toys APIs.
|
11
9
|
|
12
|
-
To get started
|
10
|
+
To get started with toys-core, see the
|
13
11
|
[Getting Started Guide](https://www.rubydoc.info/gems/toys-core/file/docs/getting-started.md)
|
14
12
|
|
15
|
-
## Contributing
|
16
|
-
|
17
|
-
While we appreciate contributions, please note that this software is currently
|
18
|
-
highly experimental, and the code is evolving very rapidly. Please contact the
|
19
|
-
author before embarking on a major pull request. More detailed contribution
|
20
|
-
guidelines will be provided when the software stabilizes further.
|
21
|
-
|
22
|
-
The source can be found on Github at https://github.com/dazuma/toys
|
23
|
-
|
24
13
|
## License
|
25
14
|
|
26
15
|
Copyright 2018 Daniel Azuma
|
@@ -28,3 +17,5 @@ Copyright 2018 Daniel Azuma
|
|
28
17
|
This software is licensed under the 3-clause BSD license.
|
29
18
|
|
30
19
|
See the LICENSE.md file for more information.
|
20
|
+
|
21
|
+
The source can be found on Github at https://github.com/dazuma/toys
|
data/lib/toys/core_version.rb
CHANGED
data/lib/toys/definition/tool.rb
CHANGED
@@ -666,7 +666,7 @@ module Toys
|
|
666
666
|
unless @definition_finished
|
667
667
|
ContextualError.capture("Error installing tool middleware!", tool_name: full_name) do
|
668
668
|
config_proc = proc {}
|
669
|
-
middleware_stack.
|
669
|
+
middleware_stack.reverse_each do |middleware|
|
670
670
|
config_proc = make_config_proc(middleware, loader, config_proc)
|
671
671
|
end
|
672
672
|
config_proc.call
|
data/lib/toys/dsl/tool.rb
CHANGED
@@ -590,23 +590,15 @@ module Toys
|
|
590
590
|
if mod.nil?
|
591
591
|
raise ToolDefinitionError, "Module not found: #{name.inspect}"
|
592
592
|
end
|
593
|
-
if mod.respond_to?(:
|
594
|
-
cur_tool.add_initializer(mod.
|
593
|
+
if mod.respond_to?(:initialization_callback) && mod.initialization_callback
|
594
|
+
cur_tool.add_initializer(mod.initialization_callback, *args)
|
595
|
+
end
|
596
|
+
if mod.respond_to?(:inclusion_callback) && mod.inclusion_callback
|
597
|
+
class_exec(*args, &mod.inclusion_callback)
|
595
598
|
end
|
596
599
|
super(mod)
|
597
600
|
end
|
598
601
|
|
599
|
-
##
|
600
|
-
# Activate the given gem. If it is not present, attempt to install it (or
|
601
|
-
# inform the user to update the bundle).
|
602
|
-
#
|
603
|
-
# @param [String] name Name of the gem
|
604
|
-
# @param [String...] requirements Version requirements
|
605
|
-
#
|
606
|
-
def gem(name, *requirements)
|
607
|
-
(@__gems ||= Utils::Gems.new).activate(name, *requirements)
|
608
|
-
end
|
609
|
-
|
610
602
|
## @private
|
611
603
|
def self.new_class(words, priority, loader)
|
612
604
|
tool_class = ::Class.new(::Toys::Tool)
|
data/lib/toys/input_file.rb
CHANGED
@@ -48,20 +48,28 @@ module Toys::InputFile # rubocop:disable Style/ClassAndModuleChildren
|
|
48
48
|
end
|
49
49
|
basename = ::File.basename(path).tr(".-", "_").gsub(/\W/, "")
|
50
50
|
name = "M#{namespace.object_id}_#{basename}"
|
51
|
-
|
52
|
-
str
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
str = build_eval_string(name, ::IO.read(path))
|
52
|
+
if str
|
53
|
+
const_set(name, namespace)
|
54
|
+
::Toys::DSL::Tool.prepare(tool_class, remaining_words, path) do
|
55
|
+
::Toys::ContextualError.capture_path("Error while loading Toys config!", path) do
|
56
|
+
# rubocop:disable Security/Eval
|
57
|
+
eval(str, __binding, path, 0)
|
58
|
+
# rubocop:enable Security/Eval
|
56
59
|
end
|
57
60
|
end
|
58
|
-
STR
|
59
|
-
::Toys::DSL::Tool.prepare(tool_class, remaining_words, path) do
|
60
|
-
::Toys::ContextualError.capture_path("Error while loading Toys config!", path) do
|
61
|
-
# rubocop:disable Security/Eval
|
62
|
-
eval(str, __binding, path, 0)
|
63
|
-
# rubocop:enable Security/Eval
|
64
|
-
end
|
65
61
|
end
|
66
62
|
end
|
63
|
+
|
64
|
+
## @private
|
65
|
+
def self.build_eval_string(module_name, string)
|
66
|
+
index = string.index(/^\s*[^#\s]/)
|
67
|
+
return nil if index.nil?
|
68
|
+
"#{string[0, index]}\n" \
|
69
|
+
"module #{module_name}\n" \
|
70
|
+
"@tool_class.class_eval do\n" \
|
71
|
+
"#{string[index..-1]}\n" \
|
72
|
+
"end\n" \
|
73
|
+
"end\n"
|
74
|
+
end
|
67
75
|
end
|
data/lib/toys/mixin.rb
CHANGED
@@ -43,12 +43,20 @@ module Toys
|
|
43
43
|
# To create a mixin, define a module, and include this module. Then define
|
44
44
|
# the methods you want to be available.
|
45
45
|
#
|
46
|
-
# If you want to perform some initialization specific to the mixin,
|
47
|
-
# `to_initialize` block
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
46
|
+
# If you want to perform some initialization specific to the mixin, you can
|
47
|
+
# provide a `to_initialize` block and/or a `to_include` block.
|
48
|
+
#
|
49
|
+
# The `to_initialize` block is called when the tool itself is instantiated.
|
50
|
+
# It has access to tool methods such as {Toys::Tool#option}, and can perform
|
51
|
+
# setup for the tool execution itself, often involving initializing some
|
52
|
+
# persistent state and storing it in the tool using {Toys::Tool#set}. The
|
53
|
+
# `to_initialize` block is passed any extra arguments that were provided to
|
54
|
+
# the `include` directive.
|
55
|
+
#
|
56
|
+
# The `to_include` block is called in the context of your tool class when
|
57
|
+
# your mixin is included. It is also passed any extra arguments that were
|
58
|
+
# provided to the `include` directive. It can be used to issue directives
|
59
|
+
# or define methods on the DSL, specific to the mixin.
|
52
60
|
#
|
53
61
|
# ## Example
|
54
62
|
#
|
@@ -95,25 +103,40 @@ module Toys
|
|
95
103
|
## @private
|
96
104
|
def self.included(mod)
|
97
105
|
return if mod.respond_to?(:to_initialize)
|
98
|
-
mod.extend(
|
106
|
+
mod.extend(ModuleMethods)
|
99
107
|
end
|
100
108
|
|
101
109
|
##
|
102
|
-
#
|
110
|
+
# Methods that will be added to a mixin module object.
|
103
111
|
#
|
104
|
-
module
|
112
|
+
module ModuleMethods
|
105
113
|
##
|
106
|
-
# Provide
|
114
|
+
# Provide a block that initializes this mixin when the tool is
|
115
|
+
# constructed.
|
107
116
|
#
|
108
117
|
def to_initialize(&block)
|
109
|
-
self.
|
118
|
+
self.initialization_callback = block
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Provide a block that modifies the tool class when the mixin is
|
123
|
+
# included.
|
124
|
+
#
|
125
|
+
def to_include(&block)
|
126
|
+
self.inclusion_callback = block
|
110
127
|
end
|
111
128
|
|
112
129
|
##
|
113
130
|
# You may alternately set the initializer block using this accessor.
|
114
131
|
# @return [Proc]
|
115
132
|
#
|
116
|
-
attr_accessor :
|
133
|
+
attr_accessor :initialization_callback
|
134
|
+
|
135
|
+
##
|
136
|
+
# You may alternately set the inclusion block using this accessor.
|
137
|
+
# @return [Proc]
|
138
|
+
#
|
139
|
+
attr_accessor :inclusion_callback
|
117
140
|
end
|
118
141
|
end
|
119
142
|
end
|
data/lib/toys/runner.rb
CHANGED
@@ -161,7 +161,7 @@ module Toys
|
|
161
161
|
tool.exit(-1)
|
162
162
|
end
|
163
163
|
end
|
164
|
-
@tool_definition.middleware_stack.
|
164
|
+
@tool_definition.middleware_stack.reverse_each do |middleware|
|
165
165
|
executor = make_executor(middleware, tool, executor)
|
166
166
|
end
|
167
167
|
catch(:result) do
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 Daniel Azuma
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are met:
|
9
|
+
#
|
10
|
+
# * Redistributions of source code must retain the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer.
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
16
|
+
# contributors to this software, may be used to endorse or promote products
|
17
|
+
# derived from this software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
;
|
31
|
+
|
32
|
+
module Toys
|
33
|
+
module StandardMixins
|
34
|
+
##
|
35
|
+
# Provides methods for installing and activating third-party gems. When
|
36
|
+
# this mixin is included, it provides a `gem` method that has the same
|
37
|
+
# effect as {Toys::Utils::Gems#activate}, so you can ensure a gem is
|
38
|
+
# present when running a tool. A `gem` directive is likewise added to the
|
39
|
+
# tool DSL itself, so you can also ensure a gem is present when defining a
|
40
|
+
# tool.
|
41
|
+
#
|
42
|
+
# You may make these methods available to your tool by including the
|
43
|
+
# following directive in your tool configuration:
|
44
|
+
#
|
45
|
+
# include :gems
|
46
|
+
#
|
47
|
+
# If you pass additional options to the include directive, those are used
|
48
|
+
# to initialize settings for the gem install process. For example:
|
49
|
+
#
|
50
|
+
# include :gems, output: $stdout, default_confirm: false
|
51
|
+
#
|
52
|
+
# This is a frontend for {Toys::Utils::Gems}. More information is
|
53
|
+
# available in that class's documentation.
|
54
|
+
#
|
55
|
+
module Gems
|
56
|
+
include Mixin
|
57
|
+
|
58
|
+
to_include do |opts = {}|
|
59
|
+
@__gems = Utils::Gems.new(opts)
|
60
|
+
|
61
|
+
def self.gems
|
62
|
+
@__gems
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.gem(name, *requirements)
|
66
|
+
gems.activate(name, *requirements)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Returns a tool-wide instance of {Toys::Utils::Gems}.
|
72
|
+
#
|
73
|
+
def gems
|
74
|
+
self.class.gems
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Activate the given gem.
|
79
|
+
#
|
80
|
+
# @param [String] name Name of the gem
|
81
|
+
# @param [String...] requirements Version requirements
|
82
|
+
#
|
83
|
+
def gem(name, *requirements)
|
84
|
+
self.class.gems.activate(name, *requirements)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/toys/tool.rb
CHANGED
@@ -259,17 +259,6 @@ module Toys
|
|
259
259
|
end
|
260
260
|
end
|
261
261
|
|
262
|
-
##
|
263
|
-
# Activate the given gem. If it is not present, attempt to install it (or
|
264
|
-
# inform the user to update the bundle).
|
265
|
-
#
|
266
|
-
# @param [String] name Name of the gem
|
267
|
-
# @param [String...] requirements Version requirements
|
268
|
-
#
|
269
|
-
def gem(name, *requirements)
|
270
|
-
(@__data[Utils::Gems] ||= Utils::Gems.new).activate(name, *requirements)
|
271
|
-
end
|
272
|
-
|
273
262
|
##
|
274
263
|
# Exit immediately with the given status code
|
275
264
|
#
|
data/lib/toys/utils/gems.rb
CHANGED
@@ -58,22 +58,35 @@ module Toys
|
|
58
58
|
end
|
59
59
|
|
60
60
|
##
|
61
|
-
# Activate the given gem.
|
61
|
+
# Activate the given gem. If it is not present, attempt to install it (or
|
62
|
+
# inform the user to update the bundle).
|
62
63
|
#
|
63
64
|
# @param [String] name Name of the gem
|
64
65
|
# @param [String...] requirements Version requirements
|
65
|
-
# @param [Boolean] default_confirm Default response for the confirmation prompt
|
66
66
|
#
|
67
|
-
def self.activate(name, *requirements
|
68
|
-
new.activate(name, *requirements
|
67
|
+
def self.activate(name, *requirements)
|
68
|
+
new.activate(name, *requirements)
|
69
69
|
end
|
70
70
|
|
71
71
|
##
|
72
72
|
# Create a new gem activator.
|
73
73
|
#
|
74
|
-
|
74
|
+
# @param [IO] input Input IO
|
75
|
+
# @param [IO] output Output IO
|
76
|
+
# @param [Boolean] suppress_confirm Suppress the confirmation prompt and
|
77
|
+
# just use the given `default_confirm` value. Default is false,
|
78
|
+
# indicating the confirmation prompt appears by default.
|
79
|
+
# @param [Boolean] default_confirm Default response for the confirmation
|
80
|
+
# prompt. Default is true.
|
81
|
+
#
|
82
|
+
def initialize(input: $stdin,
|
83
|
+
output: $stderr,
|
84
|
+
suppress_confirm: false,
|
85
|
+
default_confirm: true)
|
75
86
|
@terminal = Terminal.new(input: input, output: output)
|
76
87
|
@exec = Exec.new
|
88
|
+
@suppress_confirm = suppress_confirm ? true : false
|
89
|
+
@default_confirm = default_confirm ? true : false
|
77
90
|
end
|
78
91
|
|
79
92
|
##
|
@@ -82,18 +95,26 @@ module Toys
|
|
82
95
|
#
|
83
96
|
# @param [String] name Name of the gem
|
84
97
|
# @param [String...] requirements Version requirements
|
85
|
-
# @param [Boolean] default_confirm Default response for the confirmation prompt
|
86
98
|
#
|
87
|
-
def activate(name, *requirements
|
99
|
+
def activate(name, *requirements)
|
88
100
|
gem(name, *requirements)
|
89
|
-
rescue ::Gem::
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
101
|
+
rescue ::Gem::LoadError => e1
|
102
|
+
is_missing_spec =
|
103
|
+
if defined?(::Gem::MissingSpecError)
|
104
|
+
e1.is_a?(::Gem::MissingSpecError)
|
105
|
+
else
|
106
|
+
e1.message.include?("Could not find")
|
107
|
+
end
|
108
|
+
if is_missing_spec
|
109
|
+
install_gem(name, requirements)
|
110
|
+
begin
|
111
|
+
gem(name, *requirements)
|
112
|
+
rescue ::Gem::LoadError => e2
|
113
|
+
report_error(name, requirements, e2)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
report_error(name, requirements, e1)
|
95
117
|
end
|
96
|
-
raise ActivationFailedError, e.message
|
97
118
|
end
|
98
119
|
|
99
120
|
private
|
@@ -102,44 +123,40 @@ module Toys
|
|
102
123
|
"#{name.inspect}, #{requirements.map(&:inspect).join(', ')}"
|
103
124
|
end
|
104
125
|
|
105
|
-
def install_gem(name, requirements
|
126
|
+
def install_gem(name, requirements)
|
106
127
|
requirements_text = gem_requirements_text(name, requirements)
|
107
|
-
response =
|
108
|
-
|
128
|
+
response =
|
129
|
+
if @suppress_confirm
|
130
|
+
@default_confirm
|
131
|
+
else
|
132
|
+
@terminal.confirm("Gem needed: #{requirements_text}. Install?",
|
133
|
+
default: @default_confirm)
|
134
|
+
end
|
109
135
|
unless response
|
110
136
|
raise InstallFailedError, "Canceled installation of needed gem: #{requirements_text}"
|
111
137
|
end
|
112
|
-
|
113
|
-
raise InstallFailedError, "No gem found matching #{requirements_text}." unless version
|
114
|
-
perform_install(name, version)
|
115
|
-
activate(name, *requirements)
|
138
|
+
perform_install(name, requirements)
|
116
139
|
end
|
117
140
|
|
118
|
-
def
|
119
|
-
@terminal.spinner(leading_text: "
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
else
|
128
|
-
raise InstallFailedError, "Unable to determine existing versions of gem #{name.inspect}"
|
129
|
-
end
|
141
|
+
def perform_install(name, requirements)
|
142
|
+
result = @terminal.spinner(leading_text: "Installing gem #{name}... ",
|
143
|
+
final_text: "Done.\n") do
|
144
|
+
@exec.exec(["gem", "install", name, "--version", requirements.join(",")],
|
145
|
+
out: :capture, err: :capture)
|
146
|
+
end
|
147
|
+
@terminal.puts(result.captured_out + result.captured_err)
|
148
|
+
if result.error?
|
149
|
+
raise InstallFailedError, "Failed to install gem #{name}"
|
130
150
|
end
|
151
|
+
::Gem::Specification.reset
|
131
152
|
end
|
132
153
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
out: :capture, err: :capture)
|
138
|
-
if result.error?
|
139
|
-
@terminal.puts(result.captured_out + result.captured_err)
|
140
|
-
raise InstallFailedError, "Failed to install gem #{name} #{version}"
|
141
|
-
end
|
154
|
+
def report_error(name, requirements, err)
|
155
|
+
if ::ENV["BUNDLE_GEMFILE"]
|
156
|
+
raise GemfileUpdateNeededError.new(gem_requirements_text(name, requirements),
|
157
|
+
::ENV["BUNDLE_GEMFILE"])
|
142
158
|
end
|
159
|
+
raise ActivationFailedError, err.message
|
143
160
|
end
|
144
161
|
end
|
145
162
|
end
|
data/lib/toys/utils/terminal.rb
CHANGED
@@ -55,6 +55,12 @@ module Toys
|
|
55
55
|
# * An array of ANSI codes as integers.
|
56
56
|
#
|
57
57
|
class Terminal
|
58
|
+
##
|
59
|
+
# Fatal terminal error.
|
60
|
+
#
|
61
|
+
class TerminalError < ::StandardError
|
62
|
+
end
|
63
|
+
|
58
64
|
## ANSI style code to clear styles
|
59
65
|
CLEAR_CODE = "\e[0m"
|
60
66
|
|
@@ -207,23 +213,29 @@ module Toys
|
|
207
213
|
# Confirm with the user.
|
208
214
|
#
|
209
215
|
# @param [String] prompt Prompt string. Defaults to `"Proceed?"`.
|
210
|
-
# @param [Boolean] default Default value
|
216
|
+
# @param [Boolean,nil] default Default value, or `nil` for no default.
|
217
|
+
# Uses `nil` if not specified.
|
211
218
|
# @return [Boolean]
|
212
219
|
#
|
213
|
-
def confirm(prompt = "Proceed?", default:
|
214
|
-
y = default ? "Y" : "y"
|
215
|
-
n = default ? "n" : "N"
|
220
|
+
def confirm(prompt = "Proceed?", default: nil)
|
221
|
+
y = default == true ? "Y" : "y"
|
222
|
+
n = default == false ? "n" : "N"
|
216
223
|
write("#{prompt} (#{y}/#{n}) ")
|
217
|
-
resp = input.gets
|
224
|
+
resp = input.gets
|
218
225
|
case resp
|
219
226
|
when /^y/i
|
220
227
|
true
|
221
228
|
when /^n/i
|
222
229
|
false
|
223
|
-
when
|
230
|
+
when nil
|
231
|
+
raise TerminalError, "Cannot confirm because the input stream is at eof." if default.nil?
|
224
232
|
default
|
225
233
|
else
|
226
|
-
|
234
|
+
if !resp.strip.empty? || default.nil?
|
235
|
+
confirm("Please answer \"y\" or \"n\"")
|
236
|
+
else
|
237
|
+
default
|
238
|
+
end
|
227
239
|
end
|
228
240
|
end
|
229
241
|
|
metadata
CHANGED
@@ -1,99 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toys-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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-07-
|
11
|
+
date: 2018-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: highline
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
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: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: minitest
|
28
|
+
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '5.11'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '5.11'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest-
|
42
|
+
name: minitest-focus
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '1.1'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '1.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: minitest-rg
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '5.2'
|
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:
|
68
|
+
version: '5.2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rubocop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.57.2
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.57.2
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: yard
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 0.9.14
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 0.9.14
|
97
97
|
description: Toys-Core is the command line tool framework underlying Toys. It can
|
98
98
|
be used to create command line binaries using the internal Toys APIs.
|
99
99
|
email:
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/toys/standard_middleware/show_root_version.rb
|
132
132
|
- lib/toys/standard_mixins/exec.rb
|
133
133
|
- lib/toys/standard_mixins/fileutils.rb
|
134
|
+
- lib/toys/standard_mixins/gems.rb
|
134
135
|
- lib/toys/standard_mixins/highline.rb
|
135
136
|
- lib/toys/standard_mixins/terminal.rb
|
136
137
|
- lib/toys/template.rb
|