squared 0.4.20 → 0.4.22

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,15 +10,17 @@ module Squared
10
10
  include Common::Shell
11
11
  extend Forwardable
12
12
 
13
- OPT_VALUE = /\A([^=]+)=(.+)\z/
14
- private_constant :OPT_VALUE
13
+ OPT_VALUE = /\A-{0,2}([^= ]+)(?: *= *| +)(.+)\z/
14
+ OPT_SINGLE = /\A-([A-Za-z\d])(.+)\z/
15
+ private_constant :OPT_VALUE, :OPT_SINGLE
15
16
 
16
17
  class << self
17
18
  include Common::Format
18
19
  include Shell
19
20
  include Prompt
20
21
 
21
- def append(target, *args, delim: false, escape: false, quote: true, strip: nil, **)
22
+ def append(target, *args, delim: false, escape: false, quote: true, strip: nil, force: true, double: false,
23
+ **)
22
24
  return if (ret = args.flatten).empty?
23
25
 
24
26
  target << '--' if delim && !target.include?('--')
@@ -26,7 +28,15 @@ module Squared
26
28
  pat, s = Array(strip)
27
29
  ret.map! { |val| val.gsub(pat, s || '') }
28
30
  end
29
- ret.map! { |val| escape ? shell_escape(val, quote: quote) : shell_quote(val) } if escape || quote
31
+ if escape || quote
32
+ ret.map! do |val|
33
+ if escape
34
+ shell_escape(val, quote: quote, double: double)
35
+ else
36
+ shell_quote(val, force: force, double: double)
37
+ end
38
+ end
39
+ end
30
40
  if target.is_a?(Set)
31
41
  target.merge(ret)
32
42
  else
@@ -45,11 +55,23 @@ module Squared
45
55
  exit 1 unless pass || confirm("Run? [#{sub_style(target, styles: styles)}] [y/N] ", 'N')
46
56
  end
47
57
 
58
+ def delete_key(target, *args, value: false, reverse: false, count: -1)
59
+ ret = []
60
+ args.each do |val|
61
+ next if (opts = target.grep(matchopt(val, value))).empty?
62
+
63
+ opts = opts.first(count) if count >= 0
64
+ opts.send(reverse ? :reverse_each : :each) { |key| target.delete(key) }
65
+ ret.concat(opts)
66
+ end
67
+ ret
68
+ end
69
+
48
70
  def strip(val)
49
71
  return [] unless val
50
72
 
51
73
  val = shell_split(val) if val.is_a?(String)
52
- val.map { |s| s.sub(/\A-([a-z\d])(.+)\z/i, '\1=\2').sub(/\A--?/, '') }.reject(&:empty?)
74
+ val.map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2') }.reject(&:empty?)
53
75
  end
54
76
 
55
77
  def select(list, bare: true, no: true, single: false, double: false)
@@ -63,16 +85,37 @@ module Squared
63
85
 
64
86
  def arg?(target, *args, value: false, **)
65
87
  r, s = args.partition { |val| val.is_a?(Regexp) }
66
- unless s.empty?
67
- s.map! { |val| Regexp.escape(val.start_with?('-') ? val : shell_option(val)) }
68
- r << /\A(?:#{s.join('|')})#{value ? '[ =].' : '(?: |=|\z)'}/
69
- end
88
+ r << matchopts(s, value: value) unless s.empty?
70
89
  Array(target).compact.any? { |val| r.any? { |pat| pat.match?(val.to_s) } }
71
90
  end
72
91
 
73
92
  def pattern?(val)
74
93
  val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
75
94
  end
95
+
96
+ private
97
+
98
+ def matchopt(val, value = false)
99
+ /\A#{val.size == 1 ? shortopt(val) : longopt(val, value)}/
100
+ end
101
+
102
+ def matchopts(list, value = false)
103
+ a, b = Array(list).partition { |val| val.size == 1 || val.match?(OPT_SINGLE) }
104
+ return /\A#{shortopt(*a)}}/ if b.empty?
105
+ return /\A#{longopt(*b, value)}/ if a.empty?
106
+
107
+ /\A(?:#{shortopt(*a)}|#{longopt(*b, value)})/
108
+ end
109
+
110
+ def shortopt(*group)
111
+ group.map! { |s| s.sub(/\A-/, '') }
112
+ "-(?:#{Regexp.escape(group.join('|'))})(?:\\z|[^ =]| +[^ -])"
113
+ end
114
+
115
+ def longopt(*group, value)
116
+ group.map! { |s| s.sub(/\A--/, '') }
117
+ "--(?:#{Regexp.escape(group.join('|'))})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
118
+ end
76
119
  end
77
120
 
78
121
  attr_reader :target, :extras, :found, :errors, :values, :project, :path
@@ -80,11 +123,14 @@ module Squared
80
123
  def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
81
124
  :merge, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
82
125
  def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :last, :shift, :unshift,
83
- :pop, :push, :concat, :index, :delete_at, :join, :map, :map!, :select, :select!, :reject, :size
126
+ :pop, :push, :concat, :index, :join, :map, :map!, :detect, :select, :select!, :reject, :size,
127
+ :delete_at
84
128
 
85
129
  def_delegator :@extras, :delete, :remove
86
130
  def_delegator :@extras, :delete_at, :remove_at
87
131
  def_delegator :@extras, :delete_if, :remove_if
132
+ def_delegator :@extras, :find_all, :detect_all
133
+ def_delegator :@extras, :find_index, :detect_index
88
134
 
89
135
  def initialize(opts, list, target = Set.new, project: nil, path: nil, **kwargs, &blk)
90
136
  @target = target.is_a?(Set) ? target : target.to_set
@@ -95,7 +141,7 @@ module Squared
95
141
  parse(list, opts, **kwargs, &blk)
96
142
  end
97
143
 
98
- def parse(list, opts = extras, no: nil, single: nil, args: false, first: nil, &blk)
144
+ def parse(list, opts = extras, no: nil, single: nil, args: false, first: nil, underscore: nil, &blk)
99
145
  @extras = []
100
146
  @values = []
101
147
  bare = []
@@ -148,7 +194,7 @@ module Squared
148
194
  else
149
195
  next
150
196
  end
151
- m << flag if val[n + 2] == 'm'
197
+ m << flag if flag.size == 1 && val[n + 2] == 'm'
152
198
  bare << flag if val.end_with?('?')
153
199
  else
154
200
  bare << val
@@ -156,6 +202,22 @@ module Squared
156
202
  end
157
203
  no = (no || []).map { |val| (n = val.index('=')) ? val[0, n] : val }
158
204
  bare.concat(no)
205
+ if underscore
206
+ tr = ->(list) { list.map { |val| val.tr('-', '_') } }
207
+ @values.concat(tr.call(@values))
208
+ bare.concat(tr.call(bare))
209
+ e.concat(tr.call(e))
210
+ b.concat(tr.call(b))
211
+ m.concat(tr.call(m))
212
+ p.concat(tr.call(p))
213
+ q.concat(tr.call(q))
214
+ qq.concat(tr.call(qq))
215
+ i.concat(tr.call(i))
216
+ f.concat(tr.call(f))
217
+ si.concat(tr.call(si))
218
+ bl.concat(tr.call(bl))
219
+ no.concat(tr.call(no))
220
+ end
159
221
  numtype = [
160
222
  [i, /\A\d+\z/],
161
223
  [f, /\A\d*(?:\.\d+)?\z/],
@@ -171,7 +233,7 @@ module Squared
171
233
  add "-#{opt}"
172
234
  elsif bare.include?(opt)
173
235
  add(opt.size == 1 ? "-#{opt}" : "--#{opt}")
174
- elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
236
+ elsif opt.match?(/\Ano[-_]/) && no.include?(name = opt[3..-1])
175
237
  add "--no-#{name}"
176
238
  else
177
239
  if opt =~ OPT_VALUE
@@ -182,8 +244,14 @@ module Squared
182
244
  add shell_option(key, val, merge: merge)
183
245
  elsif q.include?(key)
184
246
  add quote_option(key, val, double: qq.include?(key), merge: merge)
185
- elsif p.include?(key) && path
186
- add quote_option(key, path + val, merge: merge)
247
+ elsif p.include?(key)
248
+ if val.match?(/\A(["']).+\1\z/)
249
+ add shell_option(key, val, escape: false, merge: merge, sep: sep)
250
+ elsif path
251
+ add quote_option(key, path + val, merge: merge, sep: sep)
252
+ else
253
+ push opt
254
+ end
187
255
  elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
188
256
  add basic_option(key, val, merge: merge)
189
257
  elsif merge
@@ -219,57 +287,86 @@ module Squared
219
287
  self
220
288
  end
221
289
 
290
+ def append_any(*args, **kwargs)
291
+ (args.empty? ? extras : args.flatten).each do |val|
292
+ if exist?(val)
293
+ add_path(val, **kwargs)
294
+ else
295
+ add_quote(val, **kwargs)
296
+ end
297
+ end
298
+ self
299
+ end
300
+
222
301
  def uniq(list)
223
- items = map { |val| nameonly(val) }
302
+ ignore = map { |val| nameonly(val) }
224
303
  list.reject do |val|
225
- next true if items.include?(s = nameonly(val))
304
+ next true if ignore.include?(s = nameonly(val))
226
305
 
227
- pat = /\A#{s = fill_option(s)}(?:#{s.start_with?('--') ? '[= ]' : '.*'}|\z)/
306
+ pat = OptionPartition.send(:matchopt, s)
228
307
  any? { |opt| opt.match?(pat) }
229
308
  end
230
309
  end
231
310
 
232
- def uniq!(list)
233
- n = size
234
- concat uniq(list)
235
- extras if size > n
236
- end
237
-
238
311
  def clear(opts = nil, errors: false, **kwargs)
239
312
  styles = project.theme[:inline] if project
240
- if !opts
241
- opts = errors ? @errors : @extras
242
- elsif errors
243
- OptionPartition.clear(target, @errors, styles: styles, **kwargs)
244
- @errors.clear
313
+ if errors
314
+ OptionPartition.clear(target, self.errors, styles: styles, **kwargs)
315
+ self.errors.clear
316
+ return self unless opts
245
317
  end
246
- OptionPartition.clear(target, opts.reject { |val| found.include?(val) }, styles: styles, **kwargs)
318
+ opts ||= extras
319
+ OptionPartition.clear(target, if found.empty?
320
+ opts
321
+ else
322
+ opts.reject { |val| found.include?(val) }
323
+ end, styles: styles, **kwargs)
247
324
  opts.clear
248
325
  self
249
326
  end
250
327
 
251
- def adjoin(*args, start: false)
328
+ def adjoin(*args, with: nil, start: false)
252
329
  i = -1
253
- (items = to_a).each_with_index do |val, index|
254
- if i == 0
255
- next unless val.start_with?('-')
256
-
257
- i = index
258
- break
259
- elsif index > 0 && !val.start_with?('-')
260
- if start
330
+ temp = to_a
331
+ if with
332
+ pat = case with
333
+ when String, Symbol
334
+ /\A#{Regexp.escape(with)}\z/
335
+ when Array
336
+ OptionPartition.send(:matchopts, with)
337
+ else
338
+ with
339
+ end
340
+ temp.each_with_index do |val, index|
341
+ if val.to_s.match?(pat)
261
342
  i = index + (start.is_a?(Numeric) ? start : 1)
262
343
  break
263
344
  end
264
- i = 0
345
+ end
346
+ else
347
+ temp.each_with_index do |val, index|
348
+ if i == 0
349
+ next unless val.start_with?('-')
350
+
351
+ i = index
352
+ break
353
+ elsif index > 0 && !val.start_with?('-')
354
+ if start
355
+ i = index + (start.is_a?(Numeric) ? start : 1)
356
+ break
357
+ end
358
+ i = 0
359
+ end
265
360
  end
266
361
  end
267
362
  if i > 0
268
363
  if args.empty?
269
364
  args = dup
270
365
  reset
366
+ else
367
+ args.each { |val| remove val }
271
368
  end
272
- args = items[0...i] + args + items[i..-1]
369
+ args = temp[0...i] + args + temp[i..-1]
273
370
  target.clear
274
371
  end
275
372
  merge args
@@ -282,7 +379,7 @@ module Squared
282
379
  end
283
380
 
284
381
  def add_quote(*args, **kwargs)
285
- merge(args.map { |val| shell_quote(val, **kwargs) })
382
+ merge(args.map! { |val| shell_quote(val, **kwargs) })
286
383
  self
287
384
  end
288
385
 
@@ -305,7 +402,8 @@ module Squared
305
402
  if path
306
403
  found.each { |val| add_path(val) }
307
404
  else
308
- merge(quote ? found.map! { |val| shell_quote(val) } : found)
405
+ found.map! { |val| shell_quote(val) } if quote
406
+ merge found
309
407
  end
310
408
  end
311
409
  self
@@ -313,6 +411,7 @@ module Squared
313
411
 
314
412
  def reset(errors: false)
315
413
  extras.clear
414
+ found.clear
316
415
  clear(errors: true) if errors
317
416
  self
318
417
  end
@@ -339,6 +438,39 @@ module Squared
339
438
  OptionPartition.arg?(target, *args, **kwargs)
340
439
  end
341
440
 
441
+ def exist?(*args, add: false, first: false, last: false)
442
+ return false unless path
443
+ return path.join(*args).exist? unless args.empty?
444
+
445
+ if first || last
446
+ return false unless (val = first ? self.first : self.last).is_a?(String)
447
+
448
+ path.join(val).exist?.tap do |ret|
449
+ next unless add && ret
450
+
451
+ add_path(first ? shift : pop)
452
+ end
453
+ else
454
+ each_with_index do |val, index|
455
+ next unless val.is_a?(String) && path.join(val).exist?
456
+
457
+ if add
458
+ remove_at index
459
+ add_path val
460
+ end
461
+ return true
462
+ end
463
+ false
464
+ end
465
+ end
466
+
467
+ def uniq!(list)
468
+ unless (list = uniq(list)).empty?
469
+ concat list
470
+ self
471
+ end
472
+ end
473
+
342
474
  private
343
475
 
344
476
  def nameonly(val)
@@ -49,11 +49,7 @@ module Squared
49
49
 
50
50
  def base_set(obj)
51
51
  TASK_BASE.clear
52
- .concat((if TASK_KEYS.empty?
53
- obj.tasks
54
- else
55
- obj.tasks.reject { |val| TASK_KEYS.include?(val) }
56
- end).freeze)
52
+ TASK_BASE.concat(obj.tasks.reject { |val| TASK_KEYS.include?(val) })
57
53
  end
58
54
 
59
55
  private
@@ -210,27 +206,25 @@ module Squared
210
206
 
211
207
  def chain?(val)
212
208
  @chain.each_value do |tasks|
213
- tasks.flatten(1).each do |task|
214
- next unless Rake::Task[task].already_invoked
209
+ tasks.flatten(1).each do |name|
210
+ next unless (task = invoked_get(name))
215
211
 
216
- if val == task || Rake::Task[task].prerequisites.any? { |pr| pr == val && Rake::Task[val].already_invoked }
217
- return true
218
- end
212
+ return true if name == val || task.prerequisites.any? { |pr| pr == val && Rake::Task[pr].already_invoked }
219
213
  end
220
214
  end
221
215
  false
222
216
  end
223
217
 
224
218
  def multiple?(val = nil)
225
- already_invoked?(multiple, val)
219
+ already_invoked? multiple, val
226
220
  end
227
221
 
228
222
  def sync?(val = nil)
229
- already_invoked?(sync, val)
223
+ already_invoked? sync, val
230
224
  end
231
225
 
232
226
  def parallel?(val = nil)
233
- already_invoked?(parallel, val)
227
+ already_invoked? parallel, val
234
228
  end
235
229
 
236
230
  def exclude?(key, empty = false)
@@ -239,12 +233,16 @@ module Squared
239
233
 
240
234
  private
241
235
 
236
+ def invoked_get(name)
237
+ return unless Rake::Task.task_defined?(name) && (ret = Rake::Task[name]).already_invoked
238
+
239
+ ret
240
+ end
241
+
242
242
  def already_invoked?(list, val)
243
- if val
244
- list.include?(val) && Rake::Task[val].already_invoked
245
- else
246
- Rake::Task.tasks.any? { |obj| obj.already_invoked && list.include?(obj.name) }
247
- end
243
+ return Rake::Task.tasks.any? { |obj| obj.already_invoked && list.include?(obj.name) } unless val
244
+
245
+ list.include?(val) && !invoked_get(val).nil?
248
246
  end
249
247
  end
250
248
 
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.4.20
4
+ version: 0.4.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
127
  requirements: []
128
- rubygems_version: 3.6.9
128
+ rubygems_version: 3.7.2
129
129
  specification_version: 4
130
130
  summary: Rake task generator for managing multi-language workspaces.
131
131
  test_files: []