toys-core 0.3.6 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/toys-core.rb +20 -5
- data/lib/toys/cli.rb +39 -32
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/{tool → definition}/acceptor.rb +21 -15
- data/lib/toys/{utils/line_output.rb → definition/alias.rb} +47 -59
- data/lib/toys/{tool/arg_definition.rb → definition/arg.rb} +17 -7
- data/lib/toys/{tool/flag_definition.rb → definition/flag.rb} +19 -9
- data/lib/toys/definition/tool.rb +574 -0
- data/lib/toys/dsl/arg.rb +118 -0
- data/lib/toys/dsl/flag.rb +132 -0
- data/lib/toys/dsl/tool.rb +521 -0
- data/lib/toys/errors.rb +2 -2
- data/lib/toys/helpers.rb +3 -3
- data/lib/toys/helpers/exec.rb +31 -25
- data/lib/toys/helpers/fileutils.rb +8 -2
- data/lib/toys/helpers/highline.rb +8 -1
- data/lib/toys/{alias.rb → helpers/terminal.rb} +44 -53
- data/lib/toys/input_file.rb +61 -0
- data/lib/toys/loader.rb +87 -77
- data/lib/toys/middleware.rb +3 -3
- data/lib/toys/middleware/add_verbosity_flags.rb +22 -20
- data/lib/toys/middleware/base.rb +53 -5
- data/lib/toys/middleware/handle_usage_errors.rb +9 -12
- data/lib/toys/middleware/set_default_descriptions.rb +6 -7
- data/lib/toys/middleware/show_help.rb +71 -67
- data/lib/toys/middleware/show_root_version.rb +9 -9
- data/lib/toys/runner.rb +157 -0
- data/lib/toys/template.rb +4 -3
- data/lib/toys/templates.rb +2 -2
- data/lib/toys/templates/clean.rb +2 -2
- data/lib/toys/templates/gem_build.rb +5 -5
- data/lib/toys/templates/minitest.rb +2 -2
- data/lib/toys/templates/rubocop.rb +2 -2
- data/lib/toys/templates/yardoc.rb +2 -2
- data/lib/toys/tool.rb +168 -625
- data/lib/toys/utils/exec.rb +19 -18
- data/lib/toys/utils/gems.rb +140 -0
- data/lib/toys/utils/help_text.rb +25 -20
- data/lib/toys/utils/terminal.rb +412 -0
- data/lib/toys/utils/wrappable_string.rb +3 -1
- metadata +15 -24
- data/lib/toys/config_dsl.rb +0 -699
- data/lib/toys/context.rb +0 -290
- data/lib/toys/helpers/spinner.rb +0 -142
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f7ff775c645d4bbd1906fab469307dcf06852e83d9fa02aba978fd0db53af21
|
4
|
+
data.tar.gz: 408ffcc9b47eff78b05228d811e2a32932a56eebe8e64381a5a96ce1c0e22caf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4969720705d06c492e7083dbd5d139b71ef3f3e260980acca8ec33771b4ee06b90e8138c341984681ff53a747fcdb256fffcbe412d30d64c9a0b32a82b0975ac
|
7
|
+
data.tar.gz: 4db5eed3cc44658511b14d017a3afac43daafc397e3094c1955ae08a95b60886673cfa2196b269a06b9c534f4614300573bf33cc2b43a39981c2bd4500c19cd6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.3.7 / 2018-05-30
|
4
|
+
|
5
|
+
* CHANGED: Execution runs in the same scope as the DSL, which lets us use normal methods instead of helper-blocks.
|
6
|
+
* CHANGED: Renamed "script" to "run", and allow setting of runnable by defining a "run" method
|
7
|
+
* CHANGED: Set up a constant scope for each config file, to make constant lookup make sense.
|
8
|
+
* CHANGED: Removed run_toys and dropped EXIT_ON_NONZERO_STATUS key in favor of using cli directly.
|
9
|
+
* CHANGED: Renamed definition_path to source_path
|
10
|
+
* CHANGED: LineOutput util changed to a simple Terminal util, and folded spinner into it.
|
11
|
+
* CHANGED: Removed spinner helper and added terminal helper.
|
12
|
+
* CHANGED: Organized DSL and definition classes
|
13
|
+
* ADDED: Helper modules scoped to the tool hierarchy
|
14
|
+
* ADDED: Utility that installs and activates third-party gems.
|
15
|
+
|
3
16
|
### 0.3.6 / 2018-05-21
|
4
17
|
|
5
18
|
* CHANGED: Renamed show_version middleware to show_root_version.
|
data/lib/toys-core.rb
CHANGED
@@ -27,8 +27,6 @@
|
|
27
27
|
# POSSIBILITY OF SUCH DAMAGE.
|
28
28
|
;
|
29
29
|
|
30
|
-
gem "highline", "~> 1.7"
|
31
|
-
|
32
30
|
##
|
33
31
|
# Toys is a Ruby library and command line tool that lets you build your own
|
34
32
|
# command line suite of tools (with commands and subcommands) using a Ruby DSL.
|
@@ -40,17 +38,34 @@ module Toys
|
|
40
38
|
# Namespace for common utility classes.
|
41
39
|
#
|
42
40
|
module Utils; end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Namespace for object definition classes.
|
44
|
+
#
|
45
|
+
module Definition; end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Namespace for DSL classes.
|
49
|
+
#
|
50
|
+
module DSL; end
|
43
51
|
end
|
44
52
|
|
45
|
-
require "toys/alias"
|
46
53
|
require "toys/cli"
|
47
|
-
require "toys/config_dsl"
|
48
|
-
require "toys/context"
|
49
54
|
require "toys/core_version"
|
55
|
+
require "toys/definition/acceptor"
|
56
|
+
require "toys/definition/alias"
|
57
|
+
require "toys/definition/arg"
|
58
|
+
require "toys/definition/flag"
|
59
|
+
require "toys/definition/tool"
|
60
|
+
require "toys/dsl/arg"
|
61
|
+
require "toys/dsl/flag"
|
62
|
+
require "toys/dsl/tool"
|
50
63
|
require "toys/errors"
|
51
64
|
require "toys/helpers"
|
65
|
+
require "toys/input_file"
|
52
66
|
require "toys/loader"
|
53
67
|
require "toys/middleware"
|
68
|
+
require "toys/runner"
|
54
69
|
require "toys/template"
|
55
70
|
require "toys/templates"
|
56
71
|
require "toys/tool"
|
data/lib/toys/cli.rb
CHANGED
@@ -28,9 +28,8 @@
|
|
28
28
|
;
|
29
29
|
|
30
30
|
require "logger"
|
31
|
-
require "highline"
|
32
31
|
|
33
|
-
require "toys/utils/
|
32
|
+
require "toys/utils/terminal"
|
34
33
|
|
35
34
|
module Toys
|
36
35
|
##
|
@@ -99,7 +98,7 @@ module Toys
|
|
99
98
|
@loader = Loader.new(
|
100
99
|
index_file_name: index_file_name,
|
101
100
|
preload_file_name: preload_file_name,
|
102
|
-
middleware_stack: middleware_stack
|
101
|
+
middleware_stack: @middleware_stack
|
103
102
|
)
|
104
103
|
@error_handler = error_handler || DefaultErrorHandler.new
|
105
104
|
end
|
@@ -209,10 +208,15 @@ module Toys
|
|
209
208
|
# @return [Integer] The resulting status code
|
210
209
|
#
|
211
210
|
def run(*args, verbosity: 0)
|
212
|
-
|
211
|
+
tool_definition, remaining = ContextualError.capture("Error finding tool definition") do
|
213
212
|
@loader.lookup(args.flatten)
|
214
213
|
end
|
215
|
-
|
214
|
+
ContextualError.capture_path(
|
215
|
+
"Error during tool execution!", tool_definition.source_path,
|
216
|
+
tool_name: tool_definition.full_name, tool_args: remaining
|
217
|
+
) do
|
218
|
+
Runner.new(self, tool_definition).run(remaining, verbosity: verbosity)
|
219
|
+
end
|
216
220
|
rescue ContextualError => e
|
217
221
|
@error_handler.call(e)
|
218
222
|
end
|
@@ -247,16 +251,20 @@ module Toys
|
|
247
251
|
##
|
248
252
|
# Create an error handler.
|
249
253
|
#
|
250
|
-
# @param [IO
|
254
|
+
# @param [IO] output Where to write errors. Default is `$stderr`.
|
251
255
|
#
|
252
|
-
def initialize(
|
253
|
-
@
|
256
|
+
def initialize(output = $stderr)
|
257
|
+
@terminal = Utils::Terminal.new(output: output)
|
254
258
|
end
|
255
259
|
|
256
|
-
##
|
260
|
+
##
|
261
|
+
# The error handler routine. Prints out the error message and backtrace.
|
262
|
+
#
|
263
|
+
# @param [Exception] error The error that occurred.
|
264
|
+
#
|
257
265
|
def call(error)
|
258
|
-
@
|
259
|
-
@
|
266
|
+
@terminal.puts(cause_string(error.cause))
|
267
|
+
@terminal.puts(context_string(error), :bold)
|
260
268
|
-1
|
261
269
|
end
|
262
270
|
|
@@ -315,13 +323,14 @@ module Toys
|
|
315
323
|
end
|
316
324
|
|
317
325
|
##
|
318
|
-
# Returns a default logger that logs to
|
326
|
+
# Returns a default logger that logs to `$stderr`.
|
319
327
|
#
|
320
328
|
# @param [IO] stream Stream to write to. Defaults to `$stderr`.
|
321
329
|
# @return [Logger]
|
322
330
|
#
|
323
331
|
def default_logger(stream = $stderr)
|
324
332
|
logger = ::Logger.new(stream)
|
333
|
+
terminal = Utils::Terminal.new(output: stream)
|
325
334
|
logger.formatter = proc do |severity, time, _progname, msg|
|
326
335
|
msg_str =
|
327
336
|
case msg
|
@@ -332,7 +341,7 @@ module Toys
|
|
332
341
|
else
|
333
342
|
msg.inspect
|
334
343
|
end
|
335
|
-
format_log(
|
344
|
+
format_log(terminal, time, severity, msg_str)
|
336
345
|
end
|
337
346
|
logger.level = ::Logger::WARN
|
338
347
|
logger
|
@@ -340,27 +349,25 @@ module Toys
|
|
340
349
|
|
341
350
|
private
|
342
351
|
|
343
|
-
def format_log(
|
352
|
+
def format_log(terminal, time, severity, msg)
|
344
353
|
timestr = time.strftime("%Y-%m-%d %H:%M:%S")
|
345
354
|
header = format("[%s %5s]", timestr, severity)
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
end
|
363
|
-
"#{header} #{msg}\n"
|
355
|
+
styled_header =
|
356
|
+
case severity
|
357
|
+
when "FATAL"
|
358
|
+
terminal.apply_styles(header, :bright_magenta, :bold, :underline)
|
359
|
+
when "ERROR"
|
360
|
+
terminal.apply_styles(header, :bright_red, :bold)
|
361
|
+
when "WARN"
|
362
|
+
terminal.apply_styles(header, :bright_yellow)
|
363
|
+
when "INFO"
|
364
|
+
terminal.apply_styles(header, :bright_cyan)
|
365
|
+
when "DEBUG"
|
366
|
+
terminal.apply_styles(header, :white)
|
367
|
+
else
|
368
|
+
header
|
369
|
+
end
|
370
|
+
"#{styled_header} #{msg}\n"
|
364
371
|
end
|
365
372
|
end
|
366
373
|
end
|
data/lib/toys/core_version.rb
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
;
|
29
29
|
|
30
30
|
module Toys
|
31
|
-
|
31
|
+
module Definition
|
32
32
|
##
|
33
33
|
# An Acceptor validates and converts arguments. It is designed to be
|
34
34
|
# compatible with the OptionParser accept mechanism.
|
@@ -47,16 +47,19 @@ module Toys
|
|
47
47
|
##
|
48
48
|
# Create a base acceptor.
|
49
49
|
#
|
50
|
-
# The
|
51
|
-
# arguments). You may subclass this object and
|
50
|
+
# The base acceptor does not do any validation (i.e. it accepts all
|
51
|
+
# arguments). You may subclass this object and override the {#match}
|
52
52
|
# method to change this behavior.
|
53
53
|
#
|
54
|
-
# The
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
54
|
+
# The base acceptor lets you provide a converter as a proc. The proc
|
55
|
+
# should take one or more arguments, the first of which is the entire
|
56
|
+
# argument string, and the others of which are any additional values
|
57
|
+
# returned from validation. The converter should return the final
|
58
|
+
# converted value of the argument.
|
59
|
+
#
|
60
|
+
# The converter may be provided either as a proc in the `converter`
|
61
|
+
# parameter, or as a block. If neither is provided, the base acceptor
|
62
|
+
# performs no conversion and uses the argument string.
|
60
63
|
#
|
61
64
|
# @param [String] name A visible name for the acceptor, shown in help.
|
62
65
|
# @param [Proc] converter A converter function. May also be given as a
|
@@ -105,7 +108,8 @@ module Toys
|
|
105
108
|
end
|
106
109
|
|
107
110
|
##
|
108
|
-
# Convert the given input.
|
111
|
+
# Convert the given input. Uses the converter provided to this object's
|
112
|
+
# constructor. Subclasses may also override this method.
|
109
113
|
#
|
110
114
|
# @param [String] str Original argument string
|
111
115
|
# @param [Object...] extra Zero or more additional arguments comprising
|
@@ -123,10 +127,11 @@ module Toys
|
|
123
127
|
#
|
124
128
|
class PatternAcceptor < Acceptor
|
125
129
|
##
|
126
|
-
# Create
|
130
|
+
# Create a pattern acceptor.
|
127
131
|
#
|
128
132
|
# You must provide a regular expression as a validator. You may also
|
129
|
-
# provide a converter.
|
133
|
+
# provide a converter proc. See {Toys::Definition::Acceptor} for details
|
134
|
+
# on the converter.
|
130
135
|
#
|
131
136
|
# @param [String] name A visible name for the acceptor, shown in help.
|
132
137
|
# @param [Regexp] regex Regular expression defining value values.
|
@@ -140,7 +145,7 @@ module Toys
|
|
140
145
|
end
|
141
146
|
|
142
147
|
##
|
143
|
-
# Overrides match to
|
148
|
+
# Overrides {Toys::Definition::Acceptor#match} to use the given regex.
|
144
149
|
#
|
145
150
|
def match(str)
|
146
151
|
@regex.match(str)
|
@@ -173,14 +178,15 @@ module Toys
|
|
173
178
|
end
|
174
179
|
|
175
180
|
##
|
176
|
-
# Overrides match to find the value.
|
181
|
+
# Overrides {Toys::Definition::Acceptor#match} to find the value.
|
177
182
|
#
|
178
183
|
def match(str)
|
179
184
|
@values.find { |s, _e| s == str }
|
180
185
|
end
|
181
186
|
|
182
187
|
##
|
183
|
-
# Overrides convert to return the original
|
188
|
+
# Overrides {Toys::Definition::Acceptor#convert} to return the original
|
189
|
+
# element.
|
184
190
|
#
|
185
191
|
def convert(_str, elem)
|
186
192
|
elem
|
@@ -27,95 +27,83 @@
|
|
27
27
|
# POSSIBILITY OF SUCH DAMAGE.
|
28
28
|
;
|
29
29
|
|
30
|
-
require "highline"
|
31
|
-
|
32
30
|
module Toys
|
33
|
-
module
|
31
|
+
module Definition
|
34
32
|
##
|
35
|
-
#
|
33
|
+
# An alias is a name that refers to another name.
|
36
34
|
#
|
37
|
-
class
|
35
|
+
class Alias
|
38
36
|
##
|
39
|
-
# Create a
|
37
|
+
# Create a new alias.
|
40
38
|
#
|
41
|
-
# @param [
|
39
|
+
# @param [Array<String>] full_name The name of the alias.
|
40
|
+
# @param [String,Array<String>] target The name of the target. May either
|
41
|
+
# be a local reference (a single string) or a global reference (an
|
42
|
+
# array of strings)
|
42
43
|
#
|
43
|
-
def initialize(
|
44
|
-
@
|
45
|
-
|
46
|
-
|
47
|
-
if styled.nil?
|
48
|
-
sink.respond_to?(:tty?) && sink.tty?
|
44
|
+
def initialize(loader, full_name, target, priority)
|
45
|
+
@target_name =
|
46
|
+
if target.is_a?(::String)
|
47
|
+
full_name[0..-2] + [target]
|
49
48
|
else
|
50
|
-
|
49
|
+
target.dup
|
51
50
|
end
|
52
|
-
@
|
51
|
+
@target_name.freeze
|
52
|
+
@full_name = full_name.dup.freeze
|
53
|
+
@priority = priority
|
54
|
+
@tool_class = DSL::Tool.new_class(@full_name, priority, loader)
|
53
55
|
end
|
54
56
|
|
55
57
|
##
|
56
|
-
#
|
57
|
-
# @return [
|
58
|
+
# Return the tool class.
|
59
|
+
# @return [Class]
|
58
60
|
#
|
59
|
-
attr_reader :
|
61
|
+
attr_reader :tool_class
|
60
62
|
|
61
63
|
##
|
62
|
-
#
|
63
|
-
#
|
64
|
+
# Return the name of the tool as an array of strings.
|
65
|
+
# This array may not be modified.
|
66
|
+
# @return [Array<String>]
|
64
67
|
#
|
65
|
-
|
68
|
+
attr_reader :full_name
|
66
69
|
|
67
70
|
##
|
68
|
-
#
|
69
|
-
# @return [Integer
|
71
|
+
# Return the priority of this alias.
|
72
|
+
# @return [Integer]
|
70
73
|
#
|
71
|
-
attr_reader :
|
74
|
+
attr_reader :priority
|
72
75
|
|
73
76
|
##
|
74
|
-
#
|
75
|
-
#
|
76
|
-
# @
|
77
|
-
# @param [Symbol...] styles Styles to apply to the entire line.
|
77
|
+
# Return the name of the target as an array of strings.
|
78
|
+
# This array may not be modified.
|
79
|
+
# @return [Array<String>]
|
78
80
|
#
|
79
|
-
|
80
|
-
str = @buffer + apply_styles(str, styles)
|
81
|
-
@buffer = ""
|
82
|
-
case sink
|
83
|
-
when ::Logger
|
84
|
-
sink.log(log_level, str)
|
85
|
-
when ::IO
|
86
|
-
sink.puts(str)
|
87
|
-
sink.flush
|
88
|
-
end
|
89
|
-
self
|
90
|
-
end
|
81
|
+
attr_reader :target_name
|
91
82
|
|
92
83
|
##
|
93
|
-
#
|
84
|
+
# Returns the local name of this tool.
|
85
|
+
# @return [String]
|
94
86
|
#
|
95
|
-
def
|
96
|
-
|
87
|
+
def simple_name
|
88
|
+
full_name.last
|
97
89
|
end
|
98
90
|
|
99
91
|
##
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
# @param [String] str The line to write
|
104
|
-
# @param [Symbol...] styles Styles to apply to the partial line.
|
92
|
+
# Returns a displayable name of this tool, generally the full name
|
93
|
+
# delimited by spaces.
|
94
|
+
# @return [String]
|
105
95
|
#
|
106
|
-
def
|
107
|
-
|
108
|
-
self
|
96
|
+
def display_name
|
97
|
+
full_name.join(" ")
|
109
98
|
end
|
110
99
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
100
|
+
##
|
101
|
+
# Returns a displayable name of the target, generally the full name
|
102
|
+
# delimited by spaces.
|
103
|
+
# @return [String]
|
104
|
+
#
|
105
|
+
def display_target
|
106
|
+
target_name.join(" ")
|
119
107
|
end
|
120
108
|
end
|
121
109
|
end
|