squared 0.6.2 → 0.6.3
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/CHANGELOG.md +40 -0
- data/README.md +23 -13
- data/lib/squared/common/base.rb +2 -2
- data/lib/squared/common/format.rb +39 -32
- data/lib/squared/common/prompt.rb +6 -4
- data/lib/squared/common/shell.rb +4 -4
- data/lib/squared/config.rb +6 -7
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +72 -23
- data/lib/squared/workspace/project/base.rb +145 -83
- data/lib/squared/workspace/project/docker.rb +15 -15
- data/lib/squared/workspace/project/git.rb +74 -27
- data/lib/squared/workspace/project/node.rb +211 -109
- data/lib/squared/workspace/project/python.rb +9 -9
- data/lib/squared/workspace/project/ruby.rb +29 -34
- data/lib/squared/workspace/project/support/class.rb +36 -652
- data/lib/squared/workspace/project/support/optionpartition.rb +641 -0
- data/lib/squared/workspace/project.rb +0 -1
- data/lib/squared/workspace/repo.rb +23 -14
- data/lib/squared/workspace/series.rb +10 -8
- data/squared.gemspec +2 -2
- metadata +3 -3
- data/lib/squared/workspace/project/support.rb +0 -3
|
@@ -1,639 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'forwardable'
|
|
4
|
-
|
|
5
3
|
module Squared
|
|
6
4
|
module Workspace
|
|
7
5
|
module Project
|
|
8
6
|
module Support
|
|
9
|
-
|
|
10
|
-
include Common::Shell
|
|
11
|
-
extend Forwardable
|
|
12
|
-
|
|
13
|
-
OPT_NAME = /\A(?:(--)|-)((?(1)[^\[\]=\s-][^\[\]=\s]*|[^\[\]=\s-]))\z/
|
|
14
|
-
OPT_VALUE = /\A-{0,2}([^\[\]=\s-][^\[\]=\s]*)(?:=|\s+)(\S.*)\z/
|
|
15
|
-
OPT_SINGLE = /\A-([^\[\]=\s-])(.+)\z/
|
|
16
|
-
private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE
|
|
17
|
-
|
|
18
|
-
class << self
|
|
19
|
-
include Common::Format
|
|
20
|
-
include Shell
|
|
21
|
-
include Prompt
|
|
22
|
-
|
|
23
|
-
def append(target, *args, delim: false, escape: false, quote: true, strip: nil, force: true, double: false,
|
|
24
|
-
filter: nil, **)
|
|
25
|
-
return if (ret = args.flatten).empty?
|
|
26
|
-
|
|
27
|
-
target << '--' if delim && !target.include?('--')
|
|
28
|
-
if strip
|
|
29
|
-
pat, s = Array(strip)
|
|
30
|
-
ret.map! { |val| val.is_a?(String) ? val.gsub(pat, s || '') : val }
|
|
31
|
-
end
|
|
32
|
-
ret, err = ret.partition { |val| filter.match?(val.to_s) } if filter
|
|
33
|
-
if block_given?
|
|
34
|
-
out = []
|
|
35
|
-
err ||= []
|
|
36
|
-
ret.each do |val|
|
|
37
|
-
case (s = yield val)
|
|
38
|
-
when String
|
|
39
|
-
out << s
|
|
40
|
-
when NilClass, FalseClass
|
|
41
|
-
err << val
|
|
42
|
-
else
|
|
43
|
-
out << val
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
ret = out
|
|
47
|
-
end
|
|
48
|
-
if escape || quote
|
|
49
|
-
ret.map! do |val|
|
|
50
|
-
if opt?(val)
|
|
51
|
-
val
|
|
52
|
-
elsif escape
|
|
53
|
-
shell_escape(val, quote: quote, double: double)
|
|
54
|
-
else
|
|
55
|
-
shell_quote(val, force: force, double: double)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
if target.is_a?(Set)
|
|
60
|
-
target.merge(ret)
|
|
61
|
-
else
|
|
62
|
-
target.concat(ret)
|
|
63
|
-
end
|
|
64
|
-
err || ret
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def clear(target, opts, pass: true, styles: nil, **kwargs)
|
|
68
|
-
return if opts.empty?
|
|
69
|
-
|
|
70
|
-
kwargs[:subject] ||= target.first.stripext
|
|
71
|
-
kwargs[:hint] ||= 'unrecognized'
|
|
72
|
-
append(target, opts, delim: true) if kwargs.delete(:append)
|
|
73
|
-
warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs)
|
|
74
|
-
exit 1 unless pass || confirm("Run? [#{sub_style(target, styles: styles)}]", 'N')
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def delete_key(target, *args, value: false, reverse: false, count: -1)
|
|
78
|
-
ret = []
|
|
79
|
-
args.each do |val|
|
|
80
|
-
next if (opts = target.grep(matchopt(val, value))).empty?
|
|
81
|
-
|
|
82
|
-
opts = opts.first(count) if count >= 0
|
|
83
|
-
opts.send(reverse ? :reverse_each : :each) { |key| target.delete(key) }
|
|
84
|
-
ret.concat(opts)
|
|
85
|
-
end
|
|
86
|
-
ret
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def strip(val)
|
|
90
|
-
return [] unless val
|
|
91
|
-
|
|
92
|
-
val = shell_split val if val.is_a?(String)
|
|
93
|
-
val.map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2') }.reject(&:empty?)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def select(list, bare: true, no: true, single: false, double: false)
|
|
97
|
-
ret = bare ? list.grep_v(/=/) : list.grep(/=/).map! { |val| val.split('=', 2).first }
|
|
98
|
-
ret.map! { |val| val.split('|', 2).last }
|
|
99
|
-
ret = ret.grep_v(/\Ano-/) unless no
|
|
100
|
-
return ret if single == double
|
|
101
|
-
|
|
102
|
-
ret.select { |val| single ? val.size == 1 : val.size > 1 }
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def uniq!(list, pass = [])
|
|
106
|
-
keys = {}
|
|
107
|
-
list.each_with_index do |val, i|
|
|
108
|
-
j = val =~ OPT_VALUE ? $1 : val
|
|
109
|
-
(keys[j] ||= []) << i unless pass.include?(j)
|
|
110
|
-
end
|
|
111
|
-
data = keys.map { |item| item[1].size > 1 ? item[1][0..-2] : [] }.reject(&:empty?)
|
|
112
|
-
return if data.empty?
|
|
113
|
-
|
|
114
|
-
data.each { |key| key.each { |i| list[i] = nil } }
|
|
115
|
-
list.compact!
|
|
116
|
-
list
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def arg?(target, *args, value: false, **)
|
|
120
|
-
r, s = args.partition { |val| val.is_a?(Regexp) }
|
|
121
|
-
r << matchopts(s, value) unless s.empty?
|
|
122
|
-
a = target.to_a
|
|
123
|
-
if (n = a.index('--'))
|
|
124
|
-
a = a[0..n]
|
|
125
|
-
end
|
|
126
|
-
r.any? { |pat| a.any?(pat) }
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def opt?(val)
|
|
130
|
-
return false unless val.is_a?(String)
|
|
131
|
-
|
|
132
|
-
val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def pattern?(val)
|
|
136
|
-
val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
private
|
|
140
|
-
|
|
141
|
-
def matchopt(val, value = false)
|
|
142
|
-
/\A#{val.size == 1 ? shortopt(val) : longopt(val, value)}/
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def matchopts(list, value = false)
|
|
146
|
-
a, b = Array(list).partition { |val| val.size == 1 || val.match?(OPT_SINGLE) }
|
|
147
|
-
return /\A#{shortopt(*a)}}/ if b.empty?
|
|
148
|
-
return /\A#{longopt(*b, value)}/ if a.empty?
|
|
149
|
-
|
|
150
|
-
/\A(?:#{shortopt(*a)}|#{longopt(*b, value)})/
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def shortopt(*group)
|
|
154
|
-
group.map! { |s| Regexp.escape(s.delete_prefix('-')) }
|
|
155
|
-
"-(?:#{group.join('|')})(?:\\z|[^ =]| +[^ -])"
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def longopt(*group, value)
|
|
159
|
-
group.map! { |s| Regexp.escape(s.delete_prefix('--')) }
|
|
160
|
-
"--(?:#{group.join('|')})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
attr_reader :target, :extras, :found, :errors, :values, :project, :path, :sep
|
|
165
|
-
|
|
166
|
-
def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
|
|
167
|
-
:merge, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
|
|
168
|
-
def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :shift, :unshift,
|
|
169
|
-
:pop, :push, :concat, :index, :join, :detect, :map, :map!, :select, :select!, :slice, :slice!,
|
|
170
|
-
:reject, :size
|
|
171
|
-
|
|
172
|
-
def_delegator :@extras, :delete, :remove
|
|
173
|
-
def_delegator :@extras, :delete_at, :remove_at
|
|
174
|
-
def_delegator :@extras, :delete_if, :remove_if
|
|
175
|
-
def_delegator :@extras, :find_all, :detect_all
|
|
176
|
-
def_delegator :@extras, :find_index, :detect_index
|
|
177
|
-
|
|
178
|
-
def initialize(opts, list, target = Set.new, project: nil, path: nil, sep: '=', **kwargs, &blk)
|
|
179
|
-
@target = target.is_a?(Set) ? target : target.to_set
|
|
180
|
-
@project = project
|
|
181
|
-
@path = path || project&.path
|
|
182
|
-
@sep = sep
|
|
183
|
-
@errors = []
|
|
184
|
-
@found = []
|
|
185
|
-
parse(list, opts, **kwargs, &blk)
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def parse(list, opts = extras, no: nil, single: nil, args: false, first: nil, underscore: nil, &blk)
|
|
189
|
-
@extras = []
|
|
190
|
-
@values = []
|
|
191
|
-
bare = []
|
|
192
|
-
e = []
|
|
193
|
-
b = []
|
|
194
|
-
m = []
|
|
195
|
-
p = []
|
|
196
|
-
q = []
|
|
197
|
-
qq = []
|
|
198
|
-
i = []
|
|
199
|
-
f = []
|
|
200
|
-
si = []
|
|
201
|
-
bl = []
|
|
202
|
-
ml = []
|
|
203
|
-
list.flat_map do |val|
|
|
204
|
-
x, y = val.split('|', 2)
|
|
205
|
-
if y
|
|
206
|
-
if (n = val.index('='))
|
|
207
|
-
x += val[n..-1]
|
|
208
|
-
end
|
|
209
|
-
[x, y]
|
|
210
|
-
else
|
|
211
|
-
x
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
.each do |val|
|
|
215
|
-
if (n = val.index('='))
|
|
216
|
-
flag = val[0, n]
|
|
217
|
-
case val[n.succ]
|
|
218
|
-
when 'e'
|
|
219
|
-
e << flag
|
|
220
|
-
when 'b'
|
|
221
|
-
b << flag
|
|
222
|
-
when 'm'
|
|
223
|
-
m << flag
|
|
224
|
-
when 'q'
|
|
225
|
-
qq << flag if val[n + 2] == 'q'
|
|
226
|
-
q << flag
|
|
227
|
-
when 'p'
|
|
228
|
-
p << flag
|
|
229
|
-
when 'i'
|
|
230
|
-
i << flag
|
|
231
|
-
when 'f'
|
|
232
|
-
f << flag
|
|
233
|
-
when 'n'
|
|
234
|
-
si << flag
|
|
235
|
-
when 'v'
|
|
236
|
-
@values << Regexp.escape(flag)
|
|
237
|
-
when '!'
|
|
238
|
-
bl << flag
|
|
239
|
-
when '+'
|
|
240
|
-
ml << flag
|
|
241
|
-
bare << flag
|
|
242
|
-
else
|
|
243
|
-
next
|
|
244
|
-
end
|
|
245
|
-
m << flag if val[n + 2] == 'm'
|
|
246
|
-
bare << flag if val.end_with?('?')
|
|
247
|
-
else
|
|
248
|
-
bare << val
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
no = (no || []).map { |val| (n = val.index('=')) ? val[0, n] : val }
|
|
252
|
-
bare.concat(no)
|
|
253
|
-
if underscore
|
|
254
|
-
tr = ->(a) { a.map { |val| val.tr('-', '_') } }
|
|
255
|
-
@values.concat(tr.call(@values))
|
|
256
|
-
bare.concat(tr.call(bare))
|
|
257
|
-
e.concat(tr.call(e))
|
|
258
|
-
b.concat(tr.call(b))
|
|
259
|
-
m.concat(tr.call(m))
|
|
260
|
-
p.concat(tr.call(p))
|
|
261
|
-
q.concat(tr.call(q))
|
|
262
|
-
qq.concat(tr.call(qq))
|
|
263
|
-
i.concat(tr.call(i))
|
|
264
|
-
f.concat(tr.call(f))
|
|
265
|
-
si.concat(tr.call(si))
|
|
266
|
-
bl.concat(tr.call(bl))
|
|
267
|
-
ml.concat(tr.call(ml))
|
|
268
|
-
no.concat(tr.call(no))
|
|
269
|
-
end
|
|
270
|
-
target.multiple.concat(ml.map { |val| val.size == 1 ? "-#{val}" : "--#{val}" }) if target.is_a?(JoinSet)
|
|
271
|
-
numtype = [
|
|
272
|
-
[i, /\A\d+\z/],
|
|
273
|
-
[f, /\A\d*(?:\.\d+)?\z/],
|
|
274
|
-
[si, /\A-?\d+\z/]
|
|
275
|
-
].freeze
|
|
276
|
-
numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && v.match?(pat) } }
|
|
277
|
-
skip = false
|
|
278
|
-
opts.each do |opt|
|
|
279
|
-
next skip = true if opt == '--'
|
|
280
|
-
next push opt if skip
|
|
281
|
-
|
|
282
|
-
if single&.match?(opt)
|
|
283
|
-
add "-#{opt}"
|
|
284
|
-
elsif bare.include?(opt)
|
|
285
|
-
add(opt.size == 1 ? "-#{opt}" : "--#{opt}")
|
|
286
|
-
elsif opt.start_with?(/no[-_]/) && no.include?(name = opt[3..-1])
|
|
287
|
-
add "--no-#{name}"
|
|
288
|
-
else
|
|
289
|
-
if opt =~ OPT_VALUE
|
|
290
|
-
key = $1
|
|
291
|
-
val = $2
|
|
292
|
-
merge = m.include?(key)
|
|
293
|
-
if e.include?(key)
|
|
294
|
-
add shell_option(key, val, merge: merge, sep: sep)
|
|
295
|
-
elsif q.include?(key)
|
|
296
|
-
add quote_option(key, val, double: qq.include?(key), merge: merge, sep: sep)
|
|
297
|
-
elsif p.include?(key)
|
|
298
|
-
if val.match?(/\A(["']).+\1\z/)
|
|
299
|
-
add shell_option(key, val, escape: false, merge: merge, sep: sep)
|
|
300
|
-
elsif path
|
|
301
|
-
add quote_option(key, path + val, merge: merge, sep: sep)
|
|
302
|
-
else
|
|
303
|
-
push opt
|
|
304
|
-
end
|
|
305
|
-
elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
|
|
306
|
-
add basic_option(key, val, merge: merge, sep: sep)
|
|
307
|
-
elsif merge
|
|
308
|
-
add basic_option(key, val, merge: true, sep: sep)
|
|
309
|
-
else
|
|
310
|
-
push opt
|
|
311
|
-
end
|
|
312
|
-
opt = key
|
|
313
|
-
else
|
|
314
|
-
push opt
|
|
315
|
-
skip = true if args
|
|
316
|
-
end
|
|
317
|
-
skip = true if first&.any? { |s| s.is_a?(Regexp) ? opt.match?(s) : !opt.include?(s) }
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
@values = @values.empty? ? /\A\s+\z/ : /\A(#{@values.join('|')})#{sep}(.+)\z/m
|
|
321
|
-
@extras.each_with_index(&blk) if block_given?
|
|
322
|
-
self
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def swap(opts = nil, &blk)
|
|
326
|
-
unless opts
|
|
327
|
-
opts = found
|
|
328
|
-
@found = []
|
|
329
|
-
end
|
|
330
|
-
opts.sort!(&blk) if block_given?
|
|
331
|
-
@extras = opts
|
|
332
|
-
self
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
def append(*args, **kwargs, &blk)
|
|
336
|
-
args = extras if args.empty?
|
|
337
|
-
out = OptionPartition.append(target, *args, **kwargs, &blk)
|
|
338
|
-
errors.concat(out) if out && (block_given? || kwargs[:filter])
|
|
339
|
-
self
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
def append_any(*args, quote: true, **kwargs)
|
|
343
|
-
(args.empty? ? extras : args.flatten).each do |val|
|
|
344
|
-
val = yield val if block_given?
|
|
345
|
-
next unless val.is_a?(String)
|
|
346
|
-
|
|
347
|
-
if exist?(val)
|
|
348
|
-
add_path(val, **kwargs)
|
|
349
|
-
elsif quote
|
|
350
|
-
add_quote(val, **kwargs)
|
|
351
|
-
else
|
|
352
|
-
add val
|
|
353
|
-
end
|
|
354
|
-
end
|
|
355
|
-
self
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
def delete_key(*args, **kwargs)
|
|
359
|
-
OptionPartition.delete_key(target, *args, **kwargs)
|
|
360
|
-
self
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
def values_of(*args, strict: true, first: false, last: false)
|
|
364
|
-
eq, s = strict ? [sep, '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
|
|
365
|
-
g = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{windows? ? '| ' : ''}))*)\""]
|
|
366
|
-
g << "'((?:[^']|'\\\\'')*)'" unless windows?
|
|
367
|
-
g << "(#{s})"
|
|
368
|
-
args.map! do |opt|
|
|
369
|
-
if opt.size == 1
|
|
370
|
-
/(?:\A| )-#{opt} ?([^ ]+)/
|
|
371
|
-
else
|
|
372
|
-
/(?:\A| )--#{opt + eq}(?:#{g.join('|')})/
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
ret = []
|
|
376
|
-
target.each do |opt|
|
|
377
|
-
args.each do |pat|
|
|
378
|
-
next unless opt =~ pat
|
|
379
|
-
|
|
380
|
-
ret << ($1 || $2 || $3)
|
|
381
|
-
break
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
return ret unless first || last
|
|
385
|
-
|
|
386
|
-
if last.is_a?(Numeric)
|
|
387
|
-
ret.last(last)
|
|
388
|
-
elsif last
|
|
389
|
-
ret.last
|
|
390
|
-
else
|
|
391
|
-
first.is_a?(Numeric) ? ret.first(first) : ret.first
|
|
392
|
-
end
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
def uniq(list)
|
|
396
|
-
ignore = map { |val| nameonly(val) }
|
|
397
|
-
list.reject { |val| ignore.include?(s = nameonly(val)) || any?(OptionPartition.send(:matchopt, s)) }
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def clear(opts = nil, errors: false, **kwargs)
|
|
401
|
-
styles = project.theme[:inline] if project
|
|
402
|
-
if errors
|
|
403
|
-
OptionPartition.clear(target, @errors, styles: styles, **kwargs)
|
|
404
|
-
@errors.clear
|
|
405
|
-
return self unless opts
|
|
406
|
-
end
|
|
407
|
-
opts ||= extras
|
|
408
|
-
OptionPartition.clear(target, opts - found, styles: styles, **kwargs)
|
|
409
|
-
opts.clear
|
|
410
|
-
self
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
def adjoin(*args, with: nil, start: false)
|
|
414
|
-
index = -1
|
|
415
|
-
temp = to_a
|
|
416
|
-
if with
|
|
417
|
-
pat = case with
|
|
418
|
-
when String, Symbol
|
|
419
|
-
/\A#{Regexp.escape(with)}\z/
|
|
420
|
-
when Array
|
|
421
|
-
OptionPartition.send(:matchopts, with)
|
|
422
|
-
else
|
|
423
|
-
with
|
|
424
|
-
end
|
|
425
|
-
temp.each_with_index do |val, i|
|
|
426
|
-
if val.to_s.match?(pat)
|
|
427
|
-
index = i + (start.is_a?(Numeric) ? start : 1)
|
|
428
|
-
break
|
|
429
|
-
end
|
|
430
|
-
end
|
|
431
|
-
else
|
|
432
|
-
temp.each_with_index do |val, i|
|
|
433
|
-
if index == 0
|
|
434
|
-
next unless val.start_with?('-')
|
|
435
|
-
|
|
436
|
-
index = i
|
|
437
|
-
break
|
|
438
|
-
elsif i > 0 && !val.start_with?('-')
|
|
439
|
-
if start
|
|
440
|
-
index = i + (start.is_a?(Numeric) ? start : 1)
|
|
441
|
-
break
|
|
442
|
-
end
|
|
443
|
-
index = 0
|
|
444
|
-
end
|
|
445
|
-
end
|
|
446
|
-
end
|
|
447
|
-
if index > 0
|
|
448
|
-
if args.empty?
|
|
449
|
-
args = dup
|
|
450
|
-
reset
|
|
451
|
-
else
|
|
452
|
-
args.each { |val| remove val }
|
|
453
|
-
end
|
|
454
|
-
args = temp[0...index] + args + temp[index..-1]
|
|
455
|
-
target.clear
|
|
456
|
-
end
|
|
457
|
-
merge args
|
|
458
|
-
self
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
def add_path(*args, force: true, double: false, **kwargs)
|
|
462
|
-
if args.empty?
|
|
463
|
-
args = select { |val| val.is_a?(String) }
|
|
464
|
-
args.map! { |val| path + val } if path
|
|
465
|
-
append(args, force: force, **kwargs)
|
|
466
|
-
else
|
|
467
|
-
add shell_quote(path ? path.join(*args) : File.join(*args), option: false, force: force, double: double)
|
|
468
|
-
end
|
|
469
|
-
self
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
def add_quote(*args, **kwargs)
|
|
473
|
-
merge(args.compact
|
|
474
|
-
.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
|
|
475
|
-
self
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
def add_option(flag, val = nil, **kwargs)
|
|
479
|
-
add shell_option(flag, val, **kwargs)
|
|
480
|
-
self
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
def add_first(fallback = nil, prefix: nil, path: false, quote: false, reverse: false, expect: false, **kwargs)
|
|
484
|
-
val = (reverse ? pop : shift) || fallback
|
|
485
|
-
if val
|
|
486
|
-
val.delete_prefix!(prefix) if prefix
|
|
487
|
-
return self if block_given? && !(val = yield val).is_a?(String)
|
|
488
|
-
|
|
489
|
-
if path
|
|
490
|
-
add_path(val, **kwargs)
|
|
491
|
-
elsif quote
|
|
492
|
-
add_quote(val, **kwargs)
|
|
493
|
-
else
|
|
494
|
-
add val
|
|
495
|
-
end
|
|
496
|
-
elsif expect
|
|
497
|
-
raise(expect.is_a?(String) ? expect : 'no value provided')
|
|
498
|
-
end
|
|
499
|
-
self
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
def last(val = nil, &blk)
|
|
503
|
-
unless block_given?
|
|
504
|
-
case val
|
|
505
|
-
when NilClass
|
|
506
|
-
return extras.last
|
|
507
|
-
when Numeric
|
|
508
|
-
return extras.last(val)
|
|
509
|
-
when String, Array, Regexp
|
|
510
|
-
val = OptionPartition.send(:matchopts, val) unless val.is_a?(Regexp)
|
|
511
|
-
blk = proc { |s| s&.match?(val) }
|
|
512
|
-
else
|
|
513
|
-
raise TypeError, "unknown: #{val}"
|
|
514
|
-
end
|
|
515
|
-
end
|
|
516
|
-
ret = find_all(&blk)
|
|
517
|
-
unless ret.empty?
|
|
518
|
-
ret = case val
|
|
519
|
-
when NilClass
|
|
520
|
-
ret.first(1)
|
|
521
|
-
when Numeric
|
|
522
|
-
ret.first(val)
|
|
523
|
-
else
|
|
524
|
-
ret
|
|
525
|
-
end
|
|
526
|
-
ret.each do |opt|
|
|
527
|
-
delete opt
|
|
528
|
-
add opt
|
|
529
|
-
end
|
|
530
|
-
end
|
|
531
|
-
val.nil? ? ret.first : ret
|
|
532
|
-
end
|
|
533
|
-
|
|
534
|
-
def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
|
|
535
|
-
found, other = if block_given?
|
|
536
|
-
partition(&blk)
|
|
537
|
-
elsif exclude.first.is_a?(Symbol)
|
|
538
|
-
partition(&exclude.first)
|
|
539
|
-
else
|
|
540
|
-
partition do |val|
|
|
541
|
-
next false if pattern && OptionPartition.pattern?(val)
|
|
542
|
-
|
|
543
|
-
exclude.none? { |pat| val.match?(Regexp.new(pat)) }
|
|
544
|
-
end
|
|
545
|
-
end
|
|
546
|
-
unless found.empty?
|
|
547
|
-
add '--' if delim
|
|
548
|
-
extras.clear
|
|
549
|
-
concat other
|
|
550
|
-
if path
|
|
551
|
-
found.each { |val| add_path(val) }
|
|
552
|
-
else
|
|
553
|
-
found.map! { |val| shell_quote(val) } if quote
|
|
554
|
-
merge found
|
|
555
|
-
end
|
|
556
|
-
end
|
|
557
|
-
self
|
|
558
|
-
end
|
|
559
|
-
|
|
560
|
-
def reset(errors: false)
|
|
561
|
-
extras.clear
|
|
562
|
-
found.clear
|
|
563
|
-
clear(errors: true) if errors
|
|
564
|
-
self
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
def append?(key, val = nil, type: nil, force: false, sep: '=', **kwargs)
|
|
568
|
-
return false unless force || !arg?(key)
|
|
569
|
-
|
|
570
|
-
val = yield self if block_given?
|
|
571
|
-
return false unless val
|
|
572
|
-
|
|
573
|
-
type ||= :quote if kwargs.empty?
|
|
574
|
-
add case type
|
|
575
|
-
when :quote
|
|
576
|
-
quote_option(key, val, sep: sep)
|
|
577
|
-
when :basic
|
|
578
|
-
basic_option(key, val, sep: sep)
|
|
579
|
-
else
|
|
580
|
-
shell_option(key, val, sep: sep, **kwargs)
|
|
581
|
-
end
|
|
582
|
-
true
|
|
583
|
-
end
|
|
584
|
-
|
|
585
|
-
def arg?(*args, **kwargs)
|
|
586
|
-
OptionPartition.arg?(target, *args, **kwargs)
|
|
587
|
-
end
|
|
588
|
-
|
|
589
|
-
def exist?(*args, add: false, first: false, last: false, glob: false)
|
|
590
|
-
return with_glob?(File.join(*args), glob) unless args.empty?
|
|
591
|
-
|
|
592
|
-
if first || last
|
|
593
|
-
return false unless (val = first ? self.first : self.last)
|
|
594
|
-
|
|
595
|
-
with_glob?(val, glob).tap do |ret|
|
|
596
|
-
next unless add && ret
|
|
597
|
-
|
|
598
|
-
add_first(path: true, reverse: !first)
|
|
599
|
-
end
|
|
600
|
-
else
|
|
601
|
-
each_with_index do |val, i|
|
|
602
|
-
next unless with_glob?(val, glob)
|
|
603
|
-
|
|
604
|
-
if add
|
|
605
|
-
remove_at i
|
|
606
|
-
add_path val
|
|
607
|
-
end
|
|
608
|
-
return true
|
|
609
|
-
end
|
|
610
|
-
false
|
|
611
|
-
end
|
|
612
|
-
end
|
|
613
|
-
|
|
614
|
-
def uniq!(list)
|
|
615
|
-
unless (list = uniq(list)).empty?
|
|
616
|
-
concat list
|
|
617
|
-
self
|
|
618
|
-
end
|
|
619
|
-
end
|
|
620
|
-
|
|
621
|
-
private
|
|
622
|
-
|
|
623
|
-
def nameonly(val)
|
|
624
|
-
val[OPT_VALUE, 1] || val
|
|
625
|
-
end
|
|
626
|
-
|
|
627
|
-
def with_glob?(val, glob = true)
|
|
628
|
-
return false unless path && val.is_a?(String) && !val.empty?
|
|
629
|
-
|
|
630
|
-
path.join(val).exist? || (glob && !path.glob(val).empty?)
|
|
631
|
-
end
|
|
632
|
-
|
|
633
|
-
def windows?
|
|
634
|
-
Rake::Win32.windows?
|
|
635
|
-
end
|
|
636
|
-
end
|
|
7
|
+
autoload :OptionPartition, File.expand_path('optionpartition', __dir__)
|
|
637
8
|
|
|
638
9
|
class JoinSet < Set
|
|
639
10
|
def self.to_s
|
|
@@ -642,10 +13,9 @@ module Squared
|
|
|
642
13
|
|
|
643
14
|
alias to_ary to_a
|
|
644
15
|
|
|
645
|
-
attr_reader :delim, :extras
|
|
646
|
-
attr_accessor :multiple
|
|
16
|
+
attr_reader :delim, :extras, :multiple
|
|
647
17
|
|
|
648
|
-
def initialize(data = [], delim: ' ', partition: '--', uniq: /\A--?[
|
|
18
|
+
def initialize(data = [], delim: ' ', partition: '--', uniq: /\A--?[^=\s-]/, multiple: [])
|
|
649
19
|
@delim = delim
|
|
650
20
|
@partition = partition
|
|
651
21
|
@uniq = uniq
|
|
@@ -654,8 +24,32 @@ module Squared
|
|
|
654
24
|
super(data.compact)
|
|
655
25
|
end
|
|
656
26
|
|
|
27
|
+
def multiple=(val)
|
|
28
|
+
case val
|
|
29
|
+
when Enumerable
|
|
30
|
+
@multiple.concat(val.to_a.map(&:to_s))
|
|
31
|
+
when String, Symbol, Pathname
|
|
32
|
+
@multiple << val.to_s
|
|
33
|
+
when NilClass, FalseClass
|
|
34
|
+
@multiple.clear
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
657
38
|
def insert(*args)
|
|
658
|
-
replace Set.new(
|
|
39
|
+
replace Set.new(compact.insert(*args))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def slice(*args)
|
|
43
|
+
compact.slice(*args)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def slice!(*args)
|
|
47
|
+
data = compact
|
|
48
|
+
data.slice!(*args).tap { replace Set.new(data) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def compact
|
|
52
|
+
to_ary.map!(&:to_s).reject(&:empty?)
|
|
659
53
|
end
|
|
660
54
|
|
|
661
55
|
def last(val, pat)
|
|
@@ -664,7 +58,7 @@ module Squared
|
|
|
664
58
|
end
|
|
665
59
|
|
|
666
60
|
def pass(&blk)
|
|
667
|
-
ret =
|
|
61
|
+
ret = compact
|
|
668
62
|
@last&.each do |val, pat, key|
|
|
669
63
|
items = []
|
|
670
64
|
index = nil
|
|
@@ -735,15 +129,12 @@ module Squared
|
|
|
735
129
|
end
|
|
736
130
|
|
|
737
131
|
def <<(obj)
|
|
738
|
-
extras!(obj)
|
|
739
|
-
end
|
|
132
|
+
return super if extras.empty? && !extras?(obj)
|
|
740
133
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
def add?(obj)
|
|
746
|
-
extras!(obj) || super
|
|
134
|
+
unless !extras.include?(@partition) && include?(obj) && @uniq.match?(s = obj.to_s) && !multiple.include?(s)
|
|
135
|
+
extras << obj
|
|
136
|
+
end
|
|
137
|
+
self
|
|
747
138
|
end
|
|
748
139
|
|
|
749
140
|
def to_a
|
|
@@ -766,20 +157,13 @@ module Squared
|
|
|
766
157
|
pass.to_yaml(*args)
|
|
767
158
|
end
|
|
768
159
|
|
|
160
|
+
alias add :<<
|
|
161
|
+
alias add? :<<
|
|
769
162
|
alias push :<<
|
|
770
163
|
alias concat merge
|
|
771
164
|
|
|
772
165
|
private
|
|
773
166
|
|
|
774
|
-
def extras!(obj)
|
|
775
|
-
return if extras.empty? && !extras?(obj)
|
|
776
|
-
|
|
777
|
-
unless !extras.include?(@partition) && include?(obj) && @uniq.match?(s = obj.to_s) && !multiple.include?(s)
|
|
778
|
-
extras << obj
|
|
779
|
-
end
|
|
780
|
-
self
|
|
781
|
-
end
|
|
782
|
-
|
|
783
167
|
def extras?(obj)
|
|
784
168
|
obj == @partition || (include?(obj) && (!@uniq.match?(s = obj.to_s) || multiple.include?(s)))
|
|
785
169
|
end
|