command_kit-completion 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog.md +14 -0
- data/lib/command_kit/completion/task.rb +38 -13
- data/lib/command_kit/completion/version.rb +1 -1
- data/spec/task_spec.rb +196 -10
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f85e448a2df37a8bc6231b839b8e56992432498384e6ea4c2e1060a9485c874
|
4
|
+
data.tar.gz: 898168ab4ed70e3e595de27c933432a085976ea81980c7bcc3572e6e2cc4c38c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45ceb26079e0d5caf31e94ea0851fc30e5175661491bed0d6da4f57feb3bc37352ef48e9f7d817f5dced1825db2aa94e0500387a8175dde6b805921c62453ab6
|
7
|
+
data.tar.gz: 8858593122d06c2e4fff8d5f78fae75cd8f23665732131d36eb2fd9c52a51e94a8aa5fe3920b5b622a4f03a16360f442b79e6fd5a9b1c96cf78389c1871a6872
|
data/ChangeLog.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
### 0.2.0 / 2024-04-26
|
2
|
+
|
3
|
+
* Also generate completion rules for option's short flags.
|
4
|
+
* Also generate `<file>`, `<directory>`, `<hostname>`, and `<user>` completion
|
5
|
+
rules for options who's value is named `FILE`, `DIR`, `HOST`, `USER`
|
6
|
+
(or ends in `_FILE`, `_DIR`, `_HOST`, `_USER`), respectively.
|
7
|
+
* Also generate `<file>`, `<directory>`, `<hostname>`, and `<user>` completion
|
8
|
+
rules for the command's first argument if it's named `FILE`, `DIR`, `HOST`,
|
9
|
+
`USER` (or ends in `_FILE`, `_DIR`, `_HOST`, `_USER`), respectively.
|
10
|
+
|
11
|
+
### 0.1.2 / 2023-12-18
|
12
|
+
|
13
|
+
* Fix namespace conflict between `FileUtils` and `CommandKit::FileUtils`.
|
14
|
+
|
1
15
|
### 0.1.1 / 2023-12-18
|
2
16
|
|
3
17
|
* Ensure that the parent directory of the output file exists before writing to
|
@@ -90,7 +90,7 @@ module CommandKit
|
|
90
90
|
completions.script
|
91
91
|
end
|
92
92
|
|
93
|
-
FileUtils.mkdir_p(File.dirname(@output_file))
|
93
|
+
::FileUtils.mkdir_p(File.dirname(@output_file))
|
94
94
|
File.write(@output_file,shell_script)
|
95
95
|
end
|
96
96
|
|
@@ -110,13 +110,25 @@ module CommandKit
|
|
110
110
|
Object.const_get(@class_name)
|
111
111
|
end
|
112
112
|
|
113
|
-
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
113
|
+
#
|
114
|
+
# Maps the argument name strings to completely suggestion `<keyword>`s.
|
115
|
+
#
|
116
|
+
# @param [String] arg
|
117
|
+
# The argument name.
|
118
|
+
#
|
119
|
+
# @return [String, nil]
|
120
|
+
# The suggestion keyword for the argument name.
|
121
|
+
#
|
122
|
+
# @since 0.2.0
|
123
|
+
#
|
124
|
+
def suggestion_for_argument(arg)
|
125
|
+
case arg
|
126
|
+
when /\AFILE\z|_FILE\z/ then '<file>'
|
127
|
+
when /\ADIR\z|_DIR\z/ then '<directory>'
|
128
|
+
when /\AHOST\z|_HOST\z/ then '<hostname>'
|
129
|
+
when /\AUSER\z|_USER\z/ then '<user>'
|
130
|
+
end
|
131
|
+
end
|
120
132
|
|
121
133
|
#
|
122
134
|
# Generates the completion rules for the given [command_kit] command
|
@@ -139,20 +151,26 @@ module CommandKit
|
|
139
151
|
# add all long option flags
|
140
152
|
command_class.options.each_value do |option|
|
141
153
|
completions[command_name] << option.long
|
154
|
+
completions[command_name] << option.short if option.short
|
142
155
|
|
143
156
|
if option.value
|
144
|
-
if (
|
157
|
+
if (suggestion = suggestion_for_argument(option.value.usage))
|
158
|
+
command_pattern = "#{command_name}*#{option.long}"
|
159
|
+
|
145
160
|
# add a special rule if the option's value USAGE maps to a
|
146
161
|
# 'completely' completion keyword (ex: `FILE` -> `<file>`).
|
147
|
-
completions[
|
148
|
-
|
149
|
-
|
162
|
+
completions[command_pattern] = [suggestion]
|
163
|
+
|
164
|
+
if option.short
|
165
|
+
# also add another rule with the option's short flag
|
166
|
+
completions["#{command_name}*#{option.short}"] = [suggestion]
|
167
|
+
end
|
150
168
|
end
|
151
169
|
end
|
152
170
|
end
|
153
171
|
end
|
154
172
|
|
155
|
-
# sub-commands
|
173
|
+
# sub-commands / first argument
|
156
174
|
if command_class.include?(CommandKit::Commands)
|
157
175
|
command_class.commands.each do |subcommand_name,subcommand|
|
158
176
|
# add all sub-command names
|
@@ -165,6 +183,13 @@ module CommandKit
|
|
165
183
|
end
|
166
184
|
|
167
185
|
completions[command_name].concat(command_class.command_aliases.keys)
|
186
|
+
elsif command_class.include?(CommandKit::Arguments)
|
187
|
+
if (argument = command_class.arguments.values.first)
|
188
|
+
if (suggestion = suggestion_for_argument(argument.usage))
|
189
|
+
# add a suggestion for the first argument
|
190
|
+
completions[command_name] << suggestion
|
191
|
+
end
|
192
|
+
end
|
168
193
|
end
|
169
194
|
|
170
195
|
# filter out any command's that have no options/sub-commands
|
data/spec/task_spec.rb
CHANGED
@@ -219,6 +219,140 @@ describe CommandKit::Completion::Task do
|
|
219
219
|
end
|
220
220
|
end
|
221
221
|
|
222
|
+
context "when the command class includes CommandKit::Arguments" do
|
223
|
+
context "and has at least one argument" do
|
224
|
+
context "and it's named FILE" do
|
225
|
+
class TestCommandWithFILEArgument < CommandKit::Command
|
226
|
+
|
227
|
+
command_name 'test'
|
228
|
+
|
229
|
+
option :foo, desc: 'Foo option'
|
230
|
+
|
231
|
+
argument :bar, usage: 'FILE', desc: 'Bar option'
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
let(:command_class) { TestCommandWithFILEArgument }
|
236
|
+
|
237
|
+
it "must add '<file>' to the command's completion rule" do
|
238
|
+
expect(subject.completion_rules_for(command_class)).to eq(
|
239
|
+
{
|
240
|
+
"test" => %w[--foo <file>]
|
241
|
+
}
|
242
|
+
)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context "and it's named DIR" do
|
247
|
+
class TestCommandWithDIRArgument < CommandKit::Command
|
248
|
+
|
249
|
+
command_name 'test'
|
250
|
+
|
251
|
+
option :foo, desc: 'Foo option'
|
252
|
+
|
253
|
+
argument :bar, usage: 'DIR', desc: 'Bar option'
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
let(:command_class) { TestCommandWithDIRArgument }
|
258
|
+
|
259
|
+
it "must add '<directory>' to the command's completion rule" do
|
260
|
+
expect(subject.completion_rules_for(command_class)).to eq(
|
261
|
+
{
|
262
|
+
"test" => %w[--foo <directory>]
|
263
|
+
}
|
264
|
+
)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
context "and it's named HOST" do
|
269
|
+
class TestCommandWithHOSTArgument < CommandKit::Command
|
270
|
+
|
271
|
+
command_name 'test'
|
272
|
+
|
273
|
+
option :foo, desc: 'Foo option'
|
274
|
+
|
275
|
+
argument :bar, usage: 'HOST', desc: 'Bar option'
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
let(:command_class) { TestCommandWithHOSTArgument }
|
280
|
+
|
281
|
+
it "must add '<hostname>' to the command's completion rule" do
|
282
|
+
expect(subject.completion_rules_for(command_class)).to eq(
|
283
|
+
{
|
284
|
+
"test" => %w[--foo <hostname>]
|
285
|
+
}
|
286
|
+
)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
context "and it's named USER" do
|
291
|
+
class TestCommandWithUSERArgument < CommandKit::Command
|
292
|
+
|
293
|
+
command_name 'test'
|
294
|
+
|
295
|
+
option :foo, desc: 'Foo option'
|
296
|
+
|
297
|
+
argument :bar, usage: 'USER', desc: 'Bar option'
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
let(:command_class) { TestCommandWithUSERArgument }
|
302
|
+
|
303
|
+
it "must add '<user>' to the command's completion rule" do
|
304
|
+
expect(subject.completion_rules_for(command_class)).to eq(
|
305
|
+
{
|
306
|
+
"test" => %w[--foo <user>]
|
307
|
+
}
|
308
|
+
)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
context "but it's named something else" do
|
313
|
+
class TestCommandWithArgument < CommandKit::Command
|
314
|
+
|
315
|
+
command_name 'test'
|
316
|
+
|
317
|
+
option :foo, desc: 'Foo option'
|
318
|
+
|
319
|
+
argument :bar, usage: 'BAR', desc: 'Bar option'
|
320
|
+
|
321
|
+
end
|
322
|
+
|
323
|
+
let(:command_class) { TestCommandWithArgument }
|
324
|
+
|
325
|
+
it "must not add additional suggestions to the command's completion rule" do
|
326
|
+
expect(subject.completion_rules_for(command_class)).to eq(
|
327
|
+
{
|
328
|
+
"test" => %w[--foo]
|
329
|
+
}
|
330
|
+
)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
context "but has no arguments" do
|
336
|
+
class TestCommandWithoutArguments < CommandKit::Command
|
337
|
+
|
338
|
+
command_name 'test'
|
339
|
+
|
340
|
+
option :foo, desc: 'Foo option'
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
let(:command_class) { TestCommandWithoutArguments }
|
345
|
+
|
346
|
+
it "must not add additional suggestions" do
|
347
|
+
expect(subject.completion_rules_for(command_class)).to eq(
|
348
|
+
{
|
349
|
+
"test" => %w[--foo]
|
350
|
+
}
|
351
|
+
)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
222
356
|
context "when the command class includes CommandKit::Commands" do
|
223
357
|
class TestCommandWithSubCommands < CommandKit::Command
|
224
358
|
include CommandKit::Commands
|
@@ -259,7 +393,7 @@ describe CommandKit::Completion::Task do
|
|
259
393
|
it "must add completion rules for the other commands" do
|
260
394
|
expect(subject.completion_rules_for(command_class)).to eq(
|
261
395
|
{
|
262
|
-
"test" => %w[--global-option help foo bar],
|
396
|
+
"test" => %w[--global-option -g help foo bar],
|
263
397
|
"test foo" => %w[--foo-opt1 --foo-opt2],
|
264
398
|
"test bar" => %w[--bar-opt1 --bar-opt2]
|
265
399
|
}
|
@@ -309,7 +443,7 @@ describe CommandKit::Completion::Task do
|
|
309
443
|
it "must include the command aliases in the completion rules" do
|
310
444
|
expect(subject.completion_rules_for(command_class)).to eq(
|
311
445
|
{
|
312
|
-
"test" => %w[--global-option help foo bar foo2 bar2],
|
446
|
+
"test" => %w[--global-option -g help foo bar foo2 bar2],
|
313
447
|
"test foo" => %w[--foo-opt1 --foo-opt2],
|
314
448
|
"test bar" => %w[--bar-opt1 --bar-opt2]
|
315
449
|
}
|
@@ -349,7 +483,7 @@ describe CommandKit::Completion::Task do
|
|
349
483
|
it "must omit the command from the completion rules" do
|
350
484
|
expect(subject.completion_rules_for(command_class)).to eq(
|
351
485
|
{
|
352
|
-
"test" => %w[--global-option help foo bar],
|
486
|
+
"test" => %w[--global-option -g help foo bar],
|
353
487
|
"test foo" => %w[--foo-opt1 --foo-opt2]
|
354
488
|
}
|
355
489
|
)
|
@@ -423,7 +557,7 @@ describe CommandKit::Completion::Task do
|
|
423
557
|
it "must recursively include completion rules for the sub-sub-commands" do
|
424
558
|
expect(subject.completion_rules_for(command_class)).to eq(
|
425
559
|
{
|
426
|
-
"test" => %w[--global-option help foo bar],
|
560
|
+
"test" => %w[--global-option -g help foo bar],
|
427
561
|
"test foo" => %w[--foo-opt1 --foo-opt2],
|
428
562
|
"test bar" => %w[--bar-opt1 --bar-opt2 help baz qux],
|
429
563
|
"test bar baz" => %w[--baz-opt1 --baz-opt2],
|
@@ -435,14 +569,65 @@ describe CommandKit::Completion::Task do
|
|
435
569
|
end
|
436
570
|
end
|
437
571
|
|
572
|
+
describe "#suggestion_for_argument" do
|
573
|
+
context "when given 'FILE'" do
|
574
|
+
it "must return '<file>'" do
|
575
|
+
expect(subject.suggestion_for_argument('FILE')).to eq('<file>')
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
context "when the string ends with '_FILE'" do
|
580
|
+
it "must return '<file>'" do
|
581
|
+
expect(subject.suggestion_for_argument('FOO_FILE')).to eq('<file>')
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
context "when given 'DIR'" do
|
586
|
+
it "must return '<directory>'" do
|
587
|
+
expect(subject.suggestion_for_argument('DIR')).to eq('<directory>')
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
context "when the string ends with '_DIR'" do
|
592
|
+
it "must return '<directory>'" do
|
593
|
+
expect(subject.suggestion_for_argument('FOO_DIR')).to eq('<directory>')
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
context "when given 'HOST'" do
|
598
|
+
it "must return '<hostname>'" do
|
599
|
+
expect(subject.suggestion_for_argument('HOST')).to eq('<hostname>')
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
context "when the string ends with '_HOST'" do
|
604
|
+
it "must return '<hostname>'" do
|
605
|
+
expect(subject.suggestion_for_argument('FOO_HOST')).to eq('<hostname>')
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
context "when given 'USER'" do
|
610
|
+
it "must return '<user>'" do
|
611
|
+
expect(subject.suggestion_for_argument('USER')).to eq('<user>')
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
context "when the string ends with '_USER'" do
|
616
|
+
it "must return '<user>'" do
|
617
|
+
expect(subject.suggestion_for_argument('FOO_USER')).to eq('<user>')
|
618
|
+
end
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
438
622
|
describe "#completion_rules" do
|
439
623
|
it "must load the class from #class_file and return the generated completion rules for it" do
|
440
624
|
expect(subject.completion_rules).to eq(
|
441
625
|
{
|
442
|
-
"foo" => %w[--config-file help config list update ls up],
|
626
|
+
"foo" => %w[--config-file -C help config list update ls up],
|
443
627
|
"foo config" => %w[help get set],
|
444
|
-
"foo update" => %w[--quiet],
|
445
|
-
"foo*--config-file" => %w[<file>]
|
628
|
+
"foo update" => %w[--quiet -q],
|
629
|
+
"foo*--config-file" => %w[<file>],
|
630
|
+
"foo*-C" => %w[<file>]
|
446
631
|
}
|
447
632
|
)
|
448
633
|
end
|
@@ -462,10 +647,11 @@ describe CommandKit::Completion::Task do
|
|
462
647
|
it "must merge the additional completion rules with the generated ones" do
|
463
648
|
expect(subject.completion_rules).to eq(
|
464
649
|
{
|
465
|
-
"foo" => %w[--config-file help config list update ls up],
|
650
|
+
"foo" => %w[--config-file -C help config list update ls up],
|
466
651
|
"foo config" => %w[help get set],
|
467
|
-
"foo update" => ['--quiet', '$(foo list)'],
|
468
|
-
"foo*--config-file" => %w[<file>]
|
652
|
+
"foo update" => ['--quiet', '-q', '$(foo list)'],
|
653
|
+
"foo*--config-file" => %w[<file>],
|
654
|
+
"foo*-C" => %w[<file>]
|
469
655
|
}
|
470
656
|
)
|
471
657
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: command_kit-completion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: command_kit
|
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '0'
|
112
112
|
requirements: []
|
113
|
-
rubygems_version: 3.4.
|
113
|
+
rubygems_version: 3.4.19
|
114
114
|
signing_key:
|
115
115
|
specification_version: 4
|
116
116
|
summary: Generate shell completions for command_kit commands
|