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.
@@ -3,10 +3,10 @@
3
3
  module Toys
4
4
  module StandardMixins
5
5
  ##
6
- # A set of helper methods for invoking subcommands. Provides shortcuts for
7
- # common cases such as invoking Ruby in a subprocess or capturing output
8
- # in a string. Also provides an interface for controlling a spawned
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
- # When a process is running, you can control it using a
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 = exec_service.exec(["git", "init"], background: true)
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
- exec(clean_cmd, **opts, &block)
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
- capture(clean_cmd, **opts, &block)
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)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fileutils"
4
-
5
3
  module Toys
6
4
  module StandardMixins
7
5
  ##
@@ -20,6 +18,7 @@ module Toys
20
18
  # @private
21
19
  #
22
20
  def self.included(mod)
21
+ require "fileutils"
23
22
  mod.include(::FileUtils)
24
23
  end
25
24
  end
@@ -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
- # You may make these methods available to your tool by including the
14
- # following directive in your tool configuration:
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 ||= Utils::Gems.new(**@__gems_opts)
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
- highline.agree(*args, &block)
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
- highline.ask(*args, &block)
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
- highline.choose(*args, &block)
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
- highline.list(*args, &block)
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
- highline.say(*args, &block)
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
- highline.indent(*args, &block)
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
- highline.newline
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
- highline.puts(*args)
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
- highline.color(*args)
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
- highline.color_code(*args)
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
- highline.uncolor(*args)
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
- highline.new_scope
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
- terminal.puts(str, *styles)
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
- terminal.write(str, *styles)
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
- terminal.ask(prompt, *styles, default: default, trailing_text: trailing_text)
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
- terminal.confirm(prompt, *styles, default: default)
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
- terminal.spinner(leading_text: leading_text, final_text: final_text,
134
- frame_length: frame_length, frames: frames, style: style,
135
- &block)
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|
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fileutils"
4
-
5
3
  module Toys
6
4
  module StandardMixins
7
5
  ##