bashly 1.3.8 → 1.4.0.rc1
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/lib/bashly/commands/doc.rb +1 -1
- data/lib/bashly/completion_builder.rb +188 -0
- data/lib/bashly/completions/bashly-completions.bash +482 -78
- data/lib/bashly/completions/completely.yaml +141 -155
- data/lib/bashly/completions/completely.yaml.gtx +62 -75
- data/lib/bashly/concerns/completions.rb +9 -46
- data/lib/bashly/config_validator.rb +3 -0
- data/lib/bashly/docs/arg.yml +11 -0
- data/lib/bashly/extensions/yaml.rb +12 -5
- data/lib/bashly/libraries/libraries.yml +15 -0
- data/lib/bashly/library_source_config.rb +1 -1
- data/lib/bashly/message_strings.rb +2 -2
- data/lib/bashly/script/argument.rb +1 -1
- data/lib/bashly/script/dependency.rb +1 -1
- data/lib/bashly/version.rb +1 -1
- data/lib/bashly.rb +3 -2
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c4417e2acaa7177450ab206c368039c46db5e2e3839b015c7dac235d23d3899a
|
|
4
|
+
data.tar.gz: e62782cd28d229c36adcc4be6d09243b693f8c1536fadcfb98ceaddb203fbc49
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f2827e99a65bbfc2cdaa77b2533400d6a85d7af72cbb35471654bb2ce840cef897f76e19c51504027559405a410cb46d150c2b2680d9b471526a94ee29dc4083
|
|
7
|
+
data.tar.gz: 1cbe9b74014155e5cbd920fa29249a4102afea7738334b811583d5bdc1ef9064a1595d87d238bc350dd46b4dbe32926546a341956b1f417b521f5d459947ba1c
|
data/lib/bashly/commands/doc.rb
CHANGED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
module Bashly
|
|
2
|
+
class CompletionBuilder
|
|
3
|
+
BUILTIN_PATTERN = /\A<([^>]+)>\z/
|
|
4
|
+
|
|
5
|
+
def initialize(command, with_version: true)
|
|
6
|
+
@command = command
|
|
7
|
+
@with_version = with_version
|
|
8
|
+
@patterns = []
|
|
9
|
+
@options = {}
|
|
10
|
+
@tokens = {}
|
|
11
|
+
@token_sources = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call
|
|
15
|
+
add_command @command, inherited_global_groups: []
|
|
16
|
+
|
|
17
|
+
result = { 'patterns' => @patterns }
|
|
18
|
+
result['options'] = @options if @options.any?
|
|
19
|
+
result['tokens'] = @tokens if @tokens.any?
|
|
20
|
+
result
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def add_command(command, inherited_global_groups:)
|
|
26
|
+
local_group = add_local_options command
|
|
27
|
+
pattern_groups = inherited_global_groups.dup
|
|
28
|
+
pattern_groups << local_group if local_group
|
|
29
|
+
|
|
30
|
+
@patterns << pattern_for(command, pattern_groups)
|
|
31
|
+
|
|
32
|
+
child_global_groups = inherited_global_groups.dup
|
|
33
|
+
if command.global_flags?
|
|
34
|
+
global_group = add_global_options command
|
|
35
|
+
child_global_groups << global_group if global_group
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
command.visible_commands.each do |child|
|
|
39
|
+
add_command child, inherited_global_groups: child_global_groups
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def pattern_for(command, option_groups)
|
|
44
|
+
parts = [command_path(command)]
|
|
45
|
+
parts.concat(option_groups.map { |group| "[#{group} options]" })
|
|
46
|
+
parts.concat positional_tokens(command)
|
|
47
|
+
parts.join ' '
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def command_path(command)
|
|
51
|
+
command_chain(command).map.with_index do |item, index|
|
|
52
|
+
index.zero? ? item.name : item.aliases.join('|')
|
|
53
|
+
end.join ' '
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def command_chain(command)
|
|
57
|
+
result = []
|
|
58
|
+
current = command
|
|
59
|
+
while current
|
|
60
|
+
result.unshift current
|
|
61
|
+
current = current.parent_command
|
|
62
|
+
end
|
|
63
|
+
result
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def add_local_options(command)
|
|
67
|
+
entries = fixed_option_entries(command) + flag_option_entries(command.visible_flags, command)
|
|
68
|
+
return if entries.empty?
|
|
69
|
+
|
|
70
|
+
name = group_name command
|
|
71
|
+
@options[name] = entries
|
|
72
|
+
name
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def add_global_options(command)
|
|
76
|
+
entries = flag_option_entries command.visible_flags, command
|
|
77
|
+
return if entries.empty?
|
|
78
|
+
|
|
79
|
+
name = "#{group_name(command)}_global"
|
|
80
|
+
@options[name] = entries
|
|
81
|
+
name
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def fixed_option_entries(command)
|
|
85
|
+
return [] if !command.root_command? && command.catch_all.catch_help?
|
|
86
|
+
|
|
87
|
+
entries = %w[--help|-h]
|
|
88
|
+
entries << '--version|-v' if command.root_command? && @with_version
|
|
89
|
+
entries
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def flag_option_entries(flags, command)
|
|
93
|
+
flags.map do |flag|
|
|
94
|
+
token_name = flag_token_name flag, command
|
|
95
|
+
flag.completion_option_entry token_name
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def flag_token_name(flag, command)
|
|
100
|
+
return unless flag.arg || flag.allowed || flag.completions
|
|
101
|
+
|
|
102
|
+
register_token flag.arg || flag.name, command, flag_source(flag)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def positional_tokens(command)
|
|
106
|
+
command.args.map do |arg|
|
|
107
|
+
token_name = register_token arg.name, command, arg_source(arg, command)
|
|
108
|
+
suffix = arg.repeatable ? '...' : nil
|
|
109
|
+
"<#{token_name}>#{suffix}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def flag_source(flag)
|
|
114
|
+
return static_source(flag.allowed) if flag.allowed
|
|
115
|
+
return completion_source(flag.completions) if flag.completions
|
|
116
|
+
|
|
117
|
+
nil
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def arg_source(arg, command)
|
|
121
|
+
return static_source(arg.allowed) if arg.allowed
|
|
122
|
+
return completion_source(arg.completions) if arg.completions
|
|
123
|
+
return completion_source(command.completions) if command.completions
|
|
124
|
+
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def static_source(values)
|
|
129
|
+
Array(values).compact.map { |value| escape_static_source value }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def completion_source(values)
|
|
133
|
+
Array(values).compact.map do |value|
|
|
134
|
+
string = value.to_s
|
|
135
|
+
builtin = string[BUILTIN_PATTERN, 1]
|
|
136
|
+
|
|
137
|
+
if builtin
|
|
138
|
+
"+#{builtin}"
|
|
139
|
+
else
|
|
140
|
+
escape_static_source string
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def escape_static_source(value)
|
|
146
|
+
string = value.to_s
|
|
147
|
+
string.start_with?('+') ? "+#{string}" : string
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def register_token(base_name, command, source)
|
|
151
|
+
preferred = token_name base_name
|
|
152
|
+
return preferred if register_token_name preferred, source
|
|
153
|
+
|
|
154
|
+
scoped = token_name "#{group_name command}_#{base_name}"
|
|
155
|
+
return scoped if register_token_name scoped, source
|
|
156
|
+
|
|
157
|
+
suffix = 2
|
|
158
|
+
loop do
|
|
159
|
+
candidate = "#{scoped}_#{suffix}"
|
|
160
|
+
return candidate if register_token_name candidate, source
|
|
161
|
+
|
|
162
|
+
suffix += 1
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def register_token_name(name, source)
|
|
167
|
+
if @token_sources.has_key? name
|
|
168
|
+
return false unless @token_sources[name] == source
|
|
169
|
+
else
|
|
170
|
+
@token_sources[name] = source
|
|
171
|
+
@tokens[name] = source
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
true
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def group_name(command)
|
|
178
|
+
token_name command.root_command? ? 'root' : command.action_name
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def token_name(value)
|
|
182
|
+
value.to_s
|
|
183
|
+
.gsub(/[^a-zA-Z0-9]+/, '_')
|
|
184
|
+
.gsub(/\A_+|_+\z/, '')
|
|
185
|
+
.downcase
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|