toys-core 0.14.7 → 0.15.1
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 +32 -0
- data/LICENSE.md +1 -1
- data/README.md +10 -5
- data/docs/guide.md +534 -39
- data/lib/toys/cli.rb +77 -176
- data/lib/toys/compat.rb +15 -30
- data/lib/toys/context.rb +51 -0
- data/lib/toys/core.rb +1 -1
- data/lib/toys/dsl/flag.rb +40 -2
- data/lib/toys/dsl/flag_group.rb +15 -5
- data/lib/toys/dsl/internal.rb +23 -8
- data/lib/toys/dsl/positional_arg.rb +32 -1
- data/lib/toys/dsl/tool.rb +174 -68
- data/lib/toys/errors.rb +2 -2
- data/lib/toys/loader.rb +2 -3
- data/lib/toys/middleware.rb +3 -2
- data/lib/toys/module_lookup.rb +1 -2
- data/lib/toys/settings.rb +9 -11
- data/lib/toys/standard_middleware/show_help.rb +4 -2
- data/lib/toys/standard_mixins/bundler.rb +16 -1
- data/lib/toys/standard_mixins/exec.rb +31 -8
- data/lib/toys/standard_mixins/fileutils.rb +1 -2
- data/lib/toys/standard_mixins/gems.rb +21 -5
- data/lib/toys/standard_mixins/highline.rb +13 -13
- data/lib/toys/standard_mixins/terminal.rb +7 -7
- data/lib/toys/standard_mixins/xdg.rb +0 -2
- data/lib/toys/tool_definition.rb +154 -53
- data/lib/toys/utils/completion_engine.rb +1 -2
- data/lib/toys/utils/exec.rb +25 -5
- data/lib/toys/utils/gems.rb +4 -1
- data/lib/toys/utils/git_cache.rb +6 -7
- data/lib/toys/utils/help_text.rb +2 -0
- data/lib/toys/utils/pager.rb +4 -3
- data/lib/toys/utils/standard_ui.rb +262 -0
- data/lib/toys/utils/terminal.rb +1 -3
- data/lib/toys/utils/xdg.rb +2 -2
- data/lib/toys-core.rb +51 -3
- metadata +6 -5
@@ -3,10 +3,10 @@
|
|
3
3
|
module Toys
|
4
4
|
module StandardMixins
|
5
5
|
##
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# in a
|
9
|
-
# process's streams.
|
6
|
+
# The `:exec` mixin provides set of helper methods for executing processes
|
7
|
+
# and subcommands. It provides shortcuts for common cases such as invoking
|
8
|
+
# a Ruby script in a subprocess or capturing output in a string. It also
|
9
|
+
# provides an interface for controlling a spawned process's streams.
|
10
10
|
#
|
11
11
|
# You can make these methods available to your tool by including the
|
12
12
|
# following directive in your tool configuration:
|
@@ -16,6 +16,25 @@ module Toys
|
|
16
16
|
# This is a frontend for {Toys::Utils::Exec}. More information is
|
17
17
|
# available in that class's documentation.
|
18
18
|
#
|
19
|
+
# ### Mixin overview
|
20
|
+
#
|
21
|
+
# The mixin provides a number of methods for spawning processes. The most
|
22
|
+
# basic are {#exec} and {#exec_proc}. The {#exec} method spawns an
|
23
|
+
# operating system process specified by an executable and a set of
|
24
|
+
# arguments. The {#exec_proc} method takes a `Proc` and forks a Ruby
|
25
|
+
# process. Both of these can be heavily configured with stream handling,
|
26
|
+
# result handling, and numerous other options described below. The mixin
|
27
|
+
# also provides convenience methods for common cases such as spawning a
|
28
|
+
# Ruby process, spawning a shell script, or capturing output.
|
29
|
+
#
|
30
|
+
# The mixin also stores default configuration that it applies to processes
|
31
|
+
# it spawns. You can change these defaults by calling {#configure_exec}.
|
32
|
+
#
|
33
|
+
# Underlying the mixin is a service object of type {Toys::Utils::Exec}.
|
34
|
+
# Normally you would use the mixin methods to access this functionality,
|
35
|
+
# but you can also retrieve the service object itself by calling
|
36
|
+
# {Toys::Context#get} with the key {Toys::StandardMixins::Exec::KEY}.
|
37
|
+
#
|
19
38
|
# ### Controlling processes
|
20
39
|
#
|
21
40
|
# A process can be started in the *foreground* or the *background*. If you
|
@@ -24,7 +43,7 @@ module Toys
|
|
24
43
|
# If you start a background process, its streams will be redirected to null
|
25
44
|
# by default, and control will be returned to you immediately.
|
26
45
|
#
|
27
|
-
#
|
46
|
+
# While a process is running, you can control it using a
|
28
47
|
# {Toys::Utils::Exec::Controller} object. Use a controller to interact with
|
29
48
|
# the process's input and output streams, send it signals, or wait for it
|
30
49
|
# to complete.
|
@@ -44,7 +63,7 @@ module Toys
|
|
44
63
|
# When running a process in the background, the controller is returned from
|
45
64
|
# the method that starts the process:
|
46
65
|
#
|
47
|
-
# controller =
|
66
|
+
# controller = exec(["git", "init"], background: true)
|
48
67
|
#
|
49
68
|
# ### Stream handling
|
50
69
|
#
|
@@ -464,7 +483,8 @@ module Toys
|
|
464
483
|
#
|
465
484
|
def exec_separate_tool(cmd, **opts, &block)
|
466
485
|
Exec._setup_clean_process(cmd) do |clean_cmd|
|
467
|
-
|
486
|
+
opts = Exec._setup_exec_opts(opts, self)
|
487
|
+
self[KEY].exec(clean_cmd, **opts, &block)
|
468
488
|
end
|
469
489
|
end
|
470
490
|
|
@@ -650,7 +670,8 @@ module Toys
|
|
650
670
|
#
|
651
671
|
def capture_separate_tool(cmd, **opts, &block)
|
652
672
|
Exec._setup_clean_process(cmd) do |clean_cmd|
|
653
|
-
|
673
|
+
opts = Exec._setup_exec_opts(opts, self)
|
674
|
+
self[KEY].capture(clean_cmd, **opts, &block)
|
654
675
|
end
|
655
676
|
end
|
656
677
|
|
@@ -809,6 +830,8 @@ module Toys
|
|
809
830
|
end
|
810
831
|
|
811
832
|
on_initialize do |**opts|
|
833
|
+
require "rbconfig"
|
834
|
+
require "shellwords"
|
812
835
|
require "toys/utils/exec"
|
813
836
|
context = self
|
814
837
|
opts = Exec._setup_exec_opts(opts, context)
|
@@ -10,11 +10,24 @@ module Toys
|
|
10
10
|
# tool DSL itself, so you can also ensure a gem is present when defining a
|
11
11
|
# tool.
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# ### Usage
|
14
|
+
#
|
15
|
+
# Make these methods available to your tool by including this mixin in your
|
16
|
+
# tool:
|
15
17
|
#
|
16
18
|
# include :gems
|
17
19
|
#
|
20
|
+
# You can then call the mixin method {#gem} to ensure that a gem is
|
21
|
+
# installed and in the load path. For example:
|
22
|
+
#
|
23
|
+
# tool "my_tool" do
|
24
|
+
# include :gems
|
25
|
+
# gem "nokogiri", "~> 1.15"
|
26
|
+
# def run
|
27
|
+
# # Do stuff with Nokogiri
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
18
31
|
# If you pass additional options to the include directive, those are used
|
19
32
|
# to initialize settings for the gem install process. For example:
|
20
33
|
#
|
@@ -34,7 +47,8 @@ module Toys
|
|
34
47
|
end
|
35
48
|
|
36
49
|
##
|
37
|
-
# Activate the given gem.
|
50
|
+
# Activate the given gem. If it is not present, attempt to install it (or
|
51
|
+
# inform the user to update the bundle).
|
38
52
|
#
|
39
53
|
# @param name [String] Name of the gem
|
40
54
|
# @param requirements [String...] Version requirements
|
@@ -51,9 +65,11 @@ module Toys
|
|
51
65
|
# @private
|
52
66
|
#
|
53
67
|
def self.gems
|
54
|
-
require "toys/utils/gems"
|
55
68
|
# rubocop:disable Naming/MemoizedInstanceVariableName
|
56
|
-
@__gems ||=
|
69
|
+
@__gems ||= begin
|
70
|
+
require "toys/utils/gems"
|
71
|
+
Utils::Gems.new(**@__gems_opts)
|
72
|
+
end
|
57
73
|
# rubocop:enable Naming/MemoizedInstanceVariableName
|
58
74
|
end
|
59
75
|
|
@@ -49,89 +49,89 @@ module Toys
|
|
49
49
|
# Calls [HighLine#agree](https://www.rubydoc.info/gems/highline/HighLine:agree)
|
50
50
|
#
|
51
51
|
def agree(*args, &block)
|
52
|
-
|
52
|
+
self[KEY].agree(*args, &block)
|
53
53
|
end
|
54
54
|
|
55
55
|
##
|
56
56
|
# Calls [HighLine#ask](https://www.rubydoc.info/gems/highline/HighLine:ask)
|
57
57
|
#
|
58
58
|
def ask(*args, &block)
|
59
|
-
|
59
|
+
self[KEY].ask(*args, &block)
|
60
60
|
end
|
61
61
|
|
62
62
|
##
|
63
63
|
# Calls [HighLine#choose](https://www.rubydoc.info/gems/highline/HighLine:choose)
|
64
64
|
#
|
65
65
|
def choose(*args, &block)
|
66
|
-
|
66
|
+
self[KEY].choose(*args, &block)
|
67
67
|
end
|
68
68
|
|
69
69
|
##
|
70
70
|
# Calls [HighLine#list](https://www.rubydoc.info/gems/highline/HighLine:list)
|
71
71
|
#
|
72
72
|
def list(*args, &block)
|
73
|
-
|
73
|
+
self[KEY].list(*args, &block)
|
74
74
|
end
|
75
75
|
|
76
76
|
##
|
77
77
|
# Calls [HighLine#say](https://www.rubydoc.info/gems/highline/HighLine:say)
|
78
78
|
#
|
79
79
|
def say(*args, &block)
|
80
|
-
|
80
|
+
self[KEY].say(*args, &block)
|
81
81
|
end
|
82
82
|
|
83
83
|
##
|
84
84
|
# Calls [HighLine#indent](https://www.rubydoc.info/gems/highline/HighLine:indent)
|
85
85
|
#
|
86
86
|
def indent(*args, &block)
|
87
|
-
|
87
|
+
self[KEY].indent(*args, &block)
|
88
88
|
end
|
89
89
|
|
90
90
|
##
|
91
91
|
# Calls [HighLine#newline](https://www.rubydoc.info/gems/highline/HighLine:newline)
|
92
92
|
#
|
93
93
|
def newline
|
94
|
-
|
94
|
+
self[KEY].newline
|
95
95
|
end
|
96
96
|
|
97
97
|
##
|
98
98
|
# Calls [HighLine#puts](https://www.rubydoc.info/gems/highline/HighLine:puts)
|
99
99
|
#
|
100
100
|
def puts(*args)
|
101
|
-
|
101
|
+
self[KEY].puts(*args)
|
102
102
|
end
|
103
103
|
|
104
104
|
##
|
105
105
|
# Calls [HighLine#color](https://www.rubydoc.info/gems/highline/HighLine:color)
|
106
106
|
#
|
107
107
|
def color(*args)
|
108
|
-
|
108
|
+
self[KEY].color(*args)
|
109
109
|
end
|
110
110
|
|
111
111
|
##
|
112
112
|
# Calls [HighLine#color_code](https://www.rubydoc.info/gems/highline/HighLine:color_code)
|
113
113
|
#
|
114
114
|
def color_code(*args)
|
115
|
-
|
115
|
+
self[KEY].color_code(*args)
|
116
116
|
end
|
117
117
|
|
118
118
|
##
|
119
119
|
# Calls [HighLine#uncolor](https://www.rubydoc.info/gems/highline/HighLine:uncolor)
|
120
120
|
#
|
121
121
|
def uncolor(*args)
|
122
|
-
|
122
|
+
self[KEY].uncolor(*args)
|
123
123
|
end
|
124
124
|
|
125
125
|
##
|
126
126
|
# Calls [HighLine#new_scope](https://www.rubydoc.info/gems/highline/HighLine:new_scope)
|
127
127
|
#
|
128
128
|
def new_scope
|
129
|
-
|
129
|
+
self[KEY].new_scope
|
130
130
|
end
|
131
131
|
|
132
132
|
on_initialize do |*args|
|
133
133
|
require "toys/utils/gems"
|
134
|
-
Toys::Utils::Gems.activate("highline", "~> 2.0")
|
134
|
+
::Toys::Utils::Gems.activate("highline", "~> 2.0")
|
135
135
|
require "highline"
|
136
136
|
self[KEY] = ::HighLine.new(*args)
|
137
137
|
self[KEY].use_color = $stdout.tty?
|
@@ -54,7 +54,7 @@ module Toys
|
|
54
54
|
# @return [self]
|
55
55
|
#
|
56
56
|
def puts(str = "", *styles)
|
57
|
-
|
57
|
+
self[KEY].puts(str, *styles)
|
58
58
|
self
|
59
59
|
end
|
60
60
|
alias say puts
|
@@ -70,7 +70,7 @@ module Toys
|
|
70
70
|
# @return [self]
|
71
71
|
#
|
72
72
|
def write(str = "", *styles)
|
73
|
-
|
73
|
+
self[KEY].write(str, *styles)
|
74
74
|
self
|
75
75
|
end
|
76
76
|
|
@@ -89,7 +89,7 @@ module Toys
|
|
89
89
|
# @return [String]
|
90
90
|
#
|
91
91
|
def ask(prompt, *styles, default: nil, trailing_text: :default)
|
92
|
-
|
92
|
+
self[KEY].ask(prompt, *styles, default: default, trailing_text: trailing_text)
|
93
93
|
end
|
94
94
|
|
95
95
|
##
|
@@ -105,7 +105,7 @@ module Toys
|
|
105
105
|
# @return [Boolean]
|
106
106
|
#
|
107
107
|
def confirm(prompt = "Proceed?", *styles, default: nil)
|
108
|
-
|
108
|
+
self[KEY].confirm(prompt, *styles, default: default)
|
109
109
|
end
|
110
110
|
|
111
111
|
##
|
@@ -130,9 +130,9 @@ module Toys
|
|
130
130
|
#
|
131
131
|
def spinner(leading_text: "", final_text: "",
|
132
132
|
frame_length: nil, frames: nil, style: nil, &block)
|
133
|
-
|
134
|
-
|
135
|
-
|
133
|
+
self[KEY].spinner(leading_text: leading_text, final_text: final_text,
|
134
|
+
frame_length: frame_length, frames: frames, style: style,
|
135
|
+
&block)
|
136
136
|
end
|
137
137
|
|
138
138
|
on_initialize do |**opts|
|