toys 0.3.6 → 0.3.7
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 +9 -0
- data/README.md +6 -5
- data/bin/toys +2 -0
- data/builtins/do.rb +4 -5
- data/builtins/system.rb +29 -15
- data/docs/guide.md +199 -23
- data/lib/toys.rb +5 -0
- data/lib/toys/standard_cli.rb +2 -2
- data/lib/toys/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7744684eb5fd0d03f650315fad4bb84bc433d0ce4e0529c82f6bf2ebcb60f9f5
|
4
|
+
data.tar.gz: 26c4d2e48917887441bd6bc03986110f7269bdd2b1f0098d1b9cd3a19a5b0248
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61445d45a25a6d64f9f2fc547e38589b7f49d8cdf08a07e7bff33b3687307bbeed4b7aa1f8528c2c91a6abf52c3bea86a79392d3d0bbf98652fe5fd2d526f693
|
7
|
+
data.tar.gz: a08b400babfecc9c6fd119447d37f62df645986b3d23e5ef381cbf7e05d766b3d1eebd97d0947bb7a8c7cd5b5f53c59aaca329f4bfbb4a8c0463520b11ca1dca
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
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: Removed spinner helper and added terminal helper.
|
10
|
+
* ADDED: Helper modules scoped to the tool hierarchy
|
11
|
+
|
3
12
|
### 0.3.6 / 2018-05-21
|
4
13
|
|
5
14
|
* CHANGED: Removed Context#new_cli and exposed Context#cli instead.
|
data/README.md
CHANGED
@@ -69,8 +69,8 @@ current directory. Copy the following into the file, and save it:
|
|
69
69
|
tool "greet" do
|
70
70
|
desc "My first tool!"
|
71
71
|
flag :whom, default: "world"
|
72
|
-
|
73
|
-
puts "Hello, #{
|
72
|
+
def run
|
73
|
+
puts "Hello, #{option(:whom)}!"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -107,9 +107,10 @@ various subtools, such as "version", are available under that namespace.
|
|
107
107
|
|
108
108
|
Toys provides a rich set of useful libraries for writing tools. It gives you a
|
109
109
|
logger and automatically provides flags to control verbosity of log output. It
|
110
|
-
includes
|
111
|
-
console-based interfaces, and
|
112
|
-
|
110
|
+
includes a simple library that you can use to produce styled output and basic
|
111
|
+
console-based interfaces, and another library that makes it easy to spawn and
|
112
|
+
control subprocesses. You can also take advantage of a variety of third-party
|
113
|
+
libraries such as Highline and TTY.
|
113
114
|
|
114
115
|
For a more detailed look at Toys, see the
|
115
116
|
{file:docs/tutorial.md Extended Tutorial} and the
|
data/bin/toys
CHANGED
data/builtins/do.rb
CHANGED
@@ -54,12 +54,11 @@ flag :delim, "-d", "--delim=VALUE",
|
|
54
54
|
|
55
55
|
remaining_args :args, desc: "A series of tools to run, separated by the delimiter"
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
.chunk { |arg| arg == delim ? :_separator : true }
|
57
|
+
def run
|
58
|
+
option(:args)
|
59
|
+
.chunk { |arg| arg == option(:delim) ? :_separator : true }
|
61
60
|
.each do |_, action|
|
62
|
-
code = run(action)
|
61
|
+
code = cli.run(action)
|
63
62
|
exit(code) unless code.zero?
|
64
63
|
end
|
65
64
|
end
|
data/builtins/system.rb
CHANGED
@@ -32,42 +32,56 @@ desc "A set of system commands for Toys"
|
|
32
32
|
long_desc "Contains tools that inspect, configure, and update Toys itself."
|
33
33
|
|
34
34
|
tool "version" do
|
35
|
-
desc "Print current Toys version
|
35
|
+
desc "Print the current Toys version"
|
36
36
|
|
37
|
-
|
37
|
+
def run
|
38
38
|
puts ::Toys::VERSION
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
tool "update" do
|
43
|
-
desc "Update Toys if a newer version is available
|
43
|
+
desc "Update Toys if a newer version is available"
|
44
44
|
|
45
45
|
long_desc "Checks rubygems for a newer version of Toys. If one is available, downloads" \
|
46
46
|
" and installs it."
|
47
47
|
|
48
48
|
flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
include :exec
|
51
|
+
include :terminal
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
version_info =
|
53
|
+
def run
|
54
|
+
configure_exec(exit_on_nonzero_status: true)
|
55
|
+
version_info = terminal.spinner(leading_text: "Checking rubygems for the latest release... ",
|
56
|
+
final_text: "Done.\n") do
|
57
|
+
capture(["gem", "query", "-q", "-r", "-e", "toys"])
|
58
|
+
end
|
56
59
|
if version_info =~ /toys\s\((.+)\)/
|
57
60
|
latest_version = ::Gem::Version.new($1)
|
58
61
|
cur_version = ::Gem::Version.new(::Toys::VERSION)
|
59
62
|
if latest_version > cur_version
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
+
prompt = "Update toys from #{cur_version} to #{latest_version}?"
|
64
|
+
exit(1) unless option(:yes) || confirm(prompt)
|
65
|
+
result = terminal.spinner(leading_text: "Installing Toys version #{latest_version}... ",
|
66
|
+
final_text: "Done.\n") do
|
67
|
+
exec(["gem", "install", "toys", "--version", latest_version],
|
68
|
+
out_to: :capture, err_to: :capture)
|
69
|
+
end
|
70
|
+
if result.error?
|
71
|
+
puts(result.captured_out + result.captured_err)
|
72
|
+
puts("Toys failed to install version #{latest_version}", :red, :bold)
|
73
|
+
exit(1)
|
74
|
+
end
|
75
|
+
puts("Toys successfully installed version #{latest_version}", :green, :bold)
|
63
76
|
elsif latest_version < cur_version
|
64
|
-
|
65
|
-
|
77
|
+
puts("Toys is already at experimental version #{cur_version}, which is later than" \
|
78
|
+
" the latest released version #{latest_version}",
|
79
|
+
:yellow, :bold)
|
66
80
|
else
|
67
|
-
|
81
|
+
puts("Toys is already at the latest version: #{latest_version}", :green, :bold)
|
68
82
|
end
|
69
83
|
else
|
70
|
-
|
84
|
+
puts("Could not get latest Toys version", :red, :bold)
|
71
85
|
exit(1)
|
72
86
|
end
|
73
87
|
end
|
data/docs/guide.md
CHANGED
@@ -14,34 +14,34 @@ This user's guide covers everything you need to know to use Toys effectively.
|
|
14
14
|
|
15
15
|
Toys is a command line *framework*. It provides a binary called `toys` along
|
16
16
|
with basic functions such as argument parsing and online help. You provide the
|
17
|
-
actual behavior of the toys binary by writing
|
17
|
+
actual behavior of the toys binary by writing **configuration files**.
|
18
18
|
|
19
19
|
Toys is a multi-command binary. You may define a collection of commands, called
|
20
|
-
|
21
|
-
`toys` binary. Tools are arranged in a hierarchy; a tool may be a
|
20
|
+
**tools**, which can be invoked by passing the tool name as an argument to the
|
21
|
+
`toys` binary. Tools are arranged in a hierarchy; a tool may be a **namespace**
|
22
22
|
that has *subtools*.
|
23
23
|
|
24
|
-
Tools may recognize command line arguments in the form of
|
25
|
-
|
26
|
-
arguments may be
|
24
|
+
Tools may recognize command line arguments in the form of **flags** and
|
25
|
+
**positional arguments**. Flags can optionally take **values**, while
|
26
|
+
positional arguments may be **required** or **optional**.
|
27
27
|
|
28
|
-
The configuration of a tool may define
|
29
|
-
for each command line argument. These descriptions are displayed in the
|
30
|
-
|
31
|
-
appear in different styles of help.
|
28
|
+
The configuration of a tool may define **descriptions**, for the tool itself,
|
29
|
+
and for each command line argument. These descriptions are displayed in the
|
30
|
+
tool's **online help** screen. Descriptions come in **long** and **short**
|
31
|
+
forms, which appear in different styles of help.
|
32
32
|
|
33
|
-
Toys searches for configuration in specifically-named
|
34
|
-
|
35
|
-
and in a
|
33
|
+
Toys searches for configuration in specifically-named **configuration files**
|
34
|
+
and **configuration directories**. It searches for these in the current
|
35
|
+
directory, its ancestors, and in a **configuration search path**.
|
36
36
|
|
37
37
|
Toys provides various features to help you write tools. This includes providing
|
38
|
-
a
|
39
|
-
can call, and
|
40
|
-
configuration.
|
38
|
+
a **logger** for each tool, **helper modules** that provide common functions a
|
39
|
+
tool can call, and **templates** which are prefabricated tools you can add to
|
40
|
+
your configuration.
|
41
41
|
|
42
|
-
Finally, Toys provides certain
|
42
|
+
Finally, Toys provides certain **built-in behavior**, including automatically
|
43
43
|
providing flags to display help screens and set verbosity. It also includes a
|
44
|
-
built-in namespace of
|
44
|
+
built-in namespace of **system tools** that let you inspect and configure the
|
45
45
|
Toys system itself.
|
46
46
|
|
47
47
|
## The Toys Command Line
|
@@ -76,7 +76,7 @@ In the following command:
|
|
76
76
|
toys system blah
|
77
77
|
|
78
78
|
There is no subtool `blah` under the `system` namespace, so Toys works backward
|
79
|
-
until it finds
|
79
|
+
until it finds an existing tool. In this case, the `system` namespace itself
|
80
80
|
does exist, so it is interpreted as the tool, and `blah` is interpreted as an
|
81
81
|
argument passed to it.
|
82
82
|
|
@@ -152,8 +152,8 @@ That will cause `--recursive` to be treated as a positional argument. (In this
|
|
152
152
|
case, as we saw earlier, the root tool will respond by printing an error
|
153
153
|
message that no subtool named `--recursive` exists.)
|
154
154
|
|
155
|
-
Note that a single hyphen by itself `-` is not considered a flag
|
156
|
-
as a positional argument.
|
155
|
+
Note that a single hyphen by itself `-` is not considered a flag, nor does it
|
156
|
+
disable flag parsing. It is treated as a normal positional argument.
|
157
157
|
|
158
158
|
#### Standard Flags
|
159
159
|
|
@@ -224,16 +224,192 @@ like so:
|
|
224
224
|
|
225
225
|
## Defining Tools
|
226
226
|
|
227
|
+
Tools are defined by writing Toys *configuration files*. The simplest form of a
|
228
|
+
configuration file is a file named `.toys.rb` (note the leading period) in the
|
229
|
+
current working directory. Such a file may define tools that are available in
|
230
|
+
the current directory, and for this section we will assume we are writing such
|
231
|
+
a file. The following section on "Understanding Configurations" will cover the
|
232
|
+
larger concerns of how configuration files are looked up and how multiple
|
233
|
+
configurations interact.
|
234
|
+
|
235
|
+
### Basic Config Syntax
|
236
|
+
|
237
|
+
The format of a Toys configuration file is a Ruby DSL including method calls
|
238
|
+
and nested blocks. The actual DSL is specified in the
|
239
|
+
[Toys::DSL::Tool class](https://www.rubydoc.info/gems/toys-core/Toys/DSL/Tool).
|
240
|
+
|
241
|
+
To create a tool, write a `tool` block, giving the tool a name. Within the
|
242
|
+
block, set the properties of the tool, including a description, the flags and
|
243
|
+
arguments recognized by the tool, and the actual functionality of the tool.
|
244
|
+
|
245
|
+
Consider the following example:
|
246
|
+
|
247
|
+
tool "greet" do
|
248
|
+
desc "Print a friendly greeting."
|
249
|
+
long_desc "Prints a friendly greeting. You may customize whom to" \
|
250
|
+
" greet, and how friendly it should be.",
|
251
|
+
"",
|
252
|
+
"Example:",
|
253
|
+
[" toys greet --shout ruby"]
|
254
|
+
|
255
|
+
optional_arg :whom, default: "world", desc: "Whom to greet."
|
256
|
+
flag :shout, "-s", "--shout", desc: "Greet loudly."
|
257
|
+
|
258
|
+
def run
|
259
|
+
greeting = "Hello, #{option(:whom)}!"
|
260
|
+
greeting.upcase! if option(:shout)
|
261
|
+
puts greeting
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
Its results should be mostly self-evident. We'll take a look at some of the
|
266
|
+
details below.
|
267
|
+
|
268
|
+
### Descriptions
|
269
|
+
|
270
|
+
Each tool may have a short and a long description. The short description is a
|
271
|
+
generally a single string that is displayed with the tool name at the top of
|
272
|
+
its help page, or in a subtool list. The long description can include multiple
|
273
|
+
strings, which are displayed in multiple lines in the "description" section of
|
274
|
+
the tool's help page. Long descriptions may include blank lines to separate
|
275
|
+
paragraphs visually.
|
276
|
+
|
277
|
+
Each description string/line is word-wrapped by default when displayed. In the
|
278
|
+
long description above, the first line is a bit longer than 80 characters, and
|
279
|
+
may be word-wrapped if displayed on an 80-character terminal.
|
280
|
+
|
281
|
+
If you need to control the wrapping behavior, pass an array of strings for that
|
282
|
+
line. Each array element will be considered a unit for wrapping purposes, and
|
283
|
+
will not be split. The example command in the long description above
|
284
|
+
illustrates how to prevent a line from being word-wrapped. This is also a
|
285
|
+
useful technique for preserving spaces and indentation.
|
286
|
+
|
287
|
+
For more details, see the reference documentation for
|
288
|
+
[DSL::Tool#desc](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:desc)
|
289
|
+
and
|
290
|
+
[DSL::Tool#long_desc](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:long_desc).
|
291
|
+
|
292
|
+
### Positional Arguments
|
293
|
+
|
294
|
+
Tools may recognize required and optional positional arguments. Each argument
|
295
|
+
must provide a name, which defines how the argument value is exposed to the
|
296
|
+
tool at execution time. The above example uses the DSL method
|
297
|
+
[DSL::Tool#optional_arg](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:optional_arg)
|
298
|
+
to declare an optional argument named `:whom`. If the argument is provided on
|
299
|
+
the command line e.g.
|
300
|
+
|
301
|
+
toys greet ruby
|
302
|
+
|
303
|
+
Then the option `:whom` is set to the string `"ruby"`. The value is made
|
304
|
+
available via the `options` hash in the tools's script. Otherwise, if the
|
305
|
+
argument is omitted, e.g.
|
306
|
+
|
307
|
+
toys greet
|
308
|
+
|
309
|
+
Then the option `:whom` is set to the default value `"world"`.
|
310
|
+
|
311
|
+
Arguments may also be **required** which means they must be provided on the
|
312
|
+
command line; otherwise the tool will report a usage error. You may declare a
|
313
|
+
required argument using the DSL method
|
314
|
+
[DSL::Tool#required_arg](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:required_arg).
|
315
|
+
|
316
|
+
When command line arguments are parsed, the required arguments are matched
|
317
|
+
first, in order, followed by the optional arguments. For example:
|
318
|
+
|
319
|
+
tool "arguments" do
|
320
|
+
optional_arg :arg2
|
321
|
+
required_arg :arg1
|
322
|
+
# ...
|
323
|
+
|
324
|
+
If a user runs
|
325
|
+
|
326
|
+
toys arguments foo
|
327
|
+
|
328
|
+
Then the required argument `:arg1` will be set to `"foo"`, and the optional
|
329
|
+
argument `:arg2` will not be set (i.e. it will remain `nil`).
|
330
|
+
|
331
|
+
If the user runs:
|
332
|
+
|
333
|
+
toys arguments foo bar
|
334
|
+
|
335
|
+
Then `:arg1` is set to `"foo"`, and `:arg2` is set to `"bar"`.
|
336
|
+
|
337
|
+
Running the following:
|
338
|
+
|
339
|
+
toys arguments
|
340
|
+
|
341
|
+
Will produce a usage error, because no value is set for the required argument
|
342
|
+
`:arg1`. Similarly, running:
|
343
|
+
|
344
|
+
toys arguments foo bar baz
|
345
|
+
|
346
|
+
Will also produce an error, since the tool does not provide an argument to
|
347
|
+
match `"baz"`.
|
348
|
+
|
349
|
+
You can also provide an "argument" to match all remaining unmatched arguments
|
350
|
+
at the end, using the DSL method
|
351
|
+
[DSL::Tool#remaining_args](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:remaining_args). For example:
|
352
|
+
|
353
|
+
tool "arguments" do
|
354
|
+
optional_arg :arg2
|
355
|
+
required_arg :arg1
|
356
|
+
remaining_args :arg3
|
357
|
+
# ...
|
358
|
+
|
359
|
+
Now, running:
|
360
|
+
|
361
|
+
toys arguments foo bar baz bey
|
362
|
+
|
363
|
+
Sets the following option data:
|
364
|
+
|
365
|
+
{arg1: "foo", arg2: "bar", arg3: ["baz", "bey"]}
|
366
|
+
|
367
|
+
Positional arguments may also have short and long descriptions, which are
|
368
|
+
displayed in online help.
|
369
|
+
|
370
|
+
### Flags
|
371
|
+
|
372
|
+
Tools may also recognize flags on the command line. In our "greet" example, we
|
373
|
+
declared a flag named `:shout`:
|
374
|
+
|
375
|
+
flag :shout, "-s", "--shout", desc: "Greet loudly."
|
376
|
+
|
377
|
+
(guid is still incomplete)
|
378
|
+
|
379
|
+
### The Execution Script
|
380
|
+
|
381
|
+
### Namespaces
|
382
|
+
|
227
383
|
## Understanding Configurations
|
228
384
|
|
229
385
|
## Helper Methods and Modules
|
230
386
|
|
231
|
-
|
387
|
+
### The Standard Helpers
|
388
|
+
|
389
|
+
## The Execution Environment
|
390
|
+
|
391
|
+
### Built-in Context
|
392
|
+
|
393
|
+
### Logging and Verbosity
|
394
|
+
|
395
|
+
### Running Tools from Tools
|
396
|
+
|
397
|
+
### Executing Subprocesses
|
398
|
+
|
399
|
+
### Formatting Output
|
232
400
|
|
233
401
|
## Prefabricated Tools with Templates
|
234
402
|
|
235
|
-
|
403
|
+
### Defining Templates
|
236
404
|
|
237
405
|
## Advanced Tool Definition Techniques
|
238
406
|
|
407
|
+
### Aliases
|
408
|
+
|
409
|
+
### Includes
|
410
|
+
|
411
|
+
### Controlling Built-in Flags
|
412
|
+
|
413
|
+
## The System Tools
|
414
|
+
|
239
415
|
## Embedding Toys
|
data/lib/toys.rb
CHANGED
data/lib/toys/standard_cli.rb
CHANGED
@@ -75,7 +75,7 @@ module Toys
|
|
75
75
|
# Short description for the standard root tool
|
76
76
|
# @return [String]
|
77
77
|
#
|
78
|
-
DEFAULT_ROOT_DESC = "Your personal command line tool
|
78
|
+
DEFAULT_ROOT_DESC = "Your personal command line tool".freeze
|
79
79
|
|
80
80
|
##
|
81
81
|
# Help text for the standard root tool
|
@@ -125,9 +125,9 @@ module Toys
|
|
125
125
|
# `$HOME:/etc` by default.
|
126
126
|
# * The builtins for the standard toys binary.
|
127
127
|
#
|
128
|
+
# @param [Toys::CLI] cli Add paths to this CLI
|
128
129
|
# @param [String,nil] directory Starting search directory for configs.
|
129
130
|
# Defaults to the current working directory.
|
130
|
-
# @param [Toys::CLI] cli Add paths to this CLI
|
131
131
|
#
|
132
132
|
def self.add_standard_paths(cli, directory: nil)
|
133
133
|
cli.add_search_path_hierarchy(start: directory)
|
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.3.
|
4
|
+
version: 0.3.7
|
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-05-
|
11
|
+
date: 2018-05-30 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.3.
|
19
|
+
version: 0.3.7
|
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.3.
|
26
|
+
version: 0.3.7
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|