toys-core 0.3.2 → 0.3.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 +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/toys/config_dsl.rb +26 -23
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/helpers.rb +3 -1
- data/lib/toys/helpers/{file_utils.rb → fileutils.rb} +7 -2
- data/lib/toys/helpers/highline.rb +127 -0
- data/lib/toys/helpers/spinner.rb +136 -0
- data/lib/toys/middleware/add_verbosity_switches.rb +2 -2
- data/lib/toys/middleware/handle_usage_errors.rb +5 -1
- data/lib/toys/middleware/show_usage.rb +11 -7
- data/lib/toys/middleware/show_version.rb +1 -1
- data/lib/toys/templates/clean.rb +1 -1
- data/lib/toys/templates/gem_build.rb +3 -1
- data/lib/toys/templates/minitest.rb +2 -2
- data/lib/toys/tool.rb +258 -99
- data/lib/toys/utils/module_lookup.rb +17 -5
- data/lib/toys/utils/usage.rb +101 -47
- data/lib/toys/utils/wrappable_string.rb +92 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ebb136d89b19617cfdaf8de9c870cce070857748abd208ab8faa4896b7e7b36
|
4
|
+
data.tar.gz: eb079b488d1da544e5f31ab0fe0f9730d77d6878549c673bc6ba4711a5d6c295
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 864c7bc16399227e29e013372611ed70df77339185593d3830a31a5092e7dea6540d62ed83704e23ce5d78410ce2b4e34ae5ce9f709d67d8bb82e5075ed09cc3
|
7
|
+
data.tar.gz: 5eb3e60cefb50d7a289ef2283a91574ede820bf1d2bb5769d8038d60d760e999f36e49882899c06f2de6dd37a23d828ee25bd1e2a0764e11cc0e31553764368c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.3.3 / 2018-05-09
|
4
|
+
|
5
|
+
* CHANGED: Renamed file_utils helper to fileutils.
|
6
|
+
* CHANGED: Renamed doc: parameter to docs:
|
7
|
+
* CHANGED: SwitchDefinition has separate fields for acceptor and docs.
|
8
|
+
* CHANGED: Description and long description are now arrays of strings.
|
9
|
+
* FIXED: Documentation strings that begin with "--" no longer cause problems.
|
10
|
+
* ADDED: Highline helper
|
11
|
+
* ADDED: Spinner helper
|
12
|
+
* ADDED: WrappableString for descriptions and docs
|
13
|
+
* IMPROVED: Usage can now customize the left column width and indent
|
14
|
+
* IMPROVED: Newlines in documentation are properly indented
|
15
|
+
|
3
16
|
### 0.3.2 / 2018-05-07
|
4
17
|
|
5
18
|
* CHANGED: Split core engine out into "toys-core" from the "toys" gem.
|
data/lib/toys/config_dsl.rb
CHANGED
@@ -164,12 +164,12 @@ module Toys
|
|
164
164
|
# Set the long description for the current tool. The long description is
|
165
165
|
# displayed in the usage documentation for the tool itself.
|
166
166
|
#
|
167
|
-
# @param [String]
|
167
|
+
# @param [String,Toys::Utils::WrappableString...] strs The long description
|
168
168
|
#
|
169
|
-
def long_desc(
|
169
|
+
def long_desc(*strs)
|
170
170
|
return self if _cur_tool.nil?
|
171
171
|
_cur_tool.definition_path = @path
|
172
|
-
_cur_tool.long_desc =
|
172
|
+
_cur_tool.long_desc = strs
|
173
173
|
self
|
174
174
|
end
|
175
175
|
|
@@ -178,12 +178,12 @@ module Toys
|
|
178
178
|
# displayed with the tool in a command list. You may also use the
|
179
179
|
# equivalent method `short_desc`.
|
180
180
|
#
|
181
|
-
# @param [String]
|
181
|
+
# @param [String,Toys::Utils::WrappableString...] strs The short description
|
182
182
|
#
|
183
|
-
def desc(
|
183
|
+
def desc(*strs)
|
184
184
|
return self if _cur_tool.nil?
|
185
185
|
_cur_tool.definition_path = @path
|
186
|
-
_cur_tool.desc =
|
186
|
+
_cur_tool.desc = strs
|
187
187
|
self
|
188
188
|
end
|
189
189
|
alias short_desc desc
|
@@ -200,8 +200,9 @@ module Toys
|
|
200
200
|
# @param [Object] default The default value. This is the value that will
|
201
201
|
# be set in the context if this switch is not provided on the command
|
202
202
|
# line. Defaults to `nil`.
|
203
|
-
# @param [String,
|
204
|
-
#
|
203
|
+
# @param [String,Toys::Utils::WrappableString,
|
204
|
+
# Array<String,Toys::Utils::WrappableString>] docs Documentation for
|
205
|
+
# the switch. Defaults to empty array.
|
205
206
|
# @param [Boolean] only_unique If true, any switches that are already
|
206
207
|
# defined in this tool are removed from this switch. For example, if
|
207
208
|
# an earlier switch uses `-a`, and this switch wants to use both
|
@@ -214,11 +215,11 @@ module Toys
|
|
214
215
|
# value. i.e. the default is effectively `-> (val, _prev) { val }`.
|
215
216
|
#
|
216
217
|
def switch(key, *switches,
|
217
|
-
accept: nil, default: nil,
|
218
|
+
accept: nil, default: nil, docs: nil, only_unique: false, handler: nil)
|
218
219
|
return self if _cur_tool.nil?
|
219
220
|
_cur_tool.definition_path = @path
|
220
221
|
_cur_tool.add_switch(key, *switches,
|
221
|
-
accept: accept, default: default,
|
222
|
+
accept: accept, default: default, docs: docs,
|
222
223
|
only_unique: only_unique, handler: handler)
|
223
224
|
self
|
224
225
|
end
|
@@ -231,13 +232,14 @@ module Toys
|
|
231
232
|
# @param [Symbol] key The key to use to retrieve the value from the
|
232
233
|
# execution context.
|
233
234
|
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
234
|
-
# @param [String,
|
235
|
-
#
|
235
|
+
# @param [String,Toys::Utils::WrappableString,
|
236
|
+
# Array<String,Toys::Utils::WrappableString>] docs Documentation for the
|
237
|
+
# arg. Defaults to empty array.
|
236
238
|
#
|
237
|
-
def required_arg(key, accept: nil,
|
239
|
+
def required_arg(key, accept: nil, docs: nil)
|
238
240
|
return self if _cur_tool.nil?
|
239
241
|
_cur_tool.definition_path = @path
|
240
|
-
_cur_tool.add_required_arg(key, accept: accept,
|
242
|
+
_cur_tool.add_required_arg(key, accept: accept, docs: docs)
|
241
243
|
self
|
242
244
|
end
|
243
245
|
|
@@ -253,13 +255,14 @@ module Toys
|
|
253
255
|
# @param [Object] default The default value. This is the value that will
|
254
256
|
# be set in the context if this argument is not provided on the command
|
255
257
|
# line. Defaults to `nil`.
|
256
|
-
# @param [String,
|
257
|
-
#
|
258
|
+
# @param [String,Toys::Utils::WrappableString,
|
259
|
+
# Array<String,Toys::Utils::WrappableString>] docs Documentation for the
|
260
|
+
# arg. Defaults to empty array.
|
258
261
|
#
|
259
|
-
def optional_arg(key, accept: nil, default: nil,
|
262
|
+
def optional_arg(key, accept: nil, default: nil, docs: nil)
|
260
263
|
return self if _cur_tool.nil?
|
261
264
|
_cur_tool.definition_path = @path
|
262
|
-
_cur_tool.add_optional_arg(key, accept: accept, default: default,
|
265
|
+
_cur_tool.add_optional_arg(key, accept: accept, default: default, docs: docs)
|
263
266
|
self
|
264
267
|
end
|
265
268
|
|
@@ -274,14 +277,14 @@ module Toys
|
|
274
277
|
# @param [Object] default The default value. This is the value that will
|
275
278
|
# be set in the context if no unmatched arguments are provided on the
|
276
279
|
# command line. Defaults to the empty array `[]`.
|
277
|
-
# @param [String,
|
278
|
-
#
|
279
|
-
#
|
280
|
+
# @param [String,Toys::Utils::WrappableString,
|
281
|
+
# Array<String,Toys::Utils::WrappableString>] docs Documentation for the
|
282
|
+
# args. Defaults to empty array.
|
280
283
|
#
|
281
|
-
def remaining_args(key, accept: nil, default: [],
|
284
|
+
def remaining_args(key, accept: nil, default: [], docs: nil)
|
282
285
|
return self if _cur_tool.nil?
|
283
286
|
_cur_tool.definition_path = @path
|
284
|
-
_cur_tool.set_remaining_args(key, accept: accept, default: default,
|
287
|
+
_cur_tool.set_remaining_args(key, accept: accept, default: default, docs: docs)
|
285
288
|
self
|
286
289
|
end
|
287
290
|
|
data/lib/toys/core_version.rb
CHANGED
data/lib/toys/helpers.rb
CHANGED
@@ -40,7 +40,9 @@ module Toys
|
|
40
40
|
# Currently recognized module names are:
|
41
41
|
#
|
42
42
|
# * `:exec` : Methods to help execute subcommands.
|
43
|
-
# * `:
|
43
|
+
# * `:fileutils` : The FileUtils standard library methods.
|
44
|
+
# * `:highline` : Methods from the highline gem.
|
45
|
+
# * `:spinner` : Displays a spinner on the terminal.
|
44
46
|
#
|
45
47
|
# @param [String,Symbol] name Name of the helper module to return
|
46
48
|
# @return [Module,nil] The module, or `nil` if not found
|
@@ -32,8 +32,13 @@ require "fileutils"
|
|
32
32
|
module Toys
|
33
33
|
module Helpers
|
34
34
|
##
|
35
|
-
#
|
35
|
+
# A module that provides all methods in the "fileutils" standard library.
|
36
36
|
#
|
37
|
-
|
37
|
+
module Fileutils
|
38
|
+
## @private
|
39
|
+
def self.extend_object(obj)
|
40
|
+
obj.extend(::FileUtils)
|
41
|
+
end
|
42
|
+
end
|
38
43
|
end
|
39
44
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Copyright 2018 Daniel Azuma
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
+
# contributors to this software, may be used to endorse or promote products
|
15
|
+
# derived from this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
;
|
29
|
+
|
30
|
+
gem "highline", "~> 1.7"
|
31
|
+
|
32
|
+
require "highline"
|
33
|
+
|
34
|
+
module Toys
|
35
|
+
module Helpers
|
36
|
+
##
|
37
|
+
# A module that provides access to highline.
|
38
|
+
#
|
39
|
+
module Highline
|
40
|
+
##
|
41
|
+
# Returns a global highline instance
|
42
|
+
# @return [::HighLine]
|
43
|
+
#
|
44
|
+
def self.highline
|
45
|
+
@highline ||= ::HighLine.new
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Returns a global highline instance
|
50
|
+
# @return [::HighLine]
|
51
|
+
#
|
52
|
+
def highline
|
53
|
+
Highline.highline
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:agree HighLine#agree
|
58
|
+
#
|
59
|
+
def agree(*args, &block)
|
60
|
+
highline.agree(*args, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:ask HighLine#ask
|
65
|
+
#
|
66
|
+
def ask(*args, &block)
|
67
|
+
highline.ask(*args, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:choose HighLine#choose
|
72
|
+
#
|
73
|
+
def choose(*args, &block)
|
74
|
+
highline.choose(*args, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:list HighLine#list
|
79
|
+
#
|
80
|
+
def list(*args, &block)
|
81
|
+
highline.list(*args, &block)
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:say HighLine#say
|
86
|
+
#
|
87
|
+
def say(*args, &block)
|
88
|
+
highline.say(*args, &block)
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine.color HighLine.color
|
93
|
+
#
|
94
|
+
def color(*args, &block)
|
95
|
+
::HighLine.color(*args, &block)
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine.color_code HighLine.color_code
|
100
|
+
#
|
101
|
+
def color_code(*args, &block)
|
102
|
+
::HighLine.color_code(*args, &block)
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine.uncolor HighLine.uncolor
|
107
|
+
#
|
108
|
+
def uncolor(*args, &block)
|
109
|
+
::HighLine.uncolor(*args, &block)
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:indent HighLine#indent
|
114
|
+
#
|
115
|
+
def indent(*args, &block)
|
116
|
+
highline.indent(*args, &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# @see https://www.rubydoc.info/gems/highline/HighLine:newline HighLine#newline
|
121
|
+
#
|
122
|
+
def newline(*args, &block)
|
123
|
+
highline.newline(*args, &block)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# Copyright 2018 Daniel Azuma
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
14
|
+
# contributors to this software, may be used to endorse or promote products
|
15
|
+
# derived from this software without specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
21
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
22
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
23
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
26
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
;
|
29
|
+
|
30
|
+
require "monitor"
|
31
|
+
|
32
|
+
module Toys
|
33
|
+
module Helpers
|
34
|
+
##
|
35
|
+
# A module that provides a spinner output.
|
36
|
+
#
|
37
|
+
module Spinner
|
38
|
+
##
|
39
|
+
# Default length of a single frame, in seconds.
|
40
|
+
# @return [Float]
|
41
|
+
#
|
42
|
+
DEFAULT_FRAME_LENGTH = 0.1
|
43
|
+
|
44
|
+
##
|
45
|
+
# Default set of frames.
|
46
|
+
# @return [Array<String,Array(String,Integer)>]
|
47
|
+
#
|
48
|
+
DEFAULT_FRAMES = ["-", "\\", "|", "/"].freeze
|
49
|
+
|
50
|
+
##
|
51
|
+
# Display a spinner during a task. You should provide a block that
|
52
|
+
# performs the long-running task. While the block is executing, a
|
53
|
+
# spinner will be displayed.
|
54
|
+
#
|
55
|
+
# @param [String] leading_text Optional leading string to display to the
|
56
|
+
# left of the spinner.
|
57
|
+
# @param [Float] frame_length Length of a single frame, in seconds.
|
58
|
+
# Defaults to {DEFAULT_FRAME_LENGTH}.
|
59
|
+
# @param [Array<String,Array<String>>] frames An array of frames. Each
|
60
|
+
# frame should be either a string, or a two-element array of string
|
61
|
+
# and integer, where the integer is the visible length of the frame
|
62
|
+
# on screen. The latter form should be used if the frame string
|
63
|
+
# contains non-printing characters such as ANSI escape codes.
|
64
|
+
# Defaults to {DEFAULT_FRAMES}.
|
65
|
+
# @param [IO] stream Stream to output the spinner to. Defaults to STDOUT.
|
66
|
+
# Note the spinner will be disabled if this stream is not a tty.
|
67
|
+
# @param [String] final_text Optional final string to display when the
|
68
|
+
# spinner is complete.
|
69
|
+
#
|
70
|
+
def spinner(leading_text: "",
|
71
|
+
frame_length: DEFAULT_FRAME_LENGTH,
|
72
|
+
frames: DEFAULT_FRAMES,
|
73
|
+
stream: $stdout,
|
74
|
+
final_text: "")
|
75
|
+
return nil unless block_given?
|
76
|
+
unless leading_text.empty?
|
77
|
+
stream.write(leading_text)
|
78
|
+
stream.flush
|
79
|
+
end
|
80
|
+
spin = SpinDriver.new(stream, frames, frame_length)
|
81
|
+
begin
|
82
|
+
yield
|
83
|
+
ensure
|
84
|
+
spin.stop
|
85
|
+
unless final_text.empty?
|
86
|
+
stream.write(final_text)
|
87
|
+
stream.flush
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
## @private
|
93
|
+
class SpinDriver
|
94
|
+
include ::MonitorMixin
|
95
|
+
|
96
|
+
def initialize(stream, frames, frame_length)
|
97
|
+
@stream = stream
|
98
|
+
@frames = frames.map { |f| f.is_a?(::Array) ? f : [f, f.size] }
|
99
|
+
@frame_length = frame_length
|
100
|
+
@cur_frame = 0
|
101
|
+
@stopping = false
|
102
|
+
@cond = new_cond
|
103
|
+
super()
|
104
|
+
@thread = @stream.tty? ? start_thread : nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def stop
|
108
|
+
synchronize do
|
109
|
+
@stopping = true
|
110
|
+
@cond.broadcast
|
111
|
+
end
|
112
|
+
@thread.join if @thread
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def start_thread
|
119
|
+
::Thread.new do
|
120
|
+
synchronize do
|
121
|
+
until @stopping
|
122
|
+
@stream.write(@frames[@cur_frame][0])
|
123
|
+
@stream.flush
|
124
|
+
@cond.wait(@frame_length)
|
125
|
+
size = @frames[@cur_frame][1]
|
126
|
+
@stream.write("\b" * size + " " * size + "\b" * size)
|
127
|
+
@cur_frame += 1
|
128
|
+
@cur_frame = 0 if @cur_frame >= @frames.size
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|