squared 0.9.0.pre2 → 0.9.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 +43 -1
- data/README.md +6 -3
- data/exe/sqd +45 -2
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +31 -17
- data/lib/squared/workspace/project/base.rb +2 -2
- data/lib/squared/workspace/project/docker.rb +1 -1
- data/lib/squared/workspace/project/git.rb +2 -2
- data/lib/squared/workspace/project/node.rb +3 -5
- data/lib/squared/workspace/project/python.rb +140 -68
- data/lib/squared/workspace/project/ruby.rb +20 -8
- data/lib/squared/workspace/project/support/class.rb +10 -10
- data/lib/squared/workspace/project/support/optionpartition.rb +12 -14
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed5b9e99423ac6374d36ad8dffd6a50f2714cef292d6324e358ae19d6a547ed9
|
|
4
|
+
data.tar.gz: 1e6358b439d1defc1f6d9601e915c49b619b00614fc104911ac0554dd61ce6cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz: '
|
|
6
|
+
metadata.gz: 0e973fe0eb9137cd8e822b3eb5e28fc8275e69f17414373205944c28350b616cb58dae4fe41eb647ab2a018f5a21a3e7e43854cf0711a4f59c15614948bb328c
|
|
7
|
+
data.tar.gz: '0293c7c12c7c8d66a7783162a4d1fd5b9a0ae87f3476e0c0dae73f9a3d918fcda4d93a31894b327161a6b571be9c4988bcb0fb2abff0c10995fe4a64af4e93de'
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## [0.9.1] - 2026-10-22
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- sqd: Option --gemfile for rerouting commands through bundle exec.
|
|
8
|
+
- Python install manager for Windows is supported.
|
|
9
|
+
- sqd: Option --sync for running threads in a series was implemented.
|
|
10
|
+
|
|
11
|
+
## [0.8.7]
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- OptionPartition can be initialized with enum and pattern options.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Python venv creation did not run post-install for package managers.
|
|
20
|
+
|
|
21
|
+
## [0.7.14]
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Python program meson prefix options use local path resolution.
|
|
26
|
+
- Bundle exec wrapper can be configured per application.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Bundle exec wrapper did not accept boolean values.
|
|
31
|
+
|
|
32
|
+
## [0.6.21]
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- RuboCop did not resolve config to project directory.
|
|
37
|
+
- Python program did not use correct separator for double dash options.
|
|
38
|
+
|
|
39
|
+
## [0.9.0] - 2026-10-12
|
|
4
40
|
|
|
5
41
|
### Added
|
|
6
42
|
|
|
@@ -36,6 +72,7 @@
|
|
|
36
72
|
- Ruby command script does not run code until it has passed validation.
|
|
37
73
|
- Ruby gem io-console is used for default console size.
|
|
38
74
|
- Node program tsc boolean options support explicit values.
|
|
75
|
+
- Python program meson prefix options use local path resolution.
|
|
39
76
|
|
|
40
77
|
### Removed
|
|
41
78
|
|
|
@@ -2197,6 +2234,9 @@
|
|
|
2197
2234
|
|
|
2198
2235
|
- Changelog was created.
|
|
2199
2236
|
|
|
2237
|
+
[0.9.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.9.1
|
|
2238
|
+
[0.9.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.9.0
|
|
2239
|
+
[0.8.7]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.7
|
|
2200
2240
|
[0.8.6]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.6
|
|
2201
2241
|
[0.8.5]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.5
|
|
2202
2242
|
[0.8.4]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.4
|
|
@@ -2204,6 +2244,7 @@
|
|
|
2204
2244
|
[0.8.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.2
|
|
2205
2245
|
[0.8.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.1
|
|
2206
2246
|
[0.8.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.0
|
|
2247
|
+
[0.7.14]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.14
|
|
2207
2248
|
[0.7.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.13
|
|
2208
2249
|
[0.7.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.12
|
|
2209
2250
|
[0.7.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.11
|
|
@@ -2218,6 +2259,7 @@
|
|
|
2218
2259
|
[0.7.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.2
|
|
2219
2260
|
[0.7.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.1
|
|
2220
2261
|
[0.7.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.0
|
|
2262
|
+
[0.6.21]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.21
|
|
2221
2263
|
[0.6.20]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.20
|
|
2222
2264
|
[0.6.19]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.19
|
|
2223
2265
|
[0.6.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.18
|
data/README.md
CHANGED
|
@@ -43,12 +43,15 @@ Usage: sqd [options] [rake options] [global...] [:targets...] -- [rake targets..
|
|
|
43
43
|
|
|
44
44
|
-s, --[no-]strict Do not run commands with invalid arguments
|
|
45
45
|
--update Use update strategy for applicable commands
|
|
46
|
+
-u, --parallel STR,PAT Run standard tasks with multi-task threads
|
|
47
|
+
-U, --sync STR,PAT Run parallel tasks in a series sequentially
|
|
46
48
|
-F, --force [STR,STR] Enable force through ENV by application
|
|
47
49
|
-y, --yes [STR,STR] Enable auto-approve through ENV by application
|
|
48
50
|
-d, --dry-run Run commands without any modifying actions
|
|
49
51
|
|
|
50
52
|
-S, --select PAGE[:CHOICE] Prompt menu selection pagination display (e.g. 15:75)
|
|
51
53
|
|
|
54
|
+
-g, --gemfile Execute commands using bundle exec and nearest Gemfile
|
|
52
55
|
-p, --pipe 0|1|2 Set file descriptor for communication
|
|
53
56
|
-o, --pipe-out FILE Write command data stream to a file
|
|
54
57
|
--fail 0..4 Set application exception level
|
|
@@ -101,11 +104,11 @@ Workspace::Application
|
|
|
101
104
|
.clean("rake clean", group: "default")
|
|
102
105
|
.clean(["build/"], group: "app")
|
|
103
106
|
.log({ file: "tmp/%Y-%m-%d.log", level: "debug" }, group: "app")
|
|
104
|
-
.add("pathname", run: "rake compile", copy: "rake install", test: "rake test", group: "default", env: { # Ruby (with C extensions)
|
|
107
|
+
.add("pathname", run: "rake compile", copy: "rake install", test: "rake test", exec: true, group: "default", env: { # Ruby (with C extensions)
|
|
105
108
|
"CFLAGS" => "-fPIC -O1"
|
|
106
109
|
})
|
|
107
|
-
.add("optparse", doc: "rake rdoc", gemspec: "optparse.gemspec", group: "default") # Uses bundler/gem_tasks (without C extensions)
|
|
108
|
-
.add("logger", copy: { from: "lib", glob: "**/*.rb", into: "/home/user/.local/gem/ruby/4.0.0/gems/logger-1.7.0" }, clean: ["tmp/"]) do
|
|
110
|
+
.add("optparse", doc: "rake rdoc", gemspec: "optparse.gemspec", exec: { rake: true, ruby: '../Gemfile', rbs: false }, group: "default") # Uses bundler/gem_tasks (without C extensions)
|
|
111
|
+
.add("logger", copy: { from: "lib", glob: "**/*.rb", into: "/home/user/.local/gem/ruby/4.0.0/gems/logger-1.7.0" }, clean: ["tmp/"]) do # autodetect: true | "rvm" | "rbenv" | "asdf" | "mise" | bundler"
|
|
109
112
|
self.gemdir = "/home/user/.local/gem/ruby/4.0.0/gems/logger-1.7.0" # Default for "into"
|
|
110
113
|
end
|
|
111
114
|
.add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node)
|
data/exe/sqd
CHANGED
|
@@ -45,6 +45,19 @@ class SqdParser < OptionParser
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
def parse_series(list, session:, flag:)
|
|
49
|
+
pattern, parallel = list.partition do |val|
|
|
50
|
+
next false if val.match?(%r{^[\w~`!@#%&\-=:;"'<>/]+$})
|
|
51
|
+
|
|
52
|
+
Regexp.new(val)
|
|
53
|
+
rescue RegexpError
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
s = flag == :sync ? '!' : ''
|
|
57
|
+
(session[:APP][:"build_pattern#{s}"] ||= []).concat(pattern.map { |pat| Regexp.new(pat) }) unless pattern.empty?
|
|
58
|
+
(session[:APP][:"build_parallel#{s}"] ||= []).concat(parallel) unless parallel.empty?
|
|
59
|
+
end
|
|
60
|
+
|
|
48
61
|
def banner_set(val, session:)
|
|
49
62
|
session[:BANNER] = val
|
|
50
63
|
ENV['BANNER'] = val ? 'true' : 'false'
|
|
@@ -118,6 +131,7 @@ end
|
|
|
118
131
|
|
|
119
132
|
SqdParser.new do |sqd|
|
|
120
133
|
session = Squared::Common::ARG
|
|
134
|
+
argv = ARGV.dup
|
|
121
135
|
sqd.banner = 'Usage: sqd [options] [rake options] [global...] [:targets...] -- [rake targets...]'
|
|
122
136
|
sqd.separator ''
|
|
123
137
|
sqd.on('-R', '--ref STR,STR', Array, 'Run global commands by class reference') do |val|
|
|
@@ -144,6 +158,12 @@ SqdParser.new do |sqd|
|
|
|
144
158
|
sqd.on('--update', 'Use update strategy for applicable commands') do
|
|
145
159
|
ENV['UPDATE'] = 'true'
|
|
146
160
|
end
|
|
161
|
+
sqd.on('-u', '--parallel STR,PAT', Array, 'Run standard tasks with multi-task threads') do |val|
|
|
162
|
+
sqd.parse_series(val, session: session, flag: :parallel)
|
|
163
|
+
end
|
|
164
|
+
sqd.on('-U', '--sync STR,PAT', Array, 'Run parallel tasks in a series sequentially') do |val|
|
|
165
|
+
sqd.parse_series(val, session: session, flag: :sync)
|
|
166
|
+
end
|
|
147
167
|
sqd.on('-F', '--force [STR,STR]', Array, 'Enable force through ENV by application') do |val|
|
|
148
168
|
sqd.parse_common(val, session: session, arg: :FORCE)
|
|
149
169
|
end
|
|
@@ -162,6 +182,24 @@ SqdParser.new do |sqd|
|
|
|
162
182
|
ENV['SELECT'] = "#{page}:#{choice}"
|
|
163
183
|
end
|
|
164
184
|
sqd.separator ''
|
|
185
|
+
sqd.on('-g', '--gemfile', 'Execute commands using bundle exec and nearest Gemfile') do
|
|
186
|
+
require 'pathname'
|
|
187
|
+
next if ENV['RUBYOPT']&.match?(/(^|\b)-r.+#{File::SEPARATOR}bundler#{File::SEPARATOR}setup\b/)
|
|
188
|
+
|
|
189
|
+
gemfile = Pathname.pwd.ascend { |path| break path if path.join('Gemfile').file? } || ENV['BUNDLE_GEMFILE']
|
|
190
|
+
next unless gemfile && (argv.delete('--gemfile') || argv.delete('-g'))
|
|
191
|
+
|
|
192
|
+
include Squared::Common
|
|
193
|
+
include Shell
|
|
194
|
+
|
|
195
|
+
argv.unshift('sqd')
|
|
196
|
+
if gemfile.is_a?(String)
|
|
197
|
+
argv.unshift("--gemfile=#{shell_escape(Pathname.new(gemfile).relative_path_from(Dir.pwd), quote: true)}")
|
|
198
|
+
gemfile = Dir.pwd
|
|
199
|
+
end
|
|
200
|
+
ENV['BUNDLE_GEMFILE'] = nil
|
|
201
|
+
exec(shell_bin('bundle'), 'exec', *argv, chdir: gemfile)
|
|
202
|
+
end
|
|
165
203
|
sqd.on('-p', '--pipe 0|1|2', Integer, 'Set file descriptor for communication') do |val|
|
|
166
204
|
sqd.error_exit('out of range', val) unless val.between?(0, 2)
|
|
167
205
|
session[:PIPE] = val
|
|
@@ -211,9 +249,14 @@ SqdParser.new do |sqd|
|
|
|
211
249
|
end
|
|
212
250
|
sqd.on('--version', 'Print the current version') do
|
|
213
251
|
puts Squared::VERSION
|
|
214
|
-
exit
|
|
252
|
+
exit
|
|
215
253
|
end
|
|
216
254
|
sqd.on('-h', '--help', 'Print the command line options') do
|
|
217
|
-
sqd.help_exit
|
|
255
|
+
if defined?(sqd.help_exit)
|
|
256
|
+
sqd.help_exit
|
|
257
|
+
else
|
|
258
|
+
puts sqd.help
|
|
259
|
+
exit
|
|
260
|
+
end
|
|
218
261
|
end
|
|
219
262
|
end.run
|
data/lib/squared/version.rb
CHANGED
|
@@ -163,8 +163,14 @@ module Squared
|
|
|
163
163
|
end
|
|
164
164
|
@pass.items.concat(kwargs[:pass].map { |val| val.is_a?(Regexp) ? val : val.to_s }) if kwargs[:pass]
|
|
165
165
|
@series = Application.register(self, @base.to_a, exclude: kwargs.fetch(:exclude, []))
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
app = ARG[:APP]
|
|
167
|
+
@series.ref_min = app[:series_ref_min] if app.key?(:series_ref_min)
|
|
168
|
+
kwargs[:pattern].concat(app[:build_pattern]) if app.key?(:build_pattern)
|
|
169
|
+
kwargs[:parallel].concat(app[:build_parallel]) if app.key?(:build_parallel)
|
|
170
|
+
kwargs[:parallel].reject! { |val| app[:build_parallel!].include?(val) } if app.key?(:build_parallel!)
|
|
171
|
+
app[:build_pattern!]&.each do |pat|
|
|
172
|
+
kwargs[:pattern].delete(pat)
|
|
173
|
+
kwargs[:parallel].reject! { |val| pat.match?(val) }
|
|
168
174
|
end
|
|
169
175
|
self.closed = 'begin'
|
|
170
176
|
pb = @stage.key?('project:begin')
|
|
@@ -652,16 +658,24 @@ module Squared
|
|
|
652
658
|
val = val.split(':') if val.is_a?(String)
|
|
653
659
|
if before || after || opts
|
|
654
660
|
pos = []
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
661
|
+
append = lambda do |data|
|
|
662
|
+
pos << case data
|
|
663
|
+
when Array
|
|
664
|
+
data.join(',')
|
|
665
|
+
when Hash
|
|
666
|
+
data.keys.join('|')
|
|
659
667
|
else
|
|
660
|
-
|
|
668
|
+
data
|
|
661
669
|
end
|
|
662
670
|
end
|
|
663
|
-
|
|
664
|
-
|
|
671
|
+
append.call(before)
|
|
672
|
+
pos << if opts.is_a?(Array)
|
|
673
|
+
arg ? "#{arg}=#{opts.join(',')}" : opts.join('|')
|
|
674
|
+
else
|
|
675
|
+
opts
|
|
676
|
+
end
|
|
677
|
+
append.call(after)
|
|
678
|
+
val << "#{val.pop}[#{pos.compact.join(',')}]"
|
|
665
679
|
end
|
|
666
680
|
out ? message(*val) : task_desc(*val)
|
|
667
681
|
end
|
|
@@ -717,12 +731,12 @@ module Squared
|
|
|
717
731
|
!@extensions.empty? || any? { |proj| proj.enabled?(base: false) }
|
|
718
732
|
end
|
|
719
733
|
|
|
720
|
-
def task_base?(
|
|
721
|
-
series.base?(
|
|
734
|
+
def task_base?(...)
|
|
735
|
+
series.base?(...)
|
|
722
736
|
end
|
|
723
737
|
|
|
724
|
-
def task_extend?(
|
|
725
|
-
series.extend?(
|
|
738
|
+
def task_extend?(...)
|
|
739
|
+
series.extend?(...)
|
|
726
740
|
end
|
|
727
741
|
|
|
728
742
|
def task_include?(obj, key, ref: nil)
|
|
@@ -758,12 +772,12 @@ module Squared
|
|
|
758
772
|
!!find(home)&.enabled?
|
|
759
773
|
end
|
|
760
774
|
|
|
761
|
-
def rootpath(
|
|
762
|
-
root.join(
|
|
775
|
+
def rootpath(...)
|
|
776
|
+
root.join(...)
|
|
763
777
|
end
|
|
764
778
|
|
|
765
|
-
def homepath(
|
|
766
|
-
home.join(
|
|
779
|
+
def homepath(...)
|
|
780
|
+
home.join(...)
|
|
767
781
|
end
|
|
768
782
|
|
|
769
783
|
def pwd
|
|
@@ -182,7 +182,7 @@ module Squared
|
|
|
182
182
|
if flags.nil?
|
|
183
183
|
case action
|
|
184
184
|
when 'ls'
|
|
185
|
-
format_desc(action, nil,
|
|
185
|
+
format_desc(action, nil, 'a/ll?,s/tandard?,range*', before: VAL_DOCKER[:ls])
|
|
186
186
|
task action, [:command] do |_, args|
|
|
187
187
|
command = param_guard(action, 'command', args: args, key: :command)
|
|
188
188
|
args = args.extras
|
|
@@ -1077,7 +1077,7 @@ module Squared
|
|
|
1077
1077
|
git(:remote, args.extras, extras: [name, url])
|
|
1078
1078
|
end
|
|
1079
1079
|
else
|
|
1080
|
-
format_desc
|
|
1080
|
+
format_desc(action, flag, 'opts*', before: OPT_GIT[:remote])
|
|
1081
1081
|
task flag, [:command] do |_, args|
|
|
1082
1082
|
command = param_guard(action, flag, args: args, key: :command)
|
|
1083
1083
|
cmd, opts = git_session('remote', opts: args.extras)
|
|
@@ -1840,7 +1840,7 @@ module Squared
|
|
|
1840
1840
|
if adding.empty? && !cached.empty? && banner?
|
|
1841
1841
|
puts(cached.lines(chomp: true).map { |val| "cached #{shell_quote(val)}" })
|
|
1842
1842
|
end
|
|
1843
|
-
ENV['COMMIT_PUSH'] =
|
|
1843
|
+
ENV['COMMIT_PUSH'] = git_value 'rev-parse --verify HEAD' if source(co) && source(pu) && !dryrun?
|
|
1844
1844
|
else
|
|
1845
1845
|
if banner?
|
|
1846
1846
|
puts 'Nothing to commit'
|
|
@@ -306,13 +306,11 @@ module Squared
|
|
|
306
306
|
format_desc action, nil, 'version|pre?{major,minor,patch}|prerelease'
|
|
307
307
|
task action, [:version] do |_, args|
|
|
308
308
|
version = param_guard(action, 'to', args: args, key: :version)
|
|
309
|
-
if version.match?(/^(
|
|
310
|
-
|
|
311
|
-
version = nil
|
|
309
|
+
if version.match?(/^(pre)?(major|minor|patch)|prerelease$/)
|
|
310
|
+
bump version.to_sym
|
|
312
311
|
else
|
|
313
|
-
|
|
312
|
+
bump :version, version
|
|
314
313
|
end
|
|
315
|
-
bump flag, version
|
|
316
314
|
end
|
|
317
315
|
when 'pack'
|
|
318
316
|
format_desc action, nil, 'opts*'
|
|
@@ -7,16 +7,18 @@ module Squared
|
|
|
7
7
|
DEP_PYTHON = %w[poetry.lock pdm.lock pylock.toml setup.cfg pyproject.toml setup.py requirements.txt].freeze
|
|
8
8
|
DIR_PYTHON = (DEP_PYTHON + %w[meson.build README.rst]).freeze
|
|
9
9
|
OPT_PYTHON = {
|
|
10
|
-
common: %w[b=+ B d E h i I O P q=+ s S u v=+ V=+ x c=q m=b W=b X=q
|
|
10
|
+
common: %w[b=+ B d E h i I O P q=+ s S u v=+ V=+ x c=q m=b W=b X=q
|
|
11
|
+
check-hash-based-pycs={always,default,never}].freeze,
|
|
11
12
|
build: %w[C=bm n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel config-json=q config-setting=q
|
|
12
13
|
installer=b o|outdir=p].freeze,
|
|
13
14
|
venv: %w[clear copies symlinks system-site-packages upgrade upgrade-deps without-scm-ignore-files without-pip
|
|
14
15
|
prompt=q].freeze,
|
|
15
16
|
virtualenv: %w[always-copy clear copies download never-download no-download no-periodic-update no-pip no-seed
|
|
16
|
-
no-setuptools no-vcs-ignore q|quiet read-only-app-data reset-app-data
|
|
17
|
-
system-site-packages with-traceback without-pip upgrade-embed-wheels
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
no-setuptools no-vcs-ignore no-venv-redirect q|quiet read-only-app-data reset-app-data
|
|
18
|
+
symlink-app-data symlinks system-site-packages with-traceback without-pip upgrade-embed-wheels
|
|
19
|
+
venv-redirect v|verbose=+ activators={bash,batch,cshell,fish,nushell,powershell,python,xonsh}
|
|
20
|
+
app-data=p creator=b discovery={builtin} extra-search-dir=p pip=b prompt=q p|python=q
|
|
21
|
+
seeder={app-data,pip} setuptools=b try-first-with=q].freeze
|
|
20
22
|
}.freeze
|
|
21
23
|
OPT_PIP = {
|
|
22
24
|
common: %w[debug disable-pip-version-check isolated no-cache-dir no-color no-input no-proxy-env
|
|
@@ -49,27 +51,34 @@ module Squared
|
|
|
49
51
|
uninstall: %w[break-system-packages y|yes r|requirement=p root-user-action=b].freeze,
|
|
50
52
|
wheel: %w[no-verify w|wheel-dir=p].freeze
|
|
51
53
|
}.freeze
|
|
54
|
+
OPT_PY = {
|
|
55
|
+
common: %w[q|quiet=+ v|verbose=+ y|yes config=p].freeze,
|
|
56
|
+
exec: %w[3=/^\.\d+(\.\d+)?$/m? V=/^:./m?].freeze,
|
|
57
|
+
install: %w[by-id configure dry-run f|force refresh u|update d|download=p s|source=q t|target=p].freeze,
|
|
58
|
+
list: %w[1|one online only-managed format={table,json,jsonl,csv,exe,prefix,url,formats} s|source=q].freeze,
|
|
59
|
+
uninstall: %w[by-id cleanup purge].freeze
|
|
60
|
+
}.freeze
|
|
52
61
|
OPT_POETRY = {
|
|
53
62
|
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet v|verbose=+ P|project=p].freeze,
|
|
54
63
|
install: %w[all-extras all-groups compile dry-run no-directory no-root only-root E|extras=q only=q with=q
|
|
55
64
|
without=q].freeze,
|
|
56
|
-
build: %w[clean config-settings=qq f|format=b o|output=p].freeze,
|
|
65
|
+
build: %w[clean c|config-settings=qq f|format=b o|output=p].freeze,
|
|
57
66
|
publish: %w[build dry-run skip-existing cert=p client-cert=p dist-dir=p p|password=q r|repository=q
|
|
58
67
|
u|username=qq].freeze
|
|
59
68
|
}.freeze
|
|
60
69
|
OPT_PDM = {
|
|
61
|
-
common: %w[c|config I|ignore-python no-cache n|non-interactive
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
publish: %w[no-build no-very-ssl
|
|
65
|
-
i|identity=b P|password=q
|
|
70
|
+
common: %w[c|config I|ignore-python no-cache n|non-interactive q|quiet v|verbose=+ p|project=p
|
|
71
|
+
k|skip=b].freeze,
|
|
72
|
+
build: %w[C=bm no-clean no-isolation no-sdist no-wheel config-setting=qq d|dest=p].freeze,
|
|
73
|
+
publish: %w[no-build no-verify-ssl no-very-ssl S|sign skip-existing ca-certs=p c|comment=q d|dest=p
|
|
74
|
+
i|identity=b P|password=q r|repository=q u|username=qq].freeze
|
|
66
75
|
}.freeze
|
|
67
76
|
OPT_HATCH = {
|
|
68
77
|
common: %w[color interactive no-color no-interactive cache-dir=p config=p data-dir=p e|env=b p|project=b
|
|
69
78
|
q|quiet=+ v|verbose=+].freeze,
|
|
70
|
-
build: %w[clean-hooks-after ext hooks-only no-hooks c|clean t|target=b].freeze,
|
|
79
|
+
build: %w[a|all clean-hooks-after ext hooks-only no-hooks c|clean t|target=b].freeze,
|
|
71
80
|
publish: %w[initialize-auth n|no-prompt y|yes a|auth=q ca-cert=p client-cert=p client-key=p o|option=q
|
|
72
|
-
p|publisher=b r|repo=q u|user=
|
|
81
|
+
p|publisher=b r|repo=q u|user=qq].freeze
|
|
73
82
|
}.freeze
|
|
74
83
|
OPT_TWINE = {
|
|
75
84
|
publish: %w[attestations disable-progress-bar non-interactive s|sign skip-existing verbose cert=p
|
|
@@ -77,15 +86,20 @@ module Squared
|
|
|
77
86
|
sign-with=b u|username=qq].freeze
|
|
78
87
|
}.freeze
|
|
79
88
|
OPT_MESON = {
|
|
80
|
-
build: %w[D=q clearcache debug errorlogs fatal-meson-warnings pkgconfig.relocatable prefer-static
|
|
81
|
-
python.allow-limited-api reconfigure stdsplit strip vsenv werror wipe auto-features=b
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
build: %w[D=q clearcache debug errorlogs fatal-meson-warnings os2-emxomf pkgconfig.relocatable prefer-static
|
|
90
|
+
python.allow-limited-api reconfigure stdsplit strip vsenv werror wipe auto-features=b
|
|
91
|
+
backend={ninja,vs,vs2010,vs2012,vs2013,vs2015,vs2017,vs2019,vs2022,vs2026,xcode,none}
|
|
92
|
+
bindir=q build.cmake-prefix-path=p build.pkg-config-path=p
|
|
93
|
+
buildtype={plain,debug,debugoptimized,release,minsize,custom} cmake-prefix-path=p cross-file=p
|
|
94
|
+
datadir=q default-library={shared,static,both} default-both-libraries={shared,static,auto}
|
|
95
|
+
force-fallback-for=q genvslite={vs2022,vs2026} includedir=q infodir=q install-umask=b
|
|
96
|
+
layout={mirror,flat} libdir=q libexecdir=q licensedir=q localedir=q localstatedir=q mandir=q
|
|
97
|
+
namingscheme={platform,classic} native-file=p optimization={plain,0,g,1,2,3,s} pkg-config-path=p
|
|
98
|
+
prefix=p python.build-config=p python.bytecompile=b python.platlibdir=p python.purelibdir=p
|
|
99
|
+
python.install-env={auto,prefix,system,venv} sbindir=q sharedstatedir=q sysconfdir=q
|
|
100
|
+
unity={on,off,subprojects} unity-size=i warnlevel={0,1,2,3,everything}
|
|
101
|
+
wrap-mode={default,nofallback,nodownload,forcefallback,nopromote}].freeze,
|
|
102
|
+
compile: %w[C=p clean v|verbose j|jobs=i l|load-average=b ninja-args=q vs-args=q xcode-args=q].freeze
|
|
89
103
|
}.freeze
|
|
90
104
|
PASS_PYTHON = {
|
|
91
105
|
python: %w[c v V].freeze,
|
|
@@ -94,7 +108,8 @@ module Squared
|
|
|
94
108
|
install: %w[C config-settings c constraint extra-index-url no-binary only-binary platform
|
|
95
109
|
r requirement].freeze,
|
|
96
110
|
list: %w[exclude extra-index-url no-binary only-binary].freeze
|
|
97
|
-
}.freeze
|
|
111
|
+
}.freeze,
|
|
112
|
+
py: %w[q v quiet verbose].freeze
|
|
98
113
|
}.freeze
|
|
99
114
|
private_constant :DEP_PYTHON, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_POETRY, :OPT_PDM, :OPT_HATCH, :OPT_TWINE,
|
|
100
115
|
:PASS_PYTHON
|
|
@@ -144,6 +159,7 @@ module Squared
|
|
|
144
159
|
'outdated' => %i[major minor patch].freeze,
|
|
145
160
|
'build' => %i[poetry pdm hatch meson python].freeze,
|
|
146
161
|
'publish' => %i[twine poetry pdm hatch].freeze,
|
|
162
|
+
'py' => %i[exec install list uninstall].freeze,
|
|
147
163
|
'run' => nil,
|
|
148
164
|
'exec' => nil
|
|
149
165
|
})
|
|
@@ -276,7 +292,7 @@ module Squared
|
|
|
276
292
|
args = args.to_a
|
|
277
293
|
if args.empty?
|
|
278
294
|
args = readline('Enter command', force: true).split(' ', 2)
|
|
279
|
-
elsif args.size == 1 && option('interactive', notequals: '0', prefix:
|
|
295
|
+
elsif args.size == 1 && option('interactive', notequals: '0', prefix: 'python')
|
|
280
296
|
args << readline('Enter arguments', force: false) unless args.first.include?(' ')
|
|
281
297
|
end
|
|
282
298
|
venv_init
|
|
@@ -346,18 +362,18 @@ module Squared
|
|
|
346
362
|
case flag
|
|
347
363
|
when :upgrade
|
|
348
364
|
task flag, [:strategy] do |_, args|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
365
|
+
val = case args.strategy
|
|
366
|
+
when 'eager'
|
|
367
|
+
'eager'
|
|
368
|
+
when /^only-if/, /needed$/
|
|
369
|
+
'only-if-needed'
|
|
370
|
+
end
|
|
371
|
+
args = if val
|
|
372
|
+
args.extras << "upgrade-strategy=#{val}"
|
|
373
|
+
else
|
|
374
|
+
args.to_a
|
|
375
|
+
end
|
|
376
|
+
install flag, args
|
|
361
377
|
end
|
|
362
378
|
when :requirement, :target
|
|
363
379
|
task flag, [:path] do |_, args|
|
|
@@ -414,6 +430,26 @@ module Squared
|
|
|
414
430
|
end)
|
|
415
431
|
end
|
|
416
432
|
break if be
|
|
433
|
+
when 'py'
|
|
434
|
+
break unless windows?
|
|
435
|
+
|
|
436
|
+
case flag
|
|
437
|
+
when :exec
|
|
438
|
+
format_desc action, flag, 'opts*'
|
|
439
|
+
task flag do |_, args|
|
|
440
|
+
opts = args.to_a
|
|
441
|
+
if (n = opts.index { |val| val.start_with?('3.') }) && (opts[n] =~ SEM_VER)
|
|
442
|
+
opts[n] = $3.to_i >= 5 ? "3=.#{$3}.#{$5 || '0'}" : '3'
|
|
443
|
+
end
|
|
444
|
+
command = ENV['PY_EXEC'] || readline('Enter command', force: true)
|
|
445
|
+
py(flag, command, opts: opts)
|
|
446
|
+
end
|
|
447
|
+
else
|
|
448
|
+
format_desc(action, flag, 'opts*', after: flag == :list ? 'filter*' : 'tag*')
|
|
449
|
+
task flag do |_, args|
|
|
450
|
+
py(flag, opts: args.to_a, banner: true)
|
|
451
|
+
end
|
|
452
|
+
end
|
|
417
453
|
end
|
|
418
454
|
end
|
|
419
455
|
end
|
|
@@ -746,10 +782,17 @@ module Squared
|
|
|
746
782
|
run(from: symjoin(flag, 'publish'), interactive: ['Publish', 'N', project])
|
|
747
783
|
end
|
|
748
784
|
|
|
749
|
-
def python(*args, sync: true, banner: verbose?, with: nil, pass: PASS_PYTHON[:python], **kwargs)
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
785
|
+
def python(*args, sync: true, banner: verbose?, with: nil, pass: PASS_PYTHON[:python], from: :python, **kwargs)
|
|
786
|
+
py = from == :py && windows?
|
|
787
|
+
list = OPT_PYTHON[:common]
|
|
788
|
+
if py
|
|
789
|
+
list += OPT_PY[:exec]
|
|
790
|
+
list.delete('V=+')
|
|
791
|
+
from = :'py:exec'
|
|
792
|
+
end
|
|
793
|
+
op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), list,
|
|
794
|
+
py ? session('py', 'exec') : session('python', path: !venv?),
|
|
795
|
+
project: self, strict: strict?, auto: %w[help V|version], sep: ' ',
|
|
753
796
|
multiple: [/^-c/], single: singleopt(:python), args: true, stdin: true)
|
|
754
797
|
op.concat(args)
|
|
755
798
|
if op.include?('-')
|
|
@@ -763,8 +806,14 @@ module Squared
|
|
|
763
806
|
op.append(escape: kwargs.fetch(:escape, false), quote: kwargs.fetch(:quote, false))
|
|
764
807
|
end
|
|
765
808
|
end
|
|
809
|
+
var = kwargs[:env]
|
|
810
|
+
if var == true
|
|
811
|
+
var = nil
|
|
812
|
+
elsif py && var.nil?
|
|
813
|
+
var = false
|
|
814
|
+
end
|
|
766
815
|
print_run(op, banner, **kwargs) unless op.stdout
|
|
767
|
-
run(sync: sync, banner: op.style?(banner), exception: exception?(**kwargs), from:
|
|
816
|
+
run(op, var, sync: sync, banner: op.style?(banner), exception: exception?(**kwargs), from: from)
|
|
768
817
|
end
|
|
769
818
|
|
|
770
819
|
def pip(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
|
|
@@ -850,6 +899,28 @@ module Squared
|
|
|
850
899
|
.then { |val| ret || val }
|
|
851
900
|
end
|
|
852
901
|
|
|
902
|
+
def py(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
|
|
903
|
+
flag = flag.to_sym
|
|
904
|
+
if flag == :exec
|
|
905
|
+
pass = PASS_PYTHON[:python] if pass.nil?
|
|
906
|
+
python(*args, sync: sync, banner: banner, with: with, pass: pass, from: :py, **kwargs)
|
|
907
|
+
else
|
|
908
|
+
pass = PASS_PYTHON[:py] if pass.nil?
|
|
909
|
+
opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
|
|
910
|
+
list = OPT_PY[:common] + OPT_PY[flag]
|
|
911
|
+
op = OptionPartition.new(opts, list, session('py', flag), project: self, strict: strict?,
|
|
912
|
+
single: singleopt(:py))
|
|
913
|
+
case flag
|
|
914
|
+
when :install, :uninstall
|
|
915
|
+
raise ArgumentError, message('no tags listed', hint: flag) if op.empty?
|
|
916
|
+
end
|
|
917
|
+
op << '-y' if option('y')
|
|
918
|
+
op.append
|
|
919
|
+
print_run(op, banner, **kwargs)
|
|
920
|
+
run(sync: sync, banner: banner, exception: exception?(**kwargs), from: symjoin('py', flag))
|
|
921
|
+
end
|
|
922
|
+
end
|
|
923
|
+
|
|
853
924
|
def serve(root, opts = [], bind: 'localhost', port: nil, **)
|
|
854
925
|
shell(python_session('-m http.server', port, basic_option('b', bind), opts: opts).first.done, chdir: root)
|
|
855
926
|
end
|
|
@@ -951,7 +1022,8 @@ module Squared
|
|
|
951
1022
|
pre = preopts(quiet: quiet)
|
|
952
1023
|
return session(name, *pre, *cmd, path: !venv?) unless opts
|
|
953
1024
|
|
|
954
|
-
op = OptionPartition.new(opts, common, project: self, strict: strict?,
|
|
1025
|
+
op = OptionPartition.new(opts, common, project: self, strict: strict?, sep: name == 'python' ? ' ' : '=',
|
|
1026
|
+
single: singleopt(name.to_sym))
|
|
955
1027
|
[session(name, *pre, *op.to_a, *cmd, path: !venv?), op.extras]
|
|
956
1028
|
end
|
|
957
1029
|
|
|
@@ -1126,6 +1198,8 @@ module Squared
|
|
|
1126
1198
|
when :pdm, :poetry
|
|
1127
1199
|
/\Av+\z/
|
|
1128
1200
|
when :twine, :meson then nil
|
|
1201
|
+
when :py
|
|
1202
|
+
/\A(vv|qq)\z/
|
|
1129
1203
|
else
|
|
1130
1204
|
/\A(v+|q+)\z/
|
|
1131
1205
|
end
|
|
@@ -1230,6 +1304,7 @@ module Squared
|
|
|
1230
1304
|
status = true
|
|
1231
1305
|
:virtualenv
|
|
1232
1306
|
else
|
|
1307
|
+
status = !banner
|
|
1233
1308
|
:venv
|
|
1234
1309
|
end
|
|
1235
1310
|
cmd, opts = python_session('-m', flag, opts: opts)
|
|
@@ -1237,34 +1312,31 @@ module Squared
|
|
|
1237
1312
|
op.append(dir, delim: true)
|
|
1238
1313
|
.clear(pass: false)
|
|
1239
1314
|
status ||= op.arg?(/\A-v+\z/)
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
elsif pdm?
|
|
1257
|
-
cmd = pdm_session 'use -f'
|
|
1258
|
-
else
|
|
1259
|
-
puts "Success: #{dir}"
|
|
1260
|
-
return
|
|
1261
|
-
end
|
|
1262
|
-
cmd << shell_quote(dir)
|
|
1263
|
-
print_run cmd, silent?
|
|
1264
|
-
run(banner: false)
|
|
1315
|
+
if run(op, env, exception: true, banner: banner) && dir.directory?
|
|
1316
|
+
args = []
|
|
1317
|
+
requires = read_pyproject 'build-system', 'requires'
|
|
1318
|
+
args.concat(requires) if requires.is_a?(Array)
|
|
1319
|
+
if poetry?
|
|
1320
|
+
requires = read_pyproject 'tool.poetry', 'requires-poetry'
|
|
1321
|
+
args << "poetry#{requires}"
|
|
1322
|
+
elsif setuptools? && !virtualenv?
|
|
1323
|
+
args << 'setuptools' << 'wheel'
|
|
1324
|
+
end
|
|
1325
|
+
pip(:install, *args, banner: false) unless args.empty?
|
|
1326
|
+
if poetry?
|
|
1327
|
+
dir += (windows? ? 'Scripts/python.exe' : 'bin/python')
|
|
1328
|
+
poetry_session 'env use'
|
|
1329
|
+
elsif pdm?
|
|
1330
|
+
pdm_session 'use -f'
|
|
1265
1331
|
else
|
|
1266
|
-
puts
|
|
1332
|
+
puts "Success: #{dir}" unless status
|
|
1333
|
+
return
|
|
1267
1334
|
end
|
|
1335
|
+
cmd << shell_quote(dir)
|
|
1336
|
+
print_run cmd, silent?
|
|
1337
|
+
run(banner: false)
|
|
1338
|
+
elsif !status
|
|
1339
|
+
puts 'Failed'
|
|
1268
1340
|
end
|
|
1269
1341
|
end
|
|
1270
1342
|
|
|
@@ -227,7 +227,7 @@ module Squared
|
|
|
227
227
|
serve_set kwargs[:serve]
|
|
228
228
|
gemfile_set kwargs[:gemspec]
|
|
229
229
|
self.autodetect = autodetect
|
|
230
|
-
@bundle = { exec: exec
|
|
230
|
+
@bundle = { exec: exec }
|
|
231
231
|
@steepfile = basepath! steep if steep
|
|
232
232
|
rubocop = rootpath('.rubocop.yml', ascend: Dir.home) if rubocop == true
|
|
233
233
|
@rubocopfile = basepath! rubocop if rubocop
|
|
@@ -1601,7 +1601,7 @@ module Squared
|
|
|
1601
1601
|
|
|
1602
1602
|
def rdbg(*args, banner: verbose?, with: nil, pass: PASS_RUBY[:rdbg], **kwargs)
|
|
1603
1603
|
opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
|
|
1604
|
-
cmd = session
|
|
1604
|
+
cmd = session(*bundle_args('rdbg'))
|
|
1605
1605
|
args.each_with_index do |val, i|
|
|
1606
1606
|
break if val == '--'
|
|
1607
1607
|
next unless exist?(val, type: 'f')
|
|
@@ -1881,7 +1881,7 @@ module Squared
|
|
|
1881
1881
|
end
|
|
1882
1882
|
|
|
1883
1883
|
def ruby_session(*cmd, **kwargs)
|
|
1884
|
-
session('ruby', *preopts, *cmd, **kwargs)
|
|
1884
|
+
session(*bundle_args('ruby'), *preopts, *cmd, **kwargs)
|
|
1885
1885
|
end
|
|
1886
1886
|
|
|
1887
1887
|
def gem_session(*cmd, **kwargs)
|
|
@@ -1899,11 +1899,10 @@ module Squared
|
|
|
1899
1899
|
end
|
|
1900
1900
|
|
|
1901
1901
|
def rbs_session(*cmd, opts: nil)
|
|
1902
|
-
|
|
1903
|
-
return session(*args, *cmd) unless opts
|
|
1902
|
+
return session(*bundle_args('rbs'), *cmd) unless opts
|
|
1904
1903
|
|
|
1905
1904
|
op = OptionPartition.new(opts, OPT_RUBY[:rbs], project: self, strict: strict?)
|
|
1906
|
-
[session(*
|
|
1905
|
+
[session(*bundle_args('rbs'), *op.to_a, *cmd), op.extras]
|
|
1907
1906
|
end
|
|
1908
1907
|
|
|
1909
1908
|
def gem_output(*cmd, **kwargs)
|
|
@@ -1911,7 +1910,7 @@ module Squared
|
|
|
1911
1910
|
end
|
|
1912
1911
|
|
|
1913
1912
|
def ruby_output(*cmd, **kwargs)
|
|
1914
|
-
session_output('ruby', *cmd, **kwargs)
|
|
1913
|
+
session_output(*bundle_args('ruby'), *cmd, **kwargs)
|
|
1915
1914
|
end
|
|
1916
1915
|
|
|
1917
1916
|
def bundle_output(*cmd, **kwargs)
|
|
@@ -1924,7 +1923,20 @@ module Squared
|
|
|
1924
1923
|
|
|
1925
1924
|
def bundle_args(*args)
|
|
1926
1925
|
if (val = @bundle[:exec])
|
|
1927
|
-
args.
|
|
1926
|
+
app = args.first
|
|
1927
|
+
if val.is_a?(Hash)
|
|
1928
|
+
env = val[app.to_s] || val[app.to_sym]
|
|
1929
|
+
return args unless env
|
|
1930
|
+
|
|
1931
|
+
val = env.is_a?(String) ? basepath!(env) : true
|
|
1932
|
+
elsif app == 'ruby'
|
|
1933
|
+
return args
|
|
1934
|
+
end
|
|
1935
|
+
if val.is_a?(String)
|
|
1936
|
+
return args unless (val = basepath!(val))
|
|
1937
|
+
|
|
1938
|
+
args.unshift("--gemfile=#{shell_escape(val.relative_path_from(path), quote: true)}")
|
|
1939
|
+
end
|
|
1928
1940
|
args.unshift('bundle', 'exec')
|
|
1929
1941
|
end
|
|
1930
1942
|
args
|
|
@@ -37,12 +37,12 @@ module Squared
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
def insert(
|
|
41
|
-
replace Set.new(compact.insert(
|
|
40
|
+
def insert(...)
|
|
41
|
+
replace Set.new(compact.insert(...))
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def slice(
|
|
45
|
-
compact.slice(
|
|
44
|
+
def slice(...)
|
|
45
|
+
compact.slice(...)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def slice!(*args)
|
|
@@ -168,16 +168,16 @@ module Squared
|
|
|
168
168
|
to_a.join(@delim)
|
|
169
169
|
end
|
|
170
170
|
|
|
171
|
-
def to_enum(
|
|
172
|
-
to_a.to_enum(
|
|
171
|
+
def to_enum(...)
|
|
172
|
+
to_a.to_enum(...)
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
-
def to_json(
|
|
176
|
-
to_a.to_json(
|
|
175
|
+
def to_json(...)
|
|
176
|
+
to_a.to_json(...)
|
|
177
177
|
end
|
|
178
178
|
|
|
179
|
-
def to_yaml(
|
|
180
|
-
to_a.to_yaml(
|
|
179
|
+
def to_yaml(...)
|
|
180
|
+
to_a.to_yaml(...)
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
alias add :<<
|
|
@@ -248,7 +248,7 @@ module Squared
|
|
|
248
248
|
end
|
|
249
249
|
|
|
250
250
|
def parse(list, opts = extras, no: nil, single: nil, args: false, multiple: nil, first: nil, underscore: nil,
|
|
251
|
-
explicit: false, bool: %w[true false], auto: [], stdin: false, &blk)
|
|
251
|
+
explicit: false, bool: %w[true false], auto: [], regexp: {}, enum: {}, stdin: false, &blk)
|
|
252
252
|
@extras = []
|
|
253
253
|
@values = []
|
|
254
254
|
bare = []
|
|
@@ -265,8 +265,6 @@ module Squared
|
|
|
265
265
|
bl = []
|
|
266
266
|
ex = []
|
|
267
267
|
ml = []
|
|
268
|
-
re = {}
|
|
269
|
-
ar = {}
|
|
270
268
|
sw = {}
|
|
271
269
|
se = {}
|
|
272
270
|
list.flat_map do |val|
|
|
@@ -288,10 +286,10 @@ module Squared
|
|
|
288
286
|
end
|
|
289
287
|
if (n = val.index('='))
|
|
290
288
|
flag = val[0, n]
|
|
291
|
-
|
|
292
|
-
mod = if
|
|
293
|
-
pre =
|
|
294
|
-
|
|
289
|
+
opt = flag.split(':')
|
|
290
|
+
mod = if opt.size > 1
|
|
291
|
+
pre = opt.shift
|
|
292
|
+
opt.map { |s| "#{pre}:#{s}" }
|
|
295
293
|
else
|
|
296
294
|
[flag]
|
|
297
295
|
end
|
|
@@ -326,14 +324,14 @@ module Squared
|
|
|
326
324
|
pat = eval(val)
|
|
327
325
|
raise SyntaxError unless pat.is_a?(Regexp)
|
|
328
326
|
|
|
329
|
-
mod.each { |key|
|
|
327
|
+
mod.each { |key| regexp[key] = pat }
|
|
330
328
|
rescue SyntaxError
|
|
331
329
|
warn "#{self.class}: invalid pattern (#{val})"
|
|
332
330
|
end
|
|
333
331
|
when '{'
|
|
334
332
|
group = val[(n + 2)..].chomp!('}')&.split(',')
|
|
335
333
|
if group
|
|
336
|
-
mod.each { |key|
|
|
334
|
+
mod.each { |key| enum[key] = group }
|
|
337
335
|
else
|
|
338
336
|
warn "#{self.class}: invalid group (#{val})"
|
|
339
337
|
end
|
|
@@ -440,8 +438,8 @@ module Squared
|
|
|
440
438
|
else
|
|
441
439
|
push opt
|
|
442
440
|
end
|
|
443
|
-
elsif !
|
|
444
|
-
group = get.call(
|
|
441
|
+
elsif !enum.empty? && has.call(enum.keys, key)
|
|
442
|
+
group = get.call(enum)
|
|
445
443
|
if group.include?(val)
|
|
446
444
|
add shell_option(key, val, force: false, **kwargs)
|
|
447
445
|
elsif @strict
|
|
@@ -449,10 +447,10 @@ module Squared
|
|
|
449
447
|
else
|
|
450
448
|
push opt
|
|
451
449
|
end
|
|
452
|
-
elsif !
|
|
453
|
-
pat = get.call(
|
|
450
|
+
elsif !regexp.empty? && has.call(regexp.keys, key)
|
|
451
|
+
pat = get.call(regexp)
|
|
454
452
|
if val.match?(pat)
|
|
455
|
-
add quote_option
|
|
453
|
+
add __send__(kwargs[:merge] ? :basic_option : :quote_option, key, val, **kwargs)
|
|
456
454
|
elsif @strict
|
|
457
455
|
clear([opt], hint: "match != /#{pat.source}/")
|
|
458
456
|
else
|
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.9.
|
|
4
|
+
version: 0.9.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- An Pham
|
|
@@ -142,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
142
142
|
- !ruby/object:Gem::Version
|
|
143
143
|
version: '0'
|
|
144
144
|
requirements: []
|
|
145
|
-
rubygems_version: 4.0.
|
|
145
|
+
rubygems_version: 4.0.23
|
|
146
146
|
specification_version: 4
|
|
147
147
|
summary: Rake task generator for managing multi-language workspaces.
|
|
148
148
|
test_files: []
|