toys 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4090b70821f47975fbfd82cd40651b3ee93e43ecf77cb7a820f20322524a3447
4
- data.tar.gz: 70440b824c11d8c7b14e0cda8bfd57f8a74df0aa084c5f47b63efbd3047a7706
3
+ metadata.gz: 7744684eb5fd0d03f650315fad4bb84bc433d0ce4e0529c82f6bf2ebcb60f9f5
4
+ data.tar.gz: 26c4d2e48917887441bd6bc03986110f7269bdd2b1f0098d1b9cd3a19a5b0248
5
5
  SHA512:
6
- metadata.gz: e2a58b4eea98ed65f797dcccdef7bc5abbb3df45aa9771263e9c69bc809b3d15507521cfc012753285dc9464c441db0d08e7a31c15c098e610fffe959888e621
7
- data.tar.gz: 41a9dbfee92b60d34cb74b07ac8599a8bf01da0203d386dcfd73a3dac8711030d97c6548ff40caa3dd63dc9fb123c14eb590dbb6a5809679978ebc081328141d
6
+ metadata.gz: 61445d45a25a6d64f9f2fc547e38589b7f49d8cdf08a07e7bff33b3687307bbeed4b7aa1f8528c2c91a6abf52c3bea86a79392d3d0bbf98652fe5fd2d526f693
7
+ data.tar.gz: a08b400babfecc9c6fd119447d37f62df645986b3d23e5ef381cbf7e05d766b3d1eebd97d0947bb7a8c7cd5b5f53c59aaca329f4bfbb4a8c0463520b11ca1dca
@@ -1,5 +1,14 @@
1
1
  # Release History
2
2
 
3
+ ### 0.3.7 / 2018-05-30
4
+
5
+ * CHANGED: Execution runs in the same scope as the DSL, which lets us use normal methods instead of helper-blocks.
6
+ * CHANGED: Renamed "script" to "run", and allow setting of runnable by defining a "run" method
7
+ * CHANGED: Set up a constant scope for each config file, to make constant lookup make sense.
8
+ * CHANGED: Removed run_toys and dropped EXIT_ON_NONZERO_STATUS key in favor of using cli directly.
9
+ * CHANGED: Removed spinner helper and added terminal helper.
10
+ * ADDED: Helper modules scoped to the tool hierarchy
11
+
3
12
  ### 0.3.6 / 2018-05-21
4
13
 
5
14
  * CHANGED: Removed Context#new_cli and exposed Context#cli instead.
data/README.md CHANGED
@@ -69,8 +69,8 @@ current directory. Copy the following into the file, and save it:
69
69
  tool "greet" do
70
70
  desc "My first tool!"
71
71
  flag :whom, default: "world"
72
- script do
73
- puts "Hello, #{options[:whom]}!"
72
+ def run
73
+ puts "Hello, #{option(:whom)}!"
74
74
  end
75
75
  end
76
76
 
@@ -107,9 +107,10 @@ various subtools, such as "version", are available under that namespace.
107
107
 
108
108
  Toys provides a rich set of useful libraries for writing tools. It gives you a
109
109
  logger and automatically provides flags to control verbosity of log output. It
110
- includes the Highline library, which you can use to produce styled output,
111
- console-based interfaces, and special effects. It also includes a library that
112
- makes it easy to control subprocesses.
110
+ includes a simple library that you can use to produce styled output and basic
111
+ console-based interfaces, and another library that makes it easy to spawn and
112
+ control subprocesses. You can also take advantage of a variety of third-party
113
+ libraries such as Highline and TTY.
113
114
 
114
115
  For a more detailed look at Toys, see the
115
116
  {file:docs/tutorial.md Extended Tutorial} and the
data/bin/toys CHANGED
@@ -29,6 +29,8 @@
29
29
  # POSSIBILITY OF SUCH DAMAGE.
30
30
  ;
31
31
 
32
+ ::ENV["TOYS_BIN_PATH"] ||= ::File.absolute_path(__FILE__)
33
+
32
34
  $LOAD_PATH.unshift(::File.absolute_path(::File.join(::File.dirname(__dir__), "lib")))
33
35
  require "toys"
34
36
 
@@ -54,12 +54,11 @@ flag :delim, "-d", "--delim=VALUE",
54
54
 
55
55
  remaining_args :args, desc: "A series of tools to run, separated by the delimiter"
56
56
 
57
- script do
58
- delim = self[:delim]
59
- self[:args]
60
- .chunk { |arg| arg == delim ? :_separator : true }
57
+ def run
58
+ option(:args)
59
+ .chunk { |arg| arg == option(:delim) ? :_separator : true }
61
60
  .each do |_, action|
62
- code = run(action)
61
+ code = cli.run(action)
63
62
  exit(code) unless code.zero?
64
63
  end
65
64
  end
@@ -32,42 +32,56 @@ desc "A set of system commands for Toys"
32
32
  long_desc "Contains tools that inspect, configure, and update Toys itself."
33
33
 
34
34
  tool "version" do
35
- desc "Print current Toys version."
35
+ desc "Print the current Toys version"
36
36
 
37
- script do
37
+ def run
38
38
  puts ::Toys::VERSION
39
39
  end
40
40
  end
41
41
 
42
42
  tool "update" do
43
- desc "Update Toys if a newer version is available."
43
+ desc "Update Toys if a newer version is available"
44
44
 
45
45
  long_desc "Checks rubygems for a newer version of Toys. If one is available, downloads" \
46
46
  " and installs it."
47
47
 
48
48
  flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
49
49
 
50
- use :exec
51
- use :highline
50
+ include :exec
51
+ include :terminal
52
52
 
53
- script do
54
- logger.info "Checking rubygems for the latest Toys release..."
55
- version_info = capture("gem query -q -r -e toys")
53
+ def run
54
+ configure_exec(exit_on_nonzero_status: true)
55
+ version_info = terminal.spinner(leading_text: "Checking rubygems for the latest release... ",
56
+ final_text: "Done.\n") do
57
+ capture(["gem", "query", "-q", "-r", "-e", "toys"])
58
+ end
56
59
  if version_info =~ /toys\s\((.+)\)/
57
60
  latest_version = ::Gem::Version.new($1)
58
61
  cur_version = ::Gem::Version.new(::Toys::VERSION)
59
62
  if latest_version > cur_version
60
- exit(1) unless options[:yes] ||
61
- agree("Update toys from #{cur_version} to #{latest_version}? (y/n) ")
62
- sh("gem install toys")
63
+ prompt = "Update toys from #{cur_version} to #{latest_version}?"
64
+ exit(1) unless option(:yes) || confirm(prompt)
65
+ result = terminal.spinner(leading_text: "Installing Toys version #{latest_version}... ",
66
+ final_text: "Done.\n") do
67
+ exec(["gem", "install", "toys", "--version", latest_version],
68
+ out_to: :capture, err_to: :capture)
69
+ end
70
+ if result.error?
71
+ puts(result.captured_out + result.captured_err)
72
+ puts("Toys failed to install version #{latest_version}", :red, :bold)
73
+ exit(1)
74
+ end
75
+ puts("Toys successfully installed version #{latest_version}", :green, :bold)
63
76
  elsif latest_version < cur_version
64
- logger.warn("Toys is already at experimental version #{cur_version}, which is later than" \
65
- " the latest released version #{latest_version}")
77
+ puts("Toys is already at experimental version #{cur_version}, which is later than" \
78
+ " the latest released version #{latest_version}",
79
+ :yellow, :bold)
66
80
  else
67
- logger.warn("Toys is already at the latest version: #{latest_version}")
81
+ puts("Toys is already at the latest version: #{latest_version}", :green, :bold)
68
82
  end
69
83
  else
70
- logger.error("Could not get latest Toys version")
84
+ puts("Could not get latest Toys version", :red, :bold)
71
85
  exit(1)
72
86
  end
73
87
  end
@@ -14,34 +14,34 @@ This user's guide covers everything you need to know to use Toys effectively.
14
14
 
15
15
  Toys is a command line *framework*. It provides a binary called `toys` along
16
16
  with basic functions such as argument parsing and online help. You provide the
17
- actual behavior of the toys binary by writing *configuration files*.
17
+ actual behavior of the toys binary by writing **configuration files**.
18
18
 
19
19
  Toys is a multi-command binary. You may define a collection of commands, called
20
- *tools*, which can be invoked by passing the tool name as an argument to the
21
- `toys` binary. Tools are arranged in a hierarchy; a tool may be a *namespace*
20
+ **tools**, which can be invoked by passing the tool name as an argument to the
21
+ `toys` binary. Tools are arranged in a hierarchy; a tool may be a **namespace**
22
22
  that has *subtools*.
23
23
 
24
- Tools may recognize command line arguments in the form of *flags* and
25
- *positional arguments*. Flags can optionally take *values*, while positional
26
- arguments may be *required* or *optional*.
24
+ Tools may recognize command line arguments in the form of **flags** and
25
+ **positional arguments**. Flags can optionally take **values**, while
26
+ positional arguments may be **required** or **optional**.
27
27
 
28
- The configuration of a tool may define *descriptions*, for the tool itself, and
29
- for each command line argument. These descriptions are displayed in the tool's
30
- *online help* screen. Descriptions come in *long* and *short* forms, which
31
- appear in different styles of help.
28
+ The configuration of a tool may define **descriptions**, for the tool itself,
29
+ and for each command line argument. These descriptions are displayed in the
30
+ tool's **online help** screen. Descriptions come in **long** and **short**
31
+ forms, which appear in different styles of help.
32
32
 
33
- Toys searches for configuration in specifically-named *configuration files* and
34
- *configuration directories*. It searches for these in the current directory,
35
- and in a *configuration search path*.
33
+ Toys searches for configuration in specifically-named **configuration files**
34
+ and **configuration directories**. It searches for these in the current
35
+ directory, its ancestors, and in a **configuration search path**.
36
36
 
37
37
  Toys provides various features to help you write tools. This includes providing
38
- a *logger* for each tool, *helper modules* that provide common functions a tool
39
- can call, and *templates* which are prefabricated tools you can add to your
40
- configuration.
38
+ a **logger** for each tool, **helper modules** that provide common functions a
39
+ tool can call, and **templates** which are prefabricated tools you can add to
40
+ your configuration.
41
41
 
42
- Finally, Toys provides certain *built-in behavior*, including automatically
42
+ Finally, Toys provides certain **built-in behavior**, including automatically
43
43
  providing flags to display help screens and set verbosity. It also includes a
44
- built-in namespace of *system tools* that let you inspect and configure the
44
+ built-in namespace of **system tools** that let you inspect and configure the
45
45
  Toys system itself.
46
46
 
47
47
  ## The Toys Command Line
@@ -76,7 +76,7 @@ In the following command:
76
76
  toys system blah
77
77
 
78
78
  There is no subtool `blah` under the `system` namespace, so Toys works backward
79
- until it finds a legitimate tool. In this case, the `system` namespace itself
79
+ until it finds an existing tool. In this case, the `system` namespace itself
80
80
  does exist, so it is interpreted as the tool, and `blah` is interpreted as an
81
81
  argument passed to it.
82
82
 
@@ -152,8 +152,8 @@ That will cause `--recursive` to be treated as a positional argument. (In this
152
152
  case, as we saw earlier, the root tool will respond by printing an error
153
153
  message that no subtool named `--recursive` exists.)
154
154
 
155
- Note that a single hyphen by itself `-` is not considered a flag and is treated
156
- as a positional argument.
155
+ Note that a single hyphen by itself `-` is not considered a flag, nor does it
156
+ disable flag parsing. It is treated as a normal positional argument.
157
157
 
158
158
  #### Standard Flags
159
159
 
@@ -224,16 +224,192 @@ like so:
224
224
 
225
225
  ## Defining Tools
226
226
 
227
+ Tools are defined by writing Toys *configuration files*. The simplest form of a
228
+ configuration file is a file named `.toys.rb` (note the leading period) in the
229
+ current working directory. Such a file may define tools that are available in
230
+ the current directory, and for this section we will assume we are writing such
231
+ a file. The following section on "Understanding Configurations" will cover the
232
+ larger concerns of how configuration files are looked up and how multiple
233
+ configurations interact.
234
+
235
+ ### Basic Config Syntax
236
+
237
+ The format of a Toys configuration file is a Ruby DSL including method calls
238
+ and nested blocks. The actual DSL is specified in the
239
+ [Toys::DSL::Tool class](https://www.rubydoc.info/gems/toys-core/Toys/DSL/Tool).
240
+
241
+ To create a tool, write a `tool` block, giving the tool a name. Within the
242
+ block, set the properties of the tool, including a description, the flags and
243
+ arguments recognized by the tool, and the actual functionality of the tool.
244
+
245
+ Consider the following example:
246
+
247
+ tool "greet" do
248
+ desc "Print a friendly greeting."
249
+ long_desc "Prints a friendly greeting. You may customize whom to" \
250
+ " greet, and how friendly it should be.",
251
+ "",
252
+ "Example:",
253
+ [" toys greet --shout ruby"]
254
+
255
+ optional_arg :whom, default: "world", desc: "Whom to greet."
256
+ flag :shout, "-s", "--shout", desc: "Greet loudly."
257
+
258
+ def run
259
+ greeting = "Hello, #{option(:whom)}!"
260
+ greeting.upcase! if option(:shout)
261
+ puts greeting
262
+ end
263
+ end
264
+
265
+ Its results should be mostly self-evident. We'll take a look at some of the
266
+ details below.
267
+
268
+ ### Descriptions
269
+
270
+ Each tool may have a short and a long description. The short description is a
271
+ generally a single string that is displayed with the tool name at the top of
272
+ its help page, or in a subtool list. The long description can include multiple
273
+ strings, which are displayed in multiple lines in the "description" section of
274
+ the tool's help page. Long descriptions may include blank lines to separate
275
+ paragraphs visually.
276
+
277
+ Each description string/line is word-wrapped by default when displayed. In the
278
+ long description above, the first line is a bit longer than 80 characters, and
279
+ may be word-wrapped if displayed on an 80-character terminal.
280
+
281
+ If you need to control the wrapping behavior, pass an array of strings for that
282
+ line. Each array element will be considered a unit for wrapping purposes, and
283
+ will not be split. The example command in the long description above
284
+ illustrates how to prevent a line from being word-wrapped. This is also a
285
+ useful technique for preserving spaces and indentation.
286
+
287
+ For more details, see the reference documentation for
288
+ [DSL::Tool#desc](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:desc)
289
+ and
290
+ [DSL::Tool#long_desc](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:long_desc).
291
+
292
+ ### Positional Arguments
293
+
294
+ Tools may recognize required and optional positional arguments. Each argument
295
+ must provide a name, which defines how the argument value is exposed to the
296
+ tool at execution time. The above example uses the DSL method
297
+ [DSL::Tool#optional_arg](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:optional_arg)
298
+ to declare an optional argument named `:whom`. If the argument is provided on
299
+ the command line e.g.
300
+
301
+ toys greet ruby
302
+
303
+ Then the option `:whom` is set to the string `"ruby"`. The value is made
304
+ available via the `options` hash in the tools's script. Otherwise, if the
305
+ argument is omitted, e.g.
306
+
307
+ toys greet
308
+
309
+ Then the option `:whom` is set to the default value `"world"`.
310
+
311
+ Arguments may also be **required** which means they must be provided on the
312
+ command line; otherwise the tool will report a usage error. You may declare a
313
+ required argument using the DSL method
314
+ [DSL::Tool#required_arg](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:required_arg).
315
+
316
+ When command line arguments are parsed, the required arguments are matched
317
+ first, in order, followed by the optional arguments. For example:
318
+
319
+ tool "arguments" do
320
+ optional_arg :arg2
321
+ required_arg :arg1
322
+ # ...
323
+
324
+ If a user runs
325
+
326
+ toys arguments foo
327
+
328
+ Then the required argument `:arg1` will be set to `"foo"`, and the optional
329
+ argument `:arg2` will not be set (i.e. it will remain `nil`).
330
+
331
+ If the user runs:
332
+
333
+ toys arguments foo bar
334
+
335
+ Then `:arg1` is set to `"foo"`, and `:arg2` is set to `"bar"`.
336
+
337
+ Running the following:
338
+
339
+ toys arguments
340
+
341
+ Will produce a usage error, because no value is set for the required argument
342
+ `:arg1`. Similarly, running:
343
+
344
+ toys arguments foo bar baz
345
+
346
+ Will also produce an error, since the tool does not provide an argument to
347
+ match `"baz"`.
348
+
349
+ You can also provide an "argument" to match all remaining unmatched arguments
350
+ at the end, using the DSL method
351
+ [DSL::Tool#remaining_args](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:remaining_args). For example:
352
+
353
+ tool "arguments" do
354
+ optional_arg :arg2
355
+ required_arg :arg1
356
+ remaining_args :arg3
357
+ # ...
358
+
359
+ Now, running:
360
+
361
+ toys arguments foo bar baz bey
362
+
363
+ Sets the following option data:
364
+
365
+ {arg1: "foo", arg2: "bar", arg3: ["baz", "bey"]}
366
+
367
+ Positional arguments may also have short and long descriptions, which are
368
+ displayed in online help.
369
+
370
+ ### Flags
371
+
372
+ Tools may also recognize flags on the command line. In our "greet" example, we
373
+ declared a flag named `:shout`:
374
+
375
+ flag :shout, "-s", "--shout", desc: "Greet loudly."
376
+
377
+ (guid is still incomplete)
378
+
379
+ ### The Execution Script
380
+
381
+ ### Namespaces
382
+
227
383
  ## Understanding Configurations
228
384
 
229
385
  ## Helper Methods and Modules
230
386
 
231
- ## The Standard Helpers
387
+ ### The Standard Helpers
388
+
389
+ ## The Execution Environment
390
+
391
+ ### Built-in Context
392
+
393
+ ### Logging and Verbosity
394
+
395
+ ### Running Tools from Tools
396
+
397
+ ### Executing Subprocesses
398
+
399
+ ### Formatting Output
232
400
 
233
401
  ## Prefabricated Tools with Templates
234
402
 
235
- ## Defining Templates
403
+ ### Defining Templates
236
404
 
237
405
  ## Advanced Tool Definition Techniques
238
406
 
407
+ ### Aliases
408
+
409
+ ### Includes
410
+
411
+ ### Controlling Built-in Flags
412
+
413
+ ## The System Tools
414
+
239
415
  ## Embedding Toys
@@ -34,6 +34,11 @@
34
34
  # individual directories.
35
35
  #
36
36
  module Toys
37
+ ##
38
+ # Path to the Toys binary
39
+ # @return [String]
40
+ #
41
+ BINARY_PATH = ::ENV["TOYS_BIN_PATH"] || "toys"
37
42
  end
38
43
 
39
44
  require "toys/version"
@@ -75,7 +75,7 @@ module Toys
75
75
  # Short description for the standard root tool
76
76
  # @return [String]
77
77
  #
78
- DEFAULT_ROOT_DESC = "Your personal command line tool.".freeze
78
+ DEFAULT_ROOT_DESC = "Your personal command line tool".freeze
79
79
 
80
80
  ##
81
81
  # Help text for the standard root tool
@@ -125,9 +125,9 @@ module Toys
125
125
  # `$HOME:/etc` by default.
126
126
  # * The builtins for the standard toys binary.
127
127
  #
128
+ # @param [Toys::CLI] cli Add paths to this CLI
128
129
  # @param [String,nil] directory Starting search directory for configs.
129
130
  # Defaults to the current working directory.
130
- # @param [Toys::CLI] cli Add paths to this CLI
131
131
  #
132
132
  def self.add_standard_paths(cli, directory: nil)
133
133
  cli.add_search_path_hierarchy(start: directory)
@@ -32,5 +32,5 @@ module Toys
32
32
  # Current version of the Toys command line binary
33
33
  # @return [String]
34
34
  #
35
- VERSION = "0.3.6".freeze
35
+ VERSION = "0.3.7".freeze
36
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-21 00:00:00.000000000 Z
11
+ date: 2018-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: toys-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.3.6
19
+ version: 0.3.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.3.6
26
+ version: 0.3.7
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement