squared 0.4.36 → 0.5.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,36 +10,16 @@ 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
17
-
18
13
  class << self
19
14
  include Common::Format
20
15
  include Shell
21
16
  include Prompt
22
17
 
23
- def append(target, *args, delim: false, escape: false, quote: true, strip: nil, force: true, double: false,
24
- **)
18
+ def append(target, *args, delim: false, escape: false, quote: true, **)
25
19
  return if (ret = args.flatten).empty?
26
20
 
27
21
  target << '--' if delim && !target.include?('--')
28
- if strip
29
- pat, s = Array(strip)
30
- ret.map! { |val| val.is_a?(String) ? val.gsub(pat, s || '') : val }
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
41
- end
42
- end
22
+ ret.map! { |val| escape ? shell_escape(val, quote: quote) : shell_quote(val) } if escape || quote
43
23
  if target.is_a?(Set)
44
24
  target.merge(ret)
45
25
  else
@@ -55,95 +35,35 @@ module Squared
55
35
  kwargs[:hint] ||= 'unrecognized'
56
36
  append(target, opts, delim: true) if kwargs.delete(:append)
57
37
  warn log_message(Logger::WARN, opts.join(', '), pass: true, **kwargs)
58
- exit 1 unless pass || confirm("Run? [#{sub_style(target, styles: styles)}] [y/N] ", 'N')
59
- end
60
-
61
- def delete_key(target, *args, value: false, reverse: false, count: -1)
62
- ret = []
63
- args.each do |val|
64
- next if (opts = target.grep(matchopt(val, value))).empty?
38
+ return if pass || confirm("Run? [#{sub_style(target, styles: styles)}] [y/N] ", 'N')
65
39
 
66
- opts = opts.first(count) if count >= 0
67
- opts.send(reverse ? :reverse_each : :each) { |key| target.delete(key) }
68
- ret.concat(opts)
69
- end
70
- ret
40
+ raise_error 'user cancelled'
71
41
  end
72
42
 
73
43
  def strip(val)
74
44
  return [] unless val
75
45
 
76
- val = shell_split val if val.is_a?(String)
77
- val.map { |s| s.sub(OPT_SINGLE, '\1=\2').sub(OPT_VALUE, '\1=\2').sub(OPT_NAME, '\2') }.reject(&:empty?)
78
- end
79
-
80
- def select(list, bare: true, no: true, single: false, double: false)
81
- ret = bare ? list.grep_v(/=/) : list.grep(/=/).map! { |val| val.split('=', 2).first }
82
- ret.map! { |val| val.split('|', 2).last }
83
- ret = ret.grep_v(/\Ano-/) unless no
84
- return ret if single == double
85
-
86
- ret.select { |val| single ? val.size == 1 : val.size > 1 }
46
+ val = shell_split(val) if val.is_a?(String)
47
+ val.map { |s| s.sub(/\A-([a-z\d])(.+)\z/i, '\1=\2').sub(/\A--?/, '') }.reject(&:empty?)
87
48
  end
88
49
 
89
50
  def arg?(target, *args, value: false, **)
90
51
  r, s = args.partition { |val| val.is_a?(Regexp) }
91
- r << matchopts(s, value) unless s.empty?
92
- a = target.to_a.compact
93
- if (n = a.index('--'))
94
- a = a[0..n]
52
+ unless s.empty?
53
+ s.map! { |val| Regexp.escape(val.start_with?('-') ? val : shell_option(val)) }
54
+ r << /\A(?:#{s.join('|')})#{value ? '[ =].' : '(?: |=|\z)'}/
95
55
  end
96
- a.any? { |val| r.any? { |pat| pat.match?(val.to_s) } }
97
- end
98
-
99
- def opt?(val)
100
- return false unless val.is_a?(String)
101
-
102
- val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
103
- end
104
-
105
- def pattern?(val)
106
- val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*})/)
107
- end
108
-
109
- private
110
-
111
- def matchopt(val, value = false)
112
- /\A#{val.size == 1 ? shortopt(val) : longopt(val, value)}/
113
- end
114
-
115
- def matchopts(list, value = false)
116
- a, b = Array(list).partition { |val| val.size == 1 || val.match?(OPT_SINGLE) }
117
- return /\A#{shortopt(*a)}/ if b.empty?
118
- return /\A#{longopt(*b, value)}/ if a.empty?
119
-
120
- /\A(?:#{shortopt(*a)}|#{longopt(*b, value)})/
121
- end
122
-
123
- def shortopt(*group)
124
- group.map! { |s| Regexp.escape(s.sub(/\A-/, '')) }
125
- "-(?:#{Regexp.escape(group.join('|'))})(?:\\z|[^ =]| +[^ -])"
126
- end
127
-
128
- def longopt(*group, value)
129
- group.map! { |s| Regexp.escape(s.sub(/\A--/, '')) }
130
- "--(?:#{Regexp.escape(group.join('|'))})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
56
+ s = target.to_a.compact
57
+ r.any? { |pat| s.any?(pat) }
131
58
  end
132
59
  end
133
60
 
134
61
  attr_reader :target, :extras, :found, :errors, :values, :project, :path
135
62
 
136
63
  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, :last, :shift, :unshift, :pop, :push, :concat, :index, :join, :map, :map!, :detect,
140
- :select, :select!, :reject, :size
141
-
142
- def_delegator :@extras, :delete, :remove
143
- def_delegator :@extras, :delete_at, :remove_at
144
- def_delegator :@extras, :delete_if, :remove_if
145
- def_delegator :@extras, :find_all, :detect_all
146
- def_delegator :@extras, :find_index, :detect_index
64
+ :merge, :delete, :delete?, :delete_if, :grep, :inspect, :to_a, :to_s
65
+ def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :last, :shift, :unshift,
66
+ :pop, :push, :join, :map, :map!, :select, :reject, :size
147
67
 
148
68
  def initialize(opts, list, target = Set.new, project: nil, path: nil, **kwargs, &blk)
149
69
  @target = target.is_a?(Set) ? target : target.to_set
@@ -154,7 +74,7 @@ module Squared
154
74
  parse(list, opts, **kwargs, &blk)
155
75
  end
156
76
 
157
- def parse(list, opts = extras, no: nil, single: nil, args: false, first: nil, underscore: nil, &blk)
77
+ def parse(list, opts = extras, no: nil, single: nil, args: false, first: nil, &blk)
158
78
  @extras = []
159
79
  @values = []
160
80
  bare = []
@@ -167,7 +87,6 @@ module Squared
167
87
  i = []
168
88
  f = []
169
89
  si = []
170
- bl = []
171
90
  list.flat_map do |val|
172
91
  x, y = val.split('|', 2)
173
92
  if y
@@ -202,12 +121,10 @@ module Squared
202
121
  si << flag
203
122
  when 'v'
204
123
  @values << Regexp.escape(flag)
205
- when '!'
206
- bl << flag
207
124
  else
208
125
  next
209
126
  end
210
- m << flag if flag.size == 1 && val[n + 2] == 'm'
127
+ m << flag if val[n + 2] == 'm'
211
128
  bare << flag if val.end_with?('?')
212
129
  else
213
130
  bare << val
@@ -215,22 +132,6 @@ module Squared
215
132
  end
216
133
  no = (no || []).map { |val| (n = val.index('=')) ? val[0, n] : val }
217
134
  bare.concat(no)
218
- if underscore
219
- tr = ->(list) { list.map { |val| val.tr('-', '_') } }
220
- @values.concat(tr.call(@values))
221
- bare.concat(tr.call(bare))
222
- e.concat(tr.call(e))
223
- b.concat(tr.call(b))
224
- m.concat(tr.call(m))
225
- p.concat(tr.call(p))
226
- q.concat(tr.call(q))
227
- qq.concat(tr.call(qq))
228
- i.concat(tr.call(i))
229
- f.concat(tr.call(f))
230
- si.concat(tr.call(si))
231
- bl.concat(tr.call(bl))
232
- no.concat(tr.call(no))
233
- end
234
135
  numtype = [
235
136
  [i, /\A\d+\z/],
236
137
  [f, /\A\d*(?:\.\d+)?\z/],
@@ -239,42 +140,35 @@ module Squared
239
140
  numcheck = ->(k, v) { numtype.any? { |flag, pat| flag.include?(k) && pat.match?(v) } }
240
141
  skip = false
241
142
  opts.each do |opt|
242
- next skip = true if opt == '--'
243
- next push opt if skip
143
+ next @extras << opt if skip
244
144
 
245
145
  if single&.match?(opt)
246
- add "-#{opt}"
146
+ target << "-#{opt}"
247
147
  elsif bare.include?(opt)
248
- add(opt.size == 1 ? "-#{opt}" : "--#{opt}")
249
- elsif opt.match?(/\Ano[-_]/) && no.include?(name = opt[3..-1])
250
- add "--no-#{name}"
148
+ target << (opt.size == 1 ? "-#{opt}" : "--#{opt}")
149
+ elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
150
+ target << "--no-#{name}"
251
151
  else
252
- if opt =~ OPT_VALUE
152
+ if opt =~ /\A([^=]+)=(.+)\z/
253
153
  key = $1
254
154
  val = $2
255
155
  merge = m.include?(key)
256
156
  if e.include?(key)
257
- add shell_option(key, val, merge: merge)
157
+ target << shell_option(key, val, merge: merge)
258
158
  elsif q.include?(key)
259
- add quote_option(key, val, double: qq.include?(key), merge: merge)
260
- elsif p.include?(key)
261
- if val.match?(/\A(["']).+\1\z/)
262
- add shell_option(key, val, escape: false, merge: merge)
263
- elsif path
264
- add quote_option(key, path + val, merge: merge)
265
- else
266
- push opt
267
- end
268
- elsif b.include?(key) || (bl.include?(key) && %w[true false].include?(val)) || numcheck.call(key, val)
269
- add basic_option(key, val, merge: merge)
159
+ target << quote_option(key, val, double: qq.include?(key), merge: merge)
160
+ elsif p.include?(key) && path
161
+ target << quote_option(key, path + val, merge: merge)
162
+ elsif b.include?(key) || numcheck.call(key, val)
163
+ target << basic_option(key, val, merge: merge)
270
164
  elsif merge
271
- add basic_option(key, val, merge: true)
165
+ target << basic_option(key, val, merge: true)
272
166
  else
273
- push opt
167
+ @extras << opt
274
168
  end
275
169
  opt = key
276
170
  else
277
- push opt
171
+ @extras << opt
278
172
  skip = true if args
279
173
  end
280
174
  skip = true if first&.any? { |s| s.is_a?(Regexp) ? opt.match?(s) : !opt.include?(s) }
@@ -295,214 +189,99 @@ module Squared
295
189
  end
296
190
 
297
191
  def append(*args, **kwargs)
298
- args = extras if args.empty?
299
- OptionPartition.append(target, *args, **kwargs)
192
+ OptionPartition.append(target, *(args.empty? ? extras : args), **kwargs)
300
193
  self
301
194
  end
302
195
 
303
- def append_any(*args, escape: false, **kwargs)
304
- quote = kwargs.fetch(:quote, true)
305
- (args.empty? ? extras : args.flatten).each do |val|
306
- if exist?(val)
307
- add_path(val, **kwargs)
308
- elsif escape
309
- add shell_escape(val, **kwargs)
310
- elsif quote
311
- add_quote(val, **kwargs)
312
- else
313
- add val
314
- end
315
- found << val if args.empty?
316
- end
317
- self
318
- end
319
-
320
- def uniq(list)
321
- ignore = map { |val| nameonly(val) }
322
- list.reject do |val|
323
- next true if ignore.include?(s = nameonly(val))
324
-
325
- pat = OptionPartition.send(:matchopt, s)
326
- any? { |opt| opt.match?(pat) }
327
- end
328
- end
329
-
330
196
  def clear(opts = nil, errors: false, **kwargs)
331
197
  styles = project.theme[:inline] if project
332
- if errors
333
- OptionPartition.clear(target, self.errors, styles: styles, **kwargs)
334
- self.errors.clear
335
- return self unless opts
198
+ if !opts
199
+ opts = errors ? @errors : @extras
200
+ elsif errors
201
+ OptionPartition.clear(target, @errors, styles: styles, **kwargs)
202
+ @errors.clear
336
203
  end
337
- opts ||= extras
338
- OptionPartition.clear(target, if found.empty?
339
- opts
340
- else
341
- opts.reject { |val| found.include?(val) }
342
- end, styles: styles, **kwargs)
204
+ OptionPartition.clear(target, opts.reject { |val| found.include?(val) }, styles: styles, **kwargs)
343
205
  opts.clear
344
206
  self
345
207
  end
346
208
 
347
- def adjoin(*args, with: nil, start: false)
348
- i = -1
349
- temp = compact
350
- if with
351
- pat = case with
352
- when String, Symbol
353
- /\A#{Regexp.escape(with)}\z/
354
- when Array
355
- OptionPartition.send(:matchopts, with)
356
- else
357
- with
358
- end
359
- temp.each_with_index do |val, index|
360
- if val.to_s.match?(pat)
361
- i = index + (start.is_a?(Numeric) ? start : 1)
362
- break
363
- end
364
- end
365
- else
366
- temp.each_with_index do |val, index|
367
- if i == 0
368
- next unless val.is_a?(String) && val.start_with?('-')
369
-
370
- i = index
371
- break
372
- elsif index > 0 && !val.to_s.start_with?('-')
373
- if start
374
- i = index + (start.is_a?(Numeric) ? start : 1)
375
- break
376
- end
377
- i = 0
378
- end
379
- end
380
- end
381
- if i > 0
382
- if args.empty?
383
- args = dup
384
- reset
385
- else
386
- args.each { |val| remove val }
387
- end
388
- args = temp[0...i] + args + temp[i..-1]
389
- target.clear
390
- end
391
- merge args
392
- self
209
+ def arg?(*args, **kwargs)
210
+ OptionPartition.arg?(target, *args, **kwargs)
393
211
  end
212
+ end
394
213
 
395
- def add_path(*args, **kwargs)
396
- add shell_quote(path ? path.join(*args) : File.join(*args), option: false, **kwargs)
397
- self
214
+ class JoinSet < Set
215
+ def self.to_s
216
+ super[/[^:]+\z/, 0]
398
217
  end
399
218
 
400
- def add_quote(*args, **kwargs)
401
- kwargs.delete(:quote)
402
- args.compact!
403
- merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
404
- self
219
+ attr_reader :delim
220
+
221
+ def initialize(data = [], delim: ' ')
222
+ super(data.compact)
223
+ @delim = delim
405
224
  end
406
225
 
407
- def delim
408
- add '--'
409
- self
226
+ def last(val, pat)
227
+ (@last ||= []).append([val, pat, $1]) if val =~ pat
228
+ self << val
410
229
  end
411
230
 
412
- def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
413
- temp, other = if block_given?
414
- partition(&blk)
415
- elsif exclude.first.is_a?(Symbol)
416
- partition(&exclude.first)
417
- else
418
- exclude.map! { |pat| Regexp.new(pat) }
419
- partition do |val|
420
- val = val.to_s
421
- next if pattern && OptionPartition.pattern?(val)
422
-
423
- exclude.none? { |pat| val.match?(pat) }
424
- end
425
- end
426
- unless temp.empty?
427
- add '--' if delim
428
- extras.clear
429
- concat other
430
- if path
431
- temp.each { |val| add_path(val) }
432
- else
433
- temp.map! { |val| shell_quote(val) } if quote
434
- merge temp
231
+ def pass(&blk)
232
+ ret = to_a.map!(&:to_s).reject(&:empty?)
233
+ @last&.each do |val, pat, key|
234
+ i = []
235
+ j = nil
236
+ ret.each_with_index do |opt, index|
237
+ if opt == val
238
+ j = index
239
+ elsif j && opt[pat, 1] == key
240
+ i << index
241
+ end
242
+ end
243
+ next unless j && !i.empty?
244
+
245
+ val = ret[j]
246
+ cur = j
247
+ i.each do |k|
248
+ ret[cur] = ret[k]
249
+ cur = k
435
250
  end
251
+ ret[i.last] = val
436
252
  end
437
- self
253
+ block_given? ? ret.reject(&blk) : ret
438
254
  end
439
255
 
440
- def reset(errors: false)
441
- extras.clear
442
- found.clear
443
- clear(errors: true) if errors
444
- self
256
+ def and(*args)
257
+ self << '&&'
258
+ merge args
445
259
  end
446
260
 
447
- def append?(key, val = nil, type: nil, force: false, **kwargs)
448
- return false unless force || !arg?(key)
449
-
450
- val = yield self if block_given?
451
- return false unless val
452
-
453
- type ||= :quote if kwargs.empty?
454
- add case type
455
- when :quote
456
- quote_option(key, val)
457
- when :basic
458
- basic_option(key, val)
459
- else
460
- shell_option(key, val, **kwargs)
461
- end
462
- true
261
+ def or(*args)
262
+ self << '||'
263
+ merge args
463
264
  end
464
265
 
465
- def arg?(*args, **kwargs)
466
- OptionPartition.arg?(target, *args, **kwargs)
266
+ def with(*args, &blk)
267
+ temp('&&', *args, &blk)
467
268
  end
468
269
 
469
- def exist?(*args, add: false, first: false, last: false)
470
- return false unless path
471
- return path.join(*args).exist? unless args.empty?
472
-
473
- if first || last
474
- return false unless (val = first ? self.first : self.last).is_a?(String)
475
-
476
- path.join(val).exist?.tap do |ret|
477
- next unless add && ret
478
-
479
- add_path(first ? shift : pop)
480
- end
481
- else
482
- each_with_index do |val, index|
483
- next unless val.is_a?(String) && path.join(val).exist?
484
-
485
- if add
486
- remove_at index
487
- add_path val
488
- end
489
- return true
490
- end
491
- false
492
- end
270
+ def temp(*args, &blk)
271
+ args.compact!
272
+ ret = pass(&blk)
273
+ ret = Set.new(ret.concat(args)).to_a unless args.empty?
274
+ ret.join(@delim)
493
275
  end
494
276
 
495
- def uniq!(list)
496
- unless (list = uniq(list)).empty?
497
- concat list
498
- self
499
- end
277
+ def done
278
+ ret = to_s
279
+ clear
280
+ ret
500
281
  end
501
282
 
502
- private
503
-
504
- def nameonly(val)
505
- val[OPT_VALUE, 1] || val
283
+ def to_s
284
+ pass.join(@delim)
506
285
  end
507
286
  end
508
287
  end
@@ -3,16 +3,6 @@
3
3
  module Squared
4
4
  module Workspace
5
5
  module Project
6
- class << self
7
- attr_accessor :line_width
8
-
9
- def max_width(lines)
10
- n = [lines.empty? ? 0 : lines.max_by(&:size).size, 80].max
11
- [n, Rake.application.terminal_width].min
12
- end
13
- end
14
-
15
- @line_width = ENV.fetch('LOG_COLUMNS', 80).to_i
16
6
  end
17
7
  end
18
8
  end