command_mapper-gen 0.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +27 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +1 -0
  6. data/ChangeLog.md +20 -0
  7. data/Gemfile +17 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.md +145 -0
  10. data/Rakefile +15 -0
  11. data/bin/command_mapper-gen +7 -0
  12. data/commnad_mapper-gen.gemspec +61 -0
  13. data/examples/grep.rb +63 -0
  14. data/gemspec.yml +26 -0
  15. data/lib/command_mapper/gen/arg.rb +43 -0
  16. data/lib/command_mapper/gen/argument.rb +53 -0
  17. data/lib/command_mapper/gen/cli.rb +233 -0
  18. data/lib/command_mapper/gen/command.rb +202 -0
  19. data/lib/command_mapper/gen/exceptions.rb +9 -0
  20. data/lib/command_mapper/gen/option.rb +66 -0
  21. data/lib/command_mapper/gen/option_value.rb +23 -0
  22. data/lib/command_mapper/gen/parsers/common.rb +49 -0
  23. data/lib/command_mapper/gen/parsers/help.rb +351 -0
  24. data/lib/command_mapper/gen/parsers/man.rb +80 -0
  25. data/lib/command_mapper/gen/parsers/options.rb +127 -0
  26. data/lib/command_mapper/gen/parsers/usage.rb +141 -0
  27. data/lib/command_mapper/gen/parsers.rb +2 -0
  28. data/lib/command_mapper/gen/task.rb +90 -0
  29. data/lib/command_mapper/gen/types/enum.rb +30 -0
  30. data/lib/command_mapper/gen/types/key_value.rb +34 -0
  31. data/lib/command_mapper/gen/types/list.rb +34 -0
  32. data/lib/command_mapper/gen/types/map.rb +36 -0
  33. data/lib/command_mapper/gen/types/num.rb +18 -0
  34. data/lib/command_mapper/gen/types/str.rb +48 -0
  35. data/lib/command_mapper/gen/types.rb +6 -0
  36. data/lib/command_mapper/gen/version.rb +6 -0
  37. data/lib/command_mapper/gen.rb +2 -0
  38. data/spec/argument_spec.rb +92 -0
  39. data/spec/cli_spec.rb +269 -0
  40. data/spec/command_spec.rb +316 -0
  41. data/spec/option_spec.rb +85 -0
  42. data/spec/option_value_spec.rb +20 -0
  43. data/spec/parsers/common_spec.rb +616 -0
  44. data/spec/parsers/help_spec.rb +612 -0
  45. data/spec/parsers/man_spec.rb +158 -0
  46. data/spec/parsers/options_spec.rb +802 -0
  47. data/spec/parsers/usage_spec.rb +1175 -0
  48. data/spec/spec_helper.rb +6 -0
  49. data/spec/task_spec.rb +69 -0
  50. data/spec/types/enum_spec.rb +45 -0
  51. data/spec/types/key_value_spec.rb +36 -0
  52. data/spec/types/list_spec.rb +36 -0
  53. data/spec/types/map_spec.rb +48 -0
  54. data/spec/types/str_spec.rb +70 -0
  55. 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
@@ -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