squared 0.5.3 → 0.5.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +159 -61
- data/README.md +662 -1273
- data/lib/squared/common/base.rb +1 -1
- data/lib/squared/common/format.rb +5 -3
- data/lib/squared/common/prompt.rb +1 -1
- data/lib/squared/common/shell.rb +13 -3
- data/lib/squared/common/system.rb +4 -4
- data/lib/squared/config.rb +8 -8
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +37 -14
- data/lib/squared/workspace/project/base.rb +143 -51
- data/lib/squared/workspace/project/docker.rb +68 -52
- data/lib/squared/workspace/project/git.rb +314 -208
- data/lib/squared/workspace/project/node.rb +42 -32
- data/lib/squared/workspace/project/python.rb +76 -30
- data/lib/squared/workspace/project/ruby.rb +121 -69
- data/lib/squared/workspace/project/support/class.rb +109 -15
- data/lib/squared/workspace/repo.rb +75 -48
- data/squared.gemspec +2 -2
- metadata +4 -5
- data/README.ruby.md +0 -724
@@ -25,8 +25,8 @@ module Squared
|
|
25
25
|
common: %w[no-color V|verbose retry=i].freeze,
|
26
26
|
install: %w[frozen no-cache no-prune system binstubs=p? path=p standalone=q? target-rbconfig=p trust-policy=b
|
27
27
|
with=q without=q].freeze,
|
28
|
-
install_base: %w[full-index quiet retry gemfile=p j|jobs=i].freeze,
|
29
|
-
update: %w[conservative local pre
|
28
|
+
install_base: %w[force full-index quiet redownload retry gemfile=p j|jobs=i].freeze,
|
29
|
+
update: %w[conservative local pre ruby strict bundler=b? g|group=q source=b].freeze,
|
30
30
|
outdated: %w[filter-major filter-minor filter-patch groups local parseable pre only-explicit strict
|
31
31
|
update-strict g|group=q source=b].freeze,
|
32
32
|
exec: %w[gemfile=p].freeze,
|
@@ -91,7 +91,7 @@ module Squared
|
|
91
91
|
'irb' => nil
|
92
92
|
})
|
93
93
|
|
94
|
-
def initialize(*, autodetect: false, gemspec: nil, **kwargs)
|
94
|
+
def initialize(*, autodetect: false, gemspec: nil, asdf: 'ruby', **kwargs)
|
95
95
|
super
|
96
96
|
if @pass.include?(Ruby.ref)
|
97
97
|
initialize_ref Ruby.ref
|
@@ -102,7 +102,13 @@ module Squared
|
|
102
102
|
end
|
103
103
|
dependfile_set GEMFILE
|
104
104
|
@autodetect = autodetect
|
105
|
-
@gemfile =
|
105
|
+
@gemfile = if gemspec == false
|
106
|
+
false
|
107
|
+
elsif gemspec
|
108
|
+
path + (gemspec.include?('.') ? gemspec : "#{gemspec}.gemspec")
|
109
|
+
elsif (gemspec = path + "#{name}.gemspec").exist? || (gemspec = path + "#{project}.gemspec").exist?
|
110
|
+
gemspec
|
111
|
+
end
|
106
112
|
return if !@output[0].nil? || !@copy.nil? || version || @autodetect || !rakefile
|
107
113
|
|
108
114
|
begin
|
@@ -126,7 +132,7 @@ module Squared
|
|
126
132
|
|
127
133
|
def populate(*, **)
|
128
134
|
super
|
129
|
-
return unless outdated? && ref?(Ruby.ref)
|
135
|
+
return unless (outdated? && ref?(Ruby.ref)) || @only
|
130
136
|
|
131
137
|
namespace name do
|
132
138
|
Ruby.subtasks do |action, flags|
|
@@ -140,21 +146,21 @@ module Squared
|
|
140
146
|
format_desc action, nil, "task+,opts*|#{indexchar}index+|#,pattern*"
|
141
147
|
task action, [:command] do |_, args|
|
142
148
|
if args.command == '#'
|
143
|
-
format_list(
|
144
|
-
|
149
|
+
format_list(raketasks, "rake[#{indexchar}N]", 'tasks', grep: args.extras, from: rakefile,
|
150
|
+
each: ->(val) { val[0] + val[1].to_s })
|
145
151
|
else
|
146
152
|
args, opts = args.to_a.partition { |val| indexitem(val) }
|
147
153
|
if args.empty?
|
148
154
|
rake(opts: opts)
|
149
155
|
else
|
150
|
-
|
156
|
+
tasks = raketasks
|
151
157
|
while (n, pre = indexitem(args.shift))
|
152
|
-
if (item =
|
158
|
+
if (item = tasks[n - 1])
|
153
159
|
cmd = pre ? "#{pre} #{item.first}" : item.first
|
154
160
|
elsif exception
|
155
|
-
indexerror n,
|
161
|
+
indexerror n, tasks
|
156
162
|
else
|
157
|
-
log.warn "rake task #{n} of #{
|
163
|
+
log.warn "rake task #{n} of #{tasks.size} (out of range)"
|
158
164
|
next
|
159
165
|
end
|
160
166
|
if opts.empty?
|
@@ -171,7 +177,7 @@ module Squared
|
|
171
177
|
format_desc action, nil, 'opts*,args*|:'
|
172
178
|
task action do |_, args|
|
173
179
|
args = args.to_a
|
174
|
-
name = basepath(
|
180
|
+
name = gemlib.any? { |file| basepath(file).join("#{gemname}.rb").exist? } ? gemname : nil
|
175
181
|
irb(name, args, args: (readline('Enter file [arguments]', force: false) if args.delete(':')))
|
176
182
|
end
|
177
183
|
else
|
@@ -209,7 +215,7 @@ module Squared
|
|
209
215
|
when :build, :push, :exec, :update
|
210
216
|
format_desc(action, flag, 'opts*', after: case flag
|
211
217
|
when :exec then 'command,args*'
|
212
|
-
when :push then 'file
|
218
|
+
when :push then 'file?|:'
|
213
219
|
when :update then 'name*'
|
214
220
|
end)
|
215
221
|
task flag do |_, args|
|
@@ -275,7 +281,7 @@ module Squared
|
|
275
281
|
end
|
276
282
|
end
|
277
283
|
|
278
|
-
def copy(from:
|
284
|
+
def copy(from: gemlib, into: @gemdir, override: false, **kwargs)
|
279
285
|
glob = kwargs[:include]
|
280
286
|
pass = kwargs[:exclude]
|
281
287
|
if @copy && !override
|
@@ -426,7 +432,16 @@ module Squared
|
|
426
432
|
|
427
433
|
def install(flag, opts = [])
|
428
434
|
bundle_session 'install', "--#{flag}"
|
429
|
-
append_bundle opts, OPT_BUNDLE[:install_base] + OPT_BUNDLE[:install] + OPT_BUNDLE[:common]
|
435
|
+
op = append_bundle opts, OPT_BUNDLE[:install_base] + OPT_BUNDLE[:install] + OPT_BUNDLE[:common]
|
436
|
+
if op.arg?('force')
|
437
|
+
op.delete('--force')
|
438
|
+
if flag != :redownload
|
439
|
+
op << '--redownload'
|
440
|
+
elsif (lock = basepath('Gemfile.lock')).exist?
|
441
|
+
config = basepath('.bundle', 'config')
|
442
|
+
lock.delete unless config.exist? && config.read.match?(/\bBUNDLE_FROZEN:\s+"true"/)
|
443
|
+
end
|
444
|
+
end
|
430
445
|
run_rb(from: :install)
|
431
446
|
end
|
432
447
|
|
@@ -451,16 +466,44 @@ module Squared
|
|
451
466
|
when :version
|
452
467
|
pwd_set do
|
453
468
|
out = []
|
454
|
-
|
469
|
+
order = { 'rvm' => -1, 'rbenv' => -1, 'chruby' => -1, 'asdf' => -1 }
|
470
|
+
ENV.fetch('PATH', '').split(':').each_with_index do |val, index|
|
471
|
+
order.each_key do |key|
|
472
|
+
if val.match?(%r{[/.]#{key}/})
|
473
|
+
order[key] = index
|
474
|
+
break
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
paths = [
|
455
479
|
'$HOME/.rvm/bin/rvm',
|
456
480
|
'/usr/local/rvm/bin/rvm',
|
457
481
|
'/usr/share/rvm/bin/rvm',
|
458
482
|
"#{ENV.fetch('RBENV_ROOT', '$HOME/.rbenv')}/bin/rbenv",
|
459
483
|
'/usr/bin/rbenv',
|
460
|
-
'/usr/local/share/chruby/chruby.sh'
|
461
|
-
|
462
|
-
|
463
|
-
|
484
|
+
'/usr/local/share/chruby/chruby.sh'
|
485
|
+
]
|
486
|
+
paths << "#{ENV.fetch('ASDF_DATA_DIR', '$HOME/.asdf')}/installs/#{@asdf.first}" if @asdf
|
487
|
+
paths.sort do |a, b|
|
488
|
+
c = -1
|
489
|
+
d = -1
|
490
|
+
order.each do |key, val|
|
491
|
+
pat = %r{/\.?#{key}}
|
492
|
+
c = val if a.match?(pat)
|
493
|
+
d = val if b.match?(pat)
|
494
|
+
end
|
495
|
+
if c == d
|
496
|
+
0
|
497
|
+
elsif c == -1
|
498
|
+
1
|
499
|
+
elsif d == -1
|
500
|
+
-1
|
501
|
+
else
|
502
|
+
c < d ? -1 : 1
|
503
|
+
end
|
504
|
+
end
|
505
|
+
.push('')
|
506
|
+
.each do |val|
|
464
507
|
next unless val.empty? || File.exist?(val.sub('$HOME', Dir.home))
|
465
508
|
|
466
509
|
trim = ->(s) { s[/\A\D+\d+\.\d+(?:\.\S+)?/, 0].sub(/\A([a-z]+)-/i, '\1 ') }
|
@@ -475,12 +518,15 @@ module Squared
|
|
475
518
|
when 'chruby.sh'
|
476
519
|
chruby = session_output 'source', val
|
477
520
|
`#{chruby.with('ruby --version')}`
|
478
|
-
when 'install'
|
479
|
-
ver = '.tool-versions'
|
480
|
-
`asdf current ruby`[/ruby\s+\S+/, 0].sub(/\s+/, ' ')
|
481
521
|
else
|
482
|
-
|
483
|
-
|
522
|
+
if @asdf
|
523
|
+
cmd = 'asdf'
|
524
|
+
ver = '.tool-versions'
|
525
|
+
`asdf current #{@asdf.first}`[/\A\S+\s+\S+/, 0].sub(/\s+/, ' ')
|
526
|
+
else
|
527
|
+
ver = nil
|
528
|
+
`ruby --version`
|
529
|
+
end
|
484
530
|
end)
|
485
531
|
break if workspace.windows?
|
486
532
|
|
@@ -488,7 +534,7 @@ module Squared
|
|
488
534
|
out << trim.call(case cmd
|
489
535
|
when 'chruby.sh'
|
490
536
|
`#{chruby.with('chruby --version')}`.sub(':', '')
|
491
|
-
when '
|
537
|
+
when 'asdf'
|
492
538
|
"asdf #{`asdf version`.delete_prefix('v')}"
|
493
539
|
else
|
494
540
|
`#{cmd} --version`
|
@@ -500,8 +546,8 @@ module Squared
|
|
500
546
|
`rbenv which ruby`
|
501
547
|
when 'chruby.sh'
|
502
548
|
`#{chruby.with('which ruby')}`
|
503
|
-
when '
|
504
|
-
`asdf which
|
549
|
+
when 'asdf'
|
550
|
+
`asdf which #{@asdf.first}`
|
505
551
|
else
|
506
552
|
`which ruby`
|
507
553
|
end)
|
@@ -566,7 +612,7 @@ module Squared
|
|
566
612
|
minor = 0
|
567
613
|
patch = 0
|
568
614
|
update = []
|
569
|
-
pwd_set(pass: !
|
615
|
+
pwd_set(pass: !gempwd.nil?, from: from) do
|
570
616
|
items = [[%w[Gem Current Latest], nil]]
|
571
617
|
IO.popen(cmd.done).each do |line|
|
572
618
|
if line =~ /^(\S+) \((\S+) < ([^)]+)\)$/
|
@@ -685,25 +731,25 @@ module Squared
|
|
685
731
|
on :last, from
|
686
732
|
return
|
687
733
|
when :build
|
688
|
-
if
|
689
|
-
op
|
690
|
-
|
691
|
-
|
692
|
-
|
734
|
+
if op.empty?
|
735
|
+
op.add_path(gemfile)
|
736
|
+
else
|
737
|
+
op.add_path(op.shift)
|
738
|
+
.clear(pass: false)
|
693
739
|
end
|
694
740
|
when :push
|
695
|
-
if op.empty?
|
696
|
-
file = path + (if (spec = gemspec)
|
741
|
+
if op.empty? || (n = op.index(':'))
|
742
|
+
file = path + (if !n && (spec = gemspec)
|
697
743
|
"#{spec.name}-#{spec.version}.gem"
|
698
744
|
else
|
699
745
|
choice_index('Select a file', Dir.glob('*.gem', base: path), force: true)
|
700
746
|
end)
|
701
747
|
else
|
702
|
-
file = path + op.shift
|
748
|
+
file = path + op.shift.yield_self { |val| val.include?('.') ? val : "#{val}.gem" }
|
703
749
|
raise_error('gem not found', hint: file) unless file.exist?
|
704
750
|
raise_error("unknown args: #{op.join(', ')}", hint: flag) unless op.empty?
|
705
751
|
end
|
706
|
-
op
|
752
|
+
op.add_path(file)
|
707
753
|
run_rb(from: from, interactive: "Push #{sub_style(gemname, styles: theme[:active])}")
|
708
754
|
return
|
709
755
|
when :exec
|
@@ -730,7 +776,7 @@ module Squared
|
|
730
776
|
raise_error('missing gemname', hint: flag) if op.empty?
|
731
777
|
case flag
|
732
778
|
when :install, :uninstall, :pristine
|
733
|
-
post = readline('Enter command [args]', force: true) if flag == :install && op.
|
779
|
+
post = readline('Enter command [args]', force: true) if flag == :install && op.remove(':')
|
734
780
|
if op.arg?('all')
|
735
781
|
if flag == :pristine
|
736
782
|
append_repeat 'skip', op.extras
|
@@ -797,7 +843,7 @@ module Squared
|
|
797
843
|
run_s(args, banner: false, from: :rake)
|
798
844
|
end
|
799
845
|
|
800
|
-
def irb(name = nil, opts = [], path:
|
846
|
+
def irb(name = nil, opts = [], path: gemlib, args: nil)
|
801
847
|
op = OptionPartition.new(opts, OPT_RUBY[:irb], session('irb'), project: self, first: [/\.rb$/])
|
802
848
|
r = args ? [] : ['bundler/setup']
|
803
849
|
r << name if name
|
@@ -815,15 +861,11 @@ module Squared
|
|
815
861
|
def gemspec
|
816
862
|
return @gemspec unless @gemspec.nil?
|
817
863
|
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
rescue StandardError => e
|
824
|
-
log.debug e
|
825
|
-
end
|
826
|
-
@gemspec ||= false
|
864
|
+
@gemspec = if (file = gemfile)
|
865
|
+
Gem::Specification.load(file.to_s) rescue false
|
866
|
+
else
|
867
|
+
false
|
868
|
+
end
|
827
869
|
end
|
828
870
|
|
829
871
|
def gemname
|
@@ -885,7 +927,6 @@ module Squared
|
|
885
927
|
end
|
886
928
|
end
|
887
929
|
end
|
888
|
-
require 'rubygems'
|
889
930
|
@gemdir = Pathname.new(Gem.dir) + gempath
|
890
931
|
else
|
891
932
|
parse = lambda do |path|
|
@@ -940,6 +981,7 @@ module Squared
|
|
940
981
|
else
|
941
982
|
op.clear
|
942
983
|
end
|
984
|
+
op
|
943
985
|
end
|
944
986
|
|
945
987
|
def ruby_session(*cmd, **kwargs)
|
@@ -981,27 +1023,10 @@ module Squared
|
|
981
1023
|
session_output('rake', *cmd, **kwargs)
|
982
1024
|
end
|
983
1025
|
|
984
|
-
def read_rakefile
|
985
|
-
@read_rakefile ||= [].tap do |ret|
|
986
|
-
pwd = rakepwd
|
987
|
-
pwd_set(pass: !pwd.nil?) do
|
988
|
-
IO.popen(rake_output(pwd, '-AT').to_s).each do |line|
|
989
|
-
next unless line =~ /^rake ((?:[^\[: ]+:?)+)(\[[^\]]+\])?/
|
990
|
-
|
991
|
-
ret << [$1, $2]
|
992
|
-
end
|
993
|
-
end
|
994
|
-
end
|
995
|
-
end
|
996
|
-
|
997
1026
|
def preopts
|
998
1027
|
verbosetype > 1 && !session_arg?('quiet') ? ['--verbose'] : []
|
999
1028
|
end
|
1000
1029
|
|
1001
|
-
def gemdir?
|
1002
|
-
!@gemdir.nil? && @gemdir.exist? && !@gemdir.empty?
|
1003
|
-
end
|
1004
|
-
|
1005
1030
|
def variables
|
1006
1031
|
(super + %i[version autodetect]).freeze
|
1007
1032
|
end
|
@@ -1015,13 +1040,26 @@ module Squared
|
|
1015
1040
|
end
|
1016
1041
|
|
1017
1042
|
def rakepwd
|
1018
|
-
return
|
1043
|
+
return unless !pwd? && semgte?(Rake::VERSION, '13.0.4')
|
1019
1044
|
|
1020
1045
|
quote_option 'C', path
|
1021
1046
|
end
|
1022
1047
|
|
1048
|
+
def raketasks
|
1049
|
+
@raketasks ||= [].tap do |ret|
|
1050
|
+
opt = rakepwd
|
1051
|
+
pwd_set(pass: !opt.nil?) do
|
1052
|
+
IO.popen(rake_output(opt, '-AT').to_s).each do |line|
|
1053
|
+
next unless line =~ /^rake ((?:[^\[: ]+:?)+)(\[[^\]]+\])?/
|
1054
|
+
|
1055
|
+
ret << [$1, $2]
|
1056
|
+
end
|
1057
|
+
end
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
|
1023
1061
|
def gempwd
|
1024
|
-
return
|
1062
|
+
return unless !pwd? && semgte?(Gem::VERSION, '3.4.2')
|
1025
1063
|
|
1026
1064
|
quote_option 'C', path
|
1027
1065
|
end
|
@@ -1034,9 +1072,23 @@ module Squared
|
|
1034
1072
|
.find { |file| File.exist?(file) } || false
|
1035
1073
|
end
|
1036
1074
|
|
1075
|
+
def gemlib
|
1076
|
+
@gemlib ||= begin
|
1077
|
+
lib = Set.new(['lib'])
|
1078
|
+
if (spec = gemspec)
|
1079
|
+
lib.merge(spec.require_paths || [])
|
1080
|
+
end
|
1081
|
+
lib.select { |file| basepath(file).exist? }
|
1082
|
+
end
|
1083
|
+
end
|
1084
|
+
|
1037
1085
|
def gempath(val = version)
|
1038
1086
|
File.join('gems', "#{gemname}-#{val}")
|
1039
1087
|
end
|
1088
|
+
|
1089
|
+
def gemdir?
|
1090
|
+
!@gemdir.nil? && @gemdir.exist? && !@gemdir.empty?
|
1091
|
+
end
|
1040
1092
|
end
|
1041
1093
|
|
1042
1094
|
Application.implement Ruby
|
@@ -10,6 +10,9 @@ module Squared
|
|
10
10
|
include Common::Shell
|
11
11
|
extend Forwardable
|
12
12
|
|
13
|
+
OPT_VALUE = /\A([^=]+)=(.+)\z/
|
14
|
+
private_constant :OPT_VALUE
|
15
|
+
|
13
16
|
class << self
|
14
17
|
include Common::Format
|
15
18
|
include Shell
|
@@ -45,6 +48,15 @@ module Squared
|
|
45
48
|
val.map { |s| s.sub(/\A-([a-z\d])(.+)\z/i, '\1=\2').sub(/\A--?/, '') }.reject(&:empty?)
|
46
49
|
end
|
47
50
|
|
51
|
+
def select(list, bare: true, no: true, single: false, double: false)
|
52
|
+
ret = bare ? list.grep_v(/=/) : list.grep(/=/).map! { |val| val.split('=', 2).first }
|
53
|
+
ret.map! { |val| val.split('|', 2).last }
|
54
|
+
ret = ret.grep_v(/^no-/) unless no
|
55
|
+
return ret if single == double
|
56
|
+
|
57
|
+
ret.select { |val| single ? val.size == 1 : val.size > 1 }
|
58
|
+
end
|
59
|
+
|
48
60
|
def arg?(target, *args, value: false, **)
|
49
61
|
r, s = args.partition { |val| val.is_a?(Regexp) }
|
50
62
|
unless s.empty?
|
@@ -54,14 +66,21 @@ module Squared
|
|
54
66
|
s = target.to_a.compact
|
55
67
|
r.any? { |pat| s.any?(pat) }
|
56
68
|
end
|
69
|
+
|
70
|
+
def pattern?(val)
|
71
|
+
val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
|
72
|
+
end
|
57
73
|
end
|
58
74
|
|
59
75
|
attr_reader :target, :extras, :found, :errors, :values, :project, :path
|
60
76
|
|
61
77
|
def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
|
62
|
-
:merge, :delete, :delete?, :delete_if, :grep, :inspect, :to_a, :to_s
|
78
|
+
:merge, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
|
63
79
|
def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :last, :shift, :unshift,
|
64
|
-
:pop, :push, :index, :delete_at, :join, :map, :map!, :select, :reject, :size
|
80
|
+
:pop, :push, :concat, :index, :delete_at, :join, :map, :map!, :select, :reject, :size
|
81
|
+
|
82
|
+
def_delegator :@extras, :delete, :remove
|
83
|
+
def_delegator :@extras, :delete_if, :remove_if
|
65
84
|
|
66
85
|
def initialize(opts, list, target = Set.new, project: nil, path: nil, **kwargs, &blk)
|
67
86
|
@target = target.is_a?(Set) ? target : target.to_set
|
@@ -139,35 +158,35 @@ module Squared
|
|
139
158
|
skip = false
|
140
159
|
opts.each do |opt|
|
141
160
|
next skip = true if opt == '--'
|
142
|
-
next
|
161
|
+
next push opt if skip
|
143
162
|
|
144
163
|
if single&.match?(opt)
|
145
|
-
|
164
|
+
add "-#{opt}"
|
146
165
|
elsif bare.include?(opt)
|
147
|
-
|
166
|
+
add(opt.size == 1 ? "-#{opt}" : "--#{opt}")
|
148
167
|
elsif opt.start_with?('no-') && no.include?(name = opt[3..-1])
|
149
|
-
|
168
|
+
add "--no-#{name}"
|
150
169
|
else
|
151
|
-
if opt =~
|
170
|
+
if opt =~ OPT_VALUE
|
152
171
|
key = $1
|
153
172
|
val = $2
|
154
173
|
merge = m.include?(key)
|
155
174
|
if e.include?(key)
|
156
|
-
|
175
|
+
add shell_option(key, val, merge: merge)
|
157
176
|
elsif q.include?(key)
|
158
|
-
|
177
|
+
add quote_option(key, val, double: qq.include?(key), merge: merge)
|
159
178
|
elsif p.include?(key) && path
|
160
|
-
|
179
|
+
add quote_option(key, path + val, merge: merge)
|
161
180
|
elsif b.include?(key) || numcheck.call(key, val)
|
162
|
-
|
181
|
+
add basic_option(key, val, merge: merge)
|
163
182
|
elsif merge
|
164
|
-
|
183
|
+
add basic_option(key, val, merge: true)
|
165
184
|
else
|
166
|
-
|
185
|
+
push opt
|
167
186
|
end
|
168
187
|
opt = key
|
169
188
|
else
|
170
|
-
|
189
|
+
push opt
|
171
190
|
skip = true if args
|
172
191
|
end
|
173
192
|
skip = true if first&.any? { |s| s.is_a?(Regexp) ? opt.match?(s) : !opt.include?(s) }
|
@@ -193,6 +212,22 @@ module Squared
|
|
193
212
|
self
|
194
213
|
end
|
195
214
|
|
215
|
+
def uniq(list)
|
216
|
+
items = map { |val| nameonly(val) }
|
217
|
+
list.reject do |val|
|
218
|
+
next true if items.include?(s = nameonly(val))
|
219
|
+
|
220
|
+
pat = /\A#{s = fill_option(s)}(?:#{s.start_with?('--') ? '[= ]' : '.*'}|\z)/
|
221
|
+
any? { |opt| opt.match?(pat) }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def uniq!(list)
|
226
|
+
n = size
|
227
|
+
concat uniq(list)
|
228
|
+
extras if size > n
|
229
|
+
end
|
230
|
+
|
196
231
|
def clear(opts = nil, errors: false, **kwargs)
|
197
232
|
styles = project.theme[:inline] if project
|
198
233
|
if !opts
|
@@ -230,10 +265,63 @@ module Squared
|
|
230
265
|
args = items[0...i] + args + items[i..-1]
|
231
266
|
target.clear
|
232
267
|
end
|
233
|
-
merge
|
268
|
+
merge args
|
234
269
|
self
|
235
270
|
end
|
236
271
|
|
272
|
+
def add_path(*args, **kwargs)
|
273
|
+
add shell_quote(path ? path.join(*args) : File.join(*args), **kwargs)
|
274
|
+
self
|
275
|
+
end
|
276
|
+
|
277
|
+
def add_quote(*args, **kwargs)
|
278
|
+
merge(args.map { |val| shell_quote(val, **kwargs) })
|
279
|
+
self
|
280
|
+
end
|
281
|
+
|
282
|
+
def splice(*exclude, quote: true, delim: true, path: false, pattern: false, &blk)
|
283
|
+
found, other = if block_given?
|
284
|
+
partition(&blk)
|
285
|
+
elsif exclude.first.is_a?(Symbol)
|
286
|
+
partition(&exclude.first)
|
287
|
+
else
|
288
|
+
partition do |val|
|
289
|
+
next false if pattern && OptionPartition.pattern?(val)
|
290
|
+
|
291
|
+
exclude.none? { |pat| val.match?(Regexp.new(pat)) }
|
292
|
+
end
|
293
|
+
end
|
294
|
+
unless found.empty?
|
295
|
+
add '--' if delim
|
296
|
+
extras.clear
|
297
|
+
concat other
|
298
|
+
if path
|
299
|
+
found.each { |val| add_path(val) }
|
300
|
+
else
|
301
|
+
merge(quote ? found.map! { |val| shell_quote(val) } : found)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
self
|
305
|
+
end
|
306
|
+
|
307
|
+
def append?(key, val = nil, type: nil, **kwargs)
|
308
|
+
return false if arg?(key)
|
309
|
+
|
310
|
+
val = yield self if block_given?
|
311
|
+
return false unless val
|
312
|
+
|
313
|
+
type ||= :quote if kwargs.empty?
|
314
|
+
op << case type
|
315
|
+
when :quote
|
316
|
+
quote_option(key, val)
|
317
|
+
when :basic
|
318
|
+
basic_option(key, val)
|
319
|
+
else
|
320
|
+
shell_option(key, val, **kwargs)
|
321
|
+
end
|
322
|
+
true
|
323
|
+
end
|
324
|
+
|
237
325
|
def reset(errors: false)
|
238
326
|
extras.clear
|
239
327
|
clear(errors: true) if errors
|
@@ -243,6 +331,12 @@ module Squared
|
|
243
331
|
def arg?(*args, **kwargs)
|
244
332
|
OptionPartition.arg?(target, *args, **kwargs)
|
245
333
|
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
def nameonly(val)
|
338
|
+
val[OPT_VALUE, 1] || val
|
339
|
+
end
|
246
340
|
end
|
247
341
|
|
248
342
|
class JoinSet < Set
|