cmds 0.1.5 → 0.2.0

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.
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