squared 0.6.0 → 0.6.1
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 +34 -0
- data/lib/squared/common/shell.rb +48 -33
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/project/base.rb +6 -6
- data/lib/squared/workspace/project/git.rb +23 -19
- data/lib/squared/workspace/project/python.rb +2 -2
- data/lib/squared/workspace/project/ruby.rb +130 -3
- data/lib/squared/workspace/project/support/class.rb +13 -6
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a3b6e4109938a7ee4ddc9d778c798ad412cd2941a6b887cc62f9bd39779b4ad
|
|
4
|
+
data.tar.gz: 6912a295b0e64223d3130d8793bce44e954c0903fd74b65eb0f420726a41f82d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 137851028240806e553b125ec638df63cb20c25b6f73328a1c08f7af7603d666a1b61ff04dde1da27995a13d0bf2a6c28e644d20b6e8beb6e26fba061191d908
|
|
7
|
+
data.tar.gz: 21c7fce48d7638aa90b9c0ef40282b30557205065f6117e0602248771cee9e628910f90125295dac4a831615adda43296112809b437f31b4db0aa9d3f03de437
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.1] - 2025-11-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Ruby method rbs supports stored command options.
|
|
8
|
+
- Ruby command rbs with Steep target was created.
|
|
9
|
+
- Common shell defined String instance method stripquote.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Project base method run argument series was backwards.
|
|
14
|
+
- Project base choice range did not detect empty list result.
|
|
15
|
+
|
|
16
|
+
## [0.5.13] - 2025-11-05
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- See `0.4.27`.
|
|
21
|
+
|
|
22
|
+
## [0.4.27] - 2025-11-05
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- OptionPartition does not add quotes when an option flag is detected.
|
|
27
|
+
- Common shell method argument option only parses options with values.
|
|
28
|
+
- Shell options with empty flags are treated as quoted strings.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- OptionPartition did not detect flags with middle dashes.
|
|
33
|
+
|
|
3
34
|
## [0.6.0] - 2025-10-31
|
|
4
35
|
|
|
5
36
|
### Added
|
|
@@ -1277,7 +1308,9 @@
|
|
|
1277
1308
|
|
|
1278
1309
|
- Changelog was created.
|
|
1279
1310
|
|
|
1311
|
+
[0.6.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.1
|
|
1280
1312
|
[0.6.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.0
|
|
1313
|
+
[0.5.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.13
|
|
1281
1314
|
[0.5.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.12
|
|
1282
1315
|
[0.5.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.11
|
|
1283
1316
|
[0.5.10]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.10
|
|
@@ -1291,6 +1324,7 @@
|
|
|
1291
1324
|
[0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
|
|
1292
1325
|
[0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
|
|
1293
1326
|
[0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
|
|
1327
|
+
[0.4.27]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.27
|
|
1294
1328
|
[0.4.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.26
|
|
1295
1329
|
[0.4.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.25
|
|
1296
1330
|
[0.4.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.24
|
data/lib/squared/common/shell.rb
CHANGED
|
@@ -6,11 +6,16 @@ require 'shellwords'
|
|
|
6
6
|
module Squared
|
|
7
7
|
module Common
|
|
8
8
|
module Shell
|
|
9
|
+
QUOTE_VALUE = /\A(["'])(.*)\1\z/m.freeze
|
|
10
|
+
private_constant :QUOTE_VALUE
|
|
11
|
+
|
|
12
|
+
String.define_method(:stripquote) { sub(QUOTE_VALUE, '\2') }
|
|
13
|
+
|
|
9
14
|
module_function
|
|
10
15
|
|
|
11
16
|
def shell_escape(val, quote: false, force: false, double: false, option: false, override: false)
|
|
12
|
-
if (r = /\A(--?)([
|
|
13
|
-
if (data = r[2].match(
|
|
17
|
+
if (r = /\A(--?)([^=\s]+)((=|\s+)(["'])?(?(5)(.*)\5|(.*)))?\z/m.match(val = val.to_s))
|
|
18
|
+
if (data = r[2].match(QUOTE_VALUE))
|
|
14
19
|
double = data[1] == '"'
|
|
15
20
|
override = true
|
|
16
21
|
elsif !r[3] || r[6]
|
|
@@ -25,9 +30,9 @@ module Squared
|
|
|
25
30
|
|
|
26
31
|
r[7]
|
|
27
32
|
end
|
|
28
|
-
r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt,
|
|
29
|
-
elsif option && val =~ /\A([
|
|
30
|
-
return val if $2.match?(
|
|
33
|
+
r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt, force: force, double: double, override: override)
|
|
34
|
+
elsif option && val =~ /\A(-{0,2}[^\[\]=\s-][^\[\]=\s]*)=(.+)\z/m
|
|
35
|
+
return val if $2.match?(QUOTE_VALUE)
|
|
31
36
|
|
|
32
37
|
"#{$1}=%s" % if $2.include?(' ')
|
|
33
38
|
shell_quote($2, option: false)
|
|
@@ -37,7 +42,7 @@ module Squared
|
|
|
37
42
|
Shellwords.escape($2)
|
|
38
43
|
end
|
|
39
44
|
elsif Rake::Win32.windows?
|
|
40
|
-
quote ? shell_quote(val,
|
|
45
|
+
quote ? shell_quote(val, force: force, double: double) : val
|
|
41
46
|
elsif val.empty?
|
|
42
47
|
''
|
|
43
48
|
else
|
|
@@ -45,46 +50,56 @@ module Squared
|
|
|
45
50
|
end
|
|
46
51
|
end
|
|
47
52
|
|
|
48
|
-
def shell_quote(val, option: true, force: true, double: false, override: false)
|
|
53
|
+
def shell_quote(val, option: true, force: true, double: false, preserve: true, override: false)
|
|
49
54
|
val = val.to_s
|
|
50
55
|
return val if (!force && !val.include?(' ')) || val.empty?
|
|
51
56
|
|
|
52
|
-
if option
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
if option
|
|
58
|
+
pat = /\A(?:-[^\[\]=\s-](?:=|\s+)?|(--)?[^\[\]=\s-][^\[\]=\s]*(?(1)(?:=|\s+)|=))(["']).+\2\z/m
|
|
59
|
+
return val if val.match?(pat)
|
|
60
|
+
end
|
|
61
|
+
q = ->(s) { s.gsub("'\\\\''", "'") }
|
|
62
|
+
if val =~ QUOTE_VALUE
|
|
63
|
+
return val if $1 == '"' && Rake::Win32.windows? && val.match?(/(?:[#{File::SEPARATOR} ]|\\")/o)
|
|
64
|
+
|
|
65
|
+
base = $2 unless preserve
|
|
66
|
+
end
|
|
67
|
+
if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
|
68
|
+
"\"#{q.call(base || val).gsub(/(?<!\\)"/, '\\"')}\""
|
|
56
69
|
else
|
|
57
|
-
"'#{val.gsub("'", "'\\\\''")}'"
|
|
70
|
+
base ? val : "'#{q.call(val).gsub("'", "'\\\\''")}'"
|
|
58
71
|
end
|
|
59
72
|
end
|
|
60
73
|
|
|
61
74
|
def shell_option(flag, val = nil, sep: '=', escape: true, quote: true, force: true, double: false, merge: false,
|
|
62
75
|
override: false)
|
|
63
76
|
flag = flag.to_s
|
|
64
|
-
if flag =~
|
|
77
|
+
if flag =~ QUOTE_VALUE
|
|
65
78
|
double = $1 == '"'
|
|
66
79
|
flag = $2
|
|
67
80
|
escape = false
|
|
68
81
|
override = true
|
|
69
82
|
end
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
sep = unless flag.empty?
|
|
84
|
+
if flag[0] == '-'
|
|
85
|
+
flag[1] == '-' ? sep : ' '
|
|
86
|
+
elsif flag.size == 1
|
|
87
|
+
pre = '-'
|
|
88
|
+
merge ? '' : ' '
|
|
89
|
+
else
|
|
90
|
+
pre = '--'
|
|
91
|
+
sep
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
"#{pre}#{flag}#{unless val.nil?
|
|
95
|
+
"#{sep}#{if escape
|
|
96
|
+
shell_escape(val, quote: quote, double: double, override: override)
|
|
97
|
+
elsif quote
|
|
98
|
+
shell_quote(val, option: false, force: force, double: double, override: override)
|
|
99
|
+
else
|
|
100
|
+
val
|
|
101
|
+
end}"
|
|
102
|
+
end}"
|
|
88
103
|
end
|
|
89
104
|
|
|
90
105
|
def shell_split(val, join: nil, **kwargs)
|
|
@@ -131,8 +146,8 @@ module Squared
|
|
|
131
146
|
|
|
132
147
|
def shell_bin(name, env: true)
|
|
133
148
|
key = name.upcase
|
|
134
|
-
shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
|
|
135
|
-
|
|
149
|
+
shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
|
|
150
|
+
option: false, force: false, double: true)
|
|
136
151
|
end
|
|
137
152
|
|
|
138
153
|
def line_width(lines)
|
data/lib/squared/version.rb
CHANGED
|
@@ -769,7 +769,7 @@ module Squared
|
|
|
769
769
|
end
|
|
770
770
|
break uri = url if data
|
|
771
771
|
end
|
|
772
|
-
unless data && (ext ||= URI.parse(uri).path[/\.(\w+)(?:\?|\z)/, 1])
|
|
772
|
+
unless data && (ext ||= URI.decode_www_form_component(URI.parse(uri).path[/\.([\w%]+)(?:\?|\z)/, 1]))
|
|
773
773
|
raise_error(data ? TypeError : RuntimeError, "no content#{data ? ' type' : ''}", hint: uri)
|
|
774
774
|
end
|
|
775
775
|
end
|
|
@@ -913,7 +913,7 @@ module Squared
|
|
|
913
913
|
end
|
|
914
914
|
|
|
915
915
|
def run(cmd = @session, var = nil, exception: self.exception, sync: true, banner: true, from: nil, chdir: path,
|
|
916
|
-
interactive: nil, hint: nil, series:
|
|
916
|
+
interactive: nil, hint: nil, series: false, **)
|
|
917
917
|
return print_error('no command session started', subject: project, hint: from, pass: true) unless cmd
|
|
918
918
|
|
|
919
919
|
cmd = cmd.target if cmd.is_a?(OptionPartition)
|
|
@@ -1468,9 +1468,9 @@ module Squared
|
|
|
1468
1468
|
printsucc
|
|
1469
1469
|
end
|
|
1470
1470
|
|
|
1471
|
-
def print_item(*val, series:
|
|
1471
|
+
def print_item(*val, series: false)
|
|
1472
1472
|
puts unless printfirst?
|
|
1473
|
-
printsucc
|
|
1473
|
+
printsucc unless series
|
|
1474
1474
|
puts val unless val.empty? || (val.size == 1 && !val.first)
|
|
1475
1475
|
end
|
|
1476
1476
|
|
|
@@ -1841,7 +1841,7 @@ module Squared
|
|
|
1841
1841
|
force: true, **kwargs)
|
|
1842
1842
|
puts unless series || printfirst?
|
|
1843
1843
|
ret = choice(msg, list, multiple: multiple, force: force, **kwargs).tap do |val|
|
|
1844
|
-
next unless val.
|
|
1844
|
+
next unless val.empty?
|
|
1845
1845
|
|
|
1846
1846
|
exit 1 if force
|
|
1847
1847
|
return nil
|
|
@@ -1853,7 +1853,7 @@ module Squared
|
|
|
1853
1853
|
ret = ret.first unless multiple
|
|
1854
1854
|
end
|
|
1855
1855
|
if accept
|
|
1856
|
-
hint = Array(ret).map { |val| sub_style(val, styles: theme[:inline]) }.join(', ')
|
|
1856
|
+
hint = Array(ret).map { |val| sub_style(val.to_s, styles: theme[:inline]) }.join(', ')
|
|
1857
1857
|
accept = Array(accept).map { |val| Array(val) }
|
|
1858
1858
|
ret = Array(ret) if accept.any? { |val| val[1] == true }
|
|
1859
1859
|
loop do
|
|
@@ -462,15 +462,18 @@ module Squared
|
|
|
462
462
|
when :add, :sign
|
|
463
463
|
format_desc action, flag, 'name,message?,commit?,remote?'
|
|
464
464
|
task flag, [:name, :message, :commit, :remote] do |_, args|
|
|
465
|
-
if (name = args.name)
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
465
|
+
remote = if (name = args.name)
|
|
466
|
+
message = args.message
|
|
467
|
+
commit = commithead args.commit
|
|
468
|
+
args.remote
|
|
469
|
+
else
|
|
470
|
+
commit, name, message = choice_commit(reflog: false, series: true,
|
|
471
|
+
values: [
|
|
472
|
+
['Enter tag name', true],
|
|
473
|
+
'Enter message'
|
|
474
|
+
])
|
|
475
|
+
choice_remote
|
|
476
|
+
end
|
|
474
477
|
tag(flag, refs: [name], message: message, commit: commit, remote: remote).tap do |ret|
|
|
475
478
|
success?(ret, !remote)
|
|
476
479
|
end
|
|
@@ -996,7 +999,7 @@ module Squared
|
|
|
996
999
|
end
|
|
997
1000
|
end
|
|
998
1001
|
append_pull(opts, OPT_GIT[:pull] + OPT_GIT[:fetch][:pull],
|
|
999
|
-
no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull]
|
|
1002
|
+
flag: flag, from: :pull, remote: remote, no: OPT_GIT[:no][:pull] + OPT_GIT[:no][:fetch][:pull])
|
|
1000
1003
|
source(sync: sync, sub: if stdout?
|
|
1001
1004
|
[
|
|
1002
1005
|
opt_style(color(:red), /^(.+)(\|\s+\d+\s+)([^-]*)(-+)(.*)$/, 4),
|
|
@@ -1044,8 +1047,8 @@ module Squared
|
|
|
1044
1047
|
def fetch(flag = nil, opts = [], sync: invoked_sync?('fetch', flag), remote: nil)
|
|
1045
1048
|
opts = git_session('fetch', opts: opts).last
|
|
1046
1049
|
opts << 'all' if flag == :all || option('all')
|
|
1047
|
-
append_pull(opts, collect_hash(OPT_GIT[:fetch]),
|
|
1048
|
-
|
|
1050
|
+
append_pull(opts, collect_hash(OPT_GIT[:fetch]), flag: flag, from: :fetch, remote: remote,
|
|
1051
|
+
no: collect_hash(OPT_GIT[:no][:fetch]))
|
|
1049
1052
|
source(sync: sync, **threadargs)
|
|
1050
1053
|
end
|
|
1051
1054
|
|
|
@@ -1427,7 +1430,7 @@ module Squared
|
|
|
1427
1430
|
return ret
|
|
1428
1431
|
end
|
|
1429
1432
|
message ||= messageopt
|
|
1430
|
-
|
|
1433
|
+
unless message || amend
|
|
1431
1434
|
return if pass
|
|
1432
1435
|
|
|
1433
1436
|
message = readline('Enter message', force: true)
|
|
@@ -1638,10 +1641,10 @@ module Squared
|
|
|
1638
1641
|
case flag
|
|
1639
1642
|
when :create
|
|
1640
1643
|
cmd << quote_option(branch.delete_prefix!('^') ? 'C' : 'c', branch)
|
|
1641
|
-
cmd << case (track ||= option('track', ignore: false))
|
|
1642
|
-
when 'n', '
|
|
1644
|
+
cmd << case (track ||= option('track', ignore: false))&.downcase
|
|
1645
|
+
when 'n', '0', 'false'
|
|
1643
1646
|
'--no-track'
|
|
1644
|
-
when 'y', '
|
|
1647
|
+
when 'y', '1', 'true'
|
|
1645
1648
|
'--track'
|
|
1646
1649
|
when 'direct', 'inherit'
|
|
1647
1650
|
basic_option 'track', track
|
|
@@ -1844,9 +1847,10 @@ module Squared
|
|
|
1844
1847
|
end
|
|
1845
1848
|
if from.nil? && (from = cmd.drop(1).find { |val| val.match?(/\A[a-z]{1,2}[a-z-]*\z/) })
|
|
1846
1849
|
from = :"git:#{from}"
|
|
1850
|
+
elsif from == false
|
|
1851
|
+
from = nil
|
|
1847
1852
|
end
|
|
1848
1853
|
banner &&= cmd.temp { |val| val.start_with?(/--(?:work-tree|git-dir)/) } if cmd.respond_to?(:temp)
|
|
1849
|
-
from = nil if from == false
|
|
1850
1854
|
end
|
|
1851
1855
|
cmd = session_done cmd
|
|
1852
1856
|
log&.info cmd
|
|
@@ -1969,7 +1973,7 @@ module Squared
|
|
|
1969
1973
|
ret = {}
|
|
1970
1974
|
status_data(*args).each do |file,|
|
|
1971
1975
|
next if !glob.empty? && glob.none? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
|
1972
|
-
next if
|
|
1976
|
+
next if pass.any? { |val| File.fnmatch?(val, file, File::FNM_DOTMATCH) }
|
|
1973
1977
|
|
|
1974
1978
|
ret[file] = algorithm.hexdigest(File.read(basepath(file)))
|
|
1975
1979
|
end
|
|
@@ -1986,7 +1990,7 @@ module Squared
|
|
|
1986
1990
|
end
|
|
1987
1991
|
end
|
|
1988
1992
|
|
|
1989
|
-
def append_pull(opts, list, target: @session,
|
|
1993
|
+
def append_pull(opts, list, flag:, from:, target: @session, no: nil, remote: nil)
|
|
1990
1994
|
target << '--force' if option('f', 'force', target: target)
|
|
1991
1995
|
append_submodules(target: target, from: from)
|
|
1992
1996
|
return if !remote && opts.empty?
|
|
@@ -31,8 +31,8 @@ module Squared
|
|
|
31
31
|
root-user-action=b t|target=p upgrade-strategy=b].freeze,
|
|
32
32
|
install_a: %w[ignore-requires-python no-index pre extra-index-url=q f|find-links=q i|index-url=q no-binary=q
|
|
33
33
|
only-binary=q].freeze,
|
|
34
|
-
install_b: %w[check-build-dependencies no-build-isolation no-clean no-deps prefer-binary
|
|
35
|
-
use-pep517 c|constraint=p group=q progress-bar=b r|requirement=p src=p].freeze,
|
|
34
|
+
install_b: %w[build-constraint check-build-dependencies no-build-isolation no-clean no-deps prefer-binary
|
|
35
|
+
require-hashes use-pep517 c|constraint=p group=q progress-bar=b r|requirement=p src=p].freeze,
|
|
36
36
|
install_c: %w[C|config-settings=q e|editable=v].freeze,
|
|
37
37
|
hash: %w[a|algorithm].freeze,
|
|
38
38
|
list: %w[e|editable exclude-editable include-editable l|local no-index not-required o|outdated pre u|uptodate
|
|
@@ -20,7 +20,8 @@ module Squared
|
|
|
20
20
|
inspect multiline no-pager noautocomplete nocolorize noecho noecho-on-assignment noinspect
|
|
21
21
|
nomultiline noprompt noscript nosingleline noverbose regexp-completor sample-book-mode script
|
|
22
22
|
simple-prompt single-irb singleline tracer truncate-echo-on-assignment type-completor verbose
|
|
23
|
-
back-trace-limit=i context-mode=i prompt=b prompt-mode=b].freeze
|
|
23
|
+
back-trace-limit=i context-mode=i prompt=b prompt-mode=b].freeze,
|
|
24
|
+
rbs: %w[I=pm r=bm no-stdlib no-collection collection=p log-level=b log-output=p repo=p].freeze
|
|
24
25
|
}.freeze
|
|
25
26
|
OPT_BUNDLE = {
|
|
26
27
|
common: %w[no-color V|verbose r|retry=i].freeze,
|
|
@@ -124,6 +125,7 @@ module Squared
|
|
|
124
125
|
ruby: %w[I disable enable dump r s].freeze,
|
|
125
126
|
rake: %w[I libdir r require].freeze,
|
|
126
127
|
irb: %w[I r].freeze,
|
|
128
|
+
rbs: %w[I r repo].freeze,
|
|
127
129
|
gem: {
|
|
128
130
|
contents: %w[s spec-dir].freeze,
|
|
129
131
|
dependency: %w[s source].freeze,
|
|
@@ -159,11 +161,12 @@ module Squared
|
|
|
159
161
|
'ruby' => %i[file script version].freeze,
|
|
160
162
|
'gem' => %i[install uninstall outdated update pristine build push exec command].freeze,
|
|
161
163
|
'bundle' => %i[install update cache exec config reinstall command].freeze,
|
|
164
|
+
'rbs' => nil,
|
|
162
165
|
'rake' => nil,
|
|
163
166
|
'irb' => nil
|
|
164
167
|
})
|
|
165
168
|
|
|
166
|
-
def initialize(*, autodetect: false, gemspec: nil, asdf: 'ruby', **kwargs)
|
|
169
|
+
def initialize(*, autodetect: false, gemspec: nil, steep: 'Steepfile', asdf: 'ruby', **kwargs)
|
|
167
170
|
super
|
|
168
171
|
if @pass.include?(Ruby.ref)
|
|
169
172
|
initialize_ref Ruby.ref
|
|
@@ -179,6 +182,7 @@ module Squared
|
|
|
179
182
|
elsif gemspec
|
|
180
183
|
basepath(gemspec.include?('.') ? gemspec : "#{gemspec}.gemspec")
|
|
181
184
|
end
|
|
185
|
+
@steepfile = basepath(steep).yield_self { |file| file if file.exist? }
|
|
182
186
|
return unless rakefile && @output[0].nil? && @copy.nil? && !version && !@autodetect
|
|
183
187
|
|
|
184
188
|
begin
|
|
@@ -250,6 +254,72 @@ module Squared
|
|
|
250
254
|
name = gemname if gemlib.any? { |file| exist?(file, "#{gemname}.rb") }
|
|
251
255
|
irb(*args, opts: opts, name: name, verbose: false)
|
|
252
256
|
end
|
|
257
|
+
when 'rbs'
|
|
258
|
+
next unless @steepfile
|
|
259
|
+
|
|
260
|
+
data = {}
|
|
261
|
+
target = nil
|
|
262
|
+
File.foreach(@steepfile) do |line|
|
|
263
|
+
if line =~ /^\s*target(?:\s+|\(\s*)(?::(\S+)|(["'])(.+)\2)/
|
|
264
|
+
target = [[], []]
|
|
265
|
+
data[$1 || $3.gsub(/[: ]/, '-')] = target
|
|
266
|
+
next
|
|
267
|
+
end
|
|
268
|
+
next unless target && line =~ /^\s*(check|signature)\s+(["'])(.+)\2/
|
|
269
|
+
|
|
270
|
+
target[$1 == 'check' ? 1 : 0] << $3
|
|
271
|
+
end
|
|
272
|
+
next if data.empty?
|
|
273
|
+
|
|
274
|
+
namespace 'rbs' do
|
|
275
|
+
data.each do |key, item|
|
|
276
|
+
sig, lib = item
|
|
277
|
+
next if sig.empty? || lib.empty?
|
|
278
|
+
|
|
279
|
+
format_desc action, key, 'sig?,path*'
|
|
280
|
+
task key do |_, args|
|
|
281
|
+
args = args.to_a
|
|
282
|
+
list = []
|
|
283
|
+
lib.each do |val|
|
|
284
|
+
val = File.join(val, '**/*.rb') unless val.include?('*') || val.end_with?('.rb')
|
|
285
|
+
list.concat(Dir.glob(val, base: path))
|
|
286
|
+
end
|
|
287
|
+
if args.empty?
|
|
288
|
+
files = choice_index('Select files', list, multiple: true, force: true, series: true,
|
|
289
|
+
accept: [accept_y('Generate?')])
|
|
290
|
+
else
|
|
291
|
+
files = []
|
|
292
|
+
args.each do |val|
|
|
293
|
+
if val.include?('*')
|
|
294
|
+
files.concat(Dir.glob(val, base: path))
|
|
295
|
+
elsif !(file = basepath(val)).exist?
|
|
296
|
+
print_error(val, hint: 'not found')
|
|
297
|
+
elsif file.directory?
|
|
298
|
+
files.concat(file.glob('**/*.rb'))
|
|
299
|
+
else
|
|
300
|
+
files << val
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
list.map! { |val| basepath(val).to_s }
|
|
304
|
+
files = files.select { |val| list.include?(basepath(val).to_s) }
|
|
305
|
+
if files.empty?
|
|
306
|
+
print_error('steep', 'no files matched', hint: "#{key}:check")
|
|
307
|
+
exit 1
|
|
308
|
+
end
|
|
309
|
+
files.uniq!
|
|
310
|
+
end
|
|
311
|
+
sig = if (n = sig.index(args.first))
|
|
312
|
+
args.shift
|
|
313
|
+
sig[n]
|
|
314
|
+
elsif sig.size > 1
|
|
315
|
+
choice_index('Select a sig', sig, force: true, series: true)
|
|
316
|
+
else
|
|
317
|
+
sig.first
|
|
318
|
+
end
|
|
319
|
+
rbs(:prototype, sig, *files)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
end
|
|
253
323
|
end
|
|
254
324
|
else
|
|
255
325
|
namespace action do
|
|
@@ -1161,6 +1231,56 @@ module Squared
|
|
|
1161
1231
|
run(banner: false, from: :irb)
|
|
1162
1232
|
end
|
|
1163
1233
|
|
|
1234
|
+
def rbs(flag, *args, banner: verbose?, with: nil, pass: nil, **kwargs)
|
|
1235
|
+
case pass
|
|
1236
|
+
when NilClass
|
|
1237
|
+
pass = PASS_RUBY[:rbs]
|
|
1238
|
+
when Array
|
|
1239
|
+
pass += PASS_RUBY[:rbs]
|
|
1240
|
+
end
|
|
1241
|
+
opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
|
|
1242
|
+
cmd, opts = rbs_session(opts: opts)
|
|
1243
|
+
op = OptionPartition.new(opts, [], cmd << flag, project: self)
|
|
1244
|
+
case flag
|
|
1245
|
+
when :prototype
|
|
1246
|
+
sig = args.shift
|
|
1247
|
+
y = option('y', ignore: false)
|
|
1248
|
+
i = 1
|
|
1249
|
+
args.map { |val| basepath(val).relative_path_from(path) }.each do |file|
|
|
1250
|
+
dir = basepath sig, file.dirname
|
|
1251
|
+
dir.mkpath unless dir.exist?
|
|
1252
|
+
base = file.basename.to_s
|
|
1253
|
+
rbs = dir.join(base.stripext + '.rbs')
|
|
1254
|
+
status = if rbs.exist?
|
|
1255
|
+
case y
|
|
1256
|
+
when '0', 'false'
|
|
1257
|
+
'ignored'
|
|
1258
|
+
else
|
|
1259
|
+
next unless y || confirm_basic('Overwrite?', rbs, 'N')
|
|
1260
|
+
|
|
1261
|
+
'overwrite'
|
|
1262
|
+
end
|
|
1263
|
+
end
|
|
1264
|
+
unless status == 'ignored'
|
|
1265
|
+
ret = run(op.target.temp(File.extname(base) == '.rbi' ? 'rbi' : 'rb', file, '>', rbs), banner: false,
|
|
1266
|
+
series: true)
|
|
1267
|
+
if !ret
|
|
1268
|
+
status = 'FAIL'
|
|
1269
|
+
elsif File.empty?(rbs)
|
|
1270
|
+
status = 'empty'
|
|
1271
|
+
end
|
|
1272
|
+
end
|
|
1273
|
+
puts "#{i.to_s.rjust(2)}. #{rbs.relative_path_from(path)}".subhint(status)
|
|
1274
|
+
i += 1
|
|
1275
|
+
end
|
|
1276
|
+
else
|
|
1277
|
+
op.clear
|
|
1278
|
+
.append(*args)
|
|
1279
|
+
print_run(op, banner, **kwargs)
|
|
1280
|
+
run(banner: false, from: :"rbs:#{flag}")
|
|
1281
|
+
end
|
|
1282
|
+
end
|
|
1283
|
+
|
|
1164
1284
|
def gemspec
|
|
1165
1285
|
return @gemspec || nil unless @gemspec.nil?
|
|
1166
1286
|
|
|
@@ -1285,6 +1405,13 @@ module Squared
|
|
|
1285
1405
|
session('rake', *preopts, *cmd, **kwargs)
|
|
1286
1406
|
end
|
|
1287
1407
|
|
|
1408
|
+
def rbs_session(*cmd, opts: nil)
|
|
1409
|
+
return session('rbs', *cmd) unless opts
|
|
1410
|
+
|
|
1411
|
+
op = OptionPartition.new(opts, OPT_RUBY[:rbs], project: self)
|
|
1412
|
+
[session('rbs', *op.to_a, *cmd), op.extras]
|
|
1413
|
+
end
|
|
1414
|
+
|
|
1288
1415
|
def gem_output(*cmd, **kwargs)
|
|
1289
1416
|
session_output('gem', *cmd, **kwargs)
|
|
1290
1417
|
end
|
|
@@ -1320,7 +1447,7 @@ module Squared
|
|
|
1320
1447
|
end
|
|
1321
1448
|
|
|
1322
1449
|
def config_set(key, *val)
|
|
1323
|
-
run(bundle_output('config set', key, *val), banner: false, series:
|
|
1450
|
+
run(bundle_output('config set', key, *val), banner: false, series: true)
|
|
1324
1451
|
end
|
|
1325
1452
|
|
|
1326
1453
|
def preopts
|
|
@@ -10,9 +10,9 @@ module Squared
|
|
|
10
10
|
include Common::Shell
|
|
11
11
|
extend Forwardable
|
|
12
12
|
|
|
13
|
-
OPT_NAME = /\A(?:(--)|-)((?(1)[
|
|
14
|
-
OPT_VALUE = /\A-{0,2}([
|
|
15
|
-
OPT_SINGLE = /\A-([
|
|
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
16
|
private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE
|
|
17
17
|
|
|
18
18
|
class << self
|
|
@@ -47,7 +47,9 @@ module Squared
|
|
|
47
47
|
end
|
|
48
48
|
if escape || quote
|
|
49
49
|
ret.map! do |val|
|
|
50
|
-
if
|
|
50
|
+
if opt?(val)
|
|
51
|
+
val
|
|
52
|
+
elsif escape
|
|
51
53
|
shell_escape(val, quote: quote, double: double)
|
|
52
54
|
else
|
|
53
55
|
shell_quote(val, force: force, double: double)
|
|
@@ -121,6 +123,10 @@ module Squared
|
|
|
121
123
|
r.any? { |pat| s.any?(pat) }
|
|
122
124
|
end
|
|
123
125
|
|
|
126
|
+
def opt?(val)
|
|
127
|
+
val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
|
|
128
|
+
end
|
|
129
|
+
|
|
124
130
|
def pattern?(val)
|
|
125
131
|
val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
|
|
126
132
|
end
|
|
@@ -442,7 +448,7 @@ module Squared
|
|
|
442
448
|
|
|
443
449
|
def add_path(*args, force: true, double: false, **kwargs)
|
|
444
450
|
if args.empty?
|
|
445
|
-
args = select { |
|
|
451
|
+
args = select { |val| val.is_a?(String) }
|
|
446
452
|
args.map! { |val| path + val } if path
|
|
447
453
|
append(args, force: force, **kwargs)
|
|
448
454
|
else
|
|
@@ -452,7 +458,8 @@ module Squared
|
|
|
452
458
|
end
|
|
453
459
|
|
|
454
460
|
def add_quote(*args, **kwargs)
|
|
455
|
-
|
|
461
|
+
args.compact!
|
|
462
|
+
merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
|
|
456
463
|
self
|
|
457
464
|
end
|
|
458
465
|
|