command_mapper-gen 0.1.0.pre1
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 +7 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +20 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +20 -0
- data/README.md +145 -0
- data/Rakefile +15 -0
- data/bin/command_mapper-gen +7 -0
- data/commnad_mapper-gen.gemspec +61 -0
- data/examples/grep.rb +63 -0
- data/gemspec.yml +26 -0
- data/lib/command_mapper/gen/arg.rb +43 -0
- data/lib/command_mapper/gen/argument.rb +53 -0
- data/lib/command_mapper/gen/cli.rb +233 -0
- data/lib/command_mapper/gen/command.rb +202 -0
- data/lib/command_mapper/gen/exceptions.rb +9 -0
- data/lib/command_mapper/gen/option.rb +66 -0
- data/lib/command_mapper/gen/option_value.rb +23 -0
- data/lib/command_mapper/gen/parsers/common.rb +49 -0
- data/lib/command_mapper/gen/parsers/help.rb +351 -0
- data/lib/command_mapper/gen/parsers/man.rb +80 -0
- data/lib/command_mapper/gen/parsers/options.rb +127 -0
- data/lib/command_mapper/gen/parsers/usage.rb +141 -0
- data/lib/command_mapper/gen/parsers.rb +2 -0
- data/lib/command_mapper/gen/task.rb +90 -0
- data/lib/command_mapper/gen/types/enum.rb +30 -0
- data/lib/command_mapper/gen/types/key_value.rb +34 -0
- data/lib/command_mapper/gen/types/list.rb +34 -0
- data/lib/command_mapper/gen/types/map.rb +36 -0
- data/lib/command_mapper/gen/types/num.rb +18 -0
- data/lib/command_mapper/gen/types/str.rb +48 -0
- data/lib/command_mapper/gen/types.rb +6 -0
- data/lib/command_mapper/gen/version.rb +6 -0
- data/lib/command_mapper/gen.rb +2 -0
- data/spec/argument_spec.rb +92 -0
- data/spec/cli_spec.rb +269 -0
- data/spec/command_spec.rb +316 -0
- data/spec/option_spec.rb +85 -0
- data/spec/option_value_spec.rb +20 -0
- data/spec/parsers/common_spec.rb +616 -0
- data/spec/parsers/help_spec.rb +612 -0
- data/spec/parsers/man_spec.rb +158 -0
- data/spec/parsers/options_spec.rb +802 -0
- data/spec/parsers/usage_spec.rb +1175 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/task_spec.rb +69 -0
- data/spec/types/enum_spec.rb +45 -0
- data/spec/types/key_value_spec.rb +36 -0
- data/spec/types/list_spec.rb +36 -0
- data/spec/types/map_spec.rb +48 -0
- data/spec/types/str_spec.rb +70 -0
- metadata +133 -0
@@ -0,0 +1,316 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/gen/command'
|
3
|
+
|
4
|
+
describe CommandMapper::Gen::Command do
|
5
|
+
let(:command_name) { "foo" }
|
6
|
+
let(:parent_command) { described_class.new('bar') }
|
7
|
+
|
8
|
+
subject { described_class.new(command_name) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "must set #command_name" do
|
12
|
+
expect(subject.command_name).to eq(command_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "must set #options to {}" do
|
16
|
+
expect(subject.options).to eq({})
|
17
|
+
end
|
18
|
+
|
19
|
+
it "must set #arguments to {}" do
|
20
|
+
expect(subject.arguments).to eq({})
|
21
|
+
end
|
22
|
+
|
23
|
+
it "must set #subcommands to {}" do
|
24
|
+
expect(subject.subcommands).to eq({})
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when a parent command is also given" do
|
28
|
+
subject { described_class.new(command_name,parent_command) }
|
29
|
+
|
30
|
+
it "must set #parent_command" do
|
31
|
+
expect(subject.parent_command).to be(parent_command)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#command_string" do
|
37
|
+
it "must return the #command_name" do
|
38
|
+
expect(subject.command_string).to eq(command_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when #parent_command is set" do
|
42
|
+
subject { described_class.new(command_name,parent_command) }
|
43
|
+
|
44
|
+
it "must return the #parent_command command_name and the #command_name" do
|
45
|
+
expect(subject.command_string).to eq(
|
46
|
+
"#{parent_command.command_name} #{command_name}"
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#man_page" do
|
53
|
+
it "must return the #command_name" do
|
54
|
+
expect(subject.man_page).to eq(command_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
context "when #parent_command is set" do
|
58
|
+
subject { described_class.new(command_name,parent_command) }
|
59
|
+
|
60
|
+
it "must return the #parent_command command_name and the #command_name" do
|
61
|
+
expect(subject.man_page).to eq(
|
62
|
+
"#{parent_command.command_name}-#{command_name}"
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#option" do
|
69
|
+
let(:flag) { "--option" }
|
70
|
+
let(:type) { CommandMapper::Gen::Types::Num.new }
|
71
|
+
let(:required) { false }
|
72
|
+
|
73
|
+
before do
|
74
|
+
subject.option(flag, value: {required: required, type: type})
|
75
|
+
end
|
76
|
+
|
77
|
+
it "must add a new Option to #options with the given flag" do
|
78
|
+
expect(subject.options[flag]).to be_kind_of(CommandMapper::Gen::Option)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "must pass additional keywords to Option#initialize" do
|
82
|
+
expect(subject.options[flag].value.required).to be(required)
|
83
|
+
expect(subject.options[flag].value.type).to be(type)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#argument" do
|
88
|
+
let(:name) { :arg1 }
|
89
|
+
let(:required) { false }
|
90
|
+
|
91
|
+
before { subject.argument(name, required: required) }
|
92
|
+
|
93
|
+
it "must add a new Argument to #argument with the given name" do
|
94
|
+
expect(subject.arguments[name]).to be_kind_of(CommandMapper::Gen::Argument)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "must pass additional keywords to Argument#initialize" do
|
98
|
+
expect(subject.arguments[name].required).to be(required)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#subcommand" do
|
103
|
+
let(:name) { :list }
|
104
|
+
|
105
|
+
before { subject.subcommand(name) }
|
106
|
+
|
107
|
+
it "must add a new Command to #subcommands with the given name" do
|
108
|
+
expect(subject.subcommands[name]).to be_kind_of(CommandMapper::Gen::Command)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "#class_name" do
|
113
|
+
context "when the #command_name is one word" do
|
114
|
+
let(:command_name) { "foo" }
|
115
|
+
|
116
|
+
it "must return the captialized version of #command_name" do
|
117
|
+
expect(subject.class_name).to eq("Foo")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when the command contains a '_'" do
|
122
|
+
let(:command_name) { "foo_bar" }
|
123
|
+
|
124
|
+
it "must return the CamelCased version of #command_name" do
|
125
|
+
expect(subject.class_name).to eq("FooBar")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "when the command contains a '-'" do
|
130
|
+
let(:command_name) { "foo-bar" }
|
131
|
+
|
132
|
+
it "must return the CamelCased version of #command_name" do
|
133
|
+
expect(subject.class_name).to eq("FooBar")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "#to_ruby" do
|
139
|
+
context "when #parent_command is nil" do
|
140
|
+
context "when #command_name is set" do
|
141
|
+
it "must print a header, define a class, and define a command block" do
|
142
|
+
expect(subject.to_ruby).to start_with(
|
143
|
+
[
|
144
|
+
"require 'command_mapper/command'",
|
145
|
+
"",
|
146
|
+
"#",
|
147
|
+
"# Represents the `#{subject.command_name}` command",
|
148
|
+
"#",
|
149
|
+
"class #{subject.class_name} < CommandMapper::Command",
|
150
|
+
"",
|
151
|
+
" command #{subject.command_name.inspect} do",
|
152
|
+
''
|
153
|
+
].join($/)
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "must end the String with 'end ... end'" do
|
158
|
+
expect(subject.to_ruby).to end_with(
|
159
|
+
[
|
160
|
+
'',
|
161
|
+
" end",
|
162
|
+
'',
|
163
|
+
"end",
|
164
|
+
''
|
165
|
+
].join($/)
|
166
|
+
)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "when #parent_command is set" do
|
172
|
+
subject { described_class.new(command_name,parent_command) }
|
173
|
+
|
174
|
+
it "must print 'subcommand ... do'" do
|
175
|
+
expect(subject.to_ruby).to start_with(
|
176
|
+
[
|
177
|
+
"subcommand #{subject.command_name.inspect} do",
|
178
|
+
"end",
|
179
|
+
''
|
180
|
+
].join($/)
|
181
|
+
)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "must end the String with a single 'end'" do
|
185
|
+
expect(subject.to_ruby).to end_with("#{$/}end#{$/}")
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
let(:option_flag) { "--option" }
|
190
|
+
let(:option_required) { false }
|
191
|
+
|
192
|
+
let(:argument_name) { :arg1 }
|
193
|
+
let(:argument_required) { false }
|
194
|
+
|
195
|
+
context "when #options are populated" do
|
196
|
+
before do
|
197
|
+
subject.option(option_flag, value: {required: option_required})
|
198
|
+
end
|
199
|
+
|
200
|
+
it "must print the 'option ...' lines within the command block" do
|
201
|
+
expect(subject.to_ruby).to include(
|
202
|
+
[
|
203
|
+
'',
|
204
|
+
" command #{subject.command_name.inspect} do",
|
205
|
+
" option #{option_flag.inspect}, value: {required: #{option_required.inspect}}",
|
206
|
+
" end",
|
207
|
+
''
|
208
|
+
].join($/)
|
209
|
+
)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "when #arguments are populated" do
|
214
|
+
before do
|
215
|
+
subject.argument(argument_name, required: argument_required)
|
216
|
+
end
|
217
|
+
|
218
|
+
it "must print the 'argument ...' lines within the command block" do
|
219
|
+
expect(subject.to_ruby).to include(
|
220
|
+
[
|
221
|
+
'',
|
222
|
+
" command #{subject.command_name.inspect} do",
|
223
|
+
" argument #{argument_name.inspect}, required: #{argument_required.inspect}",
|
224
|
+
" end",
|
225
|
+
''
|
226
|
+
].join($/)
|
227
|
+
)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
context "when #options and #arguments are both populated" do
|
232
|
+
before do
|
233
|
+
subject.option(option_flag, value: {required: option_required})
|
234
|
+
subject.argument(argument_name, required: argument_required)
|
235
|
+
end
|
236
|
+
|
237
|
+
it "must separate the option lines from the argument lines" do
|
238
|
+
expect(subject.to_ruby).to include(
|
239
|
+
[
|
240
|
+
'',
|
241
|
+
" command #{subject.command_name.inspect} do",
|
242
|
+
" option #{option_flag.inspect}, value: {required: #{option_required.inspect}}",
|
243
|
+
'',
|
244
|
+
" argument #{argument_name.inspect}, required: #{argument_required.inspect}",
|
245
|
+
" end",
|
246
|
+
''
|
247
|
+
].join($/)
|
248
|
+
)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
context "when #subcommands are populated" do
|
253
|
+
context "and when there is one subcommand" do
|
254
|
+
let(:subcommand_name) { 'baz' }
|
255
|
+
|
256
|
+
before do
|
257
|
+
subcommand = subject.subcommand(subcommand_name)
|
258
|
+
|
259
|
+
subcommand.option(option_flag, value: {required: option_required})
|
260
|
+
subcommand.argument(argument_name, required: argument_required)
|
261
|
+
end
|
262
|
+
|
263
|
+
it "must print the 'subcommand ... do' line within the command block" do
|
264
|
+
expect(subject.to_ruby).to include(
|
265
|
+
[
|
266
|
+
'',
|
267
|
+
" command #{command_name.inspect} do",
|
268
|
+
" subcommand #{subcommand_name.inspect} do",
|
269
|
+
" option #{option_flag.inspect}, value: {required: #{option_required.inspect}}",
|
270
|
+
'',
|
271
|
+
" argument #{argument_name.inspect}, required: #{argument_required.inspect}",
|
272
|
+
' end',
|
273
|
+
" end",
|
274
|
+
''
|
275
|
+
].join($/)
|
276
|
+
)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
context "and when there is more than one subcommand" do
|
281
|
+
let(:subcommand_name1) { "baz" }
|
282
|
+
let(:subcommand_name2) { "qux" }
|
283
|
+
|
284
|
+
before do
|
285
|
+
subject.subcommand(subcommand_name1)
|
286
|
+
subject.subcommand(subcommand_name2)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "must separate the 'subcommands ... do' lines" do
|
290
|
+
expect(subject.to_ruby).to include(
|
291
|
+
[
|
292
|
+
'',
|
293
|
+
" command #{command_name.inspect} do",
|
294
|
+
" subcommand #{subcommand_name1.inspect} do",
|
295
|
+
" end",
|
296
|
+
'',
|
297
|
+
" subcommand #{subcommand_name2.inspect} do",
|
298
|
+
" end",
|
299
|
+
" end"
|
300
|
+
].join($/)
|
301
|
+
)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "#save" do
|
308
|
+
let(:path) { '/path/to/file' }
|
309
|
+
|
310
|
+
it "must write #to_ruby to the given file path" do
|
311
|
+
expect(File).to receive(:write).with(path,subject.to_ruby)
|
312
|
+
|
313
|
+
subject.save(path)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
data/spec/option_spec.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/gen/option'
|
3
|
+
require 'command_mapper/gen/types/num'
|
4
|
+
|
5
|
+
describe CommandMapper::Gen::Option do
|
6
|
+
let(:flag) { '--op1' }
|
7
|
+
|
8
|
+
subject { described_class.new(flag) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "must set #flag" do
|
12
|
+
expect(subject.flag).to eq(flag)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "must default #equals to nil" do
|
16
|
+
expect(subject.equals).to be(nil)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "must default #repeats to nil" do
|
20
|
+
expect(subject.repeats).to be(nil)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "must default #value to nil" do
|
24
|
+
expect(subject.value).to be(nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when given the value: keyword argument" do
|
28
|
+
context "and it's a Types object" do
|
29
|
+
let(:value) { {type: Types::Num.new} }
|
30
|
+
|
31
|
+
subject { described_class.new(flag, value: value) }
|
32
|
+
|
33
|
+
it "must initialize #value as an OptionValue object" do
|
34
|
+
expect(subject.value).to be_kind_of(OptionValue)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when given the repeats: keyword argument" do
|
40
|
+
let(:repeats) { true }
|
41
|
+
|
42
|
+
subject { described_class.new(flag, repeats: repeats) }
|
43
|
+
|
44
|
+
it "must set #repeats" do
|
45
|
+
expect(subject.repeats).to eq(repeats)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#to_ruby" do
|
51
|
+
it "must output 'option \#{flag}'" do
|
52
|
+
expect(subject.to_ruby).to eq("option #{flag.inspect}")
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when #equals is true" do
|
56
|
+
let(:equals) { true }
|
57
|
+
|
58
|
+
subject { described_class.new(flag, equals: equals) }
|
59
|
+
|
60
|
+
it "must append 'equals: true'" do
|
61
|
+
expect(subject.to_ruby).to eq("option #{flag.inspect}, equals: #{equals.inspect}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when #repeats is true" do
|
66
|
+
let(:repeats) { true }
|
67
|
+
|
68
|
+
subject { described_class.new(flag, repeats: repeats) }
|
69
|
+
|
70
|
+
it "must append 'repeats: true'" do
|
71
|
+
expect(subject.to_ruby).to eq("option #{flag.inspect}, repeats: #{repeats.inspect}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when #type is not nil" do
|
76
|
+
let(:value) { {required: true} }
|
77
|
+
|
78
|
+
subject { described_class.new(flag, value: value) }
|
79
|
+
|
80
|
+
it "must append 'value: ...' and call the #value's #to_ruby method" do
|
81
|
+
expect(subject.to_ruby).to eq("option #{flag.inspect}, value: #{subject.value.to_ruby}")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_mapper/gen/option_value'
|
3
|
+
|
4
|
+
describe CommandMapper::Gen::OptionValue do
|
5
|
+
describe "#to_ruby" do
|
6
|
+
context "when no keywords are set" do
|
7
|
+
it "must return 'true'" do
|
8
|
+
expect(subject.to_ruby).to eq("true")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "when at least one keyword is set" do
|
13
|
+
subject { described_class.new(required: false) }
|
14
|
+
|
15
|
+
it "must return '{...}'" do
|
16
|
+
expect(subject.to_ruby).to eq("{required: false}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|