cmds 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cmds
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nrser
@@ -142,7 +142,6 @@ files:
142
142
  - bin/rspec
143
143
  - cmds.gemspec
144
144
  - lib/cmds.rb
145
- - lib/cmds/cmd.rb
146
145
  - lib/cmds/debug.rb
147
146
  - lib/cmds/erb_context.rb
148
147
  - lib/cmds/io_handler.rb
data/lib/cmds/cmd.rb DELETED
@@ -1,411 +0,0 @@
1
- # deps
2
- require 'nrser'
3
-
4
- # project
5
- require 'cmds/debug'
6
- require 'cmds/util'
7
- require 'cmds/spawn'
8
- require 'cmds/erb_context'
9
- require 'cmds/shell_eruby'
10
- require 'cmds/result'
11
-
12
- module Cmds
13
- # a command consisting of a template, base/common parameters and input,
14
- # and options.
15
- #
16
- class Cmd
17
- # ERB stirng template (with Cmds-specific extensions) for the command.
18
- #
19
- # @return [String]
20
- attr_reader :template
21
-
22
- # base/common positional parameters to render into the command
23
- # template.
24
- #
25
- # defaults to `[]`.
26
- #
27
- # {#prepare} and the methods that invoke it (like {#capture},
28
- # {#stream}, etc.) accept `*args`, which will be appended to
29
- # these values to create the final array for rendering.
30
- #
31
- # @return [Array<Object>]
32
- attr_reader :args
33
-
34
- # base/common keyword parameters to render into the command template.
35
- #
36
- # defaults to `{}`.
37
- #
38
- # {#prepare} and the methods that invoke it (like {#capture},
39
- # {#stream}, etc.) accept `**kwds`, which will be merged on top of
40
- # these values to create the final hash for rendering.
41
- #
42
- # @return [Hash{Symbol => Object}]
43
- attr_reader :kwds
44
-
45
- # string or readable IO-like object to use as default input to the
46
- # command.
47
- #
48
- # {#prepare} and the methods that invoke it (like {#capture},
49
- # {#stream}, etc.) accept an optional block that will override this
50
- # value if present.
51
- #
52
- # @return [String | #read]
53
- attr_reader :input
54
-
55
- # if `true`, will execution will raise an error on non-zero exit code.
56
- #
57
- # defaults to `false`.
58
- #
59
- # @return [Boolean]
60
- attr_reader :assert
61
-
62
- # environment variables to set for command execution.
63
- #
64
- # defaults to `{}`.
65
- #
66
- # @return [Hash{String | Symbol => String}]
67
- attr_reader :env
68
-
69
- # format specifier symbol:
70
- #
71
- # - `:squish`
72
- # - collapse rendered command string to one line.
73
- # - `:pretty`
74
- # - clean up and backslash suffix line endings.
75
- #
76
- # defaults to `:squish`.
77
- #
78
- # @return [:squish | :pretty]
79
- attr_reader :format
80
-
81
-
82
- # directory to run the command in.
83
- #
84
- # @return [nil | String]
85
- attr_reader :chdir
86
-
87
-
88
- # construct a Cmd.
89
- #
90
- # @param [String] template
91
- # sets the {#template} attribute.
92
- #
93
- # @param [Hash] opts
94
- #
95
- # @option opts [Array<Object>] :args
96
- # sets the {#args} attribute.
97
- #
98
- # @option opts [Hash{Symbol => Object}] :kwds
99
- # sets the {#kwds} attribute.
100
- #
101
- # @option opts [String | #read] :input
102
- # sets the {#input} attribute.
103
- #
104
- # @option opts [Hash{Symbol => String}] :env
105
- # sets the {#env} attribute.
106
- #
107
- # @option opts [:squish, :pretty] :format
108
- # sets the {#format} attribute.
109
- #
110
- # @option opts [nil | String] :chdir
111
- # sets the {#chdir} attribute.
112
- #
113
- def initialize template, **opts
114
- Cmds.debug "Cmd constructing...",
115
- template: template,
116
- opts: opts
117
-
118
- @template = template
119
- @args = opts[:args] || []
120
- @kwds = opts[:kwds] || {}
121
- @input = opts[:input] || nil
122
- @assert = opts[:assert] || false
123
- @env = opts[:env] || {}
124
- @format = opts[:format] || :squish
125
- @env_mode = opts[:env_mode] || :inline
126
- @chdir = opts[:chdir] || nil
127
- end # #initialize
128
-
129
-
130
- # returns a new {Cmd} with the parameters and input merged in
131
- def curry *args, **kwds, &input_block
132
- self.class.new @template, {
133
- args: (@args + args),
134
- kwds: (@kwds.merge kwds),
135
- input: (input ? input.call : @input),
136
- assert: @assert,
137
- env: @env,
138
- format: @format,
139
- chdir: @chdir,
140
- }
141
- end
142
-
143
-
144
- # render parameters into `@template`.
145
- #
146
- # @note the returned string is **not** formatted for shell execution.
147
- # Cmds passes this string through {Cmds.format} before execution,
148
- # which addresses newlines in the rendered string through "squishing"
149
- # everything down to one line or adding `\` to line ends.
150
- #
151
- # @param args (see #capture)
152
- # @param kwds (see #capture)
153
- #
154
- # @return [String]
155
- # the rendered command string.
156
- #
157
- def render *args, **kwds
158
- context = Cmds::ERBContext.new((@args + args), @kwds.merge(kwds))
159
- erb = Cmds::ShellEruby.new Cmds.replace_shortcuts(@template)
160
- rendered = NRSER.dedent erb.result(context.get_binding)
161
-
162
- if @env_mode == :inline && !@env.empty?
163
- rendered = @env.sort_by {|name, value|
164
- name
165
- }.map {|name, value|
166
- "#{ name }=#{ Cmds.esc value }"
167
- }.join("\n\n") + "\n\n" + rendered
168
- end
169
-
170
- rendered
171
- end
172
-
173
-
174
- # prepare a shell-safe command string for execution.
175
- #
176
- # @param args (see #capture)
177
- # @param kwds (see #capture)
178
- #
179
- # @return [String]
180
- # the prepared command string.
181
- #
182
- def prepare *args, **kwds
183
- Cmds.format render(*args, **kwds), @format
184
- end # #prepare
185
-
186
-
187
- def stream *args, **kwds, &io_block
188
- Cmds.debug "entering Cmd#stream",
189
- args: args,
190
- kwds: kwds,
191
- io_block: io_block
192
-
193
- Cmds.spawn prepare(*args, **kwds),
194
- input: @input,
195
- # include env if mode is spawn argument
196
- env: (@env_mode == :spawn_arg ? @env : {}),
197
- chdir: @chdir,
198
- &io_block
199
- end # #stream
200
-
201
-
202
- # executes the command and returns a {Cmds::Result} with the captured
203
- # outputs.
204
- #
205
- # @param [Array<Object>] args
206
- # positional parameters to append to those in `@args` for rendering
207
- # into the command string.
208
- #
209
- # @param [Hash{Symbol => Object}] kwds
210
- # keyword parameters that override those in `@kwds` for rendering
211
- # into the command string.
212
- #
213
- # @param [#call] input_block
214
- # optional block that returns a string or readable object to override
215
- # `@input`.
216
- #
217
- # @return [Cmds::Result]
218
- # result of execution with command string, status, stdout and stderr.
219
- #
220
- def capture *args, **kwds, &input_block
221
- Cmds.debug "entering Cmds#capture",
222
- args: args,
223
- kwds: kwds,
224
- input: input
225
-
226
- # prepare the command string
227
- cmd = prepare *args, **kwds
228
-
229
- # extract input from block via `call` if one is provided,
230
- # otherwise default to instance variable (which may be `nil`)
231
- input = input_block.nil? ? @input : input_block.call
232
-
233
- Cmds.debug "prepared",
234
- cmd: cmd,
235
- input: input
236
-
237
- # strings output will be concatenated onto
238
- out = ''
239
- err = ''
240
-
241
- Cmds.debug "calling Cmds.spawn..."
242
-
243
- status = Cmds.spawn(
244
- cmd,
245
- # include env if mode is spawn argument
246
- env: (@env_mode == :spawn_arg ? @env : {}),
247
- chdir: @chdir
248
- ) do |io|
249
- # send the input to stream, which sends it to spawn
250
- io.in = input
251
-
252
- # and concat the output lines as they come in
253
- io.on_out do |line|
254
- out += line
255
- end
256
-
257
- io.on_err do |line|
258
- err += line
259
- end
260
- end
261
-
262
- Cmds.debug "Cmds.spawn completed",
263
- status: status
264
-
265
- # build a Result
266
- # result = Cmds::Result.new cmd, status, out_reader.value, err_reader.value
267
- result = Cmds::Result.new cmd, status, out, err
268
-
269
- # tell the Result to assert if the Cmds has been told to, which will
270
- # raise a SystemCallError with the exit status if it was non-zero
271
- result.assert if @assert
272
-
273
- return result
274
- end # #capture
275
-
276
-
277
- alias_method :call, :capture
278
-
279
-
280
- # execute command and return `true` if it exited successfully.
281
- #
282
- # @param *args (see #capture)
283
- # @param **kwds (see #capture)
284
- # @param &input_block (see #capture)
285
- #
286
- # @return [Boolean]
287
- # `true` if exit code was `0`.
288
- #
289
- def ok? *args, **kwds, &io_block
290
- stream(*args, **kwds, &io_block) == 0
291
- end
292
-
293
-
294
- # execute command and return `true` if it failed.
295
- #
296
- # @param *args (see #capture)
297
- # @param **kwds (see #capture)
298
- # @param &input_block (see #capture)
299
- #
300
- # @return [Boolean]
301
- # `true` if exit code was not `0`.
302
- #
303
- def error? *args, **kwds, &io_block
304
- stream(*args, **kwds, &io_block) != 0
305
- end
306
-
307
-
308
- # def assert
309
- # capture.raise_error
310
- # end
311
-
312
-
313
- def proxy
314
- stream do |io|
315
- io.in = $stdin
316
- end
317
- end
318
-
319
-
320
- # captures and returns stdout
321
- # (sugar for `#capture(*args, **kwds, &input_block).out`).
322
- #
323
- # @see #capture
324
- # @see Result#out
325
- #
326
- # @param *args (see #capture)
327
- # @param **kwds (see #capture)
328
- # @param &input_block (see #capture)
329
- #
330
- # @return [String]
331
- # the command's stdout.
332
- #
333
- def out *args, **kwds, &input_block
334
- capture(*args, **kwds, &input_block).out
335
- end
336
-
337
-
338
- # captures and returns stdout
339
- # (sugar for `#capture(*args, **kwds, &input_block).out`).
340
- #
341
- # @see #capture
342
- # @see Result#out
343
- #
344
- # @param args [Array] see {.capture}.
345
- # @param kwds [Proc] see {.capture}.
346
- #
347
- # @return [String] the command's stdout.
348
- #
349
- # @raise [SystemCallError] if the command fails (non-zero exit status).
350
- #
351
- def out! *args, **kwds, &input
352
- capture(*args, **kwds, &input).assert.out
353
- end
354
-
355
-
356
- # captures and chomps stdout
357
- # (sugar for `#out(*subs, &input_block).chomp`).
358
- #
359
- # @see #out
360
- #
361
- # @param *args (see #capture)
362
- # @param **kwds (see #capture)
363
- # @param &input_block (see #capture)
364
- #
365
- # @return [String]
366
- # the command's chomped stdout.
367
- #
368
- def chomp *args, **kwds, &input_block
369
- out(*args, **kwds, &input_block).chomp
370
- end
371
-
372
-
373
- # captures and chomps stdout, raising an error if the command failed.
374
- # (sugar for `#out!(*subs, &input_block).chomp`).
375
- #
376
- # @see #capture
377
- # @see Result#out
378
- #
379
- # @param *args (see #capture)
380
- # @param **kwds (see #capture)
381
- # @param &input_block (see #capture)
382
- #
383
- # @return [String]
384
- # the command's chomped stdout.
385
- #
386
- # @raise [SystemCallError]
387
- # if the command fails (non-zero exit status).
388
- #
389
- def chomp! *args, **kwds, &input
390
- out!(*args, **kwds, &input).chomp
391
- end
392
-
393
-
394
- # captures and returns stdout
395
- # (sugar for `#capture(*subs, &input_block).err`).
396
- #
397
- # @param *args (see #capture)
398
- # @param **kwds (see #capture)
399
- # @param &input_block (see #capture)
400
- #
401
- # @see #capture
402
- # @see Result#err
403
- #
404
- # @return [String]
405
- # the command's stderr.
406
- #
407
- def err *args, **kwds, &input_block
408
- capture(*args, **kwds, &input_block).err
409
- end
410
- end # Cmd
411
- end # Cmds