squared 0.5.22 → 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
- **)
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)
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)
@@ -86,24 +100,29 @@ module Squared
86
100
  ret.select { |val| single ? val.size == 1 : val.size > 1 }
87
101
  end
88
102
 
89
- def arg?(target, *args, value: false, **)
90
- r, s = args.partition { |val| val.is_a?(Regexp) }
91
- r << matchopts(s, value) unless s.empty?
92
- a = target.to_a
93
- if (n = a.index('--'))
94
- 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)
95
108
  end
96
- r.any? { |pat| a.any?(pat) }
97
- end
109
+ data = keys.map { |item| item[1].size > 1 ? item[1][0..-2] : [] }.reject(&:empty?)
110
+ return if data.empty?
98
111
 
99
- def opt?(val)
100
- return false unless val.is_a?(String)
112
+ data.each { |key| key.each { |i| list[i] = nil } }
113
+ list.compact!
114
+ list
115
+ end
101
116
 
102
- 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) }
103
122
  end
104
123
 
105
124
  def pattern?(val)
106
- val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*})/)
125
+ val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
107
126
  end
108
127
 
109
128
  private
@@ -114,30 +133,29 @@ module Squared
114
133
 
115
134
  def matchopts(list, value = false)
116
135
  a, b = Array(list).partition { |val| val.size == 1 || val.match?(OPT_SINGLE) }
117
- return /\A#{shortopt(*a)}/ if b.empty?
136
+ return /\A#{shortopt(*a)}}/ if b.empty?
118
137
  return /\A#{longopt(*b, value)}/ if a.empty?
119
138
 
120
139
  /\A(?:#{shortopt(*a)}|#{longopt(*b, value)})/
121
140
  end
122
141
 
123
142
  def shortopt(*group)
124
- group.map! { |s| Regexp.escape(s.delete_prefix('-')) }
125
- "-(?:#{group.join('|')})(?:\\z|[^ =]| +[^ -])"
143
+ group.map! { |s| s.delete_prefix('-') }
144
+ "-(?:#{Regexp.escape(group.join('|'))})(?:\\z|[^ =]| +[^ -])"
126
145
  end
127
146
 
128
147
  def longopt(*group, value)
129
- group.map! { |s| Regexp.escape(s.delete_prefix('--')) }
130
- "--(?:#{group.join('|')})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
148
+ group.map! { |s| s.delete_prefix('--') }
149
+ "--(?:#{Regexp.escape(group.join('|'))})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
131
150
  end
132
151
  end
133
152
 
134
- attr_reader :target, :extras, :found, :errors, :values, :project, :path
153
+ attr_reader :target, :extras, :found, :errors, :values, :project, :path, :sep
135
154
 
136
155
  def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
137
- :merge, :compact, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
138
- def_delegators :@extras, :empty?, :member?, :each, :each_with_index, :each_with_object, :partition, :dup,
139
- :first, :shift, :unshift, :pop, :push, :concat, :index, :join, :map, :map!, :detect, :select,
140
- :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
141
159
 
142
160
  def_delegator :@extras, :delete, :remove
143
161
  def_delegator :@extras, :delete_at, :remove_at
@@ -145,10 +163,11 @@ module Squared
145
163
  def_delegator :@extras, :find_all, :detect_all
146
164
  def_delegator :@extras, :find_index, :detect_index
147
165
 
148
- 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)
149
167
  @target = target.is_a?(Set) ? target : target.to_set
150
168
  @project = project
151
169
  @path = path || project&.path
170
+ @sep = sep
152
171
  @errors = []
153
172
  @found = []
154
173
  parse(list, opts, **kwargs, &blk)
@@ -182,7 +201,7 @@ module Squared
182
201
  .each do |val|
183
202
  if (n = val.index('='))
184
203
  flag = val[0, n]
185
- case val[n + 1]
204
+ case val[n.succ]
186
205
  when 'e'
187
206
  e << flag
188
207
  when 'b'
@@ -207,7 +226,7 @@ module Squared
207
226
  else
208
227
  next
209
228
  end
210
- m << flag if flag.size == 1 && val[n + 2] == 'm'
229
+ m << flag if val[n + 2] == 'm'
211
230
  bare << flag if val.end_with?('?')
212
231
  else
213
232
  bare << val
@@ -216,7 +235,7 @@ module Squared
216
235
  no = (no || []).map { |val| (n = val.index('=')) ? val[0, n] : val }
217
236
  bare.concat(no)
218
237
  if underscore
219
- tr = ->(list) { list.map { |val| val.tr('-', '_') } }
238
+ tr = ->(a) { a.map { |val| val.tr('-', '_') } }
220
239
  @values.concat(tr.call(@values))
221
240
  bare.concat(tr.call(bare))
222
241
  e.concat(tr.call(e))
@@ -236,7 +255,7 @@ module Squared
236
255
  [f, /\A\d*(?:\.\d+)?\z/],
237
256
  [si, /\A-?\d+\z/]
238
257
  ].freeze
239
- 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) } }
240
259
  skip = false
241
260
  opts.each do |opt|
242
261
  next skip = true if opt == '--'
@@ -254,21 +273,21 @@ module Squared
254
273
  val = $2
255
274
  merge = m.include?(key)
256
275
  if e.include?(key)
257
- add shell_option(key, val, merge: merge)
276
+ add shell_option(key, val, merge: merge, sep: sep)
258
277
  elsif q.include?(key)
259
- 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)
260
279
  elsif p.include?(key)
261
280
  if val.match?(/\A(["']).+\1\z/)
262
- add shell_option(key, val, escape: false, merge: merge)
281
+ add shell_option(key, val, escape: false, merge: merge, sep: sep)
263
282
  elsif path
264
- add quote_option(key, path + val, merge: merge)
283
+ add quote_option(key, path + val, merge: merge, sep: sep)
265
284
  else
266
285
  push opt
267
286
  end
268
287
  elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
269
- add basic_option(key, val, merge: merge)
288
+ add basic_option(key, val, merge: merge, sep: sep)
270
289
  elsif merge
271
- add basic_option(key, val, merge: true)
290
+ add basic_option(key, val, merge: true, sep: sep)
272
291
  else
273
292
  push opt
274
293
  end
@@ -280,39 +299,40 @@ module Squared
280
299
  skip = true if first&.any? { |s| s.is_a?(Regexp) ? opt.match?(s) : !opt.include?(s) }
281
300
  end
282
301
  end
283
- @values = @values.empty? ? /\A\s+\z/ : /\A(#{@values.join('|')})=(.+)\z/m
302
+ @values = @values.empty? ? /\A\s+\z/ : /\A(#{@values.join('|')})#{sep}(.+)\z/m
284
303
  @extras.each_with_index(&blk) if block_given?
285
304
  self
286
305
  end
287
306
 
288
- def swap(opts = nil)
307
+ def swap(opts = nil, &blk)
289
308
  unless opts
290
309
  opts = found
291
310
  @found = []
292
311
  end
312
+ opts.sort!(&blk) if block_given?
293
313
  @extras = opts
294
314
  self
295
315
  end
296
316
 
297
- def append(*args, **kwargs)
317
+ def append(*args, **kwargs, &blk)
298
318
  args = extras if args.empty?
299
- OptionPartition.append(target, *args, **kwargs)
319
+ out = OptionPartition.append(target, *args, **kwargs, &blk)
320
+ errors.concat(out) if out && (block_given? || kwargs[:filter])
300
321
  self
301
322
  end
302
323
 
303
- def append_any(*args, escape: false, **kwargs)
304
- quote = kwargs.fetch(:quote, true)
324
+ def append_any(*args, quote: true, **kwargs)
305
325
  (args.empty? ? extras : args.flatten).each do |val|
326
+ val = yield val if block_given?
327
+ next unless val.is_a?(String)
328
+
306
329
  if exist?(val)
307
330
  add_path(val, **kwargs)
308
- elsif escape
309
- add shell_escape(val, **kwargs)
310
331
  elsif quote
311
332
  add_quote(val, **kwargs)
312
333
  else
313
334
  add val
314
335
  end
315
- found << val if args.empty?
316
336
  end
317
337
  self
318
338
  end
@@ -323,7 +343,7 @@ module Squared
323
343
  end
324
344
 
325
345
  def values_of(*args, strict: true, first: false, last: false)
326
- eq, s = strict ? ['=', '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
346
+ eq, s = strict ? [sep, '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
327
347
  g = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{windows? ? '| ' : ''}))*)\""]
328
348
  g << "'((?:[^']|'\\\\'')*)'" unless windows?
329
349
  g << "(#{s})"
@@ -362,23 +382,19 @@ module Squared
362
382
  def clear(opts = nil, errors: false, **kwargs)
363
383
  styles = project.theme[:inline] if project
364
384
  if errors
365
- OptionPartition.clear(target, self.errors, styles: styles, **kwargs)
366
- self.errors.clear
385
+ OptionPartition.clear(target, @errors, styles: styles, **kwargs)
386
+ @errors.clear
367
387
  return self unless opts
368
388
  end
369
389
  opts ||= extras
370
- OptionPartition.clear(target, if found.empty?
371
- opts
372
- else
373
- opts.reject { |val| found.include?(val) }
374
- end, styles: styles, **kwargs)
390
+ OptionPartition.clear(target, opts - found, styles: styles, **kwargs)
375
391
  opts.clear
376
392
  self
377
393
  end
378
394
 
379
395
  def adjoin(*args, with: nil, start: false)
380
- i = -1
381
- temp = compact
396
+ index = -1
397
+ temp = to_a
382
398
  if with
383
399
  pat = case with
384
400
  when String, Symbol
@@ -388,82 +404,135 @@ module Squared
388
404
  else
389
405
  with
390
406
  end
391
- temp.each_with_index do |val, index|
407
+ temp.each_with_index do |val, i|
392
408
  if val.to_s.match?(pat)
393
- i = index + (start.is_a?(Numeric) ? start : 1)
409
+ index = i + (start.is_a?(Numeric) ? start : 1)
394
410
  break
395
411
  end
396
412
  end
397
413
  else
398
- temp.each_with_index do |val, index|
399
- if i == 0
400
- 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?('-')
401
417
 
402
- i = index
418
+ index = i
403
419
  break
404
- elsif index > 0 && !val.to_s.start_with?('-')
420
+ elsif i > 0 && !val.start_with?('-')
405
421
  if start
406
- i = index + (start.is_a?(Numeric) ? start : 1)
422
+ index = i + (start.is_a?(Numeric) ? start : 1)
407
423
  break
408
424
  end
409
- i = 0
425
+ index = 0
410
426
  end
411
427
  end
412
428
  end
413
- if i > 0
429
+ if index > 0
414
430
  if args.empty?
415
431
  args = dup
416
432
  reset
417
433
  else
418
434
  args.each { |val| remove val }
419
435
  end
420
- args = temp[0...i] + args + temp[i..-1]
436
+ args = temp[0...index] + args + temp[index..-1]
421
437
  target.clear
422
438
  end
423
439
  merge args
424
440
  self
425
441
  end
426
442
 
427
- def add_path(*args, **kwargs)
428
- 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
429
451
  self
430
452
  end
431
453
 
432
454
  def add_quote(*args, **kwargs)
433
- kwargs.delete(:quote)
434
- args.compact!
435
- 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) })
436
456
  self
437
457
  end
438
458
 
439
- def delim
440
- add '--'
459
+ def add_option(flag, val = nil, **kwargs)
460
+ add shell_option(flag, val, **kwargs)
441
461
  self
442
462
  end
443
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
+
444
515
  def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
445
- temp, other = if block_given?
446
- partition(&blk)
447
- elsif exclude.first.is_a?(Symbol)
448
- partition(&exclude.first)
449
- else
450
- exclude.map! { |pat| Regexp.new(pat) }
451
- partition do |val|
452
- val = val.to_s
453
- next if pattern && OptionPartition.pattern?(val)
454
-
455
- exclude.none? { |pat| val.match?(pat) }
456
- end
457
- end
458
- 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?
459
528
  add '--' if delim
460
529
  extras.clear
461
530
  concat other
462
531
  if path
463
- temp.each { |val| add_path(val) }
532
+ found.each { |val| add_path(val) }
464
533
  else
465
- temp.map! { |val| shell_quote(val) } if quote
466
- merge temp
534
+ found.map! { |val| shell_quote(val) } if quote
535
+ merge found
467
536
  end
468
537
  end
469
538
  self
@@ -476,7 +545,7 @@ module Squared
476
545
  self
477
546
  end
478
547
 
479
- def append?(key, val = nil, type: nil, force: false, **kwargs)
548
+ def append?(key, val = nil, type: nil, force: false, sep: '=', **kwargs)
480
549
  return false unless force || !arg?(key)
481
550
 
482
551
  val = yield self if block_given?
@@ -485,11 +554,11 @@ module Squared
485
554
  type ||= :quote if kwargs.empty?
486
555
  add case type
487
556
  when :quote
488
- quote_option(key, val)
557
+ quote_option(key, val, sep: sep)
489
558
  when :basic
490
- basic_option(key, val)
559
+ basic_option(key, val, sep: sep)
491
560
  else
492
- shell_option(key, val, **kwargs)
561
+ shell_option(key, val, sep: sep, **kwargs)
493
562
  end
494
563
  true
495
564
  end
@@ -498,24 +567,23 @@ module Squared
498
567
  OptionPartition.arg?(target, *args, **kwargs)
499
568
  end
500
569
 
501
- def exist?(*args, add: false, first: false, last: false)
502
- return false unless path
503
- 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?
504
572
 
505
573
  if first || last
506
- return false unless (val = first ? self.first : self.last).is_a?(String)
574
+ return false unless (val = first ? self.first : self.last)
507
575
 
508
- path.join(val).exist?.tap do |ret|
576
+ with_glob?(val, glob).tap do |ret|
509
577
  next unless add && ret
510
578
 
511
- add_path(first ? shift : pop)
579
+ add_first(path: true, reverse: !first)
512
580
  end
513
581
  else
514
- each_with_index do |val, index|
515
- next unless val.is_a?(String) && path.join(val).exist?
582
+ each_with_index do |val, i|
583
+ next unless with_glob?(val, glob)
516
584
 
517
585
  if add
518
- remove_at index
586
+ remove_at i
519
587
  add_path val
520
588
  end
521
589
  return true
@@ -537,8 +605,13 @@ module Squared
537
605
  val[OPT_VALUE, 1] || val
538
606
  end
539
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
+
540
614
  def windows?
541
- require 'rake'
542
615
  Rake::Win32.windows?
543
616
  end
544
617
  end
@@ -548,20 +621,11 @@ module Squared
548
621
  super[/[^:]+\z/, 0]
549
622
  end
550
623
 
551
- alias to_ary to_a
552
-
553
- attr_reader :delim, :extras
624
+ attr_reader :delim
554
625
 
555
- def initialize(data = [], delim: ' ', partition: '--', uniq: /\A--?[^=\s-][^=\s]*(?:=|\s+)\S/)
556
- @delim = delim
557
- @partition = partition
558
- @uniq = uniq
559
- @extras = []
626
+ def initialize(data = [], delim: ' ')
560
627
  super(data.compact)
561
- end
562
-
563
- def compact
564
- to_ary.map!(&:to_s).reject(&:empty?)
628
+ @delim = delim
565
629
  end
566
630
 
567
631
  def last(val, pat)
@@ -570,28 +634,27 @@ module Squared
570
634
  end
571
635
 
572
636
  def pass(&blk)
573
- ret = compact
637
+ ret = to_a.map!(&:to_s).reject(&:empty?)
574
638
  @last&.each do |val, pat, key|
575
- i = []
576
- j = nil
577
- ret.each_with_index do |opt, index|
639
+ items = []
640
+ index = nil
641
+ ret.each_with_index do |opt, i|
578
642
  if opt == val
579
- j = index
580
- elsif j && opt[pat, 1] == key
581
- i << index
643
+ index = i
644
+ elsif index && opt[pat, 1] == key
645
+ items << i
582
646
  end
583
647
  end
584
- next unless j && !i.empty?
648
+ next unless index && !items.empty?
585
649
 
586
- val = ret[j]
587
- cur = j
588
- i.each do |k|
650
+ val = ret[index]
651
+ cur = index
652
+ items.each do |k|
589
653
  ret[cur] = ret[k]
590
654
  cur = k
591
655
  end
592
- ret[i.last] = val
656
+ ret[items.last] = val
593
657
  end
594
- ret.concat(extras.map(&:to_s).reject(&:empty?)) unless extras.empty?
595
658
  return ret unless block_given?
596
659
 
597
660
  ret.reject(&blk)
@@ -613,83 +676,17 @@ module Squared
613
676
 
614
677
  def temp(*args, &blk)
615
678
  args.compact!
616
- pass(&blk)
617
- .concat(args)
618
- .join(@delim)
679
+ ret = pass(&blk)
680
+ ret = Set.new(ret.concat(args)).to_a unless args.empty?
681
+ ret.join(@delim)
619
682
  end
620
683
 
621
684
  def done
622
685
  to_s.tap { clear }
623
686
  end
624
687
 
625
- def merge(enum)
626
- if !extras.empty?
627
- extras.concat(enum.to_a)
628
- self
629
- elsif (n = enum.find_index { |val| extras?(val) })
630
- data = enum.to_a
631
- @extras = if n == 0
632
- data
633
- else
634
- super(data[0...n])
635
- data[n..-1]
636
- end
637
- self
638
- else
639
- super
640
- end
641
- end
642
-
643
- def <<(obj)
644
- extras!(obj) || super
645
- end
646
-
647
- def size
648
- super + extras.size
649
- end
650
-
651
- def include?(obj)
652
- return true if super
653
- return extras.include?(obj) unless (n = extras.index(@partition))
654
-
655
- extras[0..n].include?(obj)
656
- end
657
-
658
- def to_a
659
- pass
660
- end
661
-
662
688
  def to_s
663
- to_a.join(@delim)
664
- end
665
-
666
- def to_enum(*args)
667
- to_a.to_enum(*args)
668
- end
669
-
670
- def to_json(*args)
671
- to_a.to_json(*args)
672
- end
673
-
674
- def to_yaml(*args)
675
- to_a.to_yaml(*args)
676
- end
677
-
678
- alias add :<<
679
- alias add? :<<
680
- alias member? include?
681
-
682
- private
683
-
684
- def extras!(obj)
685
- return if extras.empty? && !extras?(obj)
686
-
687
- extras << obj unless !extras.include?(@partition) && include?(obj) && @uniq.match?(obj.to_s)
688
- self
689
- end
690
-
691
- def extras?(obj)
692
- obj == @partition || (include?(obj) && !@uniq.match?(obj.to_s))
689
+ pass.join(@delim)
693
690
  end
694
691
  end
695
692
  end