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