toys 0.13.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -0
- data/README.md +18 -17
- data/builtins/system/.toys.rb +40 -0
- data/builtins/system/git-cache.rb +15 -10
- data/builtins/system/test.rb +2 -3
- data/builtins/system/tools.rb +145 -0
- data/core-docs/toys/acceptor.rb +50 -8
- data/core-docs/toys/cli.rb +3 -3
- data/core-docs/toys/completion.rb +11 -0
- data/core-docs/toys/context.rb +16 -2
- data/core-docs/toys/core.rb +1 -1
- data/core-docs/toys/dsl/tool.rb +15 -7
- data/core-docs/toys/errors.rb +33 -0
- data/core-docs/toys/flag.rb +11 -0
- data/core-docs/toys/input_file.rb +6 -0
- data/core-docs/toys/loader.rb +146 -5
- data/core-docs/toys/middleware.rb +42 -2
- data/core-docs/toys/settings.rb +17 -0
- data/core-docs/toys/source_info.rb +95 -0
- data/core-docs/toys/standard_mixins/exec.rb +69 -22
- data/core-docs/toys/standard_mixins/pager.rb +46 -0
- data/core-docs/toys/standard_mixins/xdg.rb +7 -7
- data/core-docs/toys/tool_definition.rb +69 -0
- data/core-docs/toys/utils/exec.rb +61 -27
- data/core-docs/toys/utils/pager.rb +104 -0
- data/core-docs/toys/wrappable_string.rb +12 -0
- data/docs/guide.md +92 -67
- data/lib/toys/testing.rb +33 -2
- data/lib/toys/version.rb +1 -1
- metadata +10 -6
@@ -0,0 +1,46 @@
|
|
1
|
+
module Toys
|
2
|
+
module StandardMixins
|
3
|
+
##
|
4
|
+
# **_Defined in the toys-core gem_**
|
5
|
+
#
|
6
|
+
# A mixin that provides a pager.
|
7
|
+
#
|
8
|
+
# This mixin provides an instance of {Toys::Utils::Pager}, which invokes
|
9
|
+
# an external pager for output.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# include :pager
|
14
|
+
#
|
15
|
+
# def run
|
16
|
+
# pager do |io|
|
17
|
+
# io.puts "A long string\n"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
module Pager
|
22
|
+
include Mixin
|
23
|
+
|
24
|
+
##
|
25
|
+
# Context key for the Pager object.
|
26
|
+
# @return [Object]
|
27
|
+
#
|
28
|
+
KEY = ::Object.new.freeze
|
29
|
+
|
30
|
+
##
|
31
|
+
# Access the Pager.
|
32
|
+
#
|
33
|
+
# If *no* block is given, returns the pager object.
|
34
|
+
#
|
35
|
+
# If a block is given, the pager is executed with the given block, and
|
36
|
+
# the exit code of the pager process is returned.
|
37
|
+
#
|
38
|
+
# @return [Toys::Utils::Pager] if no block is given.
|
39
|
+
# @return [Integer] if a block is given.
|
40
|
+
#
|
41
|
+
def pager(&block)
|
42
|
+
# Source available in the toys-core gem
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -12,15 +12,15 @@ module Toys
|
|
12
12
|
# the [XDG Base Directory Spec version
|
13
13
|
# 0.8](https://specifications.freedesktop.org/basedir-spec/0.8/).
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# @example
|
16
16
|
#
|
17
|
-
#
|
17
|
+
# include :xdg
|
18
18
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
19
|
+
# def run
|
20
|
+
# # Get config file paths, in order from most to least inportant
|
21
|
+
# config_files = xdg.lookup_config("my-config.toml")
|
22
|
+
# config_files.each { |path| read_my_config(path) }
|
23
|
+
# end
|
24
24
|
#
|
25
25
|
module XDG
|
26
26
|
include Mixin
|
@@ -106,6 +106,28 @@ module Toys
|
|
106
106
|
settings_attr :propagate_helper_methods, default: false
|
107
107
|
end
|
108
108
|
|
109
|
+
##
|
110
|
+
# Create a new tool.
|
111
|
+
# Should be created only from the DSL via the Loader.
|
112
|
+
#
|
113
|
+
# @private This interface is internal and subject to change without warning.
|
114
|
+
#
|
115
|
+
def initialize(parent, full_name, priority, source_root, middleware_stack, middleware_lookup,
|
116
|
+
tool_class = nil)
|
117
|
+
# Source available in the toys-core gem
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Reset the definition of this tool, deleting all definition data but
|
122
|
+
# leaving named acceptors, mixins, and templates intact.
|
123
|
+
# Should be called only from the DSL.
|
124
|
+
#
|
125
|
+
# @private This interface is internal and subject to change without warning.
|
126
|
+
#
|
127
|
+
def reset_definition
|
128
|
+
# Source available in the toys-core gem
|
129
|
+
end
|
130
|
+
|
109
131
|
##
|
110
132
|
# Settings for this tool
|
111
133
|
#
|
@@ -922,5 +944,52 @@ module Toys
|
|
922
944
|
def delegate_to(target)
|
923
945
|
# Source available in the toys-core gem
|
924
946
|
end
|
947
|
+
|
948
|
+
##
|
949
|
+
# Lookup the custom context directory in this tool and its ancestors.
|
950
|
+
#
|
951
|
+
# @private This interface is internal and subject to change without warning.
|
952
|
+
#
|
953
|
+
def lookup_custom_context_directory
|
954
|
+
# Source available in the toys-core gem
|
955
|
+
end
|
956
|
+
|
957
|
+
##
|
958
|
+
# Mark this tool as having at least one module included.
|
959
|
+
#
|
960
|
+
# @private This interface is internal and subject to change without warning.
|
961
|
+
#
|
962
|
+
def mark_includes_modules
|
963
|
+
# Source available in the toys-core gem
|
964
|
+
end
|
965
|
+
|
966
|
+
##
|
967
|
+
# Complete definition and run middleware configs. Should be called from
|
968
|
+
# the Loader only.
|
969
|
+
#
|
970
|
+
# @private This interface is internal and subject to change without warning.
|
971
|
+
#
|
972
|
+
def finish_definition(loader)
|
973
|
+
# Source available in the toys-core gem
|
974
|
+
end
|
975
|
+
|
976
|
+
##
|
977
|
+
# Run all initializers against a context. Called from the Runner.
|
978
|
+
#
|
979
|
+
# @private This interface is internal and subject to change without warning.
|
980
|
+
#
|
981
|
+
def run_initializers(context)
|
982
|
+
# Source available in the toys-core gem
|
983
|
+
end
|
984
|
+
|
985
|
+
##
|
986
|
+
# Check that the tool can still be defined. Should be called internally
|
987
|
+
# or from the DSL only.
|
988
|
+
#
|
989
|
+
# @private This interface is internal and subject to change without warning.
|
990
|
+
#
|
991
|
+
def check_definition_state(is_arg: false, is_method: false)
|
992
|
+
# Source available in the toys-core gem
|
993
|
+
end
|
925
994
|
end
|
926
995
|
end
|
@@ -50,54 +50,88 @@ module Toys
|
|
50
50
|
# options.
|
51
51
|
#
|
52
52
|
# Three general strategies are available for custom stream handling. First,
|
53
|
-
# you
|
53
|
+
# you can redirect to other streams such as files, IO objects, or Ruby
|
54
54
|
# strings. Some of these options map directly to options provided by the
|
55
|
-
# `Process#spawn` method. Second, you
|
56
|
-
# the streams programmatically. Third, you
|
55
|
+
# `Process#spawn` method. Second, you can use a controller to manipulate
|
56
|
+
# the streams programmatically. Third, you can capture output stream data
|
57
57
|
# and make it available in the result.
|
58
58
|
#
|
59
59
|
# Following is a full list of the stream handling options, along with how
|
60
60
|
# to specify them using the `:in`, `:out`, and `:err` options.
|
61
61
|
#
|
62
|
-
# * **Inherit parent stream:** You
|
62
|
+
# * **Inherit parent stream:** You can inherit the corresponding stream
|
63
63
|
# in the parent process by passing `:inherit` as the option value. This
|
64
64
|
# is the default if the subprocess is *not* run in the background.
|
65
|
-
#
|
65
|
+
#
|
66
|
+
# * **Redirect to null:** You can redirect to a null stream by passing
|
66
67
|
# `:null` as the option value. This connects to a stream that is not
|
67
68
|
# closed but contains no data, i.e. `/dev/null` on unix systems. This
|
68
69
|
# is the default if the subprocess is run in the background.
|
69
|
-
#
|
70
|
+
#
|
71
|
+
# * **Close the stream:** You can close the stream by passing `:close` as
|
70
72
|
# the option value. This is the same as passing `:close` to
|
71
73
|
# `Process#spawn`.
|
72
|
-
#
|
74
|
+
#
|
75
|
+
# * **Redirect to a file:** You can redirect to a file. This reads from
|
73
76
|
# an existing file when connected to `:in`, and creates or appends to a
|
74
77
|
# file when connected to `:out` or `:err`. To specify a file, use the
|
75
|
-
# setting `[:file, "/path/to/file"]`. You
|
78
|
+
# setting `[:file, "/path/to/file"]`. You can also, when writing a
|
76
79
|
# file, append an optional mode and permission code to the array. For
|
77
80
|
# example, `[:file, "/path/to/file", "a", 0644]`.
|
78
|
-
#
|
79
|
-
#
|
81
|
+
#
|
82
|
+
# * **Redirect to an IO object:** You can redirect to an IO object in the
|
83
|
+
# parent process, by passing the IO object as the option value. You can
|
80
84
|
# use any IO object. For example, you could connect the child's output
|
81
85
|
# to the parent's error using `out: $stderr`, or you could connect to
|
82
86
|
# an existing File stream. Unlike `Process#spawn`, this works for IO
|
83
87
|
# objects that do not have a corresponding file descriptor (such as
|
84
88
|
# StringIO objects). In such a case, a thread will be spawned to pipe
|
85
89
|
# the IO data through to the child process.
|
86
|
-
#
|
90
|
+
#
|
91
|
+
# * **Redirect to a pipe:** You can redirect to a pipe created using
|
92
|
+
# `IO.pipe` (i.e. a two-element array of read and write IO objects) by
|
93
|
+
# passing the array as the option value. This will connect the
|
94
|
+
# appropriate IO (either read or write), and close it in the parent.
|
95
|
+
# Thus, you can connect only one process to each end. If you want more
|
96
|
+
# direct control over IO closing behavior, pass the IO object (i.e. the
|
97
|
+
# element of the pipe array) directly.
|
98
|
+
#
|
99
|
+
# * **Combine with another child stream:** You can redirect one child
|
87
100
|
# output stream to another, to combine them. To merge the child's error
|
88
101
|
# stream into its output stream, use `err: [:child, :out]`.
|
89
|
-
#
|
102
|
+
#
|
103
|
+
# * **Read from a string:** You can pass a string to the input stream by
|
90
104
|
# setting `[:string, "the string"]`. This works only for `:in`.
|
91
|
-
#
|
105
|
+
#
|
106
|
+
# * **Capture output stream:** You can capture a stream and make it
|
92
107
|
# available on the {Toys::Utils::Exec::Result} object, using the
|
93
108
|
# setting `:capture`. This works only for the `:out` and `:err`
|
94
109
|
# streams.
|
95
|
-
#
|
110
|
+
#
|
111
|
+
# * **Use the controller:** You can hook a stream to the controller using
|
96
112
|
# the setting `:controller`. You can then manipulate the stream via the
|
97
113
|
# controller. If you pass a block to {Toys::Utils::Exec#exec}, it
|
98
114
|
# yields the {Toys::Utils::Exec::Controller}, giving you access to
|
99
115
|
# streams.
|
100
116
|
#
|
117
|
+
# * **Make copies of an output stream:** You can "tee," or duplicate the
|
118
|
+
# `:out` or `:err` stream and redirect those copies to various
|
119
|
+
# destinations. To specify a tee, use the setting `[:tee, ...]` where
|
120
|
+
# the additional array elements include two or more of the following.
|
121
|
+
# See the corresponding documentation above for more detail.
|
122
|
+
# * `:inherit` to direct to the parent process's stream.
|
123
|
+
# * `:capture` to capture the stream and store it in the result.
|
124
|
+
# * `:controller` to direct the stream to the controller.
|
125
|
+
# * `[:file, "/path/to/file"]` to write to a file.
|
126
|
+
# * An `IO` or `StringIO` object.
|
127
|
+
# * An array of two `IO` objects representing a pipe
|
128
|
+
#
|
129
|
+
# Additionally, the last element of the array can be a hash of options.
|
130
|
+
# Supported options include:
|
131
|
+
# * `:buffer_size` The size of the memory buffer for each element of
|
132
|
+
# the tee. Larger buffers may allow higher throughput. The default
|
133
|
+
# is 65536.
|
134
|
+
#
|
101
135
|
# ### Result handling
|
102
136
|
#
|
103
137
|
# A subprocess result is represented by a {Toys::Utils::Exec::Result}
|
@@ -167,7 +201,7 @@ module Toys
|
|
167
201
|
# not present, the command is not logged.
|
168
202
|
#
|
169
203
|
# * `:log_level` (Integer,false) Level for logging the actual command.
|
170
|
-
# Defaults to Logger::INFO if not present. You
|
204
|
+
# Defaults to Logger::INFO if not present. You can also pass `false` to
|
171
205
|
# disable logging of the command.
|
172
206
|
#
|
173
207
|
# * `:log_cmd` (String) The string logged for the actual command.
|
@@ -222,7 +256,7 @@ module Toys
|
|
222
256
|
end
|
223
257
|
|
224
258
|
##
|
225
|
-
# Execute a command. The command
|
259
|
+
# Execute a command. The command can be given as a single string to pass
|
226
260
|
# to a shell, or an array of strings indicating a posix command.
|
227
261
|
#
|
228
262
|
# If the process is not set to run in the background, and a block is
|
@@ -287,7 +321,7 @@ module Toys
|
|
287
321
|
end
|
288
322
|
|
289
323
|
##
|
290
|
-
# Execute a command. The command
|
324
|
+
# Execute a command. The command can be given as a single string to pass
|
291
325
|
# to a shell, or an array of strings indicating a posix command.
|
292
326
|
#
|
293
327
|
# Captures standard out and returns it as a string.
|
@@ -375,7 +409,7 @@ module Toys
|
|
375
409
|
# An object that controls a subprocess. This object is returned from an
|
376
410
|
# execution running in the background, or is yielded to a control block
|
377
411
|
# for an execution running in the foreground.
|
378
|
-
# You
|
412
|
+
# You can use this object to interact with the subcommand's streams,
|
379
413
|
# send signals to the process, and get its result.
|
380
414
|
#
|
381
415
|
class Controller
|
@@ -466,8 +500,8 @@ module Toys
|
|
466
500
|
##
|
467
501
|
# Redirects the remainder of the given stream.
|
468
502
|
#
|
469
|
-
# You
|
470
|
-
# specified by its path. If specifying a file, you
|
503
|
+
# You can specify the stream as an IO or IO-like object, or as a file
|
504
|
+
# specified by its path. If specifying a file, you can optionally
|
471
505
|
# provide the mode and permissions for the call to `File#open`. You can
|
472
506
|
# also specify the value `:null` to indicate the null file.
|
473
507
|
#
|
@@ -486,8 +520,8 @@ module Toys
|
|
486
520
|
##
|
487
521
|
# Redirects the remainder of the standard input stream.
|
488
522
|
#
|
489
|
-
# You
|
490
|
-
# specified by its path. If specifying a file, you
|
523
|
+
# You can specify the stream as an IO or IO-like object, or as a file
|
524
|
+
# specified by its path. If specifying a file, you can optionally
|
491
525
|
# provide the mode and permissions for the call to `File#open`. You can
|
492
526
|
# also specify the value `:null` to indicate the null file.
|
493
527
|
#
|
@@ -505,8 +539,8 @@ module Toys
|
|
505
539
|
##
|
506
540
|
# Redirects the remainder of the standard output stream.
|
507
541
|
#
|
508
|
-
# You
|
509
|
-
# specified by its path. If specifying a file, you
|
542
|
+
# You can specify the stream as an IO or IO-like object, or as a file
|
543
|
+
# specified by its path. If specifying a file, you can optionally
|
510
544
|
# provide the mode and permissions for the call to `File#open`. You can
|
511
545
|
# also specify the value `:null` to indicate the null file.
|
512
546
|
#
|
@@ -524,8 +558,8 @@ module Toys
|
|
524
558
|
##
|
525
559
|
# Redirects the remainder of the standard error stream.
|
526
560
|
#
|
527
|
-
# You
|
528
|
-
# specified by its path. If specifying a file, you
|
561
|
+
# You can specify the stream as an IO or IO-like object, or as a file
|
562
|
+
# specified by its path. If specifying a file, you can optionally
|
529
563
|
# provide the mode and permissions for the call to `File#open`.
|
530
564
|
#
|
531
565
|
# After calling this, do not interact directly with the stream.
|
@@ -540,7 +574,7 @@ module Toys
|
|
540
574
|
end
|
541
575
|
|
542
576
|
##
|
543
|
-
# Send the given signal to the process. The signal
|
577
|
+
# Send the given signal to the process. The signal can be specified
|
544
578
|
# by name or number.
|
545
579
|
#
|
546
580
|
# @param sig [Integer,String] The signal to send.
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Toys
|
2
|
+
module Utils
|
3
|
+
##
|
4
|
+
# **_Defined in the toys-core gem_**
|
5
|
+
#
|
6
|
+
# A class that invokes an external pager.
|
7
|
+
#
|
8
|
+
# @example Using a pager for regular output
|
9
|
+
#
|
10
|
+
# Toys::Utils::Pager.start do |io|
|
11
|
+
# io.puts "A long string\n"
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Piping output from a command
|
15
|
+
#
|
16
|
+
# exec_service = Toys::Utils::Exec.new
|
17
|
+
# Toys::Utils::Pager.start(exec_service: exec_service) do |io|
|
18
|
+
# exec_service.exec(["/bin/ls", "-alF"], out: io)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
class Pager
|
22
|
+
##
|
23
|
+
# Creates a new pager.
|
24
|
+
#
|
25
|
+
# @param command [String,Array<String>,boolean] The command to use to
|
26
|
+
# invoke the pager. May be specified as a string to be passed to the
|
27
|
+
# shell, an array of strings representing a posix command, the value
|
28
|
+
# `true` to use the default (normally `less -FIRX`), or the value
|
29
|
+
# `false` to disable the pager and write directly to the output
|
30
|
+
# stream. Default is `true`.
|
31
|
+
# @param exec_service [Toys::Utils::Exec] The service to use for
|
32
|
+
# executing commands, or `nil` (the default) to use a default.
|
33
|
+
# @param fallback_io [IO] An IO-like object to write to if the pager is
|
34
|
+
# disabled. Defaults to `$stdout`.
|
35
|
+
#
|
36
|
+
def initialize(command: true, exec_service: nil, fallback_io: nil)
|
37
|
+
# Source available in the toys-core gem
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Runs the pager. Takes a block and yields an IO-like object that passes
|
42
|
+
# text to the pager. Can be called multiple times on the same pager.
|
43
|
+
#
|
44
|
+
# @yieldparam io [IO] An object that can be written to, to pass data to
|
45
|
+
# the pager.
|
46
|
+
# @return [Integer] The exit code of the pager process.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
#
|
50
|
+
# pager = Toys::Utils::Pager.new
|
51
|
+
# pager.start do |io|
|
52
|
+
# io.puts "A long string\n"
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
def start
|
56
|
+
# Source available in the toys-core gem
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# The command for running the pager process. May be specified as a string
|
61
|
+
# to be passed to the shell, an array of strings representing a posix
|
62
|
+
# command, or `nil` to disable the pager and write directly to an output
|
63
|
+
# stream.
|
64
|
+
#
|
65
|
+
# @return [String,Array<String>,nil]
|
66
|
+
#
|
67
|
+
attr_accessor :command
|
68
|
+
|
69
|
+
##
|
70
|
+
# The IO stream used if the pager is disabled or could not be executed.
|
71
|
+
#
|
72
|
+
# @return [IO]
|
73
|
+
#
|
74
|
+
attr_accessor :fallback_io
|
75
|
+
|
76
|
+
class << self
|
77
|
+
##
|
78
|
+
# A convenience method that creates a pager and runs it once by calling
|
79
|
+
# {Pager#start}.
|
80
|
+
#
|
81
|
+
# @param command [String,Array<String>,boolean] The command to use to
|
82
|
+
# invoke the pager. May be specified as a string to be passed to the
|
83
|
+
# shell, an array of strings representing a posix command, the value
|
84
|
+
# `true` to use the default (normally `less -FIRX`), or the value
|
85
|
+
# `false` to disable the pager and write directly to the output
|
86
|
+
# stream. Default is `true`.
|
87
|
+
# @param exec_service [Toys::Utils::Exec] The service to use for
|
88
|
+
# executing commands, or `nil` (the default) to use a default.
|
89
|
+
# @param fallback_io [IO] An IO-like object to write to if the pager is
|
90
|
+
# disabled. Defaults to `$stdout`.
|
91
|
+
# @return [Integer] The exit code of the pager process.
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
#
|
95
|
+
# Toys::Utils::Pager.start do |io|
|
96
|
+
# io.puts "A long string\n"
|
97
|
+
# end
|
98
|
+
def start(command: true, exec_service: nil, fallback_io: nil, &block)
|
99
|
+
# Source available in the toys-core gem
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -4,9 +4,19 @@ module Toys
|
|
4
4
|
#
|
5
5
|
# A string intended for word-wrapped display.
|
6
6
|
#
|
7
|
+
# A WrappableString is an array of string "fragments" representing the atomic
|
8
|
+
# units that should not be split when word-wrapping. It should be possible to
|
9
|
+
# reconstruct the original string by joining these fragments with whitespace.
|
10
|
+
#
|
7
11
|
class WrappableString
|
8
12
|
##
|
9
13
|
# Create a wrapped string.
|
14
|
+
#
|
15
|
+
# You can pass either:
|
16
|
+
#
|
17
|
+
# * A single String, which will be split into fragments by whitespace.
|
18
|
+
# * An array of Strings representing the fragments explicitly.
|
19
|
+
#
|
10
20
|
# @param string [String,Array<String>] The string or array of string
|
11
21
|
# fragments
|
12
22
|
#
|
@@ -34,6 +44,7 @@ module Toys
|
|
34
44
|
|
35
45
|
##
|
36
46
|
# Returns true if the string is empty (i.e. has no fragments)
|
47
|
+
#
|
37
48
|
# @return [Boolean]
|
38
49
|
#
|
39
50
|
def empty?
|
@@ -42,6 +53,7 @@ module Toys
|
|
42
53
|
|
43
54
|
##
|
44
55
|
# Returns the string without any wrapping
|
56
|
+
#
|
45
57
|
# @return [String]
|
46
58
|
#
|
47
59
|
def string
|