squared 0.4.35 → 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 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
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,208 +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, quote: true, **kwargs)
304
- (args.empty? ? extras : args.flatten).each do |val|
305
- if exist?(val)
306
- add_path(val, **kwargs)
307
- elsif quote
308
- add_quote(val, **kwargs)
309
- else
310
- add val
311
- end
312
- found << val if args.empty?
313
- end
314
- self
315
- end
316
-
317
- def uniq(list)
318
- ignore = map { |val| nameonly(val) }
319
- list.reject do |val|
320
- next true if ignore.include?(s = nameonly(val))
321
-
322
- pat = OptionPartition.send(:matchopt, s)
323
- any? { |opt| opt.match?(pat) }
324
- end
325
- end
326
-
327
196
  def clear(opts = nil, errors: false, **kwargs)
328
197
  styles = project.theme[:inline] if project
329
- if errors
330
- OptionPartition.clear(target, self.errors, styles: styles, **kwargs)
331
- self.errors.clear
332
- 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
333
203
  end
334
- opts ||= extras
335
- OptionPartition.clear(target, if found.empty?
336
- opts
337
- else
338
- opts.reject { |val| found.include?(val) }
339
- end, styles: styles, **kwargs)
204
+ OptionPartition.clear(target, opts.reject { |val| found.include?(val) }, styles: styles, **kwargs)
340
205
  opts.clear
341
206
  self
342
207
  end
343
208
 
344
- def adjoin(*args, with: nil, start: false)
345
- i = -1
346
- temp = compact
347
- if with
348
- pat = case with
349
- when String, Symbol
350
- /\A#{Regexp.escape(with)}\z/
351
- when Array
352
- OptionPartition.send(:matchopts, with)
353
- else
354
- with
355
- end
356
- temp.each_with_index do |val, index|
357
- if val.to_s.match?(pat)
358
- i = index + (start.is_a?(Numeric) ? start : 1)
359
- break
360
- end
361
- end
362
- else
363
- temp.each_with_index do |val, index|
364
- if i == 0
365
- next unless val.is_a?(String) && val.start_with?('-')
366
-
367
- i = index
368
- break
369
- elsif index > 0 && !val.to_s.start_with?('-')
370
- if start
371
- i = index + (start.is_a?(Numeric) ? start : 1)
372
- break
373
- end
374
- i = 0
375
- end
376
- end
377
- end
378
- if i > 0
379
- if args.empty?
380
- args = dup
381
- reset
382
- else
383
- args.each { |val| remove val }
384
- end
385
- args = temp[0...i] + args + temp[i..-1]
386
- target.clear
387
- end
388
- merge args
389
- self
209
+ def arg?(*args, **kwargs)
210
+ OptionPartition.arg?(target, *args, **kwargs)
390
211
  end
212
+ end
391
213
 
392
- def add_path(*args, **kwargs)
393
- add shell_quote(path ? path.join(*args) : File.join(*args), option: false, **kwargs)
394
- self
214
+ class JoinSet < Set
215
+ def self.to_s
216
+ super[/[^:]+\z/, 0]
395
217
  end
396
218
 
397
- def add_quote(*args, **kwargs)
398
- args.compact!
399
- merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
400
- self
219
+ attr_reader :delim
220
+
221
+ def initialize(data = [], delim: ' ')
222
+ super(data.compact)
223
+ @delim = delim
401
224
  end
402
225
 
403
- def delim
404
- add '--'
405
- self
226
+ def last(val, pat)
227
+ (@last ||= []).append([val, pat, $1]) if val =~ pat
228
+ self << val
406
229
  end
407
230
 
408
- def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
409
- temp, other = if block_given?
410
- partition(&blk)
411
- elsif exclude.first.is_a?(Symbol)
412
- partition(&exclude.first)
413
- else
414
- partition do |val|
415
- next false if pattern && OptionPartition.pattern?(val)
416
-
417
- exclude.none? { |pat| val.match?(Regexp.new(pat)) }
418
- end
419
- end
420
- unless temp.empty?
421
- add '--' if delim
422
- extras.clear
423
- concat other
424
- if path
425
- temp.each { |val| add_path(val) }
426
- else
427
- temp.map! { |val| shell_quote(val) } if quote
428
- 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
429
250
  end
251
+ ret[i.last] = val
430
252
  end
431
- self
253
+ block_given? ? ret.reject(&blk) : ret
432
254
  end
433
255
 
434
- def reset(errors: false)
435
- extras.clear
436
- found.clear
437
- clear(errors: true) if errors
438
- self
256
+ def and(*args)
257
+ self << '&&'
258
+ merge args
439
259
  end
440
260
 
441
- def append?(key, val = nil, type: nil, force: false, **kwargs)
442
- return false unless force || !arg?(key)
443
-
444
- val = yield self if block_given?
445
- return false unless val
446
-
447
- type ||= :quote if kwargs.empty?
448
- add case type
449
- when :quote
450
- quote_option(key, val)
451
- when :basic
452
- basic_option(key, val)
453
- else
454
- shell_option(key, val, **kwargs)
455
- end
456
- true
261
+ def or(*args)
262
+ self << '||'
263
+ merge args
457
264
  end
458
265
 
459
- def arg?(*args, **kwargs)
460
- OptionPartition.arg?(target, *args, **kwargs)
266
+ def with(*args, &blk)
267
+ temp('&&', *args, &blk)
461
268
  end
462
269
 
463
- def exist?(*args, add: false, first: false, last: false)
464
- return false unless path
465
- return path.join(*args).exist? unless args.empty?
466
-
467
- if first || last
468
- return false unless (val = first ? self.first : self.last).is_a?(String)
469
-
470
- path.join(val).exist?.tap do |ret|
471
- next unless add && ret
472
-
473
- add_path(first ? shift : pop)
474
- end
475
- else
476
- each_with_index do |val, index|
477
- next unless val.is_a?(String) && path.join(val).exist?
478
-
479
- if add
480
- remove_at index
481
- add_path val
482
- end
483
- return true
484
- end
485
- false
486
- 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)
487
275
  end
488
276
 
489
- def uniq!(list)
490
- unless (list = uniq(list)).empty?
491
- concat list
492
- self
493
- end
277
+ def done
278
+ ret = to_s
279
+ clear
280
+ ret
494
281
  end
495
282
 
496
- private
497
-
498
- def nameonly(val)
499
- val[OPT_VALUE, 1] || val
283
+ def to_s
284
+ pass.join(@delim)
500
285
  end
501
286
  end
502
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