squared 0.5.19 → 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 quote || val.is_a?(Pathname)
36
- shell_quote(val, force: force, double: double)
37
- elsif escape
38
- shell_escape(val, quote: quote, 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?, :each, :each_with_index, :partition, :dup, :first, :last, :shift, :unshift,
139
- :pop, :push, :concat, :index, :join, :map, :map!, :detect, :select, :select!, :reject, :size,
140
- :delete_at
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,28 +299,33 @@ 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
324
  def append_any(*args, quote: true, **kwargs)
304
325
  (args.empty? ? extras : args.flatten).each do |val|
326
+ val = yield val if block_given?
327
+ next unless val.is_a?(String)
328
+
305
329
  if exist?(val)
306
330
  add_path(val, **kwargs)
307
331
  elsif quote
@@ -309,7 +333,6 @@ module Squared
309
333
  else
310
334
  add val
311
335
  end
312
- found << val if args.empty?
313
336
  end
314
337
  self
315
338
  end
@@ -320,7 +343,7 @@ module Squared
320
343
  end
321
344
 
322
345
  def values_of(*args, strict: true, first: false, last: false)
323
- eq, s = strict ? ['=', '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
346
+ eq, s = strict ? [sep, '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
324
347
  g = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{windows? ? '| ' : ''}))*)\""]
325
348
  g << "'((?:[^']|'\\\\'')*)'" unless windows?
326
349
  g << "(#{s})"
@@ -359,23 +382,19 @@ module Squared
359
382
  def clear(opts = nil, errors: false, **kwargs)
360
383
  styles = project.theme[:inline] if project
361
384
  if errors
362
- OptionPartition.clear(target, self.errors, styles: styles, **kwargs)
363
- self.errors.clear
385
+ OptionPartition.clear(target, @errors, styles: styles, **kwargs)
386
+ @errors.clear
364
387
  return self unless opts
365
388
  end
366
389
  opts ||= extras
367
- OptionPartition.clear(target, if found.empty?
368
- opts
369
- else
370
- opts.reject { |val| found.include?(val) }
371
- end, styles: styles, **kwargs)
390
+ OptionPartition.clear(target, opts - found, styles: styles, **kwargs)
372
391
  opts.clear
373
392
  self
374
393
  end
375
394
 
376
395
  def adjoin(*args, with: nil, start: false)
377
- i = -1
378
- temp = compact
396
+ index = -1
397
+ temp = to_a
379
398
  if with
380
399
  pat = case with
381
400
  when String, Symbol
@@ -385,79 +404,135 @@ module Squared
385
404
  else
386
405
  with
387
406
  end
388
- temp.each_with_index do |val, index|
407
+ temp.each_with_index do |val, i|
389
408
  if val.to_s.match?(pat)
390
- i = index + (start.is_a?(Numeric) ? start : 1)
409
+ index = i + (start.is_a?(Numeric) ? start : 1)
391
410
  break
392
411
  end
393
412
  end
394
413
  else
395
- temp.each_with_index do |val, index|
396
- if i == 0
397
- 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?('-')
398
417
 
399
- i = index
418
+ index = i
400
419
  break
401
- elsif index > 0 && !val.to_s.start_with?('-')
420
+ elsif i > 0 && !val.start_with?('-')
402
421
  if start
403
- i = index + (start.is_a?(Numeric) ? start : 1)
422
+ index = i + (start.is_a?(Numeric) ? start : 1)
404
423
  break
405
424
  end
406
- i = 0
425
+ index = 0
407
426
  end
408
427
  end
409
428
  end
410
- if i > 0
429
+ if index > 0
411
430
  if args.empty?
412
431
  args = dup
413
432
  reset
414
433
  else
415
434
  args.each { |val| remove val }
416
435
  end
417
- args = temp[0...i] + args + temp[i..-1]
436
+ args = temp[0...index] + args + temp[index..-1]
418
437
  target.clear
419
438
  end
420
439
  merge args
421
440
  self
422
441
  end
423
442
 
424
- def add_path(*args, **kwargs)
425
- 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
426
451
  self
427
452
  end
428
453
 
429
454
  def add_quote(*args, **kwargs)
430
- args.compact!
431
- 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) })
432
456
  self
433
457
  end
434
458
 
435
- def delim
436
- add '--'
459
+ def add_option(flag, val = nil, **kwargs)
460
+ add shell_option(flag, val, **kwargs)
437
461
  self
438
462
  end
439
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
+
440
515
  def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
441
- temp, other = if block_given?
442
- partition(&blk)
443
- elsif exclude.first.is_a?(Symbol)
444
- partition(&exclude.first)
445
- else
446
- partition do |val|
447
- next false if pattern && OptionPartition.pattern?(val)
448
-
449
- exclude.none? { |pat| val.match?(Regexp.new(pat)) }
450
- end
451
- end
452
- 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?
453
528
  add '--' if delim
454
529
  extras.clear
455
530
  concat other
456
531
  if path
457
- temp.each { |val| add_path(val) }
532
+ found.each { |val| add_path(val) }
458
533
  else
459
- temp.map! { |val| shell_quote(val) } if quote
460
- merge temp
534
+ found.map! { |val| shell_quote(val) } if quote
535
+ merge found
461
536
  end
462
537
  end
463
538
  self
@@ -470,7 +545,7 @@ module Squared
470
545
  self
471
546
  end
472
547
 
473
- def append?(key, val = nil, type: nil, force: false, **kwargs)
548
+ def append?(key, val = nil, type: nil, force: false, sep: '=', **kwargs)
474
549
  return false unless force || !arg?(key)
475
550
 
476
551
  val = yield self if block_given?
@@ -479,11 +554,11 @@ module Squared
479
554
  type ||= :quote if kwargs.empty?
480
555
  add case type
481
556
  when :quote
482
- quote_option(key, val)
557
+ quote_option(key, val, sep: sep)
483
558
  when :basic
484
- basic_option(key, val)
559
+ basic_option(key, val, sep: sep)
485
560
  else
486
- shell_option(key, val, **kwargs)
561
+ shell_option(key, val, sep: sep, **kwargs)
487
562
  end
488
563
  true
489
564
  end
@@ -492,24 +567,23 @@ module Squared
492
567
  OptionPartition.arg?(target, *args, **kwargs)
493
568
  end
494
569
 
495
- def exist?(*args, add: false, first: false, last: false)
496
- return false unless path
497
- 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?
498
572
 
499
573
  if first || last
500
- return false unless (val = first ? self.first : self.last).is_a?(String)
574
+ return false unless (val = first ? self.first : self.last)
501
575
 
502
- path.join(val).exist?.tap do |ret|
576
+ with_glob?(val, glob).tap do |ret|
503
577
  next unless add && ret
504
578
 
505
- add_path(first ? shift : pop)
579
+ add_first(path: true, reverse: !first)
506
580
  end
507
581
  else
508
- each_with_index do |val, index|
509
- next unless val.is_a?(String) && path.join(val).exist?
582
+ each_with_index do |val, i|
583
+ next unless with_glob?(val, glob)
510
584
 
511
585
  if add
512
- remove_at index
586
+ remove_at i
513
587
  add_path val
514
588
  end
515
589
  return true
@@ -531,8 +605,13 @@ module Squared
531
605
  val[OPT_VALUE, 1] || val
532
606
  end
533
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
+
534
614
  def windows?
535
- require 'rake'
536
615
  Rake::Win32.windows?
537
616
  end
538
617
  end
@@ -542,20 +621,11 @@ module Squared
542
621
  super[/[^:]+\z/, 0]
543
622
  end
544
623
 
545
- alias to_ary to_a
546
-
547
- attr_reader :delim, :extras
624
+ attr_reader :delim
548
625
 
549
- def initialize(data = [], delim: ' ', partition: '--', uniq: /\A--?[^=\s-][^=\s]*(?:=|\s+)\S/)
550
- @delim = delim
551
- @partition = partition
552
- @uniq = uniq
553
- @extras = []
626
+ def initialize(data = [], delim: ' ')
554
627
  super(data.compact)
555
- end
556
-
557
- def compact
558
- to_ary.map!(&:to_s).reject(&:empty?)
628
+ @delim = delim
559
629
  end
560
630
 
561
631
  def last(val, pat)
@@ -564,28 +634,27 @@ module Squared
564
634
  end
565
635
 
566
636
  def pass(&blk)
567
- ret = compact
637
+ ret = to_a.map!(&:to_s).reject(&:empty?)
568
638
  @last&.each do |val, pat, key|
569
- i = []
570
- j = nil
571
- ret.each_with_index do |opt, index|
639
+ items = []
640
+ index = nil
641
+ ret.each_with_index do |opt, i|
572
642
  if opt == val
573
- j = index
574
- elsif j && opt[pat, 1] == key
575
- i << index
643
+ index = i
644
+ elsif index && opt[pat, 1] == key
645
+ items << i
576
646
  end
577
647
  end
578
- next unless j && !i.empty?
648
+ next unless index && !items.empty?
579
649
 
580
- val = ret[j]
581
- cur = j
582
- i.each do |k|
650
+ val = ret[index]
651
+ cur = index
652
+ items.each do |k|
583
653
  ret[cur] = ret[k]
584
654
  cur = k
585
655
  end
586
- ret[i.last] = val
656
+ ret[items.last] = val
587
657
  end
588
- ret.concat(extras.map(&:to_s).reject(&:empty?)) unless extras.empty?
589
658
  return ret unless block_given?
590
659
 
591
660
  ret.reject(&blk)
@@ -607,83 +676,17 @@ module Squared
607
676
 
608
677
  def temp(*args, &blk)
609
678
  args.compact!
610
- pass(&blk)
611
- .concat(args)
612
- .join(@delim)
679
+ ret = pass(&blk)
680
+ ret = Set.new(ret.concat(args)).to_a unless args.empty?
681
+ ret.join(@delim)
613
682
  end
614
683
 
615
684
  def done
616
685
  to_s.tap { clear }
617
686
  end
618
687
 
619
- def merge(enum)
620
- if !extras.empty?
621
- extras.concat(enum.to_a)
622
- self
623
- elsif (n = enum.find_index { |val| extras?(val) })
624
- data = enum.to_a
625
- @extras = if n == 0
626
- data
627
- else
628
- super(data[0...n])
629
- data[n..-1]
630
- end
631
- self
632
- else
633
- super
634
- end
635
- end
636
-
637
- def <<(obj)
638
- extras!(obj) || super
639
- end
640
-
641
- def size
642
- super + extras.size
643
- end
644
-
645
- def include?(obj)
646
- return true if super
647
- return extras.include?(obj) unless (n = extras.index(@partition))
648
-
649
- extras[0..n].include?(obj)
650
- end
651
-
652
- def to_a
653
- pass
654
- end
655
-
656
688
  def to_s
657
- to_a.join(@delim)
658
- end
659
-
660
- def to_enum(*args)
661
- to_a.to_enum(*args)
662
- end
663
-
664
- def to_json(*args)
665
- to_a.to_json(*args)
666
- end
667
-
668
- def to_yaml(*args)
669
- to_a.to_yaml(*args)
670
- end
671
-
672
- alias add :<<
673
- alias add? :<<
674
- alias member? include?
675
-
676
- private
677
-
678
- def extras!(obj)
679
- return if extras.empty? && !extras?(obj)
680
-
681
- extras << obj unless !extras.include?(@partition) && include?(obj) && @uniq.match?(obj.to_s)
682
- self
683
- end
684
-
685
- def extras?(obj)
686
- obj == @partition || (include?(obj) && !@uniq.match?(obj.to_s))
689
+ pass.join(@delim)
687
690
  end
688
691
  end
689
692
  end