squared 0.4.7 → 0.4.9

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.
@@ -7,20 +7,23 @@ module Squared
7
7
  GEMFILE = %w[Gemfile Gemfile.lock gem.deps.rb Isolate].freeze
8
8
  DIR_RUBY = (GEMFILE + Rake::Application::DEFAULT_RAKEFILES + ['README.rdoc']).freeze
9
9
  OPT_RUBY = {
10
+ ruby: %w[0=im? a c e=q E=bm F=qm i=bm? I=pm l n p r=bm s S w W=bm? x=pm? d|debug jit rjit v|verbose y|yydebug
11
+ backtrace-limit=i crash-report=q disable=q dump=q enable=q encoding=b external-encoding=b
12
+ internal-encoding=b parser=b].freeze,
10
13
  rake: %w[A|all B|build-all comments n|dry-run p|execute-print=q m|multitask P|prereqs q|quiet
11
14
  X|no-deprecation-warnings N|no-search G|no-system nosearch nosystem rules s|silent g|system
12
- v|verbose backtrace=b? D|describe=q? e|execute=q E|execute-continue=q I|libdir=p job-stats=b?
13
- j|jobs=i? R|rakelib=p rakelibdir=p r|require=b suppress-backtrace=q T|tasks=q? t|trace=b?
15
+ v|verbose backtrace=b? D|describe=q? e|execute=q E|execute-continue=q job-stats=b? j|jobs=i?
16
+ I|libdir=p R|rakelib=p rakelibdir=p r|require=b suppress-backtrace=q T|tasks=q? t|trace=b?
14
17
  W|where=q?].freeze,
15
- irb: %w[d f U w E=b I=p r=b W=m? autocomplete colorize echo echo-on-assignment extra-doc-dir inf-ruby-mode
16
- inspect multiline no-pager noautocomplete nocolorize noecho noinspect noecho-on-assignment
18
+ irb: %w[d f U w E=b I=p r=b W=im? autocomplete colorize echo echo-on-assignment extra-doc-dir inf-ruby-mode
19
+ inspect multiline no-pager noautocomplete nocolorize noecho noecho-on-assignment noinspect
17
20
  nomultiline noprompt noscript nosingleline noverbose regexp-completor sample-book-mode script
18
21
  simple-prompt single-irb singleline tracer truncate-echo-on-assignment type-completor verbose
19
22
  back-trace-limit=i context-mode=i prompt=b prompt-mode=b].freeze
20
23
  }.freeze
21
24
  OPT_BUNDLE = {
22
25
  common: %w[no-color V|verbose retry=i].freeze,
23
- install: %w[frozen no-cache no-prune system path=p binstubs=p? standalone=q? target-rbconfig=p trust-policy=b
26
+ install: %w[frozen no-cache no-prune system binstubs=p? path=p standalone=q? target-rbconfig=p trust-policy=b
24
27
  with=q without=q].freeze,
25
28
  install_base: %w[full-index quiet retry gemfile=p j|jobs=i].freeze,
26
29
  update: %w[conservative local pre redownload ruby strict bundler=b? g|group=q source=b].freeze,
@@ -39,18 +42,19 @@ module Squared
39
42
  target-rbconfig=p? P|trust-policy=b without=b].freeze,
40
43
  update: %w[system=b?].freeze,
41
44
  uninstall: %w[a D I x vendor n|bindir=p i|install-dir=p platform=b v|version=b].freeze,
42
- outdated: %w[b|both clear-sources l|local no-http-proxy r|remote B|bulk-threshold=i p|http-proxy=q?
43
- platform=q source=q].freeze,
44
- push: %w[no-http-proxy attestation=p host=q key=b otp=b p|http-proxy=q?].freeze,
45
+ outdated: %w[b|both clear-sources l|local no-http-proxy r|remote B|bulk-threshold=i p|http-proxy=q? platform=q
46
+ source=q].freeze,
47
+ push: %w[no-http-proxy attestation=p host=q p|http-proxy=q? key=b otp=b].freeze,
45
48
  build: %w[force strict o|output=p platform=q].freeze,
46
- exec: %w[conservative prerelease no-prerelease g|gem=v version=b].freeze,
47
- pristine: %w[all env-shebang extensions no-env-shebang no-extensions only-executables only-missing-extensions
48
- only-plugins n|bindir=p i|install-dir=p skip=b v|version=b].freeze,
49
+ exec: %w[conservative no-prerelease prerelease g|gem=v version=b].freeze,
50
+ pristine: %w[all only-executables only-missing-extensions only-plugins n|bindir=p i|install-dir=p skip=b
51
+ v|version=b].freeze,
49
52
  no: {
50
- install: %w[env-shebang force format-executable http-proxy lock minimal-deps post-install-message
51
- prerelease suggestions user-install wrappers].freeze,
53
+ install: %w[env-shebang force format-executable http-proxy lock minimal-deps post-install-message prerelease
54
+ suggestions user-install wrappers].freeze,
52
55
  uninstall: %w[abort-on-dependent all check-development executables force format-executable
53
- ignore-dependencies user-install].freeze
56
+ ignore-dependencies user-install].freeze,
57
+ pristine: %w[env-shebang extensions].freeze
54
58
  }.freeze
55
59
  }.freeze
56
60
  private_constant :GEMFILE, :DIR_RUBY, :OPT_RUBY, :OPT_BUNDLE, :OPT_GEM
@@ -78,6 +82,7 @@ module Squared
78
82
  'update' => %i[patch minor major all].freeze,
79
83
  'outdated' => %i[patch minor major].freeze,
80
84
  'gem' => %i[install uninstall update pristine outdated push build exec].freeze,
85
+ 'ruby' => %i[file script version].freeze,
81
86
  'exec' => nil,
82
87
  'cache' => nil,
83
88
  'config' => nil,
@@ -97,7 +102,7 @@ module Squared
97
102
  end
98
103
  @autodetect = autodetect
99
104
  @dependindex = GEMFILE.index { |file| basepath(file).exist? }
100
- @dependfile = basepath(GEMFILE[@dependindex || 0])
105
+ @dependfile = @path + GEMFILE[@dependindex || 0]
101
106
  return if !@output[0].nil? || !@copy.nil? || @version || @autodetect || (file = rakefile).nil?
102
107
 
103
108
  begin
@@ -124,7 +129,7 @@ module Squared
124
129
  return unless outdated? && ref?(Ruby.ref)
125
130
 
126
131
  namespace name do
127
- @@tasks[Ruby.ref].each do |action, flags|
132
+ Ruby.subtasks do |action, flags|
128
133
  next if @pass.include?(action)
129
134
 
130
135
  if flags.nil?
@@ -156,17 +161,19 @@ module Squared
156
161
  next unless (spec = basepath("#{project}.gemspec") || basepath("#{name}.gemspec"))
157
162
  next unless basepath('lib').join("#{gemname = stripext(spec)}.rb").exist?
158
163
 
159
- format_desc action, nil, 'opts*,args*'
164
+ format_desc action, nil, 'opts*,args*|:'
160
165
  task action do |_, args|
161
- irb gemname, args.to_a
166
+ args = args.to_a
167
+ if args.last == ':'
168
+ args.pop
169
+ load = readline('Enter file and arguments', force: false)
170
+ end
171
+ irb(gemname, args, load: load)
162
172
  end
163
173
  else
164
174
  format_desc(action, nil, OPT_BUNDLE[action.to_sym], after: case action
165
- when 'cache', 'check'
166
- nil
167
- else
168
- 'command+'
169
- end)
175
+ when 'cache', 'check' then nil
176
+ else 'command+' end)
170
177
  task action do |_, args|
171
178
  bundle(action, *args.to_a)
172
179
  end
@@ -182,16 +189,49 @@ module Squared
182
189
  end
183
190
  when 'gem'
184
191
  case flag
185
- when :outdated, :build, :push, :exec
192
+ when :outdated
193
+ format_desc action, flag, 'major|minor|patch|interactive?,opts*'
194
+ task flag, [:semver] do |_, args|
195
+ case (filter = args.semver)
196
+ when 'major', 'minor', 'patch', 'interactive', 'i'
197
+ filter = 'interactive' if filter == 'i'
198
+ args = args.to_a.drop(1)
199
+ else
200
+ filter = nil
201
+ args = args.to_a
202
+ end
203
+ gem!(flag, args, filter: filter)
204
+ end
205
+ when :build, :push, :exec
186
206
  format_desc(action, flag, 'opts*', before: flag == :exec ? 'command+' : nil)
187
207
  task flag do |_, args|
188
- gemx flag, args.to_a
208
+ gem! flag, args.to_a
189
209
  end
190
210
  else
191
211
  format_desc action, flag, "opts*,name+#{flag == :pristine ? '|name?@version' : ''}"
192
212
  task flag do |_, args|
193
- opts = param_guard(action, flag, args: args.to_a)
194
- gemx flag, opts
213
+ args = param_guard(action, flag, args: args.to_a)
214
+ gem! flag, args
215
+ end
216
+ end
217
+ when 'ruby'
218
+ case flag
219
+ when :file
220
+ format_desc action, flag, 'path,opts*,args*'
221
+ task flag, [:rb] do |_, args|
222
+ file = param_guard(action, flag, args: args, key: :rb)
223
+ ruby(flag, args.to_a.drop(1), file: file)
224
+ end
225
+ when :script
226
+ format_desc action, flag, 'RUBY_E?,opts*,args*'
227
+ task flag do |_, args|
228
+ command = ENV['RUBY_E'] || readline('Enter script', force: true)
229
+ ruby(flag, args.to_a, command: command)
230
+ end
231
+ when :version
232
+ format_desc action, flag
233
+ task flag do
234
+ ruby flag
195
235
  end
196
236
  end
197
237
  end
@@ -208,6 +248,7 @@ module Squared
208
248
  elsif outdated?
209
249
  workspace.rev_clear(name)
210
250
  cmd = bundle_session 'install'
251
+ cmd << '--without=development' if prod?
211
252
  if (n = option('jobs')).to_i > 0
212
253
  cmd << "-j#{n}"
213
254
  end
@@ -215,14 +256,18 @@ module Squared
215
256
  end
216
257
  end
217
258
 
218
- def copy(from: 'lib', include: nil, exclude: nil, into: @gemdir, override: false)
259
+ def copy(from: 'lib', into: @gemdir, override: false, **kwargs)
260
+ glob = kwargs[:include]
261
+ pass = kwargs[:exclude]
219
262
  if @copy && !override
220
263
  return super unless @copy.is_a?(Hash)
221
264
 
222
265
  from = @copy[:from] if @copy.key?(:from)
223
266
  glob = @copy[:include] if @copy.key?(:include)
224
- exclude = @copy[:exclude] if @copy.key?(:exclude)
267
+ pass = @copy[:exclude] if @copy.key?(:exclude)
225
268
  into = @copy[:into] if @copy.key?(:into)
269
+ elsif @copy == false
270
+ return
226
271
  end
227
272
  return unless into
228
273
 
@@ -231,12 +276,12 @@ module Squared
231
276
  print_item unless @output[0] || task_invoked?(/^copy(?::#{Ruby.ref}|$)/)
232
277
  glob = as_a(glob || '**/*')
233
278
  as_a(from).each_with_index do |val, i|
234
- a = basepath(val)
235
- b = dest.join(val)
236
- c = glob[i] || glob[0]
237
- log.info "cp #{a.join(c)} #{b}"
279
+ a = path + val
280
+ b = dest + val
281
+ c = glob[i] || glob.first
282
+ log.info "cp #{a + c} #{b}"
238
283
  begin
239
- copy_dir(a, b, c, pass: exclude, verbose: verbose)
284
+ copy_dir(a, b, c, pass: pass, verbose: verbose)
240
285
  rescue StandardError => e
241
286
  log.error e
242
287
  ret = on(:error, :copy, e)
@@ -268,8 +313,8 @@ module Squared
268
313
  data = line.scan(SEM_VER)
269
314
  next unless (cur = data.shift) && (lat = data.shift)
270
315
 
271
- semver(cur)
272
- semver(lat)
316
+ semver cur
317
+ semver lat
273
318
  c = cur.join
274
319
  l = lat.join
275
320
  styles = []
@@ -279,7 +324,7 @@ module Squared
279
324
  end
280
325
  minor_set = -> { styles[0] = cur[2] == lat[2] ? :yellow : :green }
281
326
  if data.empty?
282
- semmajor?(cur, lat) ? major_set.() : minor_set.()
327
+ semmajor?(cur, lat) ? major_set.call : minor_set.call
283
328
  else
284
329
  data.each do |val|
285
330
  break unless line =~ /(>=?|=|~>|!=|<=?) (#{Regexp.escape(val.join)})/
@@ -287,11 +332,11 @@ module Squared
287
332
  v = semver(val).join
288
333
  case $1
289
334
  when '>', '>='
290
- semmajor?(cur, lat) ? major_set.() : minor_set.()
335
+ semmajor?(cur, lat) ? major_set.call : minor_set.call
291
336
  when '<', '<='
292
337
  if c <= v
293
338
  if semmajor?(cur, lat)
294
- major_set.()
339
+ major_set.call
295
340
  else
296
341
  styles[0] = :yellow
297
342
  end
@@ -329,11 +374,11 @@ module Squared
329
374
  index: 2)
330
375
  end
331
376
  end
332
- out.("#{start.to_s.rjust(2)}. #{line}")
377
+ out.call("#{start.to_s.rjust(2)}. #{line}")
333
378
  elsif line.start_with?('Gem')
334
379
  unless stdin?
335
380
  sub = { pat: /^(.+)(?<!\dm)(Gem|Latest)(.+)$/, styles: theme[:header], index: 2 }
336
- out.(print_footer(" # #{line.chomp}", reverse: true, sub: [sub, sub]))
381
+ out.call(print_footer(" # #{line.chomp}", reverse: true, sub: [sub, sub]))
337
382
  end
338
383
  else
339
384
  next
@@ -372,11 +417,100 @@ module Squared
372
417
  def update(flag, opts = [])
373
418
  bundle_session 'update', "--#{flag}"
374
419
  append_bundle(opts, OPT_BUNDLE[:install_base] + OPT_BUNDLE[:update] + OPT_BUNDLE[:common],
375
- append: flag == :all ? nil : /^\w+=/)
420
+ append: flag == :all ? nil : /\A\w+=/)
376
421
  run_rb(from: :update)
377
422
  end
378
423
 
379
- def gemx(flag, opts = [])
424
+ def ruby(flag, opts = [], file: nil, command: nil)
425
+ case flag
426
+ when :file, :script
427
+ op = OptionPartition.new(opts, OPT_RUBY[:ruby], ruby_session, project: self, args: true)
428
+ if file
429
+ op.extras.unshift(shell_quote(path + file))
430
+ elsif command
431
+ op << quote_option('e', command, option: false)
432
+ end
433
+ if (args = ENV['RUBY_ARGS'])
434
+ op.extras << args
435
+ end
436
+ op.append(delim: true, escape: false, quote: false) unless op.empty?
437
+ when :version
438
+ pwd_set do
439
+ out = []
440
+ [
441
+ '$HOME/.rvm/bin/rvm',
442
+ '/usr/local/rvm/bin/rvm',
443
+ '/usr/share/rvm/bin/rvm',
444
+ "#{ENV.fetch('RBENV_ROOT', '$HOME/.rbenv')}/bin/rbenv",
445
+ '/usr/bin/rbenv',
446
+ '/usr/local/share/chruby/chruby.sh',
447
+ "#{ENV.fetch('ASDF_DATA_DIR', '$HOME/.asdf')}/plugins/ruby/bin/install",
448
+ ''
449
+ ].each do |val|
450
+ next unless val.empty? || File.exist?(val.sub('$HOME', Dir.home))
451
+
452
+ trim = ->(s) { s[/\A\D+\d+\.\d+(?:\.\S+)?/, 0].sub(/\A([a-z]+)-/i, '\1 ') }
453
+ ver = '.ruby-version'
454
+ out << trim.call(case (cmd = File.basename(val))
455
+ when 'rvm'
456
+ `rvm current`[/^\S+/, 0]
457
+ when 'rbenv'
458
+ name = `rbenv version-name`
459
+ name =~ SEM_VER ? "ruby #{name}" : name
460
+ when 'chruby.sh'
461
+ chruby = session_output 'source', val
462
+ `#{chruby.with('ruby --version')}`
463
+ when 'install'
464
+ ver = '.tool-versions'
465
+ `asdf current ruby`[/ruby\s+\S+/, 0].sub(/\s+/, ' ')
466
+ else
467
+ ver = nil
468
+ `ruby --version`
469
+ end)
470
+ unless val.empty?
471
+ out << trim.call(case cmd
472
+ when 'chruby.sh'
473
+ `#{chruby.with('chruby --version')}`.sub(':', '')
474
+ when 'install'
475
+ "asdf #{`asdf version`.sub(/^v/, '')}"
476
+ else
477
+ `#{cmd} --version`
478
+ end)
479
+ end
480
+ begin
481
+ out << ('which %s' % case cmd
482
+ when 'rbenv'
483
+ `rbenv which ruby`
484
+ when 'chruby.sh'
485
+ `#{chruby.with('which ruby')}`
486
+ when 'install'
487
+ `asdf which ruby`
488
+ else
489
+ `which ruby`
490
+ end)
491
+ rescue StandardError => e
492
+ log.debug e
493
+ end
494
+ if ver
495
+ path.ascend do |ent|
496
+ next unless (ent += ver).exist?
497
+
498
+ hint = File.read(ent).lines(chomp: true).reject(&:empty?).join(', ') rescue nil
499
+ out << message("found #{ent}", hint: hint)
500
+ end
501
+ end
502
+ break
503
+ end
504
+ out.map!(&:split)
505
+ pad = out.map(&:first).map!(&:size).max
506
+ puts(out.map! { |line| "#{line.first.rjust(pad)} #{line[1..-1].join(' ')}" })
507
+ end
508
+ return
509
+ end
510
+ run_rb(banner: op.arg?('v'), from: :"ruby:#{flag}")
511
+ end
512
+
513
+ def gem!(flag, opts = [], filter: nil)
380
514
  cmd = gem_session
381
515
  case flag
382
516
  when :outdated
@@ -391,21 +525,17 @@ module Squared
391
525
  case flag
392
526
  when :install, :update
393
527
  list.concat(OPT_GEM[:install_base])
394
- no = OPT_GEM[:no][:install]
395
- first = true
396
- when :uninstall
397
- no = OPT_GEM[:no][:uninstall]
398
- first = true
399
- when :pristine
400
- first = true
528
+ first = ['=']
529
+ when :uninstall, :pristine
530
+ first = ['=']
401
531
  end
402
532
  cmd.merge(preopts)
403
- op = OptionPartition.new(opts, list, cmd, project: self, no: no, first: first)
533
+ op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GEM[:no][flag], first: first)
404
534
  op.each do |opt|
405
535
  if opt =~ op.values
406
536
  case $1
407
537
  when 'g', 'gem'
408
- op << (flag == :exec ? shell_option($1, $2) : quote_option($1, basepath($2)))
538
+ op << (flag == :exec ? shell_option($1, $2) : quote_option($1, path + $2))
409
539
  end
410
540
  elsif opt.include?('=') && !%i[outdated build push exec].include?(flag)
411
541
  op.errors << opt
@@ -420,37 +550,38 @@ module Squared
420
550
  op.clear
421
551
  on :first, from
422
552
  print_item format_banner(cmd.to_s)
553
+ major = 0
554
+ minor = 0
555
+ patch = 0
556
+ update = []
423
557
  pwd_set(pass: !pwd.nil?, from: from) do
424
558
  items = [[%w[Gem Current Latest], nil]]
425
559
  IO.popen(cmd.done).each do |line|
426
560
  if line =~ /^(\S+) \((\S+) < ([^)]+)\)$/
427
- cur = semscan($2)
428
- lat = semscan($3)
561
+ cur = semscan $2
562
+ lat = semscan $3
429
563
  items << [$~.to_a.drop(1), if semmajor?(cur, lat)
430
- %i[green bold]
564
+ 1
431
565
  else
432
- cur[2] == lat[2] ? [:yellow] : [:green]
566
+ cur[2] == lat[2] ? 3 : 2
433
567
  end]
434
568
  else
435
569
  puts line
436
570
  end
437
571
  end
438
- if items.size == 1
439
- puts 'No updates were found'
440
- else
572
+ if items.size > 1
441
573
  pad = [items.size.to_s.size + 1, 3].max
442
574
  d = 0
443
575
  e = 0
444
576
  f = 0
577
+ j = 0
578
+ queue = nil
445
579
  items.each do |item|
446
580
  a, b, c = item.first
447
581
  d = a.size if a.size > d
448
582
  e = b.size if b.size > e
449
583
  f = c.size if c.size > f
450
584
  end
451
- major = 0
452
- minor = 0
453
- patch = 0
454
585
  items.each_with_index do |item, i|
455
586
  next if i == 0 && stdin?
456
587
 
@@ -461,34 +592,88 @@ module Squared
461
592
  2.times do
462
593
  line = sub_style(line, pat: /^(.+)(?<!\dm)(#{a}|#{c})(.*)$/, styles: theme[:header], index: 2)
463
594
  end
464
- puts line
465
- puts sub_style(ARG[:BORDER][1] * n, styles: borderstyle)
595
+ queue = [line, sub_style(ARG[:BORDER][1] * n, styles: borderstyle)]
466
596
  else
467
- styles = item.last
468
- a = a.ljust(d)
469
- if styles.first == :green
470
- a = sub_style(a, styles: if styles.size == 2
471
- major += 1
472
- theme[:major]
473
- else
474
- minor += 1
475
- theme[:active]
476
- end)
597
+ g = a.ljust(d)
598
+ pat = [/^([^.]+\.)([^.]+\..+)$/, /^([^.]+\.[^.]+\.)(.+)$/]
599
+ pre = b.start_with?('0.')
600
+ latest = [theme[:current]]
601
+ case item.last
602
+ when 1
603
+ case filter
604
+ when 'major'
605
+ update << a
606
+ when 'minor', 'patch'
607
+ next
608
+ end
609
+ g = sub_style(g, styles: theme[:major])
610
+ major += 1
611
+ styles = %i[green bold]
612
+ pat = pre ? pat.first : nil
613
+ latest << :bold
614
+ when 2
615
+ case filter
616
+ when 'major', 'minor'
617
+ update << a
618
+ when 'patch'
619
+ next
620
+ end
621
+ g = sub_style(g, styles: theme[:active])
622
+ minor += 1
623
+ styles = %i[green]
624
+ pat = pre ? pat.last : pat.first
477
625
  else
626
+ case filter
627
+ when 'major', 'minor', 'patch'
628
+ update << a
629
+ end
478
630
  patch += 1
631
+ styles = %i[yellow]
632
+ pat = pat.last
479
633
  end
480
634
  b = b.rjust(e)
481
- b = sub_style(b, styles: theme[:current]) if theme[:current]
482
- c = sub_style(c.rjust(f), *colormap(styles))
483
- puts "#{"#{i}.".rjust(pad)} #{a} #{b} #{c}"
635
+ b = sub_style(b, *colormap(styles), pat: pat, index: 2)
636
+ h = sub_style(c.rjust(f), styles: latest.flatten.compact, pat: pat, index: 2)
637
+ j += 1
638
+ if queue
639
+ puts queue
640
+ queue = nil
641
+ end
642
+ puts "#{"#{j}.".rjust(pad)} #{g} #{b} #{h}"
643
+ update << a if filter == 'interactive' && confirm_outdated(a, c, item.last)
484
644
  end
485
645
  end
486
- unless stdin?
487
- status = print_footer("major #{major} / minor #{minor} / patch #{patch}", right: true).split("\n")
488
- status[1] = sub_style(status[1], pat: /^( +major )(\d+)(.+)$/, styles: theme[:major], index: 2)
489
- status[1] = sub_style(status[1], pat: /^(.+)(minor )(\d+)(.+)$/, styles: theme[:active], index: 3)
490
- puts status
646
+ end
647
+ end
648
+ if major + minor + patch == 0
649
+ puts 'No updates were found'
650
+ else
651
+ unless update.empty?
652
+ cmd = gem_output 'update', '-f'
653
+ if (val = option('document', prefix: 'gem', ignore: false))
654
+ cmd << case val
655
+ when '0', 'false'
656
+ '--no-document'
657
+ else
658
+ basic_option('document', val)
659
+ end
660
+ end
661
+ if (val = option('user-install', prefix: 'gem', ignore: false))
662
+ cmd << case val
663
+ when '0', 'false'
664
+ '--no-user-install'
665
+ else
666
+ '--user-install'
667
+ end
491
668
  end
669
+ cmd.merge(update)
670
+ run(cmd, banner: false, from: :'gem:update')
671
+ end
672
+ unless stdin?
673
+ status = print_footer("major #{major} / minor #{minor} / patch #{patch}", right: true).split("\n")
674
+ status[1] = sub_style(status[1], pat: /^( +major )(\d+)(.+)$/, styles: theme[:major], index: 2)
675
+ status[1] = sub_style(status[1], pat: /^(.+)(minor )(\d+)(.+)$/, styles: theme[:active], index: 3)
676
+ puts status
492
677
  end
493
678
  end
494
679
  on :last, from
@@ -496,13 +681,13 @@ module Squared
496
681
  when :build, :push
497
682
  if !op.empty?
498
683
  if flag == :build && op.size == 1
499
- op << shell_quote(basepath(op.first))
684
+ op << shell_quote(path + op.first)
500
685
  else
501
686
  raise_error("unknown args: #{op.join(', ')}", hint: flag)
502
687
  end
503
688
  elsif flag == :build
504
- spec = [basepath("#{project}.gemspec"), basepath("#{name}.gemspec"), *Dir.glob(basepath('*.gemspec'))]
505
- op << File.basename(spec) if (spec = spec.find { |val| File.exist?(val) })
689
+ spec = [path + "#{project}.gemspec", path + "#{name}.gemspec", *Dir.glob(path + '*.gemspec')]
690
+ op << File.basename(spec) if (spec = spec.find { |file| File.exist?(file) })
506
691
  end
507
692
  when :exec
508
693
  raise_error('missing command', hint: flag) if op.empty?
@@ -512,7 +697,7 @@ module Squared
512
697
  if flag == :pristine
513
698
  if op.arg?('all')
514
699
  append_repeat 'skip', op.extras
515
- op.clear
700
+ op.extras.clear
516
701
  elsif (n = op.first.index('@'))
517
702
  name = op.shift
518
703
  if n == 0
@@ -563,11 +748,16 @@ module Squared
563
748
  run_s(args, banner: false, from: :rake)
564
749
  end
565
750
 
566
- def irb(name, opts = [], path: basepath('lib'))
567
- op = OptionPartition.new(opts, OPT_RUBY[:irb], session('irb'), project: self, first: true)
568
- as_a(name).each { |val| op << shell_option('r', val) }
569
- as_a(path).each { |val| op << quote_option('I', val) }
570
- op.merge(op.extras)
751
+ def irb(name, opts = [], path: @path + 'lib', load: nil)
752
+ op = OptionPartition.new(opts, OPT_RUBY[:irb], session('irb'), project: self, first: [/\.rb$/])
753
+ as_a(name).each { |val| op << shell_option('r', val, merge: true) }
754
+ as_a(path).each { |val| op << quote_option('I', val, merge: true) }
755
+ if load
756
+ op << '--' << load
757
+ op.clear
758
+ else
759
+ op.append(delim: true)
760
+ end
571
761
  run(banner: false)
572
762
  end
573
763
 
@@ -579,8 +769,26 @@ module Squared
579
769
  return true if super || (@copy.is_a?(Hash) && copy.fetch(:into, nil))
580
770
  return gemdir? if @gemdir
581
771
 
582
- if @version && (home = ENV['GEM_HOME'])
583
- @gemdir = Pathname.new(home).join(gempath)
772
+ if @version
773
+ begin
774
+ case @autodetect
775
+ when 'rvm'
776
+ @gemdir = pwd_set { `rvm info homes` }[/^\s+gem:\s+"(.+)"$/, 1]
777
+ when 'rbenv'
778
+ if pwd_set { `rbenv which ruby` } =~ %r{^(.+[\\/]versions[\\/](\d\.\d)\.[^\\/]+)[\\/]bin[\\/]ruby$}
779
+ @gemdir = File.join($1, 'lib/ruby/gems', "#{$2}.0")
780
+ end
781
+ when 'asdf'
782
+ @gemdir = pwd_set { `asdf where ruby` }
783
+ @gemdir = @gemdir =~ /(\d\.\d)\.[^.]+$/ && File.join(@gemdir, 'lib/ruby/gems', "#{$1}.0")
784
+ when /bundler?/
785
+ @gemdir = pwd_set { `bundle env` }[/^\s+Gem Home\s+(.+)$/, 1]
786
+ end
787
+ rescue StandardError => e
788
+ log.debug e
789
+ else
790
+ @gemdir = Pathname.new(@gemdir) if @gemdir
791
+ end
584
792
  return true if gemdir?
585
793
  end
586
794
  return false unless @autodetect
@@ -588,7 +796,7 @@ module Squared
588
796
  set = lambda do |val, path|
589
797
  log.warn "using version #{val} (given #{@version})" if @version && @version != val
590
798
  @version = val
591
- @gemdir = Pathname.new(path.strip).join(gempath)
799
+ @gemdir = Pathname.new(path.strip) + gempath
592
800
  end
593
801
  if @version
594
802
  pwd = gempwd
@@ -600,7 +808,7 @@ module Squared
600
808
  ver.each do |val|
601
809
  next unless out =~ /\(#{Regexp.escape(val)}(?:,[^)]+|\b)\):([^\n]+)/
602
810
 
603
- set.(val, $1)
811
+ set.call(val, $1)
604
812
  break
605
813
  end
606
814
  end
@@ -612,14 +820,14 @@ module Squared
612
820
 
613
821
  lib = Regexp.new(['', 'gems', "#{project}-([^#{File::SEPARATOR}]+)", ''].join(File::SEPARATOR))
614
822
  if (ver = path[lib, 1]) && (val = path[/\A(.+)#{gempath(ver[1])}/, 1])
615
- set.(ver, val)
823
+ set.call(ver, val)
616
824
  end
617
825
  end
618
826
  if RUBY_VERSION >= '2.6'
619
827
  target = RUBY_VERSION.start_with?('2.6') ? RubyVM : $LOAD_PATH
620
- parse.(target.resolve_feature_path(project)&.last)
828
+ parse.call(target.resolve_feature_path(project)&.last)
621
829
  end
622
- pwd_set { parse.(`#{bundle_output('show', project)}`) } unless @gemdir
830
+ pwd_set { parse.call(`#{bundle_output('show', project)}`) } unless @gemdir
623
831
  end
624
832
  raise_error('parse failed', hint: @version || 'path') unless @gemdir
625
833
  rescue StandardError => e
@@ -660,6 +868,10 @@ module Squared
660
868
  end
661
869
  end
662
870
 
871
+ def ruby_session(*cmd, **kwargs)
872
+ session('ruby', *preopts, *cmd, **kwargs)
873
+ end
874
+
663
875
  def gem_session(*cmd, **kwargs)
664
876
  ret = session('gem', *cmd, **kwargs)
665
877
  return ret if cmd.empty?
@@ -683,6 +895,10 @@ module Squared
683
895
  session_output('gem', *cmd, **kwargs)
684
896
  end
685
897
 
898
+ def ruby_output(*cmd, **kwargs)
899
+ session_output('ruby', *cmd, **kwargs)
900
+ end
901
+
686
902
  def bundle_output(*cmd, **kwargs)
687
903
  session_output('bundle', *cmd, **kwargs)
688
904
  end
@@ -711,7 +927,7 @@ module Squared
711
927
  end
712
928
 
713
929
  def gemdir?
714
- @gemdir.exist? && !@gemdir.empty?
930
+ !@gemdir.nil? && @gemdir.exist? && !@gemdir.empty?
715
931
  end
716
932
 
717
933
  def variables
@@ -721,7 +937,7 @@ module Squared
721
937
  def rakefile
722
938
  return unless (file = Rake::Application::DEFAULT_RAKEFILES.find { |val| basepath(val).exist? })
723
939
 
724
- basepath file
940
+ path + file
725
941
  end
726
942
 
727
943
  def rakepwd