command_kit-completion 0.2.1 → 0.3.0
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 +4 -4
- data/.github/workflows/ruby.yml +4 -3
- data/ChangeLog.md +6 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/command_kit/completion/task.rb +51 -12
- data/lib/command_kit/completion/version.rb +1 -1
- data/spec/task_spec.rb +55 -17
- 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: 721a31416806fcf1375dfa9060827013fbde3ffc06f0d9916f31c5602d4386f7
|
4
|
+
data.tar.gz: e6bb27f5dd650bfb26b9fda270bb66a97c7c260cbaa45b3a520a93aa53594567
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e9820c5f5ae32b4f9672d9b05bec71b86e0a66a9a8ae873e74346d65fe2d5b8d37c205921689d7c842d30e1d8411328fc5181da61b57abe71fbd31518485229
|
7
|
+
data.tar.gz: 855fd91e1a677a359f62f1ebcc38350e6308e5451cfa7d69dea172ec3d88c015a2323e1b7d6559f64cd6667bd1c5ac2489d62644523e39bf80f8a2628bd64621
|
data/.github/workflows/ruby.yml
CHANGED
data/ChangeLog.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
### 0.3.0 / 2024-12-16
|
2
|
+
|
3
|
+
* Generate `<file>` and `<directory>` completion rules for arguments named
|
4
|
+
`PATH` or ending in `_PATH`, so they can tab complete both files and
|
5
|
+
directories.
|
6
|
+
|
1
7
|
### 0.2.1 / 2024-04-29
|
2
8
|
|
3
9
|
* Support loading YAML input files that contain YAML aliases.
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -10,37 +10,61 @@ require 'fileutils'
|
|
10
10
|
|
11
11
|
module CommandKit
|
12
12
|
module Completion
|
13
|
+
#
|
14
|
+
# `command_kit-completion` rake task.
|
15
|
+
#
|
16
|
+
# ## Example
|
17
|
+
#
|
18
|
+
# require 'command_kit/completion/task'
|
19
|
+
# CommandKit::Completion::Task.new(
|
20
|
+
# class_file: './examples/cli',
|
21
|
+
# class_name: 'Foo::CLI',
|
22
|
+
# output_file: 'completion.sh'
|
23
|
+
# )
|
24
|
+
#
|
13
25
|
class Task < Rake::TaskLib
|
14
26
|
|
15
27
|
# The file that the command_kit CLI is defined in.
|
16
28
|
#
|
17
29
|
# @return [String]
|
30
|
+
#
|
31
|
+
# @api private
|
18
32
|
attr_reader :class_file
|
19
33
|
|
20
34
|
# The class name of the command_kit CLI.
|
21
35
|
#
|
22
36
|
# @return [String]
|
37
|
+
#
|
38
|
+
# @api private
|
23
39
|
attr_reader :class_name
|
24
40
|
|
25
41
|
# The output file to write the shell completions to.
|
26
42
|
#
|
27
43
|
# @return [String]
|
44
|
+
#
|
45
|
+
# @api private
|
28
46
|
attr_reader :output_file
|
29
47
|
|
30
48
|
# Optional input YAML file to read additional shell completions from.
|
31
49
|
#
|
32
50
|
# @return [String, nil]
|
51
|
+
#
|
52
|
+
# @api private
|
33
53
|
attr_reader :input_file
|
34
54
|
|
35
55
|
# Specifies whether the shell completion logic should be wrapped in a
|
36
56
|
# function.
|
37
57
|
#
|
38
58
|
# @return [Boolean]
|
59
|
+
#
|
60
|
+
# @api private
|
39
61
|
attr_reader :wrap_function
|
40
62
|
|
41
63
|
# Optional function name to wrap the shell completions within.
|
42
64
|
#
|
43
65
|
# @return [String, nil]
|
66
|
+
#
|
67
|
+
# @api private
|
44
68
|
attr_reader :function_name
|
45
69
|
|
46
70
|
#
|
@@ -61,6 +85,8 @@ module CommandKit
|
|
61
85
|
#
|
62
86
|
# [completely examples]: https://github.com/DannyBen/completely?tab=readme-ov-file#using-the-completely-command-line
|
63
87
|
#
|
88
|
+
# @api public
|
89
|
+
#
|
64
90
|
def initialize(class_file: ,
|
65
91
|
class_name: ,
|
66
92
|
output_file: ,
|
@@ -81,6 +107,8 @@ module CommandKit
|
|
81
107
|
#
|
82
108
|
# Defines the `command_kit:completion` task.
|
83
109
|
#
|
110
|
+
# @api private
|
111
|
+
#
|
84
112
|
def define
|
85
113
|
task(@output_file) do
|
86
114
|
completions = Completely::Completions.new(completion_rules)
|
@@ -105,6 +133,8 @@ module CommandKit
|
|
105
133
|
#
|
106
134
|
# @return [Class]
|
107
135
|
#
|
136
|
+
# @api private
|
137
|
+
#
|
108
138
|
def load_class
|
109
139
|
require(@class_file)
|
110
140
|
Object.const_get(@class_name)
|
@@ -116,6 +146,8 @@ module CommandKit
|
|
116
146
|
# @return [Hash]
|
117
147
|
# The completion rules from the {#input_file}.
|
118
148
|
#
|
149
|
+
# @api private
|
150
|
+
#
|
119
151
|
def load_input_file
|
120
152
|
YAML.load_file(@input_file, aliases: true)
|
121
153
|
end
|
@@ -126,17 +158,20 @@ module CommandKit
|
|
126
158
|
# @param [String] arg
|
127
159
|
# The argument name.
|
128
160
|
#
|
129
|
-
# @return [String
|
161
|
+
# @return [Array<String>, nil]
|
130
162
|
# The suggestion keyword for the argument name.
|
131
163
|
#
|
132
|
-
# @since 0.
|
164
|
+
# @since 0.3.0
|
133
165
|
#
|
134
|
-
|
166
|
+
# @api private
|
167
|
+
#
|
168
|
+
def suggestions_for_argument(arg)
|
135
169
|
case arg
|
136
|
-
when /\AFILE\z|_FILE\z/ then
|
137
|
-
when /\ADIR\z|_DIR\z/ then
|
138
|
-
when /\
|
139
|
-
when /\
|
170
|
+
when /\AFILE\z|_FILE\z/ then %w[<file>]
|
171
|
+
when /\ADIR\z|_DIR\z/ then %w[<directory>]
|
172
|
+
when /\APATH\z|_PATH\z/ then %w[<file> <directory>]
|
173
|
+
when /\AHOST\z|_HOST\z/ then %w[<hostname>]
|
174
|
+
when /\AUSER\z|_USER\z/ then %w[<user>]
|
140
175
|
end
|
141
176
|
end
|
142
177
|
|
@@ -152,6 +187,8 @@ module CommandKit
|
|
152
187
|
# @return [Hash{String => Array<String>}]
|
153
188
|
# The completion rules for the command class and any sub-commands.
|
154
189
|
#
|
190
|
+
# @api private
|
191
|
+
#
|
155
192
|
def completion_rules_for(command_class)
|
156
193
|
command_name = command_class.command_name
|
157
194
|
completions = {command_name => []}
|
@@ -164,16 +201,16 @@ module CommandKit
|
|
164
201
|
completions[command_name] << option.short if option.short
|
165
202
|
|
166
203
|
if option.value
|
167
|
-
if (
|
204
|
+
if (suggestions = suggestions_for_argument(option.value.usage))
|
168
205
|
command_pattern = "#{command_name}*#{option.long}"
|
169
206
|
|
170
207
|
# add a special rule if the option's value USAGE maps to a
|
171
208
|
# 'completely' completion keyword (ex: `FILE` -> `<file>`).
|
172
|
-
completions[command_pattern] =
|
209
|
+
completions[command_pattern] = suggestions
|
173
210
|
|
174
211
|
if option.short
|
175
212
|
# also add another rule with the option's short flag
|
176
|
-
completions["#{command_name}*#{option.short}"] =
|
213
|
+
completions["#{command_name}*#{option.short}"] = suggestions
|
177
214
|
end
|
178
215
|
end
|
179
216
|
end
|
@@ -195,9 +232,9 @@ module CommandKit
|
|
195
232
|
completions[command_name].concat(command_class.command_aliases.keys)
|
196
233
|
elsif command_class.include?(CommandKit::Arguments)
|
197
234
|
if (argument = command_class.arguments.values.first)
|
198
|
-
if (
|
235
|
+
if (suggestions = suggestions_for_argument(argument.usage))
|
199
236
|
# add a suggestion for the first argument
|
200
|
-
completions[command_name]
|
237
|
+
completions[command_name].concat(suggestions)
|
201
238
|
end
|
202
239
|
end
|
203
240
|
end
|
@@ -216,6 +253,8 @@ module CommandKit
|
|
216
253
|
#
|
217
254
|
# @return [Hash{String => Array<String>}]
|
218
255
|
#
|
256
|
+
# @api private
|
257
|
+
#
|
219
258
|
def completion_rules
|
220
259
|
completion_rules = completion_rules_for(load_class)
|
221
260
|
|
data/spec/task_spec.rb
CHANGED
@@ -605,52 +605,90 @@ describe CommandKit::Completion::Task do
|
|
605
605
|
end
|
606
606
|
end
|
607
607
|
|
608
|
-
describe "#
|
608
|
+
describe "#suggestions_for_argument" do
|
609
609
|
context "when given 'FILE'" do
|
610
|
-
it "must return '<file>'" do
|
611
|
-
expect(subject.
|
610
|
+
it "must return ['<file>']" do
|
611
|
+
expect(subject.suggestions_for_argument('FILE')).to eq(
|
612
|
+
%w[<file>]
|
613
|
+
)
|
612
614
|
end
|
613
615
|
end
|
614
616
|
|
615
617
|
context "when the string ends with '_FILE'" do
|
616
|
-
it "must return '<file>'" do
|
617
|
-
expect(subject.
|
618
|
+
it "must return ['<file>']" do
|
619
|
+
expect(subject.suggestions_for_argument('FOO_FILE')).to eq(
|
620
|
+
%w[<file>]
|
621
|
+
)
|
618
622
|
end
|
619
623
|
end
|
620
624
|
|
621
625
|
context "when given 'DIR'" do
|
622
|
-
it "must return '<directory>'" do
|
623
|
-
expect(subject.
|
626
|
+
it "must return ['<directory>']" do
|
627
|
+
expect(subject.suggestions_for_argument('DIR')).to eq(
|
628
|
+
%w[<directory>]
|
629
|
+
)
|
624
630
|
end
|
625
631
|
end
|
626
632
|
|
627
633
|
context "when the string ends with '_DIR'" do
|
628
|
-
it "must return '<directory>'" do
|
629
|
-
expect(subject.
|
634
|
+
it "must return ['<directory>']" do
|
635
|
+
expect(subject.suggestions_for_argument('FOO_DIR')).to eq(
|
636
|
+
%w[<directory>]
|
637
|
+
)
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
context "when given 'PATH'" do
|
642
|
+
it "must return ['<file>', '<directory>']" do
|
643
|
+
expect(subject.suggestions_for_argument('PATH')).to eq(
|
644
|
+
%w[
|
645
|
+
<file>
|
646
|
+
<directory>
|
647
|
+
]
|
648
|
+
)
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
652
|
+
context "when the string ends with '_PATH'" do
|
653
|
+
it "must return ['<file>', '<directory>']" do
|
654
|
+
expect(subject.suggestions_for_argument('FOO_PATH')).to eq(
|
655
|
+
%w[
|
656
|
+
<file>
|
657
|
+
<directory>
|
658
|
+
]
|
659
|
+
)
|
630
660
|
end
|
631
661
|
end
|
632
662
|
|
633
663
|
context "when given 'HOST'" do
|
634
|
-
it "must return '<hostname>'" do
|
635
|
-
expect(subject.
|
664
|
+
it "must return ['<hostname>']" do
|
665
|
+
expect(subject.suggestions_for_argument('HOST')).to eq(
|
666
|
+
%w[<hostname>]
|
667
|
+
)
|
636
668
|
end
|
637
669
|
end
|
638
670
|
|
639
671
|
context "when the string ends with '_HOST'" do
|
640
|
-
it "must return '<hostname>'" do
|
641
|
-
expect(subject.
|
672
|
+
it "must return ['<hostname>']" do
|
673
|
+
expect(subject.suggestions_for_argument('FOO_HOST')).to eq(
|
674
|
+
%w[<hostname>]
|
675
|
+
)
|
642
676
|
end
|
643
677
|
end
|
644
678
|
|
645
679
|
context "when given 'USER'" do
|
646
|
-
it "must return '<user>'" do
|
647
|
-
expect(subject.
|
680
|
+
it "must return ['<user>']" do
|
681
|
+
expect(subject.suggestions_for_argument('USER')).to eq(
|
682
|
+
%w[<user>]
|
683
|
+
)
|
648
684
|
end
|
649
685
|
end
|
650
686
|
|
651
687
|
context "when the string ends with '_USER'" do
|
652
|
-
it "must return '<user>'" do
|
653
|
-
expect(subject.
|
688
|
+
it "must return ['<user>']" do
|
689
|
+
expect(subject.suggestions_for_argument('FOO_USER')).to eq(
|
690
|
+
%w[<user>]
|
691
|
+
)
|
654
692
|
end
|
655
693
|
end
|
656
694
|
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: command_kit
|
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '0'
|
113
113
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
114
|
+
rubygems_version: 3.5.22
|
115
115
|
signing_key:
|
116
116
|
specification_version: 4
|
117
117
|
summary: Generate shell completions for command_kit commands
|