squared 0.5.26 → 0.6.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.
@@ -10,9 +10,9 @@ module Squared
10
10
  include Common::Shell
11
11
  extend Forwardable
12
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/
13
+ OPT_NAME = /\A(?:(--)|-)((?(1)[A-Za-z\d]+|[A-Za-z\d]))\z/
14
+ OPT_VALUE = /\A-{0,2}([^= ]+)(?: *= *| +)(.+)\z/
15
+ OPT_SINGLE = /\A-([A-Za-z\d])(.+)\z/
16
16
  private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE
17
17
 
18
18
  class << self
@@ -21,23 +21,37 @@ module Squared
21
21
  include Prompt
22
22
 
23
23
  def append(target, *args, delim: false, escape: false, quote: true, strip: nil, force: true, double: false,
24
- preserve: true, **)
24
+ filter: nil, **)
25
25
  return if (ret = args.flatten).empty?
26
26
 
27
27
  target << '--' if delim && !target.include?('--')
28
28
  if strip
29
29
  pat, s = Array(strip)
30
- ret.map! { |val| val.is_a?(String) ? val.gsub(pat, s || '') : val }
30
+ ret.map! { |val| val.gsub(pat, s || '') }
31
31
  end
32
- ret.map! do |val|
33
- next val if opt?(val)
34
-
35
- if !(pa = val.is_a?(Pathname)) && escape
36
- shell_escape(val, quote: quote, double: double)
37
- elsif quote || pa
38
- shell_quote(val, force: force, double: double, preserve: preserve)
39
- else
40
- val
32
+ ret, err = ret.partition { |val| filter.match?(val) } 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 escape
51
+ shell_escape(val, quote: quote, double: double)
52
+ else
53
+ shell_quote(val, force: force, double: double)
54
+ end
41
55
  end
42
56
  end
43
57
  if target.is_a?(Set)
@@ -45,13 +59,13 @@ module Squared
45
59
  else
46
60
  target.concat(ret)
47
61
  end
48
- ret
62
+ err || ret
49
63
  end
50
64
 
51
65
  def clear(target, opts, pass: true, styles: nil, **kwargs)
52
66
  return if opts.empty?
53
67
 
54
- kwargs[:subject] ||= stripext target.first
68
+ kwargs[:subject] ||= target.first.stripext
55
69
  kwargs[:hint] ||= 'unrecognized'
56
70
  append(target, opts, delim: true) if kwargs.delete(:append)
57
71
  warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs)
@@ -74,25 +88,7 @@ module Squared
74
88
  return [] unless val
75
89
 
76
90
  val = shell_split val if val.is_a?(String)
77
- ret = []
78
- pass = -1
79
- (args = Array(val)).each_with_index do |s, i|
80
- next if s.empty? || pass == i
81
-
82
- if s == '--'
83
- ret << s << args[i.succ..-1].join(' ')
84
- break
85
- end
86
- next ret << s unless s.start_with?('-')
87
-
88
- if !s.include?('=') && (j = args[i.succ]) && !j.start_with?('-')
89
- ret << "#{s.sub(/^-{1,2}/, '')}=#{j}"
90
- pass = i.succ
91
- else
92
- ret << s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2')
93
- end
94
- end
95
- ret
91
+ val.map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2') }.reject(&:empty?)
96
92
  end
97
93
 
98
94
  def select(list, bare: true, no: true, single: false, double: false)
@@ -104,28 +100,29 @@ module Squared
104
100
  ret.select { |val| single ? val.size == 1 : val.size > 1 }
105
101
  end
106
102
 
107
- def arg?(target, *args, value: false, **)
108
- r, s = args.partition { |val| val.is_a?(Regexp) }
109
- r << matchopts(s, value) unless s.empty?
110
- a = target.to_a
111
- if (n = a.index('--'))
112
- a = a[0..n]
103
+ def uniq!(list, pass = [])
104
+ keys = {}
105
+ list.each_with_index do |val, i|
106
+ j = val =~ OPT_VALUE ? $1 : val
107
+ (keys[j] ||= []) << i unless pass.include?(j)
113
108
  end
114
- r.any? { |pat| a.any?(pat) }
115
- end
109
+ data = keys.map { |item| item[1].size > 1 ? item[1][0..-2] : [] }.reject(&:empty?)
110
+ return if data.empty?
116
111
 
117
- def opt?(val)
118
- return false unless val.is_a?(String)
112
+ data.each { |key| key.each { |i| list[i] = nil } }
113
+ list.compact!
114
+ list
115
+ end
119
116
 
120
- val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
117
+ def arg?(target, *args, value: false, **)
118
+ r, s = args.partition { |val| val.is_a?(Regexp) }
119
+ r << matchopts(s, value) unless s.empty?
120
+ s = target.to_a.compact
121
+ r.any? { |pat| s.any?(pat) }
121
122
  end
122
123
 
123
124
  def pattern?(val)
124
- Regexp.new(val)
125
- val.start_with?('\A', '^') || val.end_with?('\z', '$') ||
126
- val.match?(/[.)][*+?]|\(\?[:=!><]|\\[dsw\d]|\[.+\]|\{\d+,?\d*\}/i)
127
- rescue RegexpError
128
- false
125
+ val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
129
126
  end
130
127
 
131
128
  private
@@ -136,30 +133,29 @@ module Squared
136
133
 
137
134
  def matchopts(list, value = false)
138
135
  a, b = Array(list).partition { |val| val.size == 1 || val.match?(OPT_SINGLE) }
139
- return /\A#{shortopt(*a)}/ if b.empty?
136
+ return /\A#{shortopt(*a)}}/ if b.empty?
140
137
  return /\A#{longopt(*b, value)}/ if a.empty?
141
138
 
142
139
  /\A(?:#{shortopt(*a)}|#{longopt(*b, value)})/
143
140
  end
144
141
 
145
142
  def shortopt(*group)
146
- group.map! { |s| Regexp.escape(s.delete_prefix('-')) }
147
- "-(?:#{group.join('|')})(?:\\z|[^ =]| +[^ -])"
143
+ group.map! { |s| s.delete_prefix('-') }
144
+ "-(?:#{Regexp.escape(group.join('|'))})(?:\\z|[^ =]| +[^ -])"
148
145
  end
149
146
 
150
147
  def longopt(*group, value)
151
- group.map! { |s| Regexp.escape(s.delete_prefix('--')) }
152
- "--(?:#{group.join('|')})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
148
+ group.map! { |s| s.delete_prefix('--') }
149
+ "--(?:#{Regexp.escape(group.join('|'))})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
153
150
  end
154
151
  end
155
152
 
156
- attr_reader :target, :extras, :found, :errors, :values, :project, :path
153
+ attr_reader :target, :extras, :found, :errors, :values, :project, :path, :sep
157
154
 
158
155
  def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
159
- :merge, :compact, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
160
- def_delegators :@extras, :empty?, :member?, :each, :each_with_index, :each_with_object, :partition, :dup,
161
- :first, :shift, :unshift, :pop, :push, :concat, :index, :join, :map, :map!, :detect, :select,
162
- :select!, :reject, :size
156
+ :merge, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
157
+ def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :shift, :unshift,
158
+ :pop, :push, :concat, :index, :join, :map, :map!, :detect, :select, :select!, :reject, :size
163
159
 
164
160
  def_delegator :@extras, :delete, :remove
165
161
  def_delegator :@extras, :delete_at, :remove_at
@@ -167,10 +163,11 @@ module Squared
167
163
  def_delegator :@extras, :find_all, :detect_all
168
164
  def_delegator :@extras, :find_index, :detect_index
169
165
 
170
- def initialize(opts, list, target = Set.new, project: nil, path: nil, **kwargs, &blk)
166
+ def initialize(opts, list, target = Set.new, project: nil, path: nil, sep: '=', **kwargs, &blk)
171
167
  @target = target.is_a?(Set) ? target : target.to_set
172
168
  @project = project
173
169
  @path = path || project&.path
170
+ @sep = sep
174
171
  @errors = []
175
172
  @found = []
176
173
  parse(list, opts, **kwargs, &blk)
@@ -204,7 +201,7 @@ module Squared
204
201
  .each do |val|
205
202
  if (n = val.index('='))
206
203
  flag = val[0, n]
207
- case val[n + 1]
204
+ case val[n.succ]
208
205
  when 'e'
209
206
  e << flag
210
207
  when 'b'
@@ -229,7 +226,7 @@ module Squared
229
226
  else
230
227
  next
231
228
  end
232
- m << flag if flag.size == 1 && val[n + 2] == 'm'
229
+ m << flag if val[n + 2] == 'm'
233
230
  bare << flag if val.end_with?('?')
234
231
  else
235
232
  bare << val
@@ -238,7 +235,7 @@ module Squared
238
235
  no = (no || []).map { |val| (n = val.index('=')) ? val[0, n] : val }
239
236
  bare.concat(no)
240
237
  if underscore
241
- tr = ->(list) { list.map { |val| val.tr('-', '_') } }
238
+ tr = ->(a) { a.map { |val| val.tr('-', '_') } }
242
239
  @values.concat(tr.call(@values))
243
240
  bare.concat(tr.call(bare))
244
241
  e.concat(tr.call(e))
@@ -255,10 +252,10 @@ module Squared
255
252
  end
256
253
  numtype = [
257
254
  [i, /\A\d+\z/],
258
- [f, /\A(\d+(\.\d*)?|\d*\.\d+)\z/],
255
+ [f, /\A\d*(?:\.\d+)?\z/],
259
256
  [si, /\A-?\d+\z/]
260
257
  ].freeze
261
- numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && pat.match?(v) } }
258
+ numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && v.match?(pat) } }
262
259
  skip = false
263
260
  opts.each do |opt|
264
261
  next skip = true if opt == '--'
@@ -276,21 +273,21 @@ module Squared
276
273
  val = $2
277
274
  merge = m.include?(key)
278
275
  if e.include?(key)
279
- add shell_option(key, val, merge: merge)
276
+ add shell_option(key, val, merge: merge, sep: sep)
280
277
  elsif q.include?(key)
281
- add quote_option(key, val, double: qq.include?(key), merge: merge)
278
+ add quote_option(key, val, double: qq.include?(key), merge: merge, sep: sep)
282
279
  elsif p.include?(key)
283
- if val =~ /\A(["']).+\1\z/
284
- add shell_option(key, val, double: $1 == '"', escape: false, merge: merge)
280
+ if val.match?(/\A(["']).+\1\z/)
281
+ add shell_option(key, val, escape: false, merge: merge, sep: sep)
285
282
  elsif path
286
- add quote_option(key, path + val, merge: merge)
283
+ add quote_option(key, path + val, merge: merge, sep: sep)
287
284
  else
288
285
  push opt
289
286
  end
290
287
  elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
291
- add basic_option(key, val, merge: merge)
288
+ add basic_option(key, val, merge: merge, sep: sep)
292
289
  elsif merge
293
- add basic_option(key, val, merge: true)
290
+ add basic_option(key, val, merge: true, sep: sep)
294
291
  else
295
292
  push opt
296
293
  end
@@ -302,39 +299,40 @@ module Squared
302
299
  skip = true if first&.any? { |s| s.is_a?(Regexp) ? opt.match?(s) : !opt.include?(s) }
303
300
  end
304
301
  end
305
- @values = @values.empty? ? /\A\s+\z/ : /\A(#{@values.join('|')})=(.+)\z/m
302
+ @values = @values.empty? ? /\A\s+\z/ : /\A(#{@values.join('|')})#{sep}(.+)\z/m
306
303
  @extras.each_with_index(&blk) if block_given?
307
304
  self
308
305
  end
309
306
 
310
- def swap(opts = nil)
307
+ def swap(opts = nil, &blk)
311
308
  unless opts
312
309
  opts = found
313
310
  @found = []
314
311
  end
312
+ opts.sort!(&blk) if block_given?
315
313
  @extras = opts
316
314
  self
317
315
  end
318
316
 
319
- def append(*args, clear: false, preserve: '"', **kwargs)
320
- args = clear ? extras.dup.tap { extras.clear } : extras if args.empty?
321
- OptionPartition.append(target, *args, preserve: preserve, **kwargs)
317
+ def append(*args, **kwargs, &blk)
318
+ args = extras if args.empty?
319
+ out = OptionPartition.append(target, *args, **kwargs, &blk)
320
+ errors.concat(out) if out && (block_given? || kwargs[:filter])
322
321
  self
323
322
  end
324
323
 
325
- def append_any(*args, escape: false, **kwargs)
326
- quote = kwargs.fetch(:quote, true)
324
+ def append_any(*args, quote: true, **kwargs)
327
325
  (args.empty? ? extras : args.flatten).each do |val|
326
+ val = yield val if block_given?
327
+ next unless val.is_a?(String)
328
+
328
329
  if exist?(val)
329
330
  add_path(val, **kwargs)
330
- elsif escape
331
- add shell_escape(val, **kwargs)
332
331
  elsif quote
333
332
  add_quote(val, **kwargs)
334
333
  else
335
334
  add val
336
335
  end
337
- found << val if args.empty?
338
336
  end
339
337
  self
340
338
  end
@@ -345,7 +343,7 @@ module Squared
345
343
  end
346
344
 
347
345
  def values_of(*args, strict: true, first: false, last: false)
348
- eq, s = strict ? ['=', '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
346
+ eq, s = strict ? [sep, '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
349
347
  g = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{windows? ? '| ' : ''}))*)\""]
350
348
  g << "'((?:[^']|'\\\\'')*)'" unless windows?
351
349
  g << "(#{s})"
@@ -384,23 +382,19 @@ module Squared
384
382
  def clear(opts = nil, errors: false, **kwargs)
385
383
  styles = project.theme[:inline] if project
386
384
  if errors
387
- OptionPartition.clear(target, self.errors, styles: styles, **kwargs)
388
- self.errors.clear
385
+ OptionPartition.clear(target, @errors, styles: styles, **kwargs)
386
+ @errors.clear
389
387
  return self unless opts
390
388
  end
391
389
  opts ||= extras
392
- OptionPartition.clear(target, if found.empty?
393
- opts
394
- else
395
- opts.reject { |val| found.include?(val) }
396
- end, styles: styles, **kwargs)
390
+ OptionPartition.clear(target, opts - found, styles: styles, **kwargs)
397
391
  opts.clear
398
392
  self
399
393
  end
400
394
 
401
395
  def adjoin(*args, with: nil, start: false)
402
- i = -1
403
- temp = compact
396
+ index = -1
397
+ temp = to_a
404
398
  if with
405
399
  pat = case with
406
400
  when String, Symbol
@@ -410,82 +404,135 @@ module Squared
410
404
  else
411
405
  with
412
406
  end
413
- temp.each_with_index do |val, index|
407
+ temp.each_with_index do |val, i|
414
408
  if val.to_s.match?(pat)
415
- i = index + (start.is_a?(Numeric) ? start : 1)
409
+ index = i + (start.is_a?(Numeric) ? start : 1)
416
410
  break
417
411
  end
418
412
  end
419
413
  else
420
- temp.each_with_index do |val, index|
421
- if i == 0
422
- next unless val.is_a?(String) && val.start_with?('-')
414
+ temp.each_with_index do |val, i|
415
+ if index == 0
416
+ next unless val.start_with?('-')
423
417
 
424
- i = index
418
+ index = i
425
419
  break
426
- elsif index > 0 && !val.to_s.start_with?('-')
420
+ elsif i > 0 && !val.start_with?('-')
427
421
  if start
428
- i = index + (start.is_a?(Numeric) ? start : 1)
422
+ index = i + (start.is_a?(Numeric) ? start : 1)
429
423
  break
430
424
  end
431
- i = 0
425
+ index = 0
432
426
  end
433
427
  end
434
428
  end
435
- if i > 0
429
+ if index > 0
436
430
  if args.empty?
437
431
  args = dup
438
432
  reset
439
433
  else
440
434
  args.each { |val| remove val }
441
435
  end
442
- args = temp[0...i] + args + temp[i..-1]
436
+ args = temp[0...index] + args + temp[index..-1]
443
437
  target.clear
444
438
  end
445
439
  merge args
446
440
  self
447
441
  end
448
442
 
449
- def add_path(*args, **kwargs)
450
- add shell_quote(path ? path.join(*args) : File.join(*args), option: false, **kwargs)
443
+ def add_path(*args, force: true, double: false, **kwargs)
444
+ if args.empty?
445
+ args = select { |s| s.is_a?(String) }
446
+ args.map! { |val| path + val } if path
447
+ append(args, force: force, **kwargs)
448
+ else
449
+ add shell_quote(path ? path.join(*args) : File.join(*args), option: false, force: force, double: double)
450
+ end
451
451
  self
452
452
  end
453
453
 
454
454
  def add_quote(*args, **kwargs)
455
- kwargs.delete(:quote)
456
- args.compact!
457
- merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
455
+ merge(args.compact.map! { |val| val == '--' ? val : shell_quote(val, **kwargs) })
458
456
  self
459
457
  end
460
458
 
461
- def delim
462
- add '--'
459
+ def add_option(flag, val = nil, **kwargs)
460
+ add shell_option(flag, val, **kwargs)
463
461
  self
464
462
  end
465
463
 
464
+ def add_first(fallback = nil, prefix: nil, path: false, quote: false, reverse: false, expect: false, **kwargs)
465
+ val = (reverse ? pop : shift) || fallback
466
+ if val
467
+ val.delete_prefix!(prefix) if prefix
468
+ return self if block_given? && !(val = yield val).is_a?(String)
469
+
470
+ if path
471
+ add_path(val, **kwargs)
472
+ elsif quote
473
+ add_quote(val, **kwargs)
474
+ else
475
+ add val
476
+ end
477
+ elsif expect
478
+ raise(expect.is_a?(String) ? expect : 'no value provided')
479
+ end
480
+ self
481
+ end
482
+
483
+ def last(val = nil, &blk)
484
+ unless block_given?
485
+ case val
486
+ when NilClass
487
+ return extras.last
488
+ when Numeric
489
+ return extras.last(val)
490
+ when String, Array, Regexp
491
+ val = OptionPartition.send(:matchopts, val) unless val.is_a?(Regexp)
492
+ blk = proc { |s| s&.match?(val) }
493
+ else
494
+ raise TypeError, "unknown: #{val}"
495
+ end
496
+ end
497
+ ret = find_all(&blk)
498
+ unless ret.empty?
499
+ ret = case val
500
+ when NilClass
501
+ ret.first(1)
502
+ when Numeric
503
+ ret.first(val)
504
+ else
505
+ ret
506
+ end
507
+ ret.each do |opt|
508
+ delete opt
509
+ add opt
510
+ end
511
+ end
512
+ val.nil? ? ret.first : ret
513
+ end
514
+
466
515
  def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
467
- temp, other = if block_given?
468
- partition(&blk)
469
- elsif exclude.first.is_a?(Symbol)
470
- partition(&exclude.first)
471
- else
472
- exclude.map! { |pat| Regexp.new(pat) }
473
- partition do |val|
474
- val = val.to_s
475
- next if pattern && OptionPartition.pattern?(val)
476
-
477
- exclude.none? { |pat| val.match?(pat) }
478
- end
479
- end
480
- unless temp.empty?
516
+ found, other = if block_given?
517
+ partition(&blk)
518
+ elsif exclude.first.is_a?(Symbol)
519
+ partition(&exclude.first)
520
+ else
521
+ partition do |val|
522
+ next false if pattern && OptionPartition.pattern?(val)
523
+
524
+ exclude.none? { |pat| val.match?(Regexp.new(pat)) }
525
+ end
526
+ end
527
+ unless found.empty?
481
528
  add '--' if delim
482
529
  extras.clear
483
530
  concat other
484
531
  if path
485
- temp.each { |val| add_path(val) }
532
+ found.each { |val| add_path(val) }
486
533
  else
487
- temp.map! { |val| shell_quote(val) } if quote
488
- merge temp
534
+ found.map! { |val| shell_quote(val) } if quote
535
+ merge found
489
536
  end
490
537
  end
491
538
  self
@@ -498,7 +545,7 @@ module Squared
498
545
  self
499
546
  end
500
547
 
501
- def append?(key, val = nil, type: nil, force: false, **kwargs)
548
+ def append?(key, val = nil, type: nil, force: false, sep: '=', **kwargs)
502
549
  return false unless force || !arg?(key)
503
550
 
504
551
  val = yield self if block_given?
@@ -507,11 +554,11 @@ module Squared
507
554
  type ||= :quote if kwargs.empty?
508
555
  add case type
509
556
  when :quote
510
- quote_option(key, val)
557
+ quote_option(key, val, sep: sep)
511
558
  when :basic
512
- basic_option(key, val)
559
+ basic_option(key, val, sep: sep)
513
560
  else
514
- shell_option(key, val, **kwargs)
561
+ shell_option(key, val, sep: sep, **kwargs)
515
562
  end
516
563
  true
517
564
  end
@@ -520,24 +567,23 @@ module Squared
520
567
  OptionPartition.arg?(target, *args, **kwargs)
521
568
  end
522
569
 
523
- def exist?(*args, add: false, first: false, last: false)
524
- return false unless path
525
- return path.join(*args).exist? unless args.empty?
570
+ def exist?(*args, add: false, first: false, last: false, glob: false)
571
+ return with_glob?(File.join(*args), glob) unless args.empty?
526
572
 
527
573
  if first || last
528
- return false unless (val = first ? self.first : self.last).is_a?(String)
574
+ return false unless (val = first ? self.first : self.last)
529
575
 
530
- path.join(val).exist?.tap do |ret|
576
+ with_glob?(val, glob).tap do |ret|
531
577
  next unless add && ret
532
578
 
533
- add_path(first ? shift : pop)
579
+ add_first(path: true, reverse: !first)
534
580
  end
535
581
  else
536
- each_with_index do |val, index|
537
- next unless val.is_a?(String) && path.join(val).exist?
582
+ each_with_index do |val, i|
583
+ next unless with_glob?(val, glob)
538
584
 
539
585
  if add
540
- remove_at index
586
+ remove_at i
541
587
  add_path val
542
588
  end
543
589
  return true
@@ -559,8 +605,13 @@ module Squared
559
605
  val[OPT_VALUE, 1] || val
560
606
  end
561
607
 
608
+ def with_glob?(val, glob = true)
609
+ return false unless path && val.is_a?(String) && !val.empty?
610
+
611
+ path.join(val).exist? || (glob && !path.glob(val).empty?)
612
+ end
613
+
562
614
  def windows?
563
- require 'rake'
564
615
  Rake::Win32.windows?
565
616
  end
566
617
  end
@@ -570,20 +621,11 @@ module Squared
570
621
  super[/[^:]+\z/, 0]
571
622
  end
572
623
 
573
- alias to_ary to_a
624
+ attr_reader :delim
574
625
 
575
- attr_reader :delim, :extras
576
-
577
- def initialize(data = [], delim: ' ', partition: '--', uniq: /\A--?[^=\s-][^=\s]*(?:=|\s+)\S/)
578
- @delim = delim
579
- @partition = partition
580
- @uniq = uniq
581
- @extras = []
626
+ def initialize(data = [], delim: ' ')
582
627
  super(data.compact)
583
- end
584
-
585
- def compact
586
- to_ary.map!(&:to_s).reject(&:empty?)
628
+ @delim = delim
587
629
  end
588
630
 
589
631
  def last(val, pat)
@@ -592,28 +634,27 @@ module Squared
592
634
  end
593
635
 
594
636
  def pass(&blk)
595
- ret = compact
637
+ ret = to_a.map!(&:to_s).reject(&:empty?)
596
638
  @last&.each do |val, pat, key|
597
- i = []
598
- j = nil
599
- ret.each_with_index do |opt, index|
639
+ items = []
640
+ index = nil
641
+ ret.each_with_index do |opt, i|
600
642
  if opt == val
601
- j = index
602
- elsif j && opt[pat, 1] == key
603
- i << index
643
+ index = i
644
+ elsif index && opt[pat, 1] == key
645
+ items << i
604
646
  end
605
647
  end
606
- next unless j && !i.empty?
648
+ next unless index && !items.empty?
607
649
 
608
- val = ret[j]
609
- cur = j
610
- i.each do |k|
650
+ val = ret[index]
651
+ cur = index
652
+ items.each do |k|
611
653
  ret[cur] = ret[k]
612
654
  cur = k
613
655
  end
614
- ret[i.last] = val
656
+ ret[items.last] = val
615
657
  end
616
- ret.concat(extras.map(&:to_s).reject(&:empty?)) unless extras.empty?
617
658
  return ret unless block_given?
618
659
 
619
660
  ret.reject(&blk)
@@ -635,83 +676,17 @@ module Squared
635
676
 
636
677
  def temp(*args, &blk)
637
678
  args.compact!
638
- pass(&blk)
639
- .concat(args)
640
- .join(@delim)
679
+ ret = pass(&blk)
680
+ ret = Set.new(ret.concat(args)).to_a unless args.empty?
681
+ ret.join(@delim)
641
682
  end
642
683
 
643
684
  def done
644
685
  to_s.tap { clear }
645
686
  end
646
687
 
647
- def merge(enum)
648
- if !extras.empty?
649
- extras.concat(enum.to_a)
650
- self
651
- elsif (n = enum.find_index { |val| extras?(val) })
652
- data = enum.to_a
653
- @extras = if n == 0
654
- data
655
- else
656
- super(data[0...n])
657
- data[n..-1]
658
- end
659
- self
660
- else
661
- super
662
- end
663
- end
664
-
665
- def <<(obj)
666
- extras!(obj) || super
667
- end
668
-
669
- def size
670
- super + extras.size
671
- end
672
-
673
- def include?(obj)
674
- return true if super
675
- return extras.include?(obj) unless (n = extras.index(@partition))
676
-
677
- extras[0..n].include?(obj)
678
- end
679
-
680
- def to_a
681
- pass
682
- end
683
-
684
688
  def to_s
685
- to_a.join(@delim)
686
- end
687
-
688
- def to_enum(*args)
689
- to_a.to_enum(*args)
690
- end
691
-
692
- def to_json(*args)
693
- to_a.to_json(*args)
694
- end
695
-
696
- def to_yaml(*args)
697
- to_a.to_yaml(*args)
698
- end
699
-
700
- alias add :<<
701
- alias add? :<<
702
- alias member? include?
703
-
704
- private
705
-
706
- def extras!(obj)
707
- return if extras.empty? && !extras?(obj)
708
-
709
- extras << obj unless !extras.include?(@partition) && include?(obj) && @uniq.match?(obj.to_s)
710
- self
711
- end
712
-
713
- def extras?(obj)
714
- obj == @partition || (include?(obj) && !@uniq.match?(obj.to_s))
689
+ pass.join(@delim)
715
690
  end
716
691
  end
717
692
  end