toys 0.12.2 → 0.13.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/.yardopts +2 -0
- data/CHANGELOG.md +35 -0
- data/LICENSE.md +1 -1
- data/README.md +7 -4
- data/builtins/system/git-cache.rb +238 -0
- data/builtins/system/test.rb +37 -2
- data/core-docs/toys/acceptor.rb +432 -0
- data/core-docs/toys/arg_parser.rb +397 -0
- data/core-docs/toys/cli.rb +493 -0
- data/core-docs/toys/compat.rb +2 -0
- data/core-docs/toys/completion.rb +329 -0
- data/core-docs/toys/context.rb +321 -0
- data/core-docs/toys/core.rb +14 -0
- data/core-docs/toys/dsl/base.rb +56 -0
- data/core-docs/toys/dsl/flag.rb +261 -0
- data/core-docs/toys/dsl/flag_group.rb +259 -0
- data/core-docs/toys/dsl/internal.rb +4 -0
- data/core-docs/toys/dsl/positional_arg.rb +139 -0
- data/core-docs/toys/dsl/tool.rb +1530 -0
- data/core-docs/toys/errors.rb +93 -0
- data/core-docs/toys/flag.rb +549 -0
- data/core-docs/toys/flag_group.rb +186 -0
- data/core-docs/toys/input_file.rb +8 -0
- data/core-docs/toys/loader.rb +222 -0
- data/core-docs/toys/middleware.rb +295 -0
- data/core-docs/toys/mixin.rb +142 -0
- data/core-docs/toys/module_lookup.rb +75 -0
- data/core-docs/toys/positional_arg.rb +145 -0
- data/core-docs/toys/settings.rb +507 -0
- data/core-docs/toys/source_info.rb +127 -0
- data/core-docs/toys/standard_middleware/add_verbosity_flags.rb +49 -0
- data/core-docs/toys/standard_middleware/apply_config.rb +24 -0
- data/core-docs/toys/standard_middleware/handle_usage_errors.rb +33 -0
- data/core-docs/toys/standard_middleware/set_default_descriptions.rb +222 -0
- data/core-docs/toys/standard_middleware/show_help.rb +190 -0
- data/core-docs/toys/standard_middleware/show_root_version.rb +45 -0
- data/core-docs/toys/standard_mixins/bundler.rb +83 -0
- data/core-docs/toys/standard_mixins/exec.rb +645 -0
- data/core-docs/toys/standard_mixins/fileutils.rb +18 -0
- data/core-docs/toys/standard_mixins/gems.rb +48 -0
- data/core-docs/toys/standard_mixins/git_cache.rb +41 -0
- data/core-docs/toys/standard_mixins/highline.rb +133 -0
- data/core-docs/toys/standard_mixins/terminal.rb +135 -0
- data/core-docs/toys/standard_mixins/xdg.rb +49 -0
- data/core-docs/toys/template.rb +112 -0
- data/core-docs/toys/tool_definition.rb +926 -0
- data/core-docs/toys/utils/completion_engine.rb +49 -0
- data/core-docs/toys/utils/exec.rb +721 -0
- data/core-docs/toys/utils/gems.rb +185 -0
- data/core-docs/toys/utils/git_cache.rb +353 -0
- data/core-docs/toys/utils/help_text.rb +134 -0
- data/core-docs/toys/utils/terminal.rb +310 -0
- data/core-docs/toys/utils/xdg.rb +253 -0
- data/core-docs/toys/wrappable_string.rb +120 -0
- data/core-docs/toys-core.rb +63 -0
- data/docs/guide.md +497 -156
- data/lib/toys/standard_cli.rb +50 -36
- data/lib/toys/templates/clean.rb +18 -0
- data/lib/toys/templates/gem_build.rb +24 -0
- data/lib/toys/templates/minitest.rb +21 -0
- data/lib/toys/templates/rake.rb +23 -3
- data/lib/toys/templates/rdoc.rb +29 -0
- data/lib/toys/templates/rspec.rb +32 -4
- data/lib/toys/templates/rubocop.rb +14 -1
- data/lib/toys/templates/yardoc.rb +55 -0
- data/lib/toys/testing.rb +186 -109
- data/lib/toys/version.rb +1 -1
- data/lib/toys.rb +4 -2
- metadata +56 -6
data/docs/guide.md
CHANGED
@@ -10,15 +10,14 @@ details such as argument parsing, online help, and error reporting.
|
|
10
10
|
|
11
11
|
Toys is designed for software developers, IT professionals, and other power
|
12
12
|
users who want to write and organize scripts to automate their workflows. It
|
13
|
-
can also be used as a Rake
|
14
|
-
interface for your project's build tasks.
|
13
|
+
can also be used as a replacement for Rake, providing a more natural command
|
14
|
+
line interface for your project's build tasks.
|
15
15
|
|
16
16
|
Unlike most command line frameworks, Toys is *not primarily* designed to help
|
17
17
|
you build and ship a custom command line executable written in Ruby. Rather, it
|
18
|
-
provides a single executable called `toys
|
19
|
-
by
|
20
|
-
|
21
|
-
library.)
|
18
|
+
provides a single executable called `toys` whose functionality you can define
|
19
|
+
by writing configuration files. (You can, however, build your own custom
|
20
|
+
command line executable using the related **toys-core** library.)
|
22
21
|
|
23
22
|
If this is your first time using Toys, we recommend starting with the
|
24
23
|
[README](https://dazuma.github.io/toys/gems/toys/latest), which includes a
|
@@ -37,7 +36,7 @@ Toys is a command line *framework*. It provides an executable called `toys`
|
|
37
36
|
with basic functions such as argument parsing and online help. You provide the
|
38
37
|
actual behavior of the Toys executable by writing **Toys files**.
|
39
38
|
|
40
|
-
Toys is a multi-command executable. You may define any number of commands,
|
39
|
+
Toys is a *multi-command* executable. You may define any number of commands,
|
41
40
|
called **tools**, which can be invoked by passing the tool name as an argument
|
42
41
|
to the `toys` executable. Tools are arranged in a hierarchy; you may define
|
43
42
|
**namespaces** that have **subtools**.
|
@@ -45,8 +44,8 @@ to the `toys` executable. Tools are arranged in a hierarchy; you may define
|
|
45
44
|
Tools may recognize command line arguments in the form of **flags** and
|
46
45
|
**positional arguments**. Flags can optionally take **values**, while
|
47
46
|
positional arguments may be **required** or **optional**. Flags may be
|
48
|
-
organized into **flag groups**
|
49
|
-
|
47
|
+
organized into **flag groups** that support marking flags or flag combinations
|
48
|
+
as required.
|
50
49
|
|
51
50
|
The configuration of a tool may include **descriptions**, for the tool itself,
|
52
51
|
and for each command line argument. These descriptions are displayed in the
|
@@ -54,18 +53,19 @@ tool's **online help** screen. Descriptions come in **long** and **short**
|
|
54
53
|
forms, which appear in different styles of help.
|
55
54
|
|
56
55
|
Toys searches for tools in specifically-named **Toys files** and **Toys
|
57
|
-
directories**. It searches for these in the current directory, in
|
58
|
-
|
56
|
+
directories**. It searches for these in the current directory, in parent
|
57
|
+
directories, and in the Toys **search path**.
|
59
58
|
|
60
59
|
Toys provides various features to help you write tools. This includes providing
|
61
60
|
a **logger** for each tool, **mixins** that provide common functions a tool can
|
62
61
|
call (such as to control subprocesses and style output), and **templates**
|
63
|
-
which are prefabricated tools that you can configure for your needs.
|
62
|
+
which are prefabricated tools that you can configure for your needs. It also
|
63
|
+
integrates with testing frameworks, making it easy to write and run **tests**.
|
64
64
|
|
65
65
|
Finally, Toys provides useful **built-in behavior**, including automatically
|
66
66
|
providing flags to display help screens and set verbosity. It also includes a
|
67
|
-
built-in
|
68
|
-
|
67
|
+
built-in set of **system tools** that let you inspect and configure the Toys
|
68
|
+
system itself.
|
69
69
|
|
70
70
|
## The Toys command line
|
71
71
|
|
@@ -326,8 +326,7 @@ directory is called a **Toys file**. It defines tools available in that
|
|
326
326
|
directory and its subdirectories.
|
327
327
|
|
328
328
|
The format of a Toys file is a Ruby DSL that includes directives, methods, and
|
329
|
-
nested blocks. The actual DSL is specified in the
|
330
|
-
[Toys::DSL::Tool class](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool).
|
329
|
+
nested blocks. The actual DSL is specified in the {Toys::DSL::Tool} class.
|
331
330
|
|
332
331
|
To create a tool, write a `tool` block, giving the tool a name. Within the
|
333
332
|
block, use directives to set the properties of the tool, including descriptions
|
@@ -375,10 +374,8 @@ will not be split. The example command in the long description above
|
|
375
374
|
illustrates how to prevent a line from being word-wrapped. This is also a
|
376
375
|
useful technique for preserving spaces and indentation.
|
377
376
|
|
378
|
-
For more details, see the reference documentation for
|
379
|
-
|
380
|
-
and
|
381
|
-
[Toys::DSL::Tool#long_desc](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#long_desc-instance_method).
|
377
|
+
For more details, see the reference documentation for {Toys::DSL::Tool#desc}
|
378
|
+
and {Toys::DSL::Tool#long_desc}.
|
382
379
|
|
383
380
|
### Positional arguments
|
384
381
|
|
@@ -387,10 +384,9 @@ have a name, which is a key that the tool can use to obtain the argument's
|
|
387
384
|
value at execution time. Arguments may also have various properties controlling
|
388
385
|
how values are validated and expressed.
|
389
386
|
|
390
|
-
The above example uses the directive
|
391
|
-
|
392
|
-
|
393
|
-
on the command line e.g.
|
387
|
+
The above example uses the directive {Toys::DSL::Tool#optional_arg} to declare
|
388
|
+
an **optional argument** named `:whom`. If the argument is provided on the
|
389
|
+
command line e.g.
|
394
390
|
|
395
391
|
$ toys greet ruby
|
396
392
|
Hello, ruby!
|
@@ -406,13 +402,11 @@ Then the option `:whom` is set to the default value `"world"`.
|
|
406
402
|
If the option name is a valid method name, Toys will provide a method that you
|
407
403
|
can use to retrieve the value. In the above example, we retrieve the value for
|
408
404
|
the option `:whom` by calling the method `whom`. If the option name cannot be
|
409
|
-
made into a method, you can retrieve the value by calling
|
410
|
-
[Toys::Context#get](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#get-instance_method).
|
405
|
+
made into a method, you can retrieve the value by calling {Toys::Context#get}.
|
411
406
|
|
412
407
|
An argument may also be **required**, which means it must be provided on the
|
413
408
|
command line; otherwise the tool will report a usage error. You may declare a
|
414
|
-
required argument using the directive
|
415
|
-
[Toys::DSL::Tool#required_arg](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#required_arg-instance_method).
|
409
|
+
required argument using the directive {Toys::DSL::Tool#required_arg}.
|
416
410
|
|
417
411
|
#### Parsing required and optional arguments
|
418
412
|
|
@@ -479,9 +473,7 @@ because it is not provided, will default to `"the-default"` instead of `nil`.
|
|
479
473
|
|
480
474
|
Normally, unmatched arguments will result in an error message. However, you can
|
481
475
|
provide an "argument" to match all **remaining** unmatched arguments at the
|
482
|
-
end, using the directive
|
483
|
-
[Toys::DSL::Tool#remaining_args](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#remaining_args-instance_method).
|
484
|
-
For example:
|
476
|
+
end, using the directive {Toys::DSL::Tool#remaining_args}. For example:
|
485
477
|
|
486
478
|
tool "args-demo" do
|
487
479
|
required_arg :arg1
|
@@ -532,7 +524,7 @@ way, Toys provides an alternate syntax for defining arguments using a block.
|
|
532
524
|
end
|
533
525
|
|
534
526
|
For detailed info on configuring an argument using a block, see the
|
535
|
-
|
527
|
+
{Toys::DSL::PositionalArg} class.
|
536
528
|
|
537
529
|
#### Argument acceptors
|
538
530
|
|
@@ -605,8 +597,7 @@ have the same effect. A flag declaration may include any number of synonyms.
|
|
605
597
|
As with arguments, Toys will provide a method that you can call to retrieve the
|
606
598
|
option value set by a flag. In this case, a method called `shout` will be
|
607
599
|
available, and will return either true or false. If the option name cannot be
|
608
|
-
made into a method, you can retrieve the value by calling
|
609
|
-
[Toys::Context#get](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#get-instance_method).
|
600
|
+
made into a method, you can retrieve the value by calling {Toys::Context#get}.
|
610
601
|
|
611
602
|
#### Flag types
|
612
603
|
|
@@ -875,7 +866,7 @@ way, Toys provides an alternate syntax for defining flags using a block.
|
|
875
866
|
end
|
876
867
|
|
877
868
|
For detailed info on configuring an flag using a block, see the
|
878
|
-
|
869
|
+
{Toys::DSL::Flag} class.
|
879
870
|
|
880
871
|
#### Flag completions
|
881
872
|
|
@@ -1009,9 +1000,8 @@ valid Ruby method name, Toys will provide a method that you can call to get the
|
|
1009
1000
|
value. In the above example, `whom` and `shout` are such methods.
|
1010
1001
|
|
1011
1002
|
If you create a flag or argument whose option name is not a symbol *or* is not
|
1012
|
-
a valid method name, you can still get the value by calling
|
1013
|
-
|
1014
|
-
method. For example:
|
1003
|
+
a valid method name, you can still get the value by calling
|
1004
|
+
{Toys::Context#get}. For example:
|
1015
1005
|
|
1016
1006
|
tool "greet" do
|
1017
1007
|
# The name "whom-to-greet" is not a valid method name.
|
@@ -1028,9 +1018,7 @@ method. For example:
|
|
1028
1018
|
|
1029
1019
|
If a tool's `run` method finishes normally, Toys will exit with a result code
|
1030
1020
|
of 0, indicating success. You may exit immediately and/or provide a nonzero
|
1031
|
-
result by calling
|
1032
|
-
[Toys::Context#exit](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#exit-instance_method)
|
1033
|
-
method:
|
1021
|
+
result by calling {Toys::Context#exit}:
|
1034
1022
|
|
1035
1023
|
def run
|
1036
1024
|
puts "Exiting with an error..."
|
@@ -1341,10 +1329,10 @@ one big complex subtool called `unit`, you might define all the simple tools in
|
|
1341
1329
|
the index file `.toys/test/.toys.rb`, while defining the large `test unit` tool
|
1342
1330
|
in the separate file `.toys/test/unit.rb`.
|
1343
1331
|
|
1344
|
-
Toys also loads index
|
1345
|
-
means they are convenient places to define shared code that can
|
1346
|
-
the subtools defined in that directory, as we shall see later in
|
1347
|
-
[section on sharing code](#Sharing_code).
|
1332
|
+
Toys also loads the index file in a directory *before* any other files in that
|
1333
|
+
directory. This means they are convenient places to define shared code that can
|
1334
|
+
be used by all the subtools defined in that directory, as we shall see later in
|
1335
|
+
the [section on sharing code](#Sharing_code).
|
1348
1336
|
|
1349
1337
|
### The Toys search path
|
1350
1338
|
|
@@ -1397,17 +1385,15 @@ are located. Tools defined here are *global*, available everywhere.
|
|
1397
1385
|
Though it is uncommon practice, it is possible to stop the search process and
|
1398
1386
|
prevent Toys from loading tools further down in the search path (e.g. prevent
|
1399
1387
|
tools from being defined from parent directories or global directories). To do
|
1400
|
-
so, use the directive
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
parent directories.
|
1388
|
+
so, use the directive {Toys::DSL::Tool#truncate_load_path!}. This directive
|
1389
|
+
removes all directories further down the search path. It can be used, for
|
1390
|
+
example, to disable global tools when you run Toys from the current directory.
|
1391
|
+
It can also be useful if you are using
|
1392
|
+
[Bundler integration](#Using_bundler_with_a_tool) to prevent bundle conflicts
|
1393
|
+
with parent directories, by disabling tools from parent directories.
|
1407
1394
|
|
1408
1395
|
The `truncate_load_path!` directive works only if no tools from further down
|
1409
|
-
the search path have been loaded yet. It will raise
|
1410
|
-
[Toys::ToolDefinitionError](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/ToolDefinitionError)
|
1396
|
+
the search path have been loaded yet. It will raise {Toys::ToolDefinitionError}
|
1411
1397
|
if it fails to truncate the load path. In most cases, Toys is very smart about
|
1412
1398
|
loading tools only when needed, but there are exceptions. To minimize the
|
1413
1399
|
chance of problems, if you need to use `truncate_load_path!`, locate it as
|
@@ -1419,22 +1405,19 @@ early as possible in your Toys files, typically at the top of the
|
|
1419
1405
|
This section describes the context and resources available to your tool when it
|
1420
1406
|
is running; that is, what you can call from your tool's `run` method.
|
1421
1407
|
|
1422
|
-
Each tool is defined as a class that subclasses
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
[Toys::Context#exit](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#exit-instance_method)
|
1429
|
-
method to exit immediately and return an exit code. Now we will cover other
|
1430
|
-
resources available to your tool.
|
1408
|
+
Each tool is defined as a class that subclasses {Toys::Context}. The base class
|
1409
|
+
defines helper methods, and provides access to a variety of data and objects
|
1410
|
+
relevant to your tool. We have already seen earlier how to use the
|
1411
|
+
{Toys::Context#get} method to retrieve option values, and how to use the
|
1412
|
+
{Toys::Context#exit} method to exit immediately and return an exit code. Now we
|
1413
|
+
will cover other resources available to your tool.
|
1431
1414
|
|
1432
1415
|
### Built-in context
|
1433
1416
|
|
1434
1417
|
In addition to the options set by your tool's flags and command line arguments,
|
1435
|
-
a variety of other data and objects are also accessible using
|
1436
|
-
|
1437
|
-
|
1418
|
+
a variety of other data and objects are also accessible using
|
1419
|
+
{Toys::Context#get}. For example, you can get the full name of the tool being
|
1420
|
+
executed like this:
|
1438
1421
|
|
1439
1422
|
def run
|
1440
1423
|
puts "Current tool is #{get(TOOL_NAME)}"
|
@@ -1442,16 +1425,14 @@ For example, you can get the full name of the tool being executed like this:
|
|
1442
1425
|
|
1443
1426
|
The `TOOL_NAME` constant above is a well-known key that corresponds to the full
|
1444
1427
|
name (as an array of strings) of the running tool. A variety of well-known keys
|
1445
|
-
are defined in the
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
like write to the logger or look up and call other tools.
|
1428
|
+
are defined in the {Toys::Context::Key} module. They include information about
|
1429
|
+
the current execution, such as the tool name and the original command line
|
1430
|
+
arguments passed to it (before they were parsed). They also include some
|
1431
|
+
internal Toys objects, which can be used to do things like write to the logger
|
1432
|
+
or look up and call other tools.
|
1451
1433
|
|
1452
1434
|
Most of the important context also can be accessed from convenience methods.
|
1453
|
-
For example, the `TOOL_NAME` is also available from
|
1454
|
-
[Toys::Context#tool_name method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#tool_name-instance_method):
|
1435
|
+
For example, the `TOOL_NAME` is also available from {Toys::Context#tool_name}:
|
1455
1436
|
|
1456
1437
|
def run
|
1457
1438
|
puts "Current tool is #{tool_name}"
|
@@ -1464,9 +1445,8 @@ access from built-in context.
|
|
1464
1445
|
|
1465
1446
|
Toys provides a Logger (a simple instance of the Ruby standard library logger
|
1466
1447
|
that writes to standard error) for your tool to use to report status
|
1467
|
-
information. You can access this logger via the `LOGGER` context key, or
|
1468
|
-
|
1469
|
-
For example:
|
1448
|
+
information. You can access this logger via the `LOGGER` context key, or
|
1449
|
+
{Toys::Context#logger}. For example:
|
1470
1450
|
|
1471
1451
|
def run
|
1472
1452
|
logger.warn "Danger Will Robinson!"
|
@@ -1474,28 +1454,24 @@ For example:
|
|
1474
1454
|
|
1475
1455
|
The current logger level is controlled by the verbosity. Verbosity is an
|
1476
1456
|
integer context value that you can retrieve using the `VERBOSITY` context key
|
1477
|
-
or
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
easily provide command line based control of the output verbosity.
|
1457
|
+
or {Toys::Context#verbosity}. The verbosity is set to 0 by default. This
|
1458
|
+
corresponds to a logger level of `WARN`. That is, warnings, errors, and fatals
|
1459
|
+
are displayed, while infos and debugs are not. However,
|
1460
|
+
[as we saw earlier](#Standard_flags), most tools automatically respond to the
|
1461
|
+
`--verbose` and `--quiet` flags, (or `-v` and `-q`), which increment and
|
1462
|
+
decrement the verbosity value, respectively. If you pass `-v` to a tool, the
|
1463
|
+
verbosity is incremented to 1, and the logger level is set to `INFO`. If you
|
1464
|
+
pass `-q`, the verbosity is decremented to -1, and the logger level is set to
|
1465
|
+
`ERROR`. So by using the provided logger, a tool can easily provide command
|
1466
|
+
line based control of the output verbosity.
|
1488
1467
|
|
1489
1468
|
### Running tools from tools
|
1490
1469
|
|
1491
1470
|
A common operation a tool might want to do is "call" another tool. This can be
|
1492
|
-
done via the CLI object, which you can retrieve using the `CLI` key or
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
is the "main" interface to Toys. In particular, it provides the
|
1497
|
-
[Toys::CLI#run method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/CLI#run-instance_method)
|
1498
|
-
which can be used to call another tool:
|
1471
|
+
done via the CLI object, which you can retrieve using the `CLI` key or
|
1472
|
+
{Toys::Context#cli}. These return the current instance of {Toys::CLI}, which is
|
1473
|
+
the "main" interface to Toys. In particular, it provides the {Toys::CLI#run}
|
1474
|
+
method, which can be used to call another tool:
|
1499
1475
|
|
1500
1476
|
def run
|
1501
1477
|
status = cli.run("greet", "rubyists", "-v")
|
@@ -1513,10 +1489,9 @@ capture or manipulate that tool's input or output stream.
|
|
1513
1489
|
|
1514
1490
|
### Helper methods and mixins
|
1515
1491
|
|
1516
|
-
The methods of
|
1517
|
-
|
1518
|
-
|
1519
|
-
that you can use as helpers.
|
1492
|
+
The methods of {Toys::Context} are not the only methods available for your tool
|
1493
|
+
to call. We [saw earlier](#Tool_execution_basics) that a tool can define
|
1494
|
+
additional methods that you can use as helpers.
|
1520
1495
|
|
1521
1496
|
You can also include **mixins**, which are modules that bring in a whole set of
|
1522
1497
|
helper methods. Include a mixin using the `include` directive:
|
@@ -1535,9 +1510,8 @@ special `puts` method that lets you include style information such as `:bold`,
|
|
1535
1510
|
which affects the display on ANSI-capable terminals.
|
1536
1511
|
|
1537
1512
|
For details on the built-in mixins provided by Toys, see the modules under
|
1538
|
-
|
1539
|
-
|
1540
|
-
mixins have names that are symbols.
|
1513
|
+
{Toys::StandardMixins}. We will look at a few examples of the use of these
|
1514
|
+
mixins below. Built-in mixins have names that are symbols.
|
1541
1515
|
|
1542
1516
|
You can also define your own mixins, as we will see in the
|
1543
1517
|
[upcoming section on defining mixins](#Defining_mixins).
|
@@ -1572,10 +1546,8 @@ subprocesses:
|
|
1572
1546
|
* Another tool run in a separate (forked) process.
|
1573
1547
|
* A block run in a separate (forked) process.
|
1574
1548
|
|
1575
|
-
For more information, see the
|
1576
|
-
|
1577
|
-
and the underyling library
|
1578
|
-
[Toys::Utils::Exec](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Utils/Exec).
|
1549
|
+
For more information, see the {Toys::StandardMixins::Exec} mixin module and the
|
1550
|
+
underyling library {Toys::Utils::Exec}.
|
1579
1551
|
|
1580
1552
|
### Formatting output
|
1581
1553
|
|
@@ -1586,20 +1558,44 @@ can help create nicer interfaces.
|
|
1586
1558
|
|
1587
1559
|
First, there is `:terminal`, which provides some basic terminal features such
|
1588
1560
|
as styled output and simple spinners. For information, see the
|
1589
|
-
|
1590
|
-
|
1591
|
-
[Toys::Terminal](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Terminal).
|
1561
|
+
{Toys::StandardMixins::Terminal} mixin module and the underyling library
|
1562
|
+
{Toys::Utils::Terminal}.
|
1592
1563
|
|
1593
1564
|
If you prefer the venerable Highline library interface, Toys provides a mixin
|
1594
1565
|
called `:highline` that automatically installs the highline gem (version 2.x)
|
1595
1566
|
if it is not available, and makes a highline object available to the tool. For
|
1596
|
-
more information, see the
|
1597
|
-
[Toys::StandardMixins::Highline mixin module](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Highline).
|
1567
|
+
more information, see the {Toys::StandardMixins::Highline} mixin module.
|
1598
1568
|
|
1599
1569
|
You may also use other third-party gems such as
|
1600
1570
|
[tty](https://github.com/piotrmurach/tty). The section below on
|
1601
1571
|
[useful gems](#Useful_gems) provides some examples.
|
1602
1572
|
|
1573
|
+
### Standard base directories
|
1574
|
+
|
1575
|
+
Command line tools often need access to common user-specific files such as
|
1576
|
+
caches and state data. The
|
1577
|
+
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
1578
|
+
specifies standard locations for these files and standard environment variables
|
1579
|
+
that can be used to override them. Toys provides easy access to these paths via
|
1580
|
+
the `:xdg` mixin.
|
1581
|
+
|
1582
|
+
Here's a simple example:
|
1583
|
+
|
1584
|
+
tool "my-tool" do
|
1585
|
+
include :xdg
|
1586
|
+
|
1587
|
+
def run
|
1588
|
+
# Get config file paths, in order from most to least inportant
|
1589
|
+
config_files = xdg.lookup_config("my-tool/my-config.toml")
|
1590
|
+
config_files.each do |absolute_path|
|
1591
|
+
# Read the file...
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
The `lookup_config` method and many others are documented under the
|
1597
|
+
{Toys::Utils::XDG} class.
|
1598
|
+
|
1603
1599
|
## Sharing code
|
1604
1600
|
|
1605
1601
|
As you accumulate additional and more complex tools, you may find that some of
|
@@ -1910,9 +1906,7 @@ directive by setting properties on the template object.
|
|
1910
1906
|
#### Template classes
|
1911
1907
|
|
1912
1908
|
Finally, templates are classes, and you can create a template directly as a
|
1913
|
-
class by including the
|
1914
|
-
[Toys::Template](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Template)
|
1915
|
-
module in your class definition.
|
1909
|
+
class by including the {Toys::Template} module in your class definition.
|
1916
1910
|
|
1917
1911
|
class GreetTemplate
|
1918
1912
|
include Toys::Template
|
@@ -2053,8 +2047,8 @@ classes, modules, and other code. But preloaded files *automatically* loaded
|
|
2053
2047
|
To use preloaded files, you must define your tools inside a
|
2054
2048
|
[Toys directory](#Toys_directories). Before any tools inside a directory are
|
2055
2049
|
loaded, any file named `.preload.rb` in the directory is automatically
|
2056
|
-
required.
|
2057
|
-
|
2050
|
+
required. Next, any Ruby files inside a subdirectory called `.preload` are also
|
2051
|
+
automatically required.
|
2058
2052
|
|
2059
2053
|
For example, take the following directory structure:
|
2060
2054
|
|
@@ -2096,6 +2090,350 @@ Either a single `.preload.rb` file or a `.preload` directory, or both, may be
|
|
2096
2090
|
used. If both are present in the same directory, the `.preload.rb` file is
|
2097
2091
|
loaded first before the `.preload` directory contents.
|
2098
2092
|
|
2093
|
+
## Testing your tools
|
2094
|
+
|
2095
|
+
Tests play a critical part in the maintainability of any Ruby app. However, it
|
2096
|
+
can be difficult to set up tests for command line tools, Rake tasks, and
|
2097
|
+
similar code. Toys embraces testability by providing a dedicated place for
|
2098
|
+
tests, and a set of helpers that make it easy to test tools and parts of tools.
|
2099
|
+
|
2100
|
+
### Writing and running tests
|
2101
|
+
|
2102
|
+
Toys integrates with [Minitest](https://github.com/seattlerb/minitest) to
|
2103
|
+
provide a testing framework for your tools. To write tests, you must define
|
2104
|
+
your tools inside a [Toys directory](#Toys_directories). Create a directory
|
2105
|
+
called `.test` inside that directory. You can then write Minitest tests in
|
2106
|
+
files within that directory with names matching `test_*.rb`. You can also
|
2107
|
+
provide other files that do not match that name pattern, as fixture data or
|
2108
|
+
common test tools to load using `require_relative`. For example:
|
2109
|
+
|
2110
|
+
(current directory)
|
2111
|
+
|
|
2112
|
+
+- .toys/
|
2113
|
+
|
|
2114
|
+
+- greet.rb <-- defines "greet" (and subtools)
|
2115
|
+
|
|
2116
|
+
+- .test/
|
2117
|
+
|
|
2118
|
+
+- test_greet.rb <-- includes tests
|
2119
|
+
|
|
2120
|
+
+- helper.rb <-- includes helper code but not tests
|
2121
|
+
|
2122
|
+
Test files must be written against Minitest, and can use either unit test or
|
2123
|
+
spec syntax. (RSpec support is not currently available.) The framework will
|
2124
|
+
require `minitest/autorun` for you. Here is trivial example content for the
|
2125
|
+
`test_greet.rb` file:
|
2126
|
+
|
2127
|
+
# test_greet.rb
|
2128
|
+
|
2129
|
+
require_relative "helper"
|
2130
|
+
|
2131
|
+
class MyTest < Minitest::Test
|
2132
|
+
def test_hello
|
2133
|
+
assert_equal "hello", MyHelper.hello
|
2134
|
+
end
|
2135
|
+
end
|
2136
|
+
|
2137
|
+
And the `helper.rb` file:
|
2138
|
+
|
2139
|
+
# helper.rb
|
2140
|
+
|
2141
|
+
module MyHelper
|
2142
|
+
def self.hello
|
2143
|
+
"hello"
|
2144
|
+
end
|
2145
|
+
end
|
2146
|
+
|
2147
|
+
You can run tests using:
|
2148
|
+
|
2149
|
+
toys system test
|
2150
|
+
|
2151
|
+
The built-in `system test` tool searches for the closest `.toys` directory, and
|
2152
|
+
runs any tests it finds. In the example above, `toys system test` will find the
|
2153
|
+
"hello" test in the file `.toys/.test/test_greet.rb`, run it, and display the
|
2154
|
+
results.
|
2155
|
+
|
2156
|
+
Now, the example above defines a file called `test_greet.rb` but it doesn't
|
2157
|
+
actually test our `greet` tool. So let's cover how to invoke tools from tests
|
2158
|
+
so you can test their functionality.
|
2159
|
+
|
2160
|
+
### Testing tool functionality
|
2161
|
+
|
2162
|
+
Included in the Toys gem is the helper module {Toys::Testing}, which provides
|
2163
|
+
methods that load and execute tools for testing purposes. You can access these
|
2164
|
+
methods by including this module in your test class or `describe` block:
|
2165
|
+
|
2166
|
+
class MyTest < Minitest::Test
|
2167
|
+
include Toys::Testing
|
2168
|
+
|
2169
|
+
# Write your tests..
|
2170
|
+
end
|
2171
|
+
|
2172
|
+
The simplest way to test a tool's functionality is by running it and observing
|
2173
|
+
the results. To run a tool, invoke the {Toys::Testing#toys_run_tool} method,
|
2174
|
+
passing in the name of the tool and its arguments as if you were invoking the
|
2175
|
+
tool from the command line. For example, recall our original `greet` tool that
|
2176
|
+
takes an optional argument and a `--shout` flag:
|
2177
|
+
|
2178
|
+
# greet.rb
|
2179
|
+
|
2180
|
+
desc "Print a friendly greeting."
|
2181
|
+
long_desc "Prints a friendly greeting. You may customize whom to" \
|
2182
|
+
" greet, and how friendly it should be.",
|
2183
|
+
"",
|
2184
|
+
"Example:",
|
2185
|
+
[" toys greet --shout ruby"]
|
2186
|
+
|
2187
|
+
optional_arg :whom, default: "world", desc: "Whom to greet."
|
2188
|
+
flag :shout, "-s", "--shout", desc: "Greet loudly."
|
2189
|
+
|
2190
|
+
def run
|
2191
|
+
greeting = "Hello, #{whom}!"
|
2192
|
+
greeting = greeting.upcase if shout
|
2193
|
+
puts greeting
|
2194
|
+
end
|
2195
|
+
|
2196
|
+
To execute the tool from a test, call `toys_run_tool` and pass it `["greet"]`
|
2197
|
+
as the command:
|
2198
|
+
|
2199
|
+
class GreetTest < Minitest::Test
|
2200
|
+
include Toys::Testing
|
2201
|
+
|
2202
|
+
def test_greet_with_no_arguents
|
2203
|
+
exit_code = toys_run_tool(["greet"])
|
2204
|
+
assert_equal(0, exit_code)
|
2205
|
+
end
|
2206
|
+
end
|
2207
|
+
|
2208
|
+
The `toys_run_tool` method executes the tool and returns the numeric exit code,
|
2209
|
+
which we can assert is 0 for a successful run. However, when we run this test,
|
2210
|
+
notice that "Hello, world!" is printed to the console in the middle of the test
|
2211
|
+
run. That is, of course, what our "greet" tool does. But normally, if you are
|
2212
|
+
testing a tool that writes to standard out, you'll want to assert against that
|
2213
|
+
output rather than have it pollute your test output. So typically, you'll wrap
|
2214
|
+
a call to `toys_run_tool` in a
|
2215
|
+
[`capture_subprocess_io`](http://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-capture_subprocess_io)
|
2216
|
+
block, to capture the output. So here's a complete test for our `greet` tool:
|
2217
|
+
|
2218
|
+
class GreetTest < Minitest::Test
|
2219
|
+
include Toys::Testing
|
2220
|
+
|
2221
|
+
def test_greet_with_no_arguents
|
2222
|
+
out, err = capture_subprocess_io do
|
2223
|
+
exit_code = toys_run_tool(["greet"])
|
2224
|
+
assert_equal(0, exit_code)
|
2225
|
+
end
|
2226
|
+
assert_equal("Hello, world!\n", out)
|
2227
|
+
assert_empty(err)
|
2228
|
+
end
|
2229
|
+
end
|
2230
|
+
|
2231
|
+
Generally, you should test various use cases of your tool, including the effect
|
2232
|
+
of passing different arguments and flags. For example, here's a test of the
|
2233
|
+
`--shout` flag:
|
2234
|
+
|
2235
|
+
class GreetTest < Minitest::Test
|
2236
|
+
include Toys::Testing
|
2237
|
+
|
2238
|
+
def test_greet_with_shout_flag
|
2239
|
+
out, err = capture_subprocess_io do
|
2240
|
+
exit_code = toys_run_tool(["greet", "--shout])
|
2241
|
+
assert_equal(0, exit_code)
|
2242
|
+
end
|
2243
|
+
assert_equal("HELLO, WORLD!\n", out)
|
2244
|
+
assert_empty(err)
|
2245
|
+
end
|
2246
|
+
end
|
2247
|
+
|
2248
|
+
It is important to note that `toys_run_tool` executes the tool *in-process* in
|
2249
|
+
your tests. This may be appropriate for simple tools, but may not work for
|
2250
|
+
other cases such as tools that replace the current process using
|
2251
|
+
[Kernel#exec](http://ruby-doc.org/core/Kernel.html#method-i-exec), or tools
|
2252
|
+
that require user interaction. For these cases, you can run a tool in a
|
2253
|
+
separate forked process using the {Toys::Testing#toys_exec_tool} method, which
|
2254
|
+
we shall look at next.
|
2255
|
+
|
2256
|
+
### Running tools out of process
|
2257
|
+
|
2258
|
+
The {Toys::Testing#toys_exec_tool} method, like {Toys::Testing#toys_run_tool},
|
2259
|
+
executes a tool and lets you assert on its behavior. However, while
|
2260
|
+
`toys_run_tool` executes the tool *within the test process*, `toys_exec_tool`
|
2261
|
+
*forks a separate process* to run the tool. This insulates your tests from
|
2262
|
+
anything disruptive the tool might do (such as replacing the current process).
|
2263
|
+
It also provides access to the powerful subprocess control functionality
|
2264
|
+
provided by Toys, letting you redirect, capture, or interact with the tool's
|
2265
|
+
streams while it is running.
|
2266
|
+
|
2267
|
+
There are two ways to run `toys_exec_tool`: in "capture" or "controller" mode.
|
2268
|
+
If you *do not* pass a block to `toys_exec_tool`, you are running in "capture"
|
2269
|
+
mode. It will close the input stream, and capture the output and error streams
|
2270
|
+
and return an object that provides the exit code and the stream contents. This
|
2271
|
+
object is actually an instance of {Toys::Utils::Exec::Result}, the same class
|
2272
|
+
returned by methods from the `:exec` mixin. Thus, we could use "capture" mode
|
2273
|
+
to rewrite our greeting test as follows:
|
2274
|
+
|
2275
|
+
class GreetTest < Minitest::Test
|
2276
|
+
include Toys::Testing
|
2277
|
+
|
2278
|
+
def test_greet_with_no_arguents
|
2279
|
+
result = toys_exec_tool(["greet"])
|
2280
|
+
assert_equal(0, result.exit_code)
|
2281
|
+
assert_equal("Hello, world!\n", result.captured_out)
|
2282
|
+
assert_empty(result.captured_err)
|
2283
|
+
end
|
2284
|
+
end
|
2285
|
+
|
2286
|
+
If you pass a block to `toys_exec_tool`, you will be running in "controller"
|
2287
|
+
mode. In this mode, all the tool's streams are redirected to a controller
|
2288
|
+
object that is passed to your block. See the controller's interface at
|
2289
|
+
{Toys::Utils::Exec::Controller} for more information.
|
2290
|
+
|
2291
|
+
In either mode, you can still override many aspects of the subprocess's
|
2292
|
+
behavior. For example, "capture" closes the input stream by default, but you
|
2293
|
+
can override this and pass data into the tool's input stream by providing the
|
2294
|
+
`:in` keyword argument. The various arguments available are documented in the
|
2295
|
+
{Toys::Utils::Exec} class. Here is an example, passing a string into our tool's
|
2296
|
+
input stream:
|
2297
|
+
|
2298
|
+
class GreetTest < Minitest::Test
|
2299
|
+
include Toys::Testing
|
2300
|
+
|
2301
|
+
def test_greet_ignores_the_input_stream
|
2302
|
+
result = toys_exec_tool(["greet"], in: [:string, "I am ignored"])
|
2303
|
+
assert_equal(0, result.exit_code)
|
2304
|
+
assert_equal("Hello, world!\n", result.captured_out)
|
2305
|
+
assert_empty(result.captured_err)
|
2306
|
+
end
|
2307
|
+
end
|
2308
|
+
|
2309
|
+
It is important to note that `toys_exec_tool` requires the Ruby runtime and
|
2310
|
+
underlying operating system to support `fork`. Standard "MRI" Ruby running on a
|
2311
|
+
Mac or Linux system will work; but JRuby, TruffleRuby, and any Ruby running on
|
2312
|
+
Windows, will not support `fork` and will not be able to run tests that use
|
2313
|
+
`toys_exec_tool`.
|
2314
|
+
|
2315
|
+
### Testing helper methods
|
2316
|
+
|
2317
|
+
The {Toys::Testing} module also provides a way to load tools and test
|
2318
|
+
individual methods without running the entire tool. This can be useful for
|
2319
|
+
writing unit tests for tools that are large, complex, or otherwise should not
|
2320
|
+
be executed in their entirety during testing.
|
2321
|
+
|
2322
|
+
To test individual methods, pass a block to {Toys::Testing#toys_exec_tool}.
|
2323
|
+
This method loads the tool associated with the given command line, parses the
|
2324
|
+
command line arguments, and prepares the tool for execution, but does not
|
2325
|
+
invoke the `run` method. The tool's context is passed to the block, and you can
|
2326
|
+
then execute any of the tool's helper methods and check assertions.
|
2327
|
+
|
2328
|
+
Let's consider an example tool with a helper method:
|
2329
|
+
|
2330
|
+
tool "hello" do
|
2331
|
+
flag :shout
|
2332
|
+
|
2333
|
+
# The normal entrypoint "run" method
|
2334
|
+
def run
|
2335
|
+
puts message
|
2336
|
+
end
|
2337
|
+
|
2338
|
+
# A helper method
|
2339
|
+
def message
|
2340
|
+
shout ? "HELLO" : "hello"
|
2341
|
+
end
|
2342
|
+
end
|
2343
|
+
|
2344
|
+
Normally, testing this tool would involve capturing and asserting against the
|
2345
|
+
output printed by the `run` method. However, we can also test the `message`
|
2346
|
+
method in isolation without capturing any streams by loading the tool and
|
2347
|
+
calling the method directly.
|
2348
|
+
|
2349
|
+
class MyTest < Minitest::Test
|
2350
|
+
include Toys::Testing
|
2351
|
+
|
2352
|
+
# A test of the tool when passed no command-line arguments
|
2353
|
+
def test_message_without_shout
|
2354
|
+
# Load the tool
|
2355
|
+
toys_load_tool(["hello"]) do |tool|
|
2356
|
+
# The tool's context is passed to the block, and you can use it to
|
2357
|
+
# call the tool's methods.
|
2358
|
+
assert_equal("hello", tool.message)
|
2359
|
+
end
|
2360
|
+
end
|
2361
|
+
|
2362
|
+
# Another test that includes a command-line flag
|
2363
|
+
def test_message_with_shout
|
2364
|
+
toys_load_tool(["hello", "--shout"]) do |tool|
|
2365
|
+
assert_equal("HELLO", tool.message)
|
2366
|
+
end
|
2367
|
+
end
|
2368
|
+
end
|
2369
|
+
|
2370
|
+
Like `toys_run_tool`, `toys_load_tool` loads the tool *in-process* in your
|
2371
|
+
tests. This means it would be difficult to use it to test methods that replace
|
2372
|
+
the current process or depend on user interaction. It is not currently possible
|
2373
|
+
to fork `toys_load_tool` into a separate process because Minitest would not be
|
2374
|
+
able to track assertions in that separate process. It is therefore appropriate
|
2375
|
+
mainly for true unit tests of isolated methods.
|
2376
|
+
|
2377
|
+
### Organizing and selecting tests
|
2378
|
+
|
2379
|
+
So far we learned how to define tests in a `.test` directory located directly
|
2380
|
+
within a `.toys` directory. However, it is also possible to locate `.test`
|
2381
|
+
directories within subdirectories. Just like tools and tool namespaces can be
|
2382
|
+
defined within a directory structure, so corresponding tests can be associated
|
2383
|
+
with those tools by putting them in the same subdirectories.
|
2384
|
+
|
2385
|
+
Consider the following `.toys` directory that includes `build` and `deploy`
|
2386
|
+
tools:
|
2387
|
+
|
2388
|
+
(current directory)
|
2389
|
+
|
|
2390
|
+
+- .toys/
|
2391
|
+
|
|
2392
|
+
+- build/
|
2393
|
+
| |
|
2394
|
+
| +- .toys.rb <-- defines "build" (and subtools)
|
2395
|
+
| |
|
2396
|
+
| +- .test/
|
2397
|
+
| |
|
2398
|
+
| +- test_build.rb <-- defines tests for "build"
|
2399
|
+
|
|
2400
|
+
+- deploy/
|
2401
|
+
|
|
2402
|
+
+- .toys.rb <-- defines "deploy" (and subtools)
|
2403
|
+
|
|
2404
|
+
+- .test/
|
2405
|
+
|
|
2406
|
+
+- test_staging.rb <-- defines tests for "deploy"
|
2407
|
+
|
|
2408
|
+
+- test_prod.rb <-- defines more tests for "deploy"
|
2409
|
+
|
2410
|
+
We've now created separate sets of tests under the `build/` and `deploy/`
|
2411
|
+
subdirectories. These are associated with those tools, and we can now run those
|
2412
|
+
sets of tests independently.
|
2413
|
+
|
2414
|
+
To run just the tests under `build/`:
|
2415
|
+
|
2416
|
+
toys system test build
|
2417
|
+
|
2418
|
+
To run just the tests under `deploy/`:
|
2419
|
+
|
2420
|
+
toys system test deploy
|
2421
|
+
|
2422
|
+
Now, if you do not provide a specific tool:
|
2423
|
+
|
2424
|
+
toys system test
|
2425
|
+
|
2426
|
+
...Toys will recursively search for `.test` directories, and run *all* the
|
2427
|
+
tests, including both the build and deploy tests. To disable this recursive
|
2428
|
+
search, pass `--no-recursive`. In the above case, that will result in no tests
|
2429
|
+
running because there are no tests defined at the top level.
|
2430
|
+
|
2431
|
+
It is also possible to focus on specific tests using the
|
2432
|
+
[minitest-focus](https://github.com/seattlerb/minitest-focus) gem. Pass the
|
2433
|
+
`--minitest-focus` argument to `toys system test` to tell it to load the gem,
|
2434
|
+
and you will be able to use the `focus` keyword in your tests to temporarily
|
2435
|
+
focus on a few tests.
|
2436
|
+
|
2099
2437
|
## Using third-party gems
|
2100
2438
|
|
2101
2439
|
The toys executable itself uses only two gems: **toys** and **toys-core**. It
|
@@ -2135,9 +2473,9 @@ feasible for their Gemfiles to be present in every directory from which you
|
|
2135
2473
|
might want to run them.
|
2136
2474
|
|
2137
2475
|
Second, it's possible for a variety of tools to be available together,
|
2138
|
-
including both locally and globally defined, with potentially different
|
2139
|
-
dependencies. With `bundle exec`, you must choose beforehand which
|
2140
|
-
use.
|
2476
|
+
including both locally and globally defined tools, with potentially different
|
2477
|
+
sets of dependencies. With `bundle exec`, you must choose beforehand which
|
2478
|
+
bundle to use.
|
2141
2479
|
|
2142
2480
|
Although traditional `bundle exec` doesn't always work, Toys provides ways for
|
2143
2481
|
individual tools to manage their own gem dependencies.
|
@@ -2176,9 +2514,8 @@ as `bundle exec`, but it applies only to the running tool.
|
|
2176
2514
|
|
2177
2515
|
In many cases, you might find that bundler is needed for many or most of the
|
2178
2516
|
tools you write for a particular project. In this case, you might find it
|
2179
|
-
convenient to use
|
2180
|
-
|
2181
|
-
to include the bundle in all your tools. For example:
|
2517
|
+
convenient to use {Toys::DSL::Tool#subtool_apply} to include the bundle in all
|
2518
|
+
your tools. For example:
|
2182
2519
|
|
2183
2520
|
# Include bundler in every tool under this one
|
2184
2521
|
subtool_apply do
|
@@ -2244,9 +2581,8 @@ simply install the bundle without asking for confirmation:
|
|
2244
2581
|
# etc...
|
2245
2582
|
end
|
2246
2583
|
|
2247
|
-
See the documentation for
|
2248
|
-
|
2249
|
-
for more information about bundler options.
|
2584
|
+
See the documentation for {Toys::StandardMixins::Bundler} for more information
|
2585
|
+
about bundler options.
|
2250
2586
|
|
2251
2587
|
#### Solving bundle conflicts
|
2252
2588
|
|
@@ -2270,15 +2606,15 @@ Toys.
|
|
2270
2606
|
|
2271
2607
|
It might also happen if one tool that uses one bundle, *calls* a tool that uses
|
2272
2608
|
a different bundle. If you need to do this, use the
|
2273
|
-
|
2274
|
-
|
2275
|
-
|
2609
|
+
{Toys::StandardMixins::Exec#exec_separate_tool} method from the `:exec` mixin,
|
2610
|
+
to call the tool. This method spawns a separate process with a clean Bundler
|
2611
|
+
setup for running the tool.
|
2276
2612
|
|
2277
2613
|
#### When a bundle is needed to define a tool
|
2278
2614
|
|
2279
2615
|
Usually, the `:bundler` mixin sets up your bundle when the tool is *executed*.
|
2280
2616
|
However, occasionally, you need the gems in the bundle to *define* a tool. This
|
2281
|
-
might happen, for instance, if your bundle includes
|
2617
|
+
might happen, for instance, if your bundle includes gems that define mixins or
|
2282
2618
|
templates used by your tool.
|
2283
2619
|
|
2284
2620
|
If you need the bundle set up immediately because its gems are needed by the
|
@@ -2324,9 +2660,8 @@ provides a way for a tool to install individual gems without using Bundler.
|
|
2324
2660
|
|
2325
2661
|
Here's an example tool that just runs `rake`. Because it requires rake to be
|
2326
2662
|
installed in order to run the tool, we call the
|
2327
|
-
|
2328
|
-
|
2329
|
-
method:
|
2663
|
+
{Toys::StandardMixins::Gems#gem} method (which is provided by the `:gems`
|
2664
|
+
mixin) at the beginning of the `run` method:
|
2330
2665
|
|
2331
2666
|
tool "rake" do
|
2332
2667
|
include :gems
|
@@ -2381,10 +2716,8 @@ The above techniques for installing a bundle or activating a gem directly, are
|
|
2381
2716
|
all part of the tool definition DSL. However, the functionality is also
|
2382
2717
|
available outside the DSL---for example, from a class-based mixin.
|
2383
2718
|
|
2384
|
-
To set up a bundle, call
|
2385
|
-
|
2386
|
-
(Note that you must `require "toys/utils/gems"` explicitly before invoking the
|
2387
|
-
[Toys::Utils::Gems](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Utils/Gems)
|
2719
|
+
To set up a bundle, call {Toys::Utils::Gems#bundle}. (Note that you must
|
2720
|
+
`require "toys/utils/gems"` explicitly before invoking the {Toys::Utils::Gems}
|
2388
2721
|
class because, like all classes under `Toys::Utils`, Toys does not load it
|
2389
2722
|
automatically.) For example:
|
2390
2723
|
|
@@ -2392,9 +2725,8 @@ automatically.) For example:
|
|
2392
2725
|
gem_utils = Toys::Utils::Gems.new
|
2393
2726
|
gem_utils.bundle(search_dirs: Dir.getwd)
|
2394
2727
|
|
2395
|
-
To activate single gems explicitly, call
|
2396
|
-
|
2397
|
-
For example:
|
2728
|
+
To activate single gems explicitly, call {Toys::Utils::Gems#activate}. For
|
2729
|
+
example:
|
2398
2730
|
|
2399
2731
|
require "toys/utils/gems"
|
2400
2732
|
gem_utils = Toys::Utils::Gems.new
|
@@ -2485,7 +2817,7 @@ how to use Toys for some of the things traditionally done with Rake.
|
|
2485
2817
|
### Comparing Toys and Rake
|
2486
2818
|
|
2487
2819
|
Although Toys and Rake serve many of the same use cases, they have very
|
2488
|
-
different design goals, and it is useful to understand
|
2820
|
+
different design goals, and it is useful to understand the differences.
|
2489
2821
|
|
2490
2822
|
Rake's design is based on the classic "make" tool often provided in unix
|
2491
2823
|
development environments. This design focuses on *targets* and *dependencies*,
|
@@ -2837,8 +3169,7 @@ Now `toys test` delegates to, and thus has the same effect as `toys test unit`.
|
|
2837
3169
|
|
2838
3170
|
Sometimes a group of tools are set up similarly or share a set of flags,
|
2839
3171
|
mixins, or other directives. You can apply a set of directives to all subtools
|
2840
|
-
(recursively) of the current tool, using the
|
2841
|
-
[Toys::DSL::Tool#subtool_apply](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#subtool_apply-instance_method)
|
3172
|
+
(recursively) of the current tool, using the {Toys::DSL::Tool#subtool_apply}
|
2842
3173
|
directive.
|
2843
3174
|
|
2844
3175
|
For example, it is common for tools to use the `:exec` built-in mixin to invoke
|
@@ -2910,7 +3241,7 @@ to accept integers from 1 to 5 is:
|
|
2910
3241
|
acceptor("1to5", [1, 2, 3, 4, 5])
|
2911
3242
|
|
2912
3243
|
There are various other options. See the reference documentation for
|
2913
|
-
|
3244
|
+
{Toys::DSL::Tool#acceptor}.
|
2914
3245
|
|
2915
3246
|
An acceptor is available to the tool in which it is defined, and any subtools
|
2916
3247
|
and descendants defined at the same point in the Toys search path, but not from
|
@@ -3042,8 +3373,8 @@ verbatim to a subprocess.
|
|
3042
3373
|
To disable argument parsing, use the `disable_argument_parsing` directive. This
|
3043
3374
|
directive disables parsing and validation of flags and positional arguments.
|
3044
3375
|
(Thus, it is incompatible with specifying any flags or arguments for the tool.)
|
3045
|
-
Instead, you can retrieve the raw arguments using the
|
3046
|
-
|
3376
|
+
Instead, you can retrieve the raw arguments using the {Toys::Context#args}
|
3377
|
+
method.
|
3047
3378
|
|
3048
3379
|
Here is an example that wraps calls to git:
|
3049
3380
|
|
@@ -3130,8 +3461,8 @@ handler.
|
|
3130
3461
|
|
3131
3462
|
If your handler block or method takes a parameter, Toys will pass it the array
|
3132
3463
|
of usage errors. Otherwise, you can get the array by calling
|
3133
|
-
|
3134
|
-
|
3464
|
+
{Toys::Context#usage_errors}. This array will provide you with a list of the
|
3465
|
+
usage errors encountered.
|
3135
3466
|
|
3136
3467
|
You can also get information about the arguments that could not be parsed from
|
3137
3468
|
the context. For example, the list of unrecognized flags is available from the
|
@@ -3167,15 +3498,13 @@ directory named `.data` and copy your data files there.
|
|
3167
3498
|
|
3168
3499
|
You may then "find" a data file by providing the relative path to the file from
|
3169
3500
|
the `.data` directory. When defining a tool, use the
|
3170
|
-
|
3171
|
-
|
3172
|
-
|
3173
|
-
|
3174
|
-
|
3175
|
-
|
3176
|
-
on it
|
3177
|
-
among the data files, and returns the full path to that file system object. You
|
3178
|
-
may then read the file or perform any other operation on it.
|
3501
|
+
{Toys::DSL::Tool#find_data} directive in a Toys file. Or, at tool execution
|
3502
|
+
time, call {Toys::Context#find_data} (which is a convenience method for getting
|
3503
|
+
the tool source object using the `TOOL_SOURCE` key, and calling
|
3504
|
+
{Toys::SourceInfo#find_data} on it). In either case, `find_data` locates a
|
3505
|
+
matching file (or directory) among the data files, and returns the full path to
|
3506
|
+
that file system object. You may then read the file or perform any other
|
3507
|
+
operation on it.
|
3179
3508
|
|
3180
3509
|
For example, take the following directory structure:
|
3181
3510
|
|
@@ -3451,6 +3780,18 @@ using zsh, however, you can use the `bashcompinit` function to load the toys
|
|
3451
3780
|
bash completion (as well as other bash-based completions). This *mostly* works,
|
3452
3781
|
with a few caveats. Native zsh completion is on the future roadmap.
|
3453
3782
|
|
3783
|
+
### Managing the Git cache
|
3784
|
+
|
3785
|
+
Toys manages a cache of files downloaded from remote Git repositories. This is
|
3786
|
+
used, for example, to share tools via Git. You can manage the contents of the
|
3787
|
+
Toys Git Cache using subtools under the `system git-cache` namespace. This
|
3788
|
+
includes querying the cache and using it to download files from git, gathering
|
3789
|
+
information about cache status, and deleting old data.
|
3790
|
+
|
3791
|
+
To display general information and a list of tools, run:
|
3792
|
+
|
3793
|
+
toys system git-cache --help
|
3794
|
+
|
3454
3795
|
## Writing your own CLI using Toys
|
3455
3796
|
|
3456
3797
|
Although Toys is not primarily designed to help you write a custom command-line
|