toys-core 0.14.7 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  ##