toys 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +35 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +7 -4
  6. data/builtins/system/git-cache.rb +238 -0
  7. data/builtins/system/test.rb +37 -2
  8. data/core-docs/toys/acceptor.rb +432 -0
  9. data/core-docs/toys/arg_parser.rb +397 -0
  10. data/core-docs/toys/cli.rb +493 -0
  11. data/core-docs/toys/compat.rb +2 -0
  12. data/core-docs/toys/completion.rb +329 -0
  13. data/core-docs/toys/context.rb +321 -0
  14. data/core-docs/toys/core.rb +14 -0
  15. data/core-docs/toys/dsl/base.rb +56 -0
  16. data/core-docs/toys/dsl/flag.rb +261 -0
  17. data/core-docs/toys/dsl/flag_group.rb +259 -0
  18. data/core-docs/toys/dsl/internal.rb +4 -0
  19. data/core-docs/toys/dsl/positional_arg.rb +139 -0
  20. data/core-docs/toys/dsl/tool.rb +1530 -0
  21. data/core-docs/toys/errors.rb +93 -0
  22. data/core-docs/toys/flag.rb +549 -0
  23. data/core-docs/toys/flag_group.rb +186 -0
  24. data/core-docs/toys/input_file.rb +8 -0
  25. data/core-docs/toys/loader.rb +222 -0
  26. data/core-docs/toys/middleware.rb +295 -0
  27. data/core-docs/toys/mixin.rb +142 -0
  28. data/core-docs/toys/module_lookup.rb +75 -0
  29. data/core-docs/toys/positional_arg.rb +145 -0
  30. data/core-docs/toys/settings.rb +507 -0
  31. data/core-docs/toys/source_info.rb +127 -0
  32. data/core-docs/toys/standard_middleware/add_verbosity_flags.rb +49 -0
  33. data/core-docs/toys/standard_middleware/apply_config.rb +24 -0
  34. data/core-docs/toys/standard_middleware/handle_usage_errors.rb +33 -0
  35. data/core-docs/toys/standard_middleware/set_default_descriptions.rb +222 -0
  36. data/core-docs/toys/standard_middleware/show_help.rb +190 -0
  37. data/core-docs/toys/standard_middleware/show_root_version.rb +45 -0
  38. data/core-docs/toys/standard_mixins/bundler.rb +83 -0
  39. data/core-docs/toys/standard_mixins/exec.rb +645 -0
  40. data/core-docs/toys/standard_mixins/fileutils.rb +18 -0
  41. data/core-docs/toys/standard_mixins/gems.rb +48 -0
  42. data/core-docs/toys/standard_mixins/git_cache.rb +41 -0
  43. data/core-docs/toys/standard_mixins/highline.rb +133 -0
  44. data/core-docs/toys/standard_mixins/terminal.rb +135 -0
  45. data/core-docs/toys/standard_mixins/xdg.rb +49 -0
  46. data/core-docs/toys/template.rb +112 -0
  47. data/core-docs/toys/tool_definition.rb +926 -0
  48. data/core-docs/toys/utils/completion_engine.rb +49 -0
  49. data/core-docs/toys/utils/exec.rb +721 -0
  50. data/core-docs/toys/utils/gems.rb +185 -0
  51. data/core-docs/toys/utils/git_cache.rb +353 -0
  52. data/core-docs/toys/utils/help_text.rb +134 -0
  53. data/core-docs/toys/utils/terminal.rb +310 -0
  54. data/core-docs/toys/utils/xdg.rb +253 -0
  55. data/core-docs/toys/wrappable_string.rb +120 -0
  56. data/core-docs/toys-core.rb +63 -0
  57. data/docs/guide.md +497 -156
  58. data/lib/toys/standard_cli.rb +50 -36
  59. data/lib/toys/templates/clean.rb +18 -0
  60. data/lib/toys/templates/gem_build.rb +24 -0
  61. data/lib/toys/templates/minitest.rb +21 -0
  62. data/lib/toys/templates/rake.rb +23 -3
  63. data/lib/toys/templates/rdoc.rb +29 -0
  64. data/lib/toys/templates/rspec.rb +32 -4
  65. data/lib/toys/templates/rubocop.rb +14 -1
  66. data/lib/toys/templates/yardoc.rb +55 -0
  67. data/lib/toys/testing.rb +186 -109
  68. data/lib/toys/version.rb +1 -1
  69. data/lib/toys.rb +4 -2
  70. 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 replacement, providing a more natural command line
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`. You define the commands recognized
19
- by the Toys executable by writing configuration files. (You can, however, build
20
- your own custom command line executable using the related **toys-core**
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** which support different kinds of constraints on
49
- which flags are required.
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 its
58
- ancestors, and in the Toys **search path**.
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 namespace of **system tools** that let you inspect and configure the
68
- Toys system itself.
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
- [Toys::DSL::Tool#desc](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#desc-instance_method)
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
- [Toys::DSL::Tool#optional_arg](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#optional_arg-instance_method)
392
- to declare an **optional argument** named `:whom`. If the argument is provided
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
- [Toys::DSL::PositionalArg class](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/PositionalArg).
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
- [Toys::DSL::Flag class](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Flag).
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 the
1013
- [Toys::Context#get](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#get-instance_method)
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 the
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 files first before other files in the directory. This
1345
- means they are convenient places to define shared code that can be used by all
1346
- the subtools defined in that directory, as we shall see later in the
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
- [Toys::DSL::Tool#truncate_load_path!](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#truncate_load_path!-instance_method). This directive removes all
1402
- directories further down the search path. It can be used, for example, to
1403
- disable global tools when you run Toys from the current directory. It can also
1404
- be useful if you are using [Bundler integration](#Using_bundler_with_a_tool) to
1405
- prevent bundle conflicts with parent directories, by disabling tools from
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
- [Toys::Context](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context).
1424
- The base class defines helper methods, and provides access to a variety of data
1425
- and objects relevant to your tool. We have already seen earlier how to use the
1426
- [Toys::Context#get](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#get-instance_method)
1427
- method to retrieve option values, and how to use the
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 the
1436
- [Toys::Context#get method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#get-instance_method)
1437
- For example, you can get the full name of the tool being executed like this:
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
- [Toys::Context::Key module](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context/Key).
1447
- They include information about the current execution, such as the tool name and
1448
- the original command line arguments passed to it (before they were parsed).
1449
- They also include some internal Toys objects, which can be used to do things
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 the
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 the
1468
- [Toys::Context#logger method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#logger-instance_method).
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 the
1478
- [Toys::Context#verbosity method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#verbosity-instance_method).
1479
- The verbosity is set to 0 by default. This corresponds to a logger level of
1480
- `WARN`. That is, warnings, errors, and fatals are displayed, while infos and
1481
- debugs are not. However, [as we saw earlier](#Standard_flags), most tools
1482
- automatically respond to the `--verbose` and `--quiet` flags, (or `-v` and
1483
- `-q`), which increment and decrement the verbosity value, respectively. If you
1484
- run a tool with `-v`, the verbosity is incremented to 1, and the logger level
1485
- is set to `INFO`. If you set `-q`, the verbosity is decremented to -1, and the
1486
- logger level is set to `ERROR`. So by using the provided logger, a tool can
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 the
1493
- [Toys::Context#cli method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#cli-instance_method).
1494
- These return the current instance of
1495
- [Toys::CLI](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/CLI) which
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 [Toys::Context](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context)
1517
- are not the only methods available for your tool to call. We
1518
- [saw earlier](#Tool_execution_basics) that a tool can define additional methods
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
- [Toys::StandardMixins](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins).
1539
- We will look at a few examples of the use of these mixins below. Built-in
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
- [Toys::StandardMixins::Exec mixin module](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Exec)
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
- [Toys::StandardMixins::Terminal mixin module](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Terminal)
1590
- and the underyling library
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. Additionally, any Ruby files inside a subdirectory called `.preload`
2057
- are also automatically required.
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 sets of
2139
- dependencies. With `bundle exec`, you must choose beforehand which bundle to
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
- [Toys::DSL::Tool#subtool_apply](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#subtool_apply-instance_method)
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
- [Toys::StandardMixins::Bundler](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Bundler)
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
- [Toys::StandardMixins::Exec#exec_separate_tool](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Exec#exec_separate_tool-instance_method)
2274
- method from the `:exec` mixin, to call the tool. This method spawns a separate
2275
- process with a clean Bundler setup for running the tool.
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 gesm that define mixins or
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
- [Toys::StandardMixins::Gems#gem](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/StandardMixins/Gems#gem-instance_method)
2328
- method (which is provided by the `:gems` mixin) at the beginning of the `run`
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
- [Toys::Utils::Gems#bundle](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Utils/Gems#bundle-instance_method).
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
- [Toys::Utils::Gems#activate](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Utils/Gems#activate-instance_method).
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 them.
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
- [Toys::DSL::Tool#acceptor](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#acceptor-instance_method).
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
- [Toys::Context#args method](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#args-instance_method).
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
- [Toys::Context#usage_errors](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#usage_errors-instance_method).
3134
- This array will provide you with a list of the usage errors encountered.
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
- [Toys::DSL::Tool#find_data](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/DSL/Tool#find_data-instance_method)
3171
- directive in a Toys file. Or, at tool execution time, call
3172
- [Toys::Context#find_data](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/Context#find_data-instance_method)
3173
- (which is a convenience method for getting the tool source object using the
3174
- `TOOL_SOURCE` key, and calling
3175
- [Toys::SourceInfo#find_data](https://dazuma.github.io/toys/gems/toys-core/latest/Toys/SourceInfo#find_data-instance_method)
3176
- on it). In either case, `find_data` locates a matching file (or directory)
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