toys 0.12.2 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|