squared 0.8.2 → 0.8.4

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,10 +10,11 @@ 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/
16
- private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE
13
+ OPT_NAME = /\A(?:(--)|-)((?(1)[^=\s-][^=\s]*|[^=\s-]))\z/.freeze
14
+ OPT_VALUE = /\A-{0,2}([^=\s-][^=\s]*)(?:=|\s+)(\S.*)\z/.freeze
15
+ OPT_SINGLE = /\A-([^=\s-])(.+)\z/.freeze
16
+ QUOTE_VALUE = /\A(["'])(.+)\1\z/m.freeze
17
+ private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE, :QUOTE_VALUE
17
18
 
18
19
  class << self
19
20
  include Common::Format
@@ -22,12 +23,21 @@ module Squared
22
23
 
23
24
  def append(target, *args, delim: false, escape: false, quote: true, strip: nil, double: false, filter: nil,
24
25
  pass: nil, **kwargs)
25
- return if (ret = args.flatten(1)).empty?
26
+ ret = args.flatten(1)
27
+ return if ret.empty?
26
28
 
27
29
  target << '--' if delim && !target.include?('--')
28
30
  if strip
29
31
  pat, s = Array(strip)
30
- ret.map! { |val| val.is_a?(String) ? val.gsub(pat, s || '') : val }
32
+ ret.map! do |val|
33
+ next val unless val.is_a?(String)
34
+
35
+ if pat.is_a?(String) && pat.size == 1 && s.nil?
36
+ val.delete_prefix(pat)
37
+ else
38
+ val.gsub(pat, s || '')
39
+ end
40
+ end
31
41
  end
32
42
  if filter
33
43
  ret, err = ret.partition { |val| filter.match?(val.to_s) }
@@ -87,8 +97,26 @@ module Squared
87
97
 
88
98
  def strip(val)
89
99
  val = shell_split val if val.is_a?(String)
90
- Array(val).map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2') }
91
- .reject(&:empty?)
100
+ ret = []
101
+ pass = -1
102
+ args = Array(val)
103
+ args.each_with_index do |s, i|
104
+ next if s.empty? || pass == i
105
+
106
+ if s == '--'
107
+ ret << s << args[i.succ..-1].join(' ')
108
+ break
109
+ end
110
+ next ret << s unless s.start_with?('-')
111
+
112
+ if !s.include?('=') && (j = args[i.succ]) && !j.start_with?('-')
113
+ ret << "#{s.sub(/^-{1,2}/, '')}=#{j}"
114
+ pass = i.succ
115
+ else
116
+ ret << s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2')
117
+ end
118
+ end
119
+ ret
92
120
  end
93
121
 
94
122
  def select(list, bare: true, no: true, single: false, double: false)
@@ -102,21 +130,17 @@ module Squared
102
130
 
103
131
  def union(list, other)
104
132
  base = list.map { |val| parse_option(val).first }
105
- other.each do |val|
106
- next if base.include?(parse_option(val).first)
107
-
108
- list << val
109
- end
110
- list
133
+ list + other.each_with_object([]) { |val, out| out << val unless base.include?(parse_option(val).first) }
111
134
  end
112
135
 
113
136
  def uniq!(list, pass: [])
114
- keys = {}
115
- list.each_with_index do |val, i|
116
- j = val =~ OPT_VALUE ? $1 : val
117
- (keys[j] ||= []) << i unless pass.include?(j)
118
- end
119
- data = keys.map { |item| item[1].size > 1 ? item[1][0..-2] : [] }.reject(&:empty?)
137
+ data = list.each_with_object({})
138
+ .with_index do |(val, out), i|
139
+ j = val =~ OPT_VALUE ? $1 : val
140
+ (out[j] ||= []) << i unless pass.include?(j)
141
+ end
142
+ .map { |item| item[1].size > 1 ? item[1][0..-2] : [] }
143
+ .reject(&:empty?)
120
144
  return if data.empty?
121
145
 
122
146
  data.each { |key| key.each { |i| list[i] = nil } }
@@ -162,8 +186,11 @@ module Squared
162
186
  end
163
187
 
164
188
  def pattern?(val)
189
+ Regexp.new(val)
165
190
  val.start_with?('\A', '^') || val.end_with?('\z', '$') ||
166
191
  val.match?(/[.)][*+?]|\(\?[:=!><]|\\[dsw\d]|\[.+\]|\{\d+,?\d*\}/i)
192
+ rescue RegexpError
193
+ false
167
194
  end
168
195
 
169
196
  private
@@ -218,7 +245,7 @@ module Squared
218
245
  end
219
246
 
220
247
  def parse(list, opts = extras, no: nil, single: nil, args: false, multiple: nil, first: nil, underscore: nil,
221
- stdin: false, &blk)
248
+ explicit: false, bool: %w[true false], stdin: false, &blk)
222
249
  @extras = []
223
250
  @values = []
224
251
  bare = []
@@ -232,7 +259,10 @@ module Squared
232
259
  f = []
233
260
  si = []
234
261
  bl = []
262
+ ex = []
235
263
  ml = []
264
+ re = {}
265
+ ar = {}
236
266
  sw = {}
237
267
  se = {}
238
268
  list.flat_map do |val|
@@ -261,13 +291,13 @@ module Squared
261
291
  else
262
292
  [flag]
263
293
  end
294
+ bare.concat(mod) if val.chomp!('?')
295
+ m.concat(mod) if val.chomp!('m')
264
296
  case val[n.succ]
265
297
  when 'e'
266
298
  e.concat(mod)
267
299
  when 'b'
268
300
  b.concat(mod)
269
- when 'm'
270
- m.concat(mod)
271
301
  when 'q'
272
302
  qq.concat(mod) if val[n + 2] == 'q'
273
303
  q.concat(mod)
@@ -286,13 +316,27 @@ module Squared
286
316
  when '+'
287
317
  ml.concat(mod)
288
318
  bare.concat(mod)
289
- else
290
- next
319
+ when '/'
320
+ begin
321
+ val = val[n.succ..-1]
322
+ pat = eval(val)
323
+ raise SyntaxError unless pat.is_a?(Regexp)
324
+
325
+ mod.each { |key| re[key] = pat }
326
+ rescue SyntaxError
327
+ warn "#{self.class}: invalid pattern (#{val})"
328
+ end
329
+ when '{'
330
+ group = val[(n + 2)..-1].chomp!('}')&.split(',')
331
+ if group
332
+ mod.each { |key| ar[key] = group }
333
+ else
334
+ warn "#{self.class}: invalid group (#{val})"
335
+ end
291
336
  end
292
- m.concat(mod) if val[n + 2] == 'm'
293
- bare.concat(mod) if val.end_with?('?')
294
337
  else
295
338
  bare << val
339
+ ex << val if explicit
296
340
  mod = [val]
297
341
  end
298
342
  mod.each do |key|
@@ -325,7 +369,7 @@ module Squared
325
369
  end
326
370
  numtype = [
327
371
  [i, /\A\d+\z/],
328
- [f, /\A\d*(\.\d+)?\z/],
372
+ [f, /\A(\d+(\.\d*)?|\d*\.\d+)\z/],
329
373
  [si, /\A-?\d+\z/]
330
374
  ].freeze
331
375
  numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && v.match?(pat) } }
@@ -355,33 +399,57 @@ module Squared
355
399
  elsif opt.start_with?(/no[-_]/) && no.include?(s = opt[3..-1])
356
400
  add "--no-#{s}"
357
401
  else
402
+ has = lambda do |list, key|
403
+ return true if list.include?(key)
404
+ return false unless (pre = list.find { |s| s.end_with?(':*') })
405
+
406
+ key.start_with?(pre.chomp('*')) && !key.end_with?(':')
407
+ end
358
408
  if opt =~ OPT_VALUE
359
409
  key = $1
360
410
  val = $2
361
- has = lambda do |a|
362
- return true if a.include?(key)
363
- return false unless (k = a.find { |s| s.end_with?(':*') })
364
-
365
- key.start_with?(k.chomp('*')) && !key.end_with?(':')
366
- end
367
- kwargs = { sep: se[key] || sep, merge: has.call(m), switch: sw[key] }
368
- if has.call(e) || (has.call(bl) && %w[true false].include?(val))
411
+ get = ->(h) { h[key] || h.find { |k,| k.end_with?(':*') }.last }
412
+ kwargs = { sep: se[key] || sep, merge: has.call(m, key), switch: sw[key] }
413
+ if has.call(e, key) || (has.call(bl, key) && bool.include?(val))
369
414
  add shell_option(key, val, **kwargs)
370
- elsif has.call(q)
371
- add quote_option(key, val, double: has.call(qq), **kwargs)
372
- elsif has.call(p)
373
- if val.match?(/\A(["']).+\1\z/)
374
- add shell_option(key, val, escape: false, **kwargs)
415
+ elsif has.call(ex, key) && bool.include?(val)
416
+ add shell_option(key, val, explicit: explicit, **kwargs)
417
+ elsif has.call(q, key)
418
+ add quote_option(key, val, double: has.call(qq, key), **kwargs)
419
+ elsif has.call(p, key)
420
+ if val =~ QUOTE_VALUE
421
+ add shell_option(key, val, double: $1 == '"', escape: false, **kwargs)
375
422
  elsif path
376
423
  add quote_option(key, path + val, **kwargs)
377
424
  else
378
425
  push opt
379
426
  end
380
- elsif kwargs[:merge] || has.call(b) || numcheck.call(key, val) || se[key] || sw[key]
427
+ elsif !ar.empty? && has.call(ar.keys, key)
428
+ group = get.call(ar)
429
+ if group.include?(val)
430
+ add shell_option(key, val, force: false, **kwargs)
431
+ elsif @strict
432
+ clear([opt], hint: "include != {#{group.join(',')}}")
433
+ else
434
+ push opt
435
+ end
436
+ elsif !re.empty? && has.call(re.keys, key)
437
+ pat = get.call(re)
438
+ if val.match?(pat)
439
+ add quote_option(key, val, **kwargs)
440
+ elsif @strict
441
+ clear([opt], hint: "match != /#{pat.source}/")
442
+ else
443
+ push opt
444
+ end
445
+ elsif kwargs[:merge] || has.call(b, key) || numcheck.call(key, val) || se[key] || sw[key]
381
446
  add basic_option(key, val, **kwargs)
382
447
  else
383
448
  push opt
384
449
  end
450
+ opt = key unless opt == last
451
+ elsif has.call(m, key = opt[0]) && opt[1..-1] =~ QUOTE_VALUE
452
+ add basic_option(key, $2, double: $1 == '"', **kwargs, merge: true)
385
453
  opt = key
386
454
  else
387
455
  push opt
@@ -449,8 +517,8 @@ module Squared
449
517
 
450
518
  def values_of(*args, strict: true, first: false, last: false)
451
519
  eq, s = strict ? [sep, '[^ ]+'] : ['(?:=| +)', '[^-][^ ]*']
452
- g = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{'| ' if windows?}))*)\""]
453
- g << "'((?:[^']|'\\\\'')*)'" unless windows?
520
+ g = ["\"((?:[^\"]|(?<=\\\\)\"(?!$#{'| ' if Common::Host.windows?}))*)\""]
521
+ g << "'((?:[^']|'\\\\'')*)'" unless Common::Host.windows?
454
522
  g << "(#{s})"
455
523
  list = args.map do |opt|
456
524
  if opt.size == 1
@@ -582,7 +650,11 @@ module Squared
582
650
  val = val.delete_prefix(prefix) if prefix
583
651
  if strip
584
652
  pat, s = Array(strip)
585
- val = val.gsub(pat, s || '')
653
+ val = if pat.is_a?(String) && pat.size == 1 && s.nil?
654
+ val.delete_prefix(pat)
655
+ else
656
+ val.gsub(pat, s || '')
657
+ end
586
658
  end
587
659
  end
588
660
  unless block_given? && !(val = yield val).is_a?(String)
@@ -722,16 +794,13 @@ module Squared
722
794
  end
723
795
 
724
796
  def exist?(*args, add: false, first: false, last: false, glob: false)
725
- return !args.first.nil? && with_glob?(File.join(*args), glob) unless args.empty?
797
+ return !args.include?(nil) && with_glob?(File.join(*args), glob) unless args.empty?
726
798
 
727
799
  if first || last
728
- return false unless (val = first ? self.first : self.last)
800
+ val = first ? self.first : self.last
801
+ return false unless val
729
802
 
730
- with_glob?(val, glob).tap do |ret|
731
- next unless add && ret
732
-
733
- add_first(path: true, reverse: !first)
734
- end
803
+ with_glob?(val, glob).tap { |ret| add_first(path: true, reverse: !first) if add && ret }
735
804
  else
736
805
  each_with_index do |val, i|
737
806
  next unless with_glob?(val, glob)
@@ -766,11 +835,6 @@ module Squared
766
835
 
767
836
  path.join(val).exist? || (glob && !path.glob(val).empty?)
768
837
  end
769
-
770
- def windows?
771
- require 'rake'
772
- Rake::Win32.windows?
773
- end
774
838
  end
775
839
  end
776
840
  end
@@ -126,7 +126,8 @@ module Squared
126
126
  stage = nil
127
127
  opts = %w[force rebase detach submodules fail no-update gc]
128
128
  desc = lambda do |val, alt = nil|
129
- if (ver = branch || alt)
129
+ ver = branch || alt
130
+ if ver
130
131
  val = val.sub('{0}', "opts*=#{opts.join(',')}")
131
132
  task_desc(path, val, ver)
132
133
  else
@@ -184,8 +185,7 @@ module Squared
184
185
  end
185
186
  env('REPO_GROUPS', **envargs) do |val|
186
187
  g = case val
187
- when '0', 'false'
188
- nil
188
+ when '0', 'false' then nil
189
189
  else
190
190
  val
191
191
  end
@@ -314,9 +314,7 @@ module Squared
314
314
  i = -1
315
315
  n = repo_scriptdata(proj, name).reduce(0) do |a, b|
316
316
  i += 1
317
- next a unless b
318
-
319
- a + (1 << i)
317
+ b ? a + (1 << i) : a
320
318
  end
321
319
  proj.global(n) && (pass || g.include?(proj.group) || r.any? { |val| proj.ref?(val) })
322
320
  end
@@ -362,7 +360,7 @@ module Squared
362
360
  def repo_install?(dir = root, parent: false)
363
361
  return true if root?(dir, pass: ['.repo']) || dir.join('.repo').directory?
364
362
 
365
- parent && root.children.none? { |ent| ent.directory? && ent.basename.to_s[0] != '.' && ent != home }
363
+ parent && root.children.none? { |ent| ent.directory? && ent != home }
366
364
  end
367
365
  end
368
366
 
@@ -23,8 +23,8 @@ module Squared
23
23
  @exclude = exclude.freeze
24
24
  @task = Struct::SeriesData.new(workspace.config_get(:rename))
25
25
  @data = {}
26
- project.each_with_index do |obj, index|
27
- if index == 0
26
+ project.each_with_index do |obj, i|
27
+ if i == 0
28
28
  target = @task.base
29
29
  obj.tasks.each do |key|
30
30
  target << key
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -80,6 +80,7 @@ files:
80
80
  - lib/squared/common.rb
81
81
  - lib/squared/common/base.rb
82
82
  - lib/squared/common/format.rb
83
+ - lib/squared/common/host.rb
83
84
  - lib/squared/common/prompt.rb
84
85
  - lib/squared/common/shell.rb
85
86
  - lib/squared/common/system.rb
@@ -125,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
126
  - !ruby/object:Gem::Version
126
127
  version: '0'
127
128
  requirements: []
128
- rubygems_version: 4.0.15
129
+ rubygems_version: 4.0.19
129
130
  specification_version: 4
130
131
  summary: Rake task generator for managing multi-language workspaces.
131
132
  test_files: []