cmds 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|