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