cmds 0.0.9 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/Rakefile +7 -2
- data/bin/rake +3 -0
- data/bin/rspec +3 -0
- data/cmds.gemspec +1 -1
- data/lib/cmds/cmd.rb +376 -0
- data/lib/cmds/debug.rb +2 -2
- data/lib/cmds/erb_context.rb +3 -3
- data/lib/cmds/io_handler.rb +2 -2
- data/lib/cmds/pipe.rb +1 -1
- data/lib/cmds/result.rb +10 -6
- data/lib/cmds/shell_eruby.rb +2 -2
- data/lib/cmds/spawn.rb +251 -0
- data/lib/cmds/sugar.rb +145 -222
- data/lib/cmds/util/defaults.rb +71 -0
- data/lib/cmds/util/params.rb +56 -0
- data/lib/cmds/util/tokenize_option.rb +118 -0
- data/lib/cmds/util/tokenize_options.rb +50 -0
- data/lib/cmds/util.rb +35 -195
- data/lib/cmds/version.rb +2 -2
- data/lib/cmds.rb +3 -36
- data/scratch/proxy.rb +1 -1
- data/spec/cmds/assert_spec.rb +1 -1
- data/spec/cmds/capture_spec.rb +9 -25
- data/spec/cmds/chomp_spec.rb +7 -7
- data/spec/cmds/curry_spec.rb +1 -1
- data/spec/cmds/err_spec.rb +9 -6
- data/spec/cmds/error_spec.rb +6 -6
- data/spec/cmds/ok_spec.rb +2 -2
- data/spec/cmds/out_spec.rb +7 -7
- data/spec/cmds/{sub_spec.rb → prepare_spec.rb} +20 -32
- data/spec/cmds/stream_spec.rb +4 -4
- data/spec/cmds/util/tokenize_option_spec.rb +119 -0
- data/spec/cmds_spec.rb +11 -0
- metadata +15 -12
- data/lib/cmds/capture.rb +0 -47
- data/lib/cmds/stream.rb +0 -239
- data/spec/cmds/expand_option_hash_spec.rb +0 -61
- data/test/bin/dspec +0 -1
@@ -0,0 +1,71 @@
|
|
1
|
+
module Cmds
|
2
|
+
# hash of common default values used in method options.
|
3
|
+
#
|
4
|
+
# don't use them directly -- use {Cmds.defaults}.
|
5
|
+
#
|
6
|
+
# the values themselves are frozen so we don't have to worry about cloning
|
7
|
+
# them before providing them for use.
|
8
|
+
#
|
9
|
+
# the constant Hash itself is **not** frozen -- you can mutate this to
|
10
|
+
# change the default options for **ALL** Cmds method calls...
|
11
|
+
# just be aware of what you're doing. not recommended
|
12
|
+
# outside of quick hacks and small scripts since other pieces and parts
|
13
|
+
# you don't even know about may depend on said behavior.
|
14
|
+
#
|
15
|
+
DEFAULTS = {
|
16
|
+
# positional arguments for a command
|
17
|
+
args: [],
|
18
|
+
|
19
|
+
# keyword arguments for a command
|
20
|
+
kwds: {},
|
21
|
+
|
22
|
+
# how to format a command string for execution
|
23
|
+
format: :squish,
|
24
|
+
|
25
|
+
# what to do with array option values
|
26
|
+
array_mode: :join,
|
27
|
+
|
28
|
+
# what to join array option values with when using `array_mode = :join`
|
29
|
+
array_join_string: ',',
|
30
|
+
|
31
|
+
# what to do with false array values
|
32
|
+
false_mode: :omit,
|
33
|
+
}.map {|k, v| [k, v.freeze]}.to_h
|
34
|
+
|
35
|
+
# merge an method call options hash with common defaults for the module.
|
36
|
+
#
|
37
|
+
# this makes it easy to use the same defaults in many different methods
|
38
|
+
# without repeating the declarations everywhere.
|
39
|
+
#
|
40
|
+
# @param [Hash] opts
|
41
|
+
# hash of overrides provided by method caller.
|
42
|
+
#
|
43
|
+
# @param [Array<Symbol>, '*'] keys
|
44
|
+
# keys for the defaults you want to use.
|
45
|
+
#
|
46
|
+
# @param [Hash<Symbol, Object>] extras
|
47
|
+
# extra keys and values to add to the returned defaults.
|
48
|
+
#
|
49
|
+
# @return [Hash<Symbol, Object>]
|
50
|
+
# defaults to use in the method call.
|
51
|
+
#
|
52
|
+
def self.defaults opts, keys = '*', extras = {}
|
53
|
+
if keys == '*'
|
54
|
+
DEFAULTS
|
55
|
+
else
|
56
|
+
keys.
|
57
|
+
map {|key|
|
58
|
+
[key, DEFAULTS.fetch(key)]
|
59
|
+
}.
|
60
|
+
to_h
|
61
|
+
end.
|
62
|
+
merge!(extras).
|
63
|
+
merge!(opts)
|
64
|
+
end
|
65
|
+
|
66
|
+
# proxy through to class method {Cmds.defaults}.
|
67
|
+
#
|
68
|
+
def defaults opts, keys = '*', extras = {}
|
69
|
+
self.class.defaults opts, keys, extras
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Cmds
|
2
|
+
class Params
|
3
|
+
# Cmds instance execution methods take a splat and block
|
4
|
+
def self.normalize *params, &input
|
5
|
+
args = []
|
6
|
+
kwds = {}
|
7
|
+
input = input_block.nil? ? nil : input_block.call
|
8
|
+
|
9
|
+
case subs.length
|
10
|
+
when 0
|
11
|
+
# nothing to do
|
12
|
+
when 1
|
13
|
+
# can either be a hash, which is interpreted as a keywords,
|
14
|
+
# or an array, which is interpreted as positional arguments
|
15
|
+
case subs[0]
|
16
|
+
when Hash
|
17
|
+
kwds = subs[0]
|
18
|
+
|
19
|
+
when Array
|
20
|
+
args = subs[0]
|
21
|
+
|
22
|
+
else
|
23
|
+
raise TypeError.new NRSER.squish <<-BLOCK
|
24
|
+
first *subs arg must be Array or Hash, not #{ subs[0].inspect }
|
25
|
+
BLOCK
|
26
|
+
end
|
27
|
+
|
28
|
+
when 2
|
29
|
+
# first arg needs to be an array, second a hash
|
30
|
+
unless subs[0].is_a? Array
|
31
|
+
raise TypeError.new NRSER.squish <<-BLOCK
|
32
|
+
first *subs arg needs to be an array, not #{ subs[0].inspect }
|
33
|
+
BLOCK
|
34
|
+
end
|
35
|
+
|
36
|
+
unless subs[1].is_a? Hash
|
37
|
+
raise TypeError.new NRSER.squish <<-BLOCK
|
38
|
+
second *subs arg needs to be a Hash, not #{ subs[1].inspect }
|
39
|
+
BLOCK
|
40
|
+
end
|
41
|
+
|
42
|
+
args, kwds = subs
|
43
|
+
else
|
44
|
+
raise ArgumentError.new NRSER.squish <<-BLOCK
|
45
|
+
must provide one or two *subs arguments, received #{ 1 + subs.length }
|
46
|
+
BLOCK
|
47
|
+
end
|
48
|
+
|
49
|
+
return {
|
50
|
+
args: args,
|
51
|
+
kwds: kwds,
|
52
|
+
input: input,
|
53
|
+
}
|
54
|
+
end # .normalize
|
55
|
+
end # Params
|
56
|
+
end # Cmds
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nrser/refinements'
|
3
|
+
|
4
|
+
using NRSER
|
5
|
+
|
6
|
+
require_relative "defaults"
|
7
|
+
|
8
|
+
module Cmds
|
9
|
+
# turn an option name and value into an array of shell-escaped string
|
10
|
+
# token suitable for use in a command.
|
11
|
+
#
|
12
|
+
# @param [String] name
|
13
|
+
# string name (one or more characters).
|
14
|
+
#
|
15
|
+
# @param [*] value
|
16
|
+
# value of the option.
|
17
|
+
#
|
18
|
+
# @param [Hash] opts
|
19
|
+
# @option [Symbol] :array_mode (:multiple)
|
20
|
+
# one of:
|
21
|
+
#
|
22
|
+
# 1. `:multiple` (default) provide one token for each value.
|
23
|
+
#
|
24
|
+
# expand_option 'blah', [1, 2, 3]
|
25
|
+
# => ['--blah=1', '--blah=2', '--blah=3']
|
26
|
+
#
|
27
|
+
# 2. `:join` -- join values in one token.
|
28
|
+
#
|
29
|
+
# expand_option 'blah', [1, 2, 3], array_mode: :join
|
30
|
+
# => ['--blah=1,2,3']
|
31
|
+
#
|
32
|
+
# @option [String] :array_join_string (',')
|
33
|
+
# string to join array values with when `:array_mode` is `:join`.
|
34
|
+
#
|
35
|
+
# @return [Array<String>]
|
36
|
+
# string tokens.
|
37
|
+
#
|
38
|
+
def self.tokenize_option name, value, opts = {}
|
39
|
+
opts = defaults opts, [:array_mode, :array_join_string, :false_mode]
|
40
|
+
|
41
|
+
unless name.is_a?(String) && name.length > 0
|
42
|
+
raise ArgumentError.new <<-END.squish
|
43
|
+
`name` must be a String of length greater than zero,
|
44
|
+
found #{ name.inspect }
|
45
|
+
END
|
46
|
+
end
|
47
|
+
|
48
|
+
prefix, separator = if name.length == 1
|
49
|
+
# -b <value> style
|
50
|
+
['-', ' ']
|
51
|
+
else
|
52
|
+
# --blah=<value> style
|
53
|
+
['--', '=']
|
54
|
+
end
|
55
|
+
|
56
|
+
case value
|
57
|
+
when nil
|
58
|
+
[]
|
59
|
+
|
60
|
+
when Array
|
61
|
+
# the PITA one
|
62
|
+
case opts[:array_mode]
|
63
|
+
when :repeat
|
64
|
+
# `-b 1 -b 2 -b 3` / `--blah=1 --blah=2 --blah=3` style
|
65
|
+
value.flatten.map {|v|
|
66
|
+
prefix + esc(name) + separator + esc(v)
|
67
|
+
}
|
68
|
+
|
69
|
+
when :join
|
70
|
+
# `-b 1,2,3` / `--blah=1,2,3` style
|
71
|
+
[ prefix +
|
72
|
+
esc(name) +
|
73
|
+
separator +
|
74
|
+
esc(value.join opts[:array_join_string]) ]
|
75
|
+
|
76
|
+
when :json
|
77
|
+
[prefix + esc(name) + separator + esc(JSON.dump value)]
|
78
|
+
|
79
|
+
else
|
80
|
+
# SOL
|
81
|
+
raise ArgumentError.new <<-END.squish
|
82
|
+
bad array_mode option: #{ opts[:array_mode] },
|
83
|
+
should be :repeat, :join or :json
|
84
|
+
END
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
when true
|
89
|
+
# `-b` or `--blah`
|
90
|
+
[prefix + esc(name)]
|
91
|
+
|
92
|
+
when false
|
93
|
+
case opts[:false_mode]
|
94
|
+
when :omit
|
95
|
+
# don't emit any token for a false boolean
|
96
|
+
[]
|
97
|
+
when :no
|
98
|
+
# `--no-blah` style
|
99
|
+
#
|
100
|
+
# but there's not really a great way to handle short names...
|
101
|
+
# we use `--no-b`
|
102
|
+
#
|
103
|
+
["--no-#{ esc(name) }"]
|
104
|
+
|
105
|
+
else
|
106
|
+
raise ArgumentError.new <<-END.squish
|
107
|
+
bad :false_mode option: #{ opts[:false_mode] },
|
108
|
+
should be :omit or :no
|
109
|
+
END
|
110
|
+
end
|
111
|
+
|
112
|
+
else
|
113
|
+
# we let .esc handle it
|
114
|
+
[prefix + esc(name) + separator + esc(value)]
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative 'tokenize_option'
|
2
|
+
|
3
|
+
module Cmds
|
4
|
+
# escape option hash.
|
5
|
+
#
|
6
|
+
# this is only useful for the two common option styles:
|
7
|
+
#
|
8
|
+
# - single character keys become `-<char> <value>`
|
9
|
+
#
|
10
|
+
# {x: 1} => "-x 1"
|
11
|
+
#
|
12
|
+
# - longer keys become `--<key>=<value>` options
|
13
|
+
#
|
14
|
+
# {blah: 2} => "--blah=2"
|
15
|
+
#
|
16
|
+
# if you have something else, you're going to have to just put it in
|
17
|
+
# the cmd itself, like:
|
18
|
+
#
|
19
|
+
# Cmds "blah -assholeOptionOn:%{s}", "ok"
|
20
|
+
#
|
21
|
+
# or whatever similar shit said command requires.
|
22
|
+
#
|
23
|
+
# however, if the value is an Array, it will repeat the option for each
|
24
|
+
# value:
|
25
|
+
#
|
26
|
+
# {x: [1, 2, 3]} => "-x 1 -x 2 -x 3"
|
27
|
+
# {blah: [1, 2, 3]} => "--blah=1 --blah=2 --blah=3"
|
28
|
+
#
|
29
|
+
# i can't think of any right now, but i swear i've seen commands that take
|
30
|
+
# opts that way.
|
31
|
+
#
|
32
|
+
def self.tokenize_options hash, opts = {}
|
33
|
+
opts = defaults opts, [:array_mode, :array_join_string, :false_mode]
|
34
|
+
|
35
|
+
hash.map {|key, value|
|
36
|
+
# keys need to be strings
|
37
|
+
key = key.to_s unless key.is_a? String
|
38
|
+
|
39
|
+
[key, value]
|
40
|
+
|
41
|
+
}.sort {|(key_a, value_a), (key_b, value_b)|
|
42
|
+
# sort by the (now string) keys
|
43
|
+
key_a <=> key_b
|
44
|
+
|
45
|
+
}.map {|key, value|
|
46
|
+
tokenize_option key, value
|
47
|
+
|
48
|
+
}.flatten.join ' '
|
49
|
+
end # .tokenize_options
|
50
|
+
end
|
data/lib/cmds/util.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# util functions
|
2
|
-
|
2
|
+
|
3
|
+
# stdlib
|
4
|
+
require 'shellwords'
|
5
|
+
|
6
|
+
require_relative 'util/tokenize_options'
|
7
|
+
|
8
|
+
module Cmds
|
3
9
|
# class methods
|
4
10
|
# =============
|
5
11
|
|
@@ -8,73 +14,7 @@ class Cmds
|
|
8
14
|
# also makes it easier to change or customize or whatever
|
9
15
|
def self.esc str
|
10
16
|
Shellwords.escape str
|
11
|
-
end
|
12
|
-
|
13
|
-
# escape option hash.
|
14
|
-
#
|
15
|
-
# this is only useful for the two common option styles:
|
16
|
-
#
|
17
|
-
# - single character keys become `-<char> <value>`
|
18
|
-
#
|
19
|
-
# {x: 1} => "-x 1"
|
20
|
-
#
|
21
|
-
# - longer keys become `--<key>=<value>` options
|
22
|
-
#
|
23
|
-
# {blah: 2} => "--blah=2"
|
24
|
-
#
|
25
|
-
# if you have something else, you're going to have to just put it in
|
26
|
-
# the cmd itself, like:
|
27
|
-
#
|
28
|
-
# Cmds "blah -assholeOptionOn:%{s}", "ok"
|
29
|
-
#
|
30
|
-
# or whatever similar shit said command requires.
|
31
|
-
#
|
32
|
-
# however, if the value is an Array, it will repeat the option for each
|
33
|
-
# value:
|
34
|
-
#
|
35
|
-
# {x: [1, 2, 3]} => "-x 1 -x 2 -x 3"
|
36
|
-
# {blah: [1, 2, 3]} => "--blah=1 --blah=2 --blah=3"
|
37
|
-
#
|
38
|
-
# i can't think of any right now, but i swear i've seen commands that take
|
39
|
-
# opts that way.
|
40
|
-
#
|
41
|
-
def self.expand_option_hash hash
|
42
|
-
hash.map {|key, values|
|
43
|
-
# keys need to be strings
|
44
|
-
key = key.to_s unless key.is_a? String
|
45
|
-
|
46
|
-
[key, values]
|
47
|
-
|
48
|
-
}.sort {|(key_a, values_a), (key_b, values_b)|
|
49
|
-
# sort by the (now string) keys
|
50
|
-
key_a <=> key_b
|
51
|
-
|
52
|
-
}.map {|key, values|
|
53
|
-
# for simplicity's sake, treat all values like an array
|
54
|
-
values = [values] unless values.is_a? Array
|
55
|
-
|
56
|
-
# keys of length 1 expand to `-x v` form
|
57
|
-
expanded = if key.length == 1
|
58
|
-
values.map {|value|
|
59
|
-
if value.nil?
|
60
|
-
"-#{ esc key }"
|
61
|
-
else
|
62
|
-
"-#{ esc key } #{ esc value}"
|
63
|
-
end
|
64
|
-
}
|
65
|
-
|
66
|
-
# longer keys expand to `--key=value` form
|
67
|
-
else
|
68
|
-
values.map {|value|
|
69
|
-
if value.nil?
|
70
|
-
"--#{ esc key }"
|
71
|
-
else
|
72
|
-
"--#{ esc key }=#{ esc value }"
|
73
|
-
end
|
74
|
-
}
|
75
|
-
end
|
76
|
-
}.flatten.join ' '
|
77
|
-
end # ::expand_option_hash
|
17
|
+
end
|
78
18
|
|
79
19
|
# expand one of the substitutions
|
80
20
|
def self.expand_sub sub
|
@@ -83,108 +23,37 @@ class Cmds
|
|
83
23
|
# nil is just an empty string, NOT an empty string bash token
|
84
24
|
''
|
85
25
|
when Hash
|
86
|
-
|
26
|
+
tokenize_options sub
|
87
27
|
else
|
88
28
|
esc sub.to_s
|
89
29
|
end
|
90
30
|
end # ::expand_sub
|
91
|
-
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
# @param args [Array] positional substitutions for occurances of
|
102
|
-
# - `<%= arg %>`
|
103
|
-
# - `%s`
|
104
|
-
#
|
105
|
-
# tokens in the `template` parameter.
|
106
|
-
#
|
107
|
-
# @param kwds [Hash] keyword subsitutions for occurances of the form
|
108
|
-
#
|
109
|
-
# - `<%= key %>`
|
110
|
-
# - `%{key}`
|
111
|
-
# - `%<key>s`
|
112
|
-
#
|
113
|
-
# as well as optional
|
114
|
-
#
|
115
|
-
# - `<%= key? %>`
|
116
|
-
# - `%{key?}`
|
117
|
-
# - `%<key?>s`
|
118
|
-
#
|
119
|
-
# tokens in the `template` parameter (where `key` is replaced with the
|
120
|
-
# symbol name in the hash).
|
121
|
-
#
|
122
|
-
# @return [String] formated command string suitable for execution.
|
123
|
-
#
|
124
|
-
# @raise [TypeError] if `args` is not an {Array}.
|
125
|
-
# @raise [TypeError] if `kwds` is not a {Hash}.
|
126
|
-
#
|
127
|
-
def self.sub template, args = [], kwds = {}
|
128
|
-
raise TypeError.new("args must be an Array") unless args.is_a? Array
|
129
|
-
raise TypeError.new("kwds must be an Hash") unless kwds.is_a? Hash
|
130
|
-
|
131
|
-
context = ERBContext.new(args, kwds)
|
132
|
-
erb = ShellEruby.new replace_shortcuts(template)
|
133
|
-
|
134
|
-
NRSER.squish erb.result(context.get_binding)
|
135
|
-
end # ::sub
|
136
|
-
|
137
|
-
def self.options subs, input_block
|
138
|
-
args = []
|
139
|
-
kwds = {}
|
140
|
-
input = input_block.nil? ? nil : input_block.call
|
141
|
-
|
142
|
-
case subs.length
|
143
|
-
when 0
|
144
|
-
# nothing to do
|
145
|
-
when 1
|
146
|
-
# can either be a hash, which is interpreted as a keywords,
|
147
|
-
# or an array, which is interpreted as positional arguments
|
148
|
-
case subs[0]
|
149
|
-
when Hash
|
150
|
-
kwds = subs[0]
|
151
|
-
|
152
|
-
when Array
|
153
|
-
args = subs[0]
|
154
|
-
|
155
|
-
else
|
156
|
-
raise TypeError.new NRSER.squish <<-BLOCK
|
157
|
-
first *subs arg must be Array or Hash, not #{ subs[0].inspect }
|
158
|
-
BLOCK
|
159
|
-
end
|
160
|
-
|
161
|
-
when 2
|
162
|
-
# first arg needs to be an array, second a hash
|
163
|
-
unless subs[0].is_a? Array
|
164
|
-
raise TypeError.new NRSER.squish <<-BLOCK
|
165
|
-
first *subs arg needs to be an array, not #{ subs[0].inspect }
|
166
|
-
BLOCK
|
167
|
-
end
|
168
|
-
|
169
|
-
unless subs[1].is_a? Hash
|
170
|
-
raise TypeError.new NRSER.squish <<-BLOCK
|
171
|
-
second *subs arg needs to be a Hash, not #{ subs[1].inspect }
|
172
|
-
BLOCK
|
173
|
-
end
|
174
|
-
|
175
|
-
args, kwds = subs
|
31
|
+
|
32
|
+
# formats a command string
|
33
|
+
def self.format string, with = :squish
|
34
|
+
case with
|
35
|
+
when :squish
|
36
|
+
NRSER.squish string
|
37
|
+
|
38
|
+
when :pretty
|
39
|
+
pretty_format string
|
40
|
+
|
176
41
|
else
|
177
|
-
|
178
|
-
must provide one or two *subs arguments, received #{ 1 + subs.length }
|
179
|
-
BLOCK
|
42
|
+
with.call string
|
180
43
|
end
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.pretty_format string
|
47
|
+
string.lines.map {|line|
|
48
|
+
line = line.rstrip
|
49
|
+
|
50
|
+
if line.end_with? '\\'
|
51
|
+
line
|
52
|
+
else
|
53
|
+
line + ' \\'
|
54
|
+
end
|
55
|
+
}.join("\n")
|
56
|
+
end
|
188
57
|
|
189
58
|
def self.replace_shortcuts template
|
190
59
|
template
|
@@ -219,34 +88,5 @@ class Cmds
|
|
219
88
|
'\1<\2>s'
|
220
89
|
)
|
221
90
|
end # ::replace_shortcuts
|
222
|
-
|
223
|
-
|
224
|
-
# ================
|
225
|
-
|
226
|
-
# returns a new `Cmds` with the subs and input block merged in
|
227
|
-
def curry *subs, &input_block
|
228
|
-
self.class.new @template, merge_options(subs, input_block)
|
229
|
-
end
|
230
|
-
|
231
|
-
private
|
232
|
-
|
233
|
-
# merges options already present on the object with options
|
234
|
-
# provided via subs and input_block and returns a new options
|
235
|
-
# Hash
|
236
|
-
def merge_options subs, input_block
|
237
|
-
# get the options present in the arguments
|
238
|
-
options = Cmds.options subs, input_block
|
239
|
-
# the new args are created by appending the provided args to the
|
240
|
-
# existing ones
|
241
|
-
options[:args] = @args + options[:args]
|
242
|
-
# the new kwds are created by merging the provided kwds into the
|
243
|
-
# exising ones (new values override previous)
|
244
|
-
options[:kwds] = @kwds.merge options[:kwds]
|
245
|
-
# if there is input present via the provided block, it is used.
|
246
|
-
# otherwise, previous input is used, which may be `nil`
|
247
|
-
options[:input] ||= @input
|
248
|
-
return options
|
249
|
-
end # #merge_options
|
250
|
-
|
251
|
-
# end private
|
252
|
-
end # class Cmds
|
91
|
+
|
92
|
+
end # module Cmds
|
data/lib/cmds/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.0
|
1
|
+
module Cmds
|
2
|
+
VERSION = "0.1.0"
|
3
3
|
end
|
data/lib/cmds.rb
CHANGED
@@ -1,36 +1,3 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require 'thread'
|
5
|
-
|
6
|
-
# deps
|
7
|
-
require 'nrser'
|
8
|
-
|
9
|
-
# project
|
10
|
-
require "cmds/capture"
|
11
|
-
require "cmds/debug"
|
12
|
-
require "cmds/erb_context"
|
13
|
-
require "cmds/io_handler"
|
14
|
-
require "cmds/pipe"
|
15
|
-
require "cmds/result"
|
16
|
-
require "cmds/shell_eruby"
|
17
|
-
require "cmds/stream"
|
18
|
-
require "cmds/sugar"
|
19
|
-
require "cmds/util"
|
20
|
-
require "cmds/version"
|
21
|
-
|
22
|
-
class Cmds
|
23
|
-
attr_reader :template, :args, :kwds, :input, :assert
|
24
|
-
|
25
|
-
def initialize template, opts = {}
|
26
|
-
Cmds.debug "Cmds constructed",
|
27
|
-
template: template,
|
28
|
-
options: opts
|
29
|
-
|
30
|
-
@template = template
|
31
|
-
@args = opts[:args] || []
|
32
|
-
@kwds = opts[:kwds] || {}
|
33
|
-
@input = opts[:input] || nil
|
34
|
-
@assert = opts[:assert] || false
|
35
|
-
end # #initialize
|
36
|
-
end
|
1
|
+
require 'cmds/version'
|
2
|
+
require 'cmds/cmd'
|
3
|
+
require 'cmds/sugar'
|
data/scratch/proxy.rb
CHANGED
data/spec/cmds/assert_spec.rb
CHANGED
@@ -11,6 +11,6 @@ describe "Cmds::assert" do
|
|
11
11
|
|
12
12
|
it "should be chainable when the command is ok" do
|
13
13
|
expect( Cmds!("echo hey").out ).to eq "hey\n"
|
14
|
-
expect( Cmds.new("echo hey").capture.assert.out ).to eq "hey\n"
|
14
|
+
expect( Cmds::Cmd.new("echo hey").capture.assert.out ).to eq "hey\n"
|
15
15
|
end
|
16
16
|
end # Cmds::run
|
data/spec/cmds/capture_spec.rb
CHANGED
@@ -3,13 +3,13 @@ require 'spec_helper'
|
|
3
3
|
describe "Cmds::capture" do
|
4
4
|
it "captures stdout" do
|
5
5
|
expect(
|
6
|
-
Cmds.new(%{ruby -e '$stdout.puts "hey"'}).capture.out
|
6
|
+
Cmds::Cmd.new(%{ruby -e '$stdout.puts "hey"'}).capture.out
|
7
7
|
).to eq "hey\n"
|
8
8
|
end
|
9
9
|
|
10
10
|
it "captures stderr" do
|
11
11
|
expect(
|
12
|
-
Cmds.new(%{ruby -e '$stderr.puts "ho"'}).capture.err
|
12
|
+
Cmds::Cmd.new(%{ruby -e '$stderr.puts "ho"'}).capture.err
|
13
13
|
).to eq "ho\n"
|
14
14
|
end
|
15
15
|
|
@@ -25,7 +25,7 @@ describe "Cmds::capture" do
|
|
25
25
|
|
26
26
|
context "positional args" do
|
27
27
|
let(:result) {
|
28
|
-
Cmds "./test/echo_cmd.rb <%= arg %>",
|
28
|
+
Cmds "./test/echo_cmd.rb <%= arg %>", "hello world!"
|
29
29
|
}
|
30
30
|
|
31
31
|
it_behaves_like "executes correctly"
|
@@ -41,31 +41,15 @@ describe "Cmds::capture" do
|
|
41
41
|
|
42
42
|
end # context echo_cmd.rb 'hello world!'
|
43
43
|
|
44
|
-
# context "feeding kwargs to args cmd" do
|
45
|
-
# let(:result) {
|
46
|
-
# Cmds "./test/echo_cmd.rb %s", s: "sup y'all"
|
47
|
-
# }
|
48
|
-
|
49
|
-
# it "" do
|
50
|
-
# expect( result.cmd ).to eq nil
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
|
54
|
-
it "should error when second (subs) arg is not a hash or array" do
|
55
|
-
expect {
|
56
|
-
Cmds "./test/echo_cmd.rb <%= arg %>", "hello world!"
|
57
|
-
}.to raise_error TypeError
|
58
|
-
end
|
59
|
-
|
60
44
|
it "is reusable" do
|
61
|
-
args_cmd = Cmds.new "./test/echo_cmd.rb <%= arg %>"
|
62
|
-
kwds_cmd = Cmds.new "./test/echo_cmd.rb <%= s %>"
|
45
|
+
args_cmd = Cmds::Cmd.new "./test/echo_cmd.rb <%= arg %>"
|
46
|
+
kwds_cmd = Cmds::Cmd.new "./test/echo_cmd.rb <%= s %>"
|
63
47
|
|
64
48
|
args = ["arg one", "arg two", "arg three"]
|
65
49
|
|
66
50
|
args.each do |arg|
|
67
51
|
results = [
|
68
|
-
args_cmd.capture(
|
52
|
+
args_cmd.capture(arg),
|
69
53
|
kwds_cmd.capture(s: arg)
|
70
54
|
]
|
71
55
|
|
@@ -86,12 +70,12 @@ describe "Cmds::capture" do
|
|
86
70
|
}
|
87
71
|
|
88
72
|
it "accepts input via options" do
|
89
|
-
cmd = Cmds.new(ECHO_CMD, input: input)
|
73
|
+
cmd = Cmds::Cmd.new(ECHO_CMD, input: input)
|
90
74
|
expect( echo_cmd_stdin cmd.capture ).to eq input
|
91
75
|
end
|
92
76
|
|
93
77
|
it "accepts input via block" do
|
94
|
-
cmd = Cmds.new ECHO_CMD
|
78
|
+
cmd = Cmds::Cmd.new ECHO_CMD
|
95
79
|
expect( echo_cmd_stdin cmd.capture { input } ).to eq input
|
96
80
|
end
|
97
81
|
|
@@ -100,7 +84,7 @@ describe "Cmds::capture" do
|
|
100
84
|
input = f.read
|
101
85
|
f.rewind
|
102
86
|
|
103
|
-
cmd = Cmds.new ECHO_CMD
|
87
|
+
cmd = Cmds::Cmd.new ECHO_CMD
|
104
88
|
expect( echo_cmd_stdin cmd.capture { f } ).to eq input
|
105
89
|
end
|
106
90
|
end
|