squared 0.6.1 → 0.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a3b6e4109938a7ee4ddc9d778c798ad412cd2941a6b887cc62f9bd39779b4ad
4
- data.tar.gz: 6912a295b0e64223d3130d8793bce44e954c0903fd74b65eb0f420726a41f82d
3
+ metadata.gz: c638ae780897008e5115630f70db5a8ce7e1930fd31e7d1984b16d775218e16b
4
+ data.tar.gz: 231f5fc087b0b3dfcff0289f5601b0c70f0a9e6db63ff7309b7c86d96ae0a1ef
5
5
  SHA512:
6
- metadata.gz: 137851028240806e553b125ec638df63cb20c25b6f73328a1c08f7af7603d666a1b61ff04dde1da27995a13d0bf2a6c28e644d20b6e8beb6e26fba061191d908
7
- data.tar.gz: 21c7fce48d7638aa90b9c0ef40282b30557205065f6117e0602248771cee9e628910f90125295dac4a831615adda43296112809b437f31b4db0aa9d3f03de437
6
+ metadata.gz: 175e72f4f5821922928b2b95a7f831dc42e91bbc41f093686cd253a68794b4b34db8af2bb9d103871cd19dfdf4d21ddd1d2bf30efdd8a8b4f5a7475be77b9988
7
+ data.tar.gz: 7c619485cf6d8046ba0e2acd99afcb698137e6342fd68b454c1195f9f32517d133aada79783813c15978eb1af132113aa94c422d425ae76b36a033345c81a4e3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.6.2] - 2025-11-08
4
+
5
+ ### Added
6
+
7
+ - JoinSet methods [add|merge] were aliased to [push|concat].
8
+ - JoinSet supports values that can be used multiple times.
9
+
10
+ ### Changed
11
+
12
+ - Ruby command rake can multiple indexed tasks with separate options.
13
+
14
+ ### Fixed
15
+
16
+ - Session global program options were untested and worthless upon draft.
17
+
18
+ ## [0.5.15] - 2025-11-08
19
+
20
+ ### Fixed
21
+
22
+ - See `0.4.29`.
23
+
24
+ ## [0.4.29] - 2025-11-08
25
+
26
+ ### Fixed
27
+
28
+ - OptionPartition was created by mistake and is unreliable in every way.
29
+
30
+ ## [0.5.14] - 2025-11-08
31
+
32
+ ### Fixed
33
+
34
+ - See `0.4.28`.
35
+
36
+ ## [0.4.28] - 2025-11-08
37
+
38
+ ### Fixed
39
+
40
+ - Project base method build as arrays parsed unrelated arguments.
41
+ - OptionPartition method arg? does not check after "--" delimiter.
42
+ - OptionPartition did not support duplicate values after "--" delimiter.
43
+ - OptionPartition method opt? did not type check for String.
44
+
3
45
  ## [0.6.1] - 2025-11-05
4
46
 
5
47
  ### Added
@@ -12,6 +54,7 @@
12
54
 
13
55
  - Project base method run argument series was backwards.
14
56
  - Project base choice range did not detect empty list result.
57
+ - Project base method build as arrays parsed unrelated arguments.
15
58
 
16
59
  ## [0.5.13] - 2025-11-05
17
60
 
@@ -1308,8 +1351,11 @@
1308
1351
 
1309
1352
  - Changelog was created.
1310
1353
 
1354
+ [0.6.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.2
1311
1355
  [0.6.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.1
1312
1356
  [0.6.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.0
1357
+ [0.5.15]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.15
1358
+ [0.5.14]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.14
1313
1359
  [0.5.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.13
1314
1360
  [0.5.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.12
1315
1361
  [0.5.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.11
@@ -1324,6 +1370,8 @@
1324
1370
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
1325
1371
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
1326
1372
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
1373
+ [0.4.29]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.29
1374
+ [0.4.28]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.28
1327
1375
  [0.4.27]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.27
1328
1376
  [0.4.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.26
1329
1377
  [0.4.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.25
@@ -266,8 +266,8 @@ module Squared
266
266
  sub.each { |h| s = sub_style(s, **h) }
267
267
  s = "#{b0} #{s} #{b0}"
268
268
  if border
269
- s = sub_style(s, **opt_style(border, /\A(#{Regexp.escape(b0)})(.+)\z/m))
270
- s = sub_style(s, **opt_style(border, /\A(.+)(#{Regexp.escape(b0)})\z/m, 2))
269
+ s = sub_style(s, **opt_style(border, /\A(#{Regexp.escape(b0)})(.+)\z/om))
270
+ s = sub_style(s, **opt_style(border, /\A(.+)(#{Regexp.escape(b0)})\z/om, 2))
271
271
  end
272
272
  s
273
273
  end
@@ -156,6 +156,7 @@ module Squared
156
156
  end
157
157
 
158
158
  def fill_option(val, **kwargs)
159
+ return val unless val.is_a?(::String)
159
160
  return "-#{val}" if val.match?(/\A(?:[a-z]\d*|\d)\z/i)
160
161
 
161
162
  shell_escape(val.start_with?('-') ? val : "--#{val}", **kwargs)
@@ -271,7 +271,7 @@ module Squared
271
271
  end
272
272
  end
273
273
  rescue StandardError
274
- log&.warn "#{Viewer}(#{type}) => #{file && "#{file} "}{#{key}: undefined}"
274
+ log&.warn "#{Viewer}(#{type}) => #{"#{file} " if file}{#{key}: undefined}"
275
275
  val = Regexp.escape($!.message)
276
276
  key = key.sub(/(#{val})\.|\.(#{val})|(#{val})/) do
277
277
  s = "<#{$3 || $2 || $1}>"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.6.1'
4
+ VERSION = '0.6.2'
5
5
  end
@@ -553,31 +553,31 @@ module Squared
553
553
  cmd = cmd.join(' && ')
554
554
  else
555
555
  cmd, opts, var, flags, extra = args
556
- end
557
- if cmd
558
- return run_b(cmd, sync: sync, from: from) if cmd.is_a?(Proc) || cmd.is_a?(Method)
559
-
560
- cmd = as_get cmd, from
561
- opts = compose(opts, script: false) if opts && respond_to?(:compose)
562
- flags = append_hash(flags, target: []).join(' ') if flags.is_a?(Hash)
563
- case opts
564
- when Hash
565
- cmd = Array(cmd).push(flags)
566
- .concat(append_hash(opts, target: [], build: true))
567
- .compact
568
- .join(' ')
569
- when Enumerable
570
- cmd = Array(cmd).concat(opts.to_a)
571
- cmd.map! { |val| "#{val} #{flags}" } if flags
572
- cmd = cmd.join(' && ')
556
+ if cmd
557
+ return run_b(cmd, sync: sync, from: from) if cmd.is_a?(Proc) || cmd.is_a?(Method)
558
+
559
+ cmd = as_get cmd, from
560
+ opts = compose(opts, script: false) if opts && respond_to?(:compose)
561
+ flags = append_hash(flags, target: []).join(' ') if flags.is_a?(Hash)
562
+ cmd = case opts
563
+ when Hash
564
+ Array(cmd).push(flags)
565
+ .concat(append_hash(opts, target: [], build: true))
566
+ .compact
567
+ .join(' ')
568
+ when Enumerable
569
+ cmd = Array(cmd).concat(opts.to_a)
570
+ cmd.map! { |val| "#{val} #{flags}" } if flags
571
+ cmd.join(' && ')
572
+ else
573
+ [cmd, flags, opts].compact.join(' ')
574
+ end
573
575
  else
574
- cmd = [cmd, flags, opts].compact.join(' ') if opts || flags
575
- end
576
- else
577
- return unless (opts || extra) && respond_to?(:compose)
576
+ return unless (opts || extra) && respond_to?(:compose)
578
577
 
579
- cmd = compose(as_get(opts, from), flags, script: true, args: extra, from: from)
580
- from = :script if from == :run && script?
578
+ cmd = compose(as_get(opts, from), flags, script: true, args: extra, from: from)
579
+ from = :script if from == :run && script?
580
+ end
581
581
  end
582
582
  run(cmd, var, sync: sync, banner: banner, from: from)
583
583
  end
@@ -596,12 +596,12 @@ module Squared
596
596
  if proj.respond_to?(meth.to_sym)
597
597
  begin
598
598
  proj.__send__(meth, sync: sync)
599
- next
600
599
  rescue StandardError => e
601
600
  on_error(e, :prereqs, exception: true)
602
601
  end
602
+ else
603
+ print_error(name, "method: #{meth}", subject: 'prereqs', hint: 'undefined')
603
604
  end
604
- print_error(name, 'method not found', subject: 'prereqs', hint: meth)
605
605
  end
606
606
  elsif proj.build?
607
607
  proj.build(sync: sync)
@@ -1023,6 +1023,8 @@ module Squared
1023
1023
  end
1024
1024
 
1025
1025
  def exist?(*args)
1026
+ return false if (args = args.compact).empty?
1027
+
1026
1028
  basepath(*args).exist?
1027
1029
  end
1028
1030
 
@@ -1359,10 +1361,10 @@ module Squared
1359
1361
  ret = JoinSet.new(cmd.flatten(1))
1360
1362
  if options
1361
1363
  env("#{prefix.upcase}_OPTIONS") do |val|
1362
- if val.start_with('-')
1363
- ret.concat(shell_parse(val))
1364
+ if val.start_with?('-')
1365
+ ret.merge(shell_parse(val))
1364
1366
  else
1365
- split_escape(val) { |opt| ret.last(fill_option(opt), /\A(--?[^= ]+)[= ].+\z/m) }
1367
+ split_escape(val) { |opt| ret.last(fill_option(opt), /\A(--?[^\[\]=\s-][^\[\]=\s]*)[=\s].+\z/m) }
1366
1368
  end
1367
1369
  end
1368
1370
  end
@@ -1699,11 +1701,12 @@ module Squared
1699
1701
  **kwargs)
1700
1702
  return if list.empty?
1701
1703
 
1704
+ kwargs[:ignore] = false if no && !kwargs.key?(:ignore)
1702
1705
  [].tap do |ret|
1703
1706
  list.flatten.each do |flag|
1704
1707
  next unless (val = option(flag, target: target, **kwargs))
1705
1708
 
1706
- if val == '0' && no
1709
+ if no && val == '0'
1707
1710
  flag = "no-#{flag}"
1708
1711
  val = nil
1709
1712
  end
@@ -1804,6 +1807,12 @@ module Squared
1804
1807
  print_error(e, subject: name)
1805
1808
  end
1806
1809
 
1810
+ def parse_env(key)
1811
+ env(key) do |val|
1812
+ val.start_with?('-') ? shell_parse(val) : split_escape(val).map! { |opt| fill_option(opt) }
1813
+ end || []
1814
+ end
1815
+
1807
1816
  def param_guard(action, flag, args:, key: nil, pat: nil, values: nil)
1808
1817
  if args && key
1809
1818
  val = args.fetch(key, nil)
@@ -1841,7 +1850,7 @@ module Squared
1841
1850
  force: true, **kwargs)
1842
1851
  puts unless series || printfirst?
1843
1852
  ret = choice(msg, list, multiple: multiple, force: force, **kwargs).tap do |val|
1844
- next unless val.empty?
1853
+ next unless !val || val.empty?
1845
1854
 
1846
1855
  exit 1 if force
1847
1856
  return nil
@@ -2012,7 +2021,7 @@ module Squared
2012
2021
  end
2013
2022
 
2014
2023
  def indexerror(val, list = nil)
2015
- raise_error IndexError, "requested index #{val}", hint: list && "of #{list.size}"
2024
+ raise_error IndexError, "requested index #{val}", hint: ("of #{list.size}" if list)
2016
2025
  end
2017
2026
 
2018
2027
  def indexchar
@@ -2333,15 +2342,33 @@ module Squared
2333
2342
  end
2334
2343
 
2335
2344
  def has_value?(target, *args)
2345
+ return false unless target.is_a?(Enumerable)
2346
+
2336
2347
  args = args.first if args.size == 1 && args.first.is_a?(Enumerable)
2337
2348
  case target
2338
2349
  when Hash
2339
2350
  args.is_a?(Enumerable) ? args.any? { |obj| target.value?(obj) } : target.value?(args)
2340
- when Enumerable
2341
- args.is_a?(Enumerable) ? args.any? { |obj| target.include?(obj) } : target.include?(args)
2342
2351
  else
2343
- false
2352
+ args.is_a?(Enumerable) ? args.any? { |obj| target.include?(obj) } : target.include?(args)
2353
+ end
2354
+ end
2355
+
2356
+ def has_value!(target, *args, first: false)
2357
+ return unless target.is_a?(Enumerable)
2358
+
2359
+ args = args.first if args.size == 1 && args.first.is_a?(Enumerable)
2360
+ found = false
2361
+ args.each do |val|
2362
+ if target.respond_to?(:delete?)
2363
+ found = true if target.delete?(val)
2364
+ elsif target.respond_to?(:delete)
2365
+ found = true if target.delete(val)
2366
+ elsif target.include?(val)
2367
+ found = true
2368
+ end
2369
+ break if found && first
2344
2370
  end
2371
+ target if found
2345
2372
  end
2346
2373
 
2347
2374
  def variables
@@ -154,12 +154,8 @@ module Squared
154
154
  task action, [:command] do |_, args|
155
155
  command = param_guard(action, 'command', args: args, key: :command)
156
156
  args = args.extras
157
- a = args.delete('a') || args.delete('all')
158
157
  ls = case command
159
- when 'network'
160
- a = nil
161
- 'ls'
162
- when 'image', 'container'
158
+ when 'image', 'container', 'network'
163
159
  'ls'
164
160
  when 'compose'
165
161
  'ps'
@@ -167,7 +163,7 @@ module Squared
167
163
  raise_error ArgumentError, 'unrecognized command', hint: command
168
164
  end
169
165
  data = VAL_DOCKER[:ls][command.to_sym]
170
- if args.delete('s') || args.delete('standard')
166
+ if has_value!(args, 's', 'standard')
171
167
  cols = data.first(data.index('CreatedAt'))
172
168
  else
173
169
  cols = []
@@ -184,7 +180,8 @@ module Squared
184
180
  cols = choice_index('Select a column', data, multiple: true, force: true, attempts: 1)
185
181
  end
186
182
  end
187
- cmd = docker_output(command, ls, a && '-a')
183
+ cmd = docker_output command, ls
184
+ cmd << '-a' unless command == 'network' || !has_value!(args, 'a', 'all')
188
185
  cmd << quote_option('format', "table #{cols.map! { |val| "{{.#{val}}}" }.join("\t")}")
189
186
  run(cmd, banner: false, from: :ls)
190
187
  end
@@ -949,8 +946,7 @@ module Squared
949
946
  end
950
947
 
951
948
  def tagjoin(*args, char: '/')
952
- args.compact!
953
- args.join(char) unless args.empty?
949
+ args.join(char) unless (args = args.compact).empty?
954
950
  end
955
951
 
956
952
  def tagname(val)
@@ -31,7 +31,7 @@ module Squared
31
31
  return self
32
32
  end
33
33
  if base
34
- base = base.match?(GIT_PROTO) ? "#{base.chomp('/')}/" : @root + base
34
+ base = base.match?(GIT_PROTO) ? "#{base.chomp('/')}/" : rootpath(base)
35
35
  repo.each do |target|
36
36
  if target.is_a?(Project::Git)
37
37
  data[target.localname] = target.project
@@ -50,7 +50,7 @@ module Squared
50
50
  end
51
51
  unless uri.match?(GIT_PROTO) || Pathname.new(uri).absolute?
52
52
  if uri.start_with?('.')
53
- uri = @root + uri
53
+ uri = rootpath uri
54
54
  elsif base
55
55
  uri = base + uri
56
56
  else
@@ -154,9 +154,9 @@ module Squared
154
154
  namespace=p].freeze,
155
155
  add: %w[A e|edit f|force ignore-errors ignore-missing i|interactive n|dry-run p|patch pathspec-file-nul
156
156
  refresh renormalize sparse u|update v|verbose chmod=b pathspec-from-file=p].freeze,
157
- branch: %w[a|all create-reflog i|ignore-case omit-empty q|quiet r|remotes v|verbose abbrev=i color=b column=b
158
- contains=b format=q merged=b no-contains=b no-merged=b points-at=b u|set-upstream-to=b sort=q
159
- t|track=b].freeze,
157
+ branch: %w[a|all create-reflog i|ignore-case omit-empty q|quiet r|remotes v|verbose=+ abbrev=i color=b
158
+ column=b contains=b format=q merged=b no-contains=b no-merged=b points-at=b u|set-upstream-to=b
159
+ sort=q t|track=b].freeze,
160
160
  checkout: %w[l d|detach f|force ignore-other-worktrees ignore-skip-worktree-bits m|merge p|patch
161
161
  pathspec-file-nul q|quiet ours theirs conflict=b orphan=b pathspec-from-file=p t|track=b].freeze,
162
162
  diff: {
@@ -183,9 +183,9 @@ module Squared
183
183
  A|after-context=i B|before-context=i color=b C|context=i m|max-count=n max-depth=i
184
184
  open-files-in-pager=b threads=n].freeze,
185
185
  mv: %w[k f|force n|dry-run v|verbose].freeze,
186
- revert: %w[e S=bm? abort continue n|no-commit quit reference skip cleanup=b gpg-sign=b? m|mainline=i
187
- s|signoff strategy=b X|strategy-option=b].freeze,
188
- rm: %w[r cached f|force n|dry-run ignore-unmatch pathspec-file-nul q|quiet sparse v|verbose
186
+ revert: %w[e S=bm? n|no-commit reference cleanup=b gpg-sign=b? m|mainline=i s|signoff strategy=b
187
+ X|strategy-option=b].freeze,
188
+ rm: %w[r cached f|force n|dry-run ignore-unmatch pathspec-file-nul q|quiet sparse
189
189
  pathspec-from-file=p].freeze
190
190
  }.freeze,
191
191
  log: {
@@ -245,7 +245,7 @@ module Squared
245
245
  pop: %w[index].freeze,
246
246
  apply: %w[index].freeze
247
247
  }.freeze,
248
- status: %w[z u=bm? b|branch long s|short show-stash v|verbose column=b find-renames=i? ignore-submodules=b?
248
+ status: %w[z u=bm? b|branch long s|short show-stash v|verbose=+ column=b find-renames=i? ignore-submodules=b?
249
249
  ignored=b? porcelain=b? untracked-files=b?].freeze,
250
250
  submodule: {
251
251
  status: %w[cached recursive].freeze,
@@ -296,7 +296,8 @@ module Squared
296
296
  send: %w[continue skip abort quit].freeze,
297
297
  value: %w[true false merges interactive].freeze
298
298
  }.freeze,
299
- reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze
299
+ reset: %w[soft mixed hard merge keep recurse-submodules no-recurse-submodules].freeze,
300
+ revbuild: %w[untracked-files ignore-submodules ignored].freeze
300
301
  }.freeze
301
302
  private_constant :OPT_GIT, :VAL_GIT
302
303
 
@@ -1151,7 +1152,7 @@ module Squared
1151
1152
  append_option(OptionPartition.select(OPT_GIT[:stash][:push], no: false), no: true, ignore: false)
1152
1153
  append_message
1153
1154
  end
1154
- source(banner: !quiet?, sync: sync, **threadargs)
1155
+ source(sync: sync, banner: !quiet?, **threadargs)
1155
1156
  end
1156
1157
 
1157
1158
  def status(flag = nil, opts = [])
@@ -1217,22 +1218,22 @@ module Squared
1217
1218
  kwargs = kwargs.key?(:include) || kwargs.key?(:exclude) ? statusargs.call : @revbuild || {}
1218
1219
  case flag
1219
1220
  when :build
1220
- op = OptionPartition.new(opts, %w[ignore-submodules=b? ignored=b? untracked-files=b?], project: self)
1221
+ op = OptionPartition.new(opts, VAL_GIT[:revbuild].map { |key| "#{key}=b?" }, project: self)
1221
1222
  op.clear(append: true)
1222
1223
  args = op.to_a
1223
1224
  else
1224
- args = [
1225
- option('untracked-files', prefix: 'git') { |val| basic_option('untracked-files', val) },
1226
- option('ignore-submodules', prefix: 'git') { |val| basic_option('ignore-submodules', val) },
1227
- option('ignored', prefix: 'git') { |val| basic_option('ignored', val) }
1228
- ].compact
1225
+ args = parse_env('GIT_OPTIONS')
1226
+ .grep(/\A--#{Regexp.union(*VAL_GIT[:revbuild])}/)
1227
+ .concat(VAL_GIT[:revbuild].map { |key| option(key, prefix: 'git') { |val| basic_option(key, val) } })
1228
+ .compact
1229
+ OptionPartition.uniq!(args)
1229
1230
  end
1230
1231
  if (cur = workspace.rev_entry(name)) && cur['revision'] == sha && !env('REVBUILD_FORCE')
1231
1232
  files = status_digest(*args, **kwargs)
1232
1233
  if cur['files'].size == files.size && cur['files'].find { |key, val| files[key] != val }.nil?
1233
1234
  workspace.rev_timeutc(name, 'build') unless (since = workspace.rev_timesince(name, 'build'))
1234
1235
  if stdout?
1235
- puts log_message(Logger::INFO, name, 'no changes', subject: 'revbuild', hint: since && "#{since} ago")
1236
+ puts log_message(Logger::INFO, name, 'no changes', subject: 'revbuild', hint: ("#{since} ago" if since))
1236
1237
  end
1237
1238
  return
1238
1239
  end
@@ -1754,7 +1755,12 @@ module Squared
1754
1755
  def git(flag, opts = [])
1755
1756
  cmd, opts = git_session(flag, opts: opts)
1756
1757
  list = OPT_GIT[:git].fetch(flag, []) + OPT_GIT.fetch(flag, [])
1757
- list.concat(OPT_GIT[:log][:diff_context]) if flag == :add
1758
+ case flag
1759
+ when :add
1760
+ list.concat(OPT_GIT[:log][:diff_context])
1761
+ when :revert
1762
+ list.concat(VAL_GIT[:rebase][:send])
1763
+ end
1758
1764
  op = OptionPartition.new(opts, list, cmd, project: self, no: OPT_GIT[:no][flag], single: /\A\d+\z/,
1759
1765
  first: case flag
1760
1766
  when :blame, :revert then nil
@@ -1766,7 +1772,7 @@ module Squared
1766
1772
  op.append(basepath(op.remove_at(n)), delim: true)
1767
1773
  .clear
1768
1774
  when :revert
1769
- if VAL_GIT[:rebase][:send].any? { |val| op.arg?(val) }
1775
+ if op.arg?(*VAL_GIT[:rebase][:send])
1770
1776
  op.clear
1771
1777
  elsif op.empty?
1772
1778
  raise_error 'no commit target'
@@ -302,22 +302,21 @@ module Squared
302
302
  end
303
303
  end
304
304
  when 'publish'
305
- format_desc(action, flag, 'otp?,d/ry-run?,p/ublic|r/estricted?',
306
- before: ('tag' if flag == :tag))
305
+ format_desc(action, flag, 'otp?,p/ublic|r/estricted?,d/ry-run?', before: ('tag' if flag == :tag))
307
306
  task flag do |_, args|
308
307
  args = args.to_a
309
- dryrun = true if args.delete('dry-run') || args.delete('d')
310
- access = if args.delete('public') || args.delete('p')
311
- 'public'
312
- elsif args.delete('restricted') || args.delete('r')
308
+ access = if has_value!(args, 'r', 'restricted')
313
309
  'restricted'
310
+ elsif has_value!(args, 'p', 'public')
311
+ 'public'
314
312
  end
313
+ dryrun = has_value!(args, 'd', 'dry-run')
315
314
  if flag == :latest
316
315
  otp = args.first
317
316
  else
318
317
  tag, otp = param_guard(action, flag, args: args)
319
318
  end
320
- publish(flag, otp: otp, tag: tag, dryrun: dryrun, access: access)
319
+ publish(flag, otp: otp, tag: tag, access: access, dryrun: dryrun)
321
320
  end
322
321
  when 'tsc'
323
322
  break unless @tsfile
@@ -325,15 +324,11 @@ module Squared
325
324
  format_desc(action, flag, 'opts*', "#{flag == :project ? 'before' : 'after'}": 'config?')
326
325
  task flag do |_, args|
327
326
  args = args.to_a
328
- if flag == :project
329
- project = if !args.empty? && exist?(args.first)
330
- args.shift
331
- else
332
- @tsfile
333
- end
334
- end
335
- watch = !(args.delete('watch') || args.delete('w')).nil?
336
- tsc(*args, banner: true, project: project, build: flag == :build, watch: watch)
327
+ tsc(*args, banner: true, "#{flag}": if flag == :build
328
+ true
329
+ else
330
+ exist?(args.first) ? args.shift : @tsfile
331
+ end, watch: has_value!(args, 'w', 'watch'))
337
332
  end
338
333
  end
339
334
  end
@@ -345,6 +340,8 @@ module Squared
345
340
 
346
341
  def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, files: nil, workspace: false,
347
342
  link: false, force: false, override: false, sync: invoked_sync?('copy'), **kwargs)
343
+ return if @copy == false
344
+
348
345
  glob = kwargs[:include]
349
346
  pass = kwargs[:exclude]
350
347
  if @copy && !override
@@ -361,8 +358,6 @@ module Squared
361
358
  create = @copy[:create] if @copy.key?(:create)
362
359
  glob = @copy[:include] if @copy.key?(:include)
363
360
  pass = @copy[:exclude] if @copy.key?(:exclude)
364
- elsif @copy == false
365
- return
366
361
  end
367
362
  items = []
368
363
  if build? && path != @workspace.home && @workspace.home?
@@ -381,7 +376,7 @@ module Squared
381
376
  dest = dir
382
377
  @workspace.rev_clear(dest, sync: sync)
383
378
  when String
384
- dest = @workspace.root + dir
379
+ dest = @workspace.rootpath(dir)
385
380
  @workspace.rev_clear(dest, sync: sync)
386
381
  when Symbol
387
382
  dest = if (proj = @workspace.find(name: dir))
@@ -918,12 +913,9 @@ module Squared
918
913
  end
919
914
 
920
915
  def bump(flag, val = nil)
921
- if flag != :version
922
- val = sembump version, flag
923
- return if val == version
924
- elsif !val
925
- return
926
- end
916
+ val = sembump version, flag unless flag == :version
917
+ return unless val
918
+
927
919
  doc = dependfile.read
928
920
  if doc.sub!(/"version"\s*:\s*"#{version}"/, "\"version\": \"#{val}\"")
929
921
  unless dryrun?
@@ -7,16 +7,16 @@ module Squared
7
7
  DEP_PYTHON = %w[poetry.lock setup.cfg pyproject.toml setup.py requirements.txt].freeze
8
8
  DIR_PYTHON = (DEP_PYTHON + %w[README.rst]).freeze
9
9
  OPT_PYTHON = {
10
- common: %w[b B d E h i I O P q s S u v x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
10
+ common: %w[b=+ B d E h i I O P q=+ s S u v=+ x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
11
11
  build: %w[n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel C|config-setting=q installer=b
12
12
  o|outdir=p].freeze,
13
13
  venv: %w[clear copies symlinks system-site-packages upgrade upgrade-deps without-scm-ignore-files without-pip
14
14
  prompt=q].freeze
15
15
  }.freeze
16
16
  OPT_PIP = {
17
- common: %w[debug disable-pip-version-check isolated no-cache-dir no-color no-input q|quiet require-virtualenv
18
- v|verbose cache-dir=p cert=p client-cert=p exists-action=b keyring-provider=b log=p proxy=q
19
- python=q resume-retries=i retries=i timeout=i trusted-host=b use-deprecated=b
17
+ common: %w[debug disable-pip-version-check isolated no-cache-dir no-color no-input require-virtualenv
18
+ q|quiet=+ v|verbose=+ cache-dir=p cert=p client-cert=p exists-action=b keyring-provider=b log=p
19
+ proxy=q python=q resume-retries=i retries=i timeout=i trusted-host=b use-deprecated=b
20
20
  use-feature=b].freeze,
21
21
  cache: %w[format=b].freeze,
22
22
  completion: %w[b|bash f|fish p|powershell z|zsh].freeze,
@@ -43,21 +43,21 @@ module Squared
43
43
  wheel: %w[no-verify w|wheel-dir=p].freeze
44
44
  }.freeze
45
45
  OPT_POETRY = {
46
- common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet v|verbose P|project=p].freeze,
46
+ common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet=+ v|verbose=+ P|project=p].freeze,
47
47
  build: %w[clean config-settings=qq f|format=b o|output=p].freeze,
48
48
  publish: %w[build dry-run skip-existing cert=p client-cert=p dist-dir=p p|password=b r|repository=q
49
49
  u|username=b].freeze
50
50
  }.freeze
51
51
  OPT_PDM = {
52
52
  common: %w[I|ignore-python no-cache n|non-interactive].freeze,
53
- build: %w[C=bm no-clean no-isolation no-sdist no-wheel quiet verbose config-setting=q d|dest=p p|project=p
54
- k|skip=b].freeze,
55
- publish: %w[no-build no-very-ssl quiet S|sign skip-existing verbose ca-certs=p c|comment=q d|dest=p
53
+ build: %w[C=bm no-clean no-isolation no-sdist no-wheel q|quiet v|verbose=+ config-setting=q d|dest=p
54
+ p|project=p k|skip=b].freeze,
55
+ publish: %w[no-build no-very-ssl q|quiet S|sign skip-existing v|verbose=+ ca-certs=p c|comment=q d|dest=p
56
56
  i|identity=b P|password=q p|project=p r|repository=q k|skip=b u|username=b].freeze
57
57
  }.freeze
58
58
  OPT_HATCH = {
59
59
  common: %w[color interactive no-color no-interactive cache-dir=p config=p data-dir=p e|env=b p|project=b
60
- q|quiet v|verbose].freeze,
60
+ q|quiet=+ v|verbose=+].freeze,
61
61
  build: %w[clean-hooks-after ext hooks-only no-hooks c|clean t|target=b].freeze,
62
62
  publish: %w[initialize-auth n|no-prompt y|yes a|auth=q ca-cert=p client-cert=p client-key=p o|option=q
63
63
  p|publisher=b r|repo=q u|user=q].freeze
@@ -923,6 +923,8 @@ module Squared
923
923
  case flag
924
924
  when :python
925
925
  /\A(?:v+|q+|b+)\z/
926
+ when :pdm
927
+ /\Av+\z/
926
928
  when :twine
927
929
  nil
928
930
  else
@@ -217,33 +217,41 @@ module Squared
217
217
  when 'rake'
218
218
  next unless rakefile
219
219
 
220
- format_desc action, nil, "task+,opts*|#{indexchar}index+|#,pattern*"
220
+ format_desc action, nil, "task+|#{indexchar}index+,opts*|#,pattern*"
221
221
  task action, [:command] do |_, args|
222
222
  if args.command == '#'
223
223
  format_list(raketasks, "rake[#{indexchar}N]", 'tasks', grep: args.extras, from: rakefile, &:join)
224
224
  else
225
- items, opts = args.to_a.partition { |val| indexitem(val) }
226
- if items.empty?
227
- rake(banner: true, opts: opts)
228
- else
229
- tasks = raketasks
230
- while (n, pre = indexitem(items.shift))
225
+ tasks = raketasks
226
+ cmd = nil
227
+ opts = []
228
+ queue = lambda do
229
+ if cmd
230
+ cmd += "[#{opts.join(',')}]" unless opts.empty?
231
+ rake(cmd, banner: true)
232
+ cmd = nil
233
+ elsif !opts.empty?
234
+ rake(banner: true, opts: opts)
235
+ end
236
+ opts.clear
237
+ end
238
+ args.to_a.each do |item|
239
+ if (n, pre = indexitem(item))
240
+ queue.call
231
241
  if (item = tasks[n.pred])
232
- cmd = pre ? "#{pre} #{item.first}" : item.first
242
+ cmd = [pre, item.first].compact.join(' ')
233
243
  elsif exception
234
244
  indexerror n, tasks
235
245
  else
236
246
  log.warn "rake task #{n} of #{tasks.size} (out of range)"
237
- next
238
- end
239
- if opts.empty?
240
- rake(cmd, banner: true)
241
- else
242
- rake(cmd + "[#{opts.join(',')}]", banner: true)
243
247
  opts.clear
248
+ next
244
249
  end
250
+ else
251
+ opts << item
245
252
  end
246
253
  end
254
+ queue.call
247
255
  end
248
256
  end
249
257
  when 'irb'
@@ -344,9 +352,9 @@ module Squared
344
352
  end
345
353
  gem(flag, opts: opts, banner: true, filter: {
346
354
  semver: semver,
347
- update: opts.delete('u') || opts.delete('update'),
348
- interactive: opts.delete('i') || opts.delete('interactive'),
349
- select: opts.delete('s') || opts.delete('select')
355
+ update: has_value!(opts, 'u', 'update'),
356
+ interactive: has_value!(opts, 'i', 'interactive'),
357
+ select: has_value!(opts, 's', 'select')
350
358
  })
351
359
  end
352
360
  when :build, :push, :exec, :update
@@ -390,7 +398,7 @@ module Squared
390
398
  format_desc action, flag, 'f/orce?,opts*'
391
399
  task flag do |_, args|
392
400
  opts = args.to_a
393
- opts << 'redownload' if opts.delete('f') || opts.delete('force')
401
+ opts << 'redownload' if has_value!(opts, 'f', 'force')
394
402
  if (lock = basepath('Gemfile.lock')).exist?
395
403
  config = basepath '.bundle', 'config'
396
404
  if config.exist? && config.read.match?(/\bBUNDLE_FROZEN:\s+"true"/)
@@ -476,17 +484,17 @@ module Squared
476
484
  end
477
485
 
478
486
  def copy(from: gemlib, into: @gemdir, override: false, **kwargs)
487
+ return if @copy == false
488
+
479
489
  glob = kwargs[:include]
480
490
  pass = kwargs[:exclude]
481
491
  if @copy && !override
482
492
  return super unless @copy.is_a?(Hash)
483
493
 
484
494
  from = @copy[:from] if @copy.key?(:from)
495
+ into = @copy[:into] if @copy.key?(:into)
485
496
  glob = @copy[:include] if @copy.key?(:include)
486
497
  pass = @copy[:exclude] if @copy.key?(:exclude)
487
- into = @copy[:into] if @copy.key?(:into)
488
- elsif @copy == false
489
- return
490
498
  end
491
499
  return unless into
492
500
 
@@ -509,8 +517,8 @@ module Squared
509
517
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
510
518
  cmd = bundle_output 'outdated'
511
519
  if flag
512
- se = (opts.delete('s') || opts.delete('select')) && !stdin?
513
- up = opts.delete('u') || opts.delete('update')
520
+ se = has_value!(opts, 's', 'select') && !stdin?
521
+ up = has_value!(opts, 'u', 'update')
514
522
  cmd << "--#{flag}"
515
523
  OptionPartition.new(opts, bundleopts(:outdated), cmd, project: self)
516
524
  .clear
@@ -743,6 +751,7 @@ module Squared
743
751
  end
744
752
  out.map!(&:split)
745
753
  pad = out.map(&:first).map!(&:size).max
754
+ print_item
746
755
  puts(out.map! { |line| '%*s %s' % [pad, line.first, line[1..-1].join(' ')] })
747
756
  end
748
757
  return
@@ -1134,9 +1143,7 @@ module Squared
1134
1143
  output = val.match?(/(?:un)?set/)
1135
1144
  else
1136
1145
  a = op.dup
1137
- b = op.shift
1138
- c = op.shift
1139
- d = op.shift
1146
+ b, c, d = op.slice!(0, 3)
1140
1147
  e = op.arg?('global', 'local')
1141
1148
  op << b
1142
1149
  getname = -> { op << (c || readline('Enter name', force: true)) }
@@ -11,7 +11,7 @@ module Squared
11
11
  extend Forwardable
12
12
 
13
13
  OPT_NAME = /\A(?:(--)|-)((?(1)[^\[\]=\s-][^\[\]=\s]*|[^\[\]=\s-]))\z/
14
- OPT_VALUE = /\A-{0,2}([^\[\]=\s-][^\[\]=\s]*)(?:\s*=\s*|\s+)(.+)\z/
14
+ OPT_VALUE = /\A-{0,2}([^\[\]=\s-][^\[\]=\s]*)(?:=|\s+)(\S.*)\z/
15
15
  OPT_SINGLE = /\A-([^\[\]=\s-])(.+)\z/
16
16
  private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE
17
17
 
@@ -27,9 +27,9 @@ module Squared
27
27
  target << '--' if delim && !target.include?('--')
28
28
  if strip
29
29
  pat, s = Array(strip)
30
- ret.map! { |val| val.gsub(pat, s || '') }
30
+ ret.map! { |val| val.is_a?(String) ? val.gsub(pat, s || '') : val }
31
31
  end
32
- ret, err = ret.partition { |val| filter.match?(val) } if filter
32
+ ret, err = ret.partition { |val| filter.match?(val.to_s) } if filter
33
33
  if block_given?
34
34
  out = []
35
35
  err ||= []
@@ -119,11 +119,16 @@ module Squared
119
119
  def arg?(target, *args, value: false, **)
120
120
  r, s = args.partition { |val| val.is_a?(Regexp) }
121
121
  r << matchopts(s, value) unless s.empty?
122
- s = target.to_a.compact
123
- r.any? { |pat| s.any?(pat) }
122
+ a = target.to_a
123
+ if (n = a.index('--'))
124
+ a = a[0..n]
125
+ end
126
+ r.any? { |pat| a.any?(pat) }
124
127
  end
125
128
 
126
129
  def opt?(val)
130
+ return false unless val.is_a?(String)
131
+
127
132
  val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
128
133
  end
129
134
 
@@ -146,13 +151,13 @@ module Squared
146
151
  end
147
152
 
148
153
  def shortopt(*group)
149
- group.map! { |s| s.delete_prefix('-') }
150
- "-(?:#{Regexp.escape(group.join('|'))})(?:\\z|[^ =]| +[^ -])"
154
+ group.map! { |s| Regexp.escape(s.delete_prefix('-')) }
155
+ "-(?:#{group.join('|')})(?:\\z|[^ =]| +[^ -])"
151
156
  end
152
157
 
153
158
  def longopt(*group, value)
154
- group.map! { |s| s.delete_prefix('--') }
155
- "--(?:#{Regexp.escape(group.join('|'))})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
159
+ group.map! { |s| Regexp.escape(s.delete_prefix('--')) }
160
+ "--(?:#{group.join('|')})(?:#{value ? '=[^ ]| +[^ -]' : '[= ]|\z'})"
156
161
  end
157
162
  end
158
163
 
@@ -161,7 +166,8 @@ module Squared
161
166
  def_delegators :@target, :+, :-, :<<, :any?, :none?, :include?, :add, :add?, :find, :find_all, :find_index,
162
167
  :merge, :delete, :delete?, :delete_if, :grep, :grep_v, :inspect, :to_a, :to_s
163
168
  def_delegators :@extras, :empty?, :each, :each_with_index, :partition, :dup, :first, :shift, :unshift,
164
- :pop, :push, :concat, :index, :join, :map, :map!, :detect, :select, :select!, :reject, :size
169
+ :pop, :push, :concat, :index, :join, :detect, :map, :map!, :select, :select!, :slice, :slice!,
170
+ :reject, :size
165
171
 
166
172
  def_delegator :@extras, :delete, :remove
167
173
  def_delegator :@extras, :delete_at, :remove_at
@@ -193,6 +199,7 @@ module Squared
193
199
  f = []
194
200
  si = []
195
201
  bl = []
202
+ ml = []
196
203
  list.flat_map do |val|
197
204
  x, y = val.split('|', 2)
198
205
  if y
@@ -229,6 +236,9 @@ module Squared
229
236
  @values << Regexp.escape(flag)
230
237
  when '!'
231
238
  bl << flag
239
+ when '+'
240
+ ml << flag
241
+ bare << flag
232
242
  else
233
243
  next
234
244
  end
@@ -254,8 +264,10 @@ module Squared
254
264
  f.concat(tr.call(f))
255
265
  si.concat(tr.call(si))
256
266
  bl.concat(tr.call(bl))
267
+ ml.concat(tr.call(ml))
257
268
  no.concat(tr.call(no))
258
269
  end
270
+ target.multiple.concat(ml.map { |val| val.size == 1 ? "-#{val}" : "--#{val}" }) if target.is_a?(JoinSet)
259
271
  numtype = [
260
272
  [i, /\A\d+\z/],
261
273
  [f, /\A\d*(?:\.\d+)?\z/],
@@ -458,8 +470,8 @@ module Squared
458
470
  end
459
471
 
460
472
  def add_quote(*args, **kwargs)
461
- args.compact!
462
- merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
473
+ merge(args.compact
474
+ .map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
463
475
  self
464
476
  end
465
477
 
@@ -628,11 +640,22 @@ module Squared
628
640
  super[/[^:]+\z/, 0]
629
641
  end
630
642
 
631
- attr_reader :delim
643
+ alias to_ary to_a
632
644
 
633
- def initialize(data = [], delim: ' ')
634
- super(data.compact)
645
+ attr_reader :delim, :extras
646
+ attr_accessor :multiple
647
+
648
+ def initialize(data = [], delim: ' ', partition: '--', uniq: /\A--?[^\[\]=\s-]/, multiple: [])
635
649
  @delim = delim
650
+ @partition = partition
651
+ @uniq = uniq
652
+ @multiple = multiple
653
+ @extras = []
654
+ super(data.compact)
655
+ end
656
+
657
+ def insert(*args)
658
+ replace Set.new(to_ary.reject { |val| val.nil? || (val.is_a?(String) && val.empty?) }.insert(*args))
636
659
  end
637
660
 
638
661
  def last(val, pat)
@@ -641,7 +664,7 @@ module Squared
641
664
  end
642
665
 
643
666
  def pass(&blk)
644
- ret = to_a.map!(&:to_s).reject(&:empty?)
667
+ ret = to_ary.map!(&:to_s).reject(&:empty?)
645
668
  @last&.each do |val, pat, key|
646
669
  items = []
647
670
  index = nil
@@ -662,6 +685,7 @@ module Squared
662
685
  end
663
686
  ret[items.last] = val
664
687
  end
688
+ ret.concat(extras.map(&:to_s).reject(&:empty?)) unless extras.empty?
665
689
  return ret unless block_given?
666
690
 
667
691
  ret.reject(&blk)
@@ -683,18 +707,82 @@ module Squared
683
707
 
684
708
  def temp(*args, &blk)
685
709
  args.compact!
686
- ret = pass(&blk)
687
- ret = Set.new(ret.concat(args)).to_a unless args.empty?
688
- ret.join(@delim)
710
+ pass(&blk)
711
+ .concat(args)
712
+ .join(@delim)
689
713
  end
690
714
 
691
715
  def done
692
716
  to_s.tap { clear }
693
717
  end
694
718
 
719
+ def merge(enum)
720
+ if !extras.empty?
721
+ extras.concat(enum.to_a)
722
+ self
723
+ elsif (n = enum.find_index { |val| extras?(val) })
724
+ data = enum.to_a
725
+ @extras = if n == 0
726
+ data
727
+ else
728
+ super(data[0...n])
729
+ data[n..-1]
730
+ end
731
+ self
732
+ else
733
+ super
734
+ end
735
+ end
736
+
737
+ def <<(obj)
738
+ extras!(obj) || super
739
+ end
740
+
741
+ def add(obj)
742
+ extras!(obj) || super
743
+ end
744
+
745
+ def add?(obj)
746
+ extras!(obj) || super
747
+ end
748
+
749
+ def to_a
750
+ pass
751
+ end
752
+
695
753
  def to_s
696
754
  pass.join(@delim)
697
755
  end
756
+
757
+ def to_enum(*args)
758
+ pass.to_enum(*args)
759
+ end
760
+
761
+ def to_json(*args)
762
+ pass.to_json(*args)
763
+ end
764
+
765
+ def to_yaml(*args)
766
+ pass.to_yaml(*args)
767
+ end
768
+
769
+ alias push :<<
770
+ alias concat merge
771
+
772
+ private
773
+
774
+ def extras!(obj)
775
+ return if extras.empty? && !extras?(obj)
776
+
777
+ unless !extras.include?(@partition) && include?(obj) && @uniq.match?(s = obj.to_s) && !multiple.include?(s)
778
+ extras << obj
779
+ end
780
+ self
781
+ end
782
+
783
+ def extras?(obj)
784
+ obj == @partition || (include?(obj) && (!@uniq.match?(s = obj.to_s) || multiple.include?(s)))
785
+ end
698
786
  end
699
787
  end
700
788
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -124,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  requirements: []
127
- rubygems_version: 3.7.2
127
+ rubygems_version: 3.6.9
128
128
  specification_version: 4
129
129
  summary: Rake task generator for managing multi-language workspaces.
130
130
  test_files: []