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