squared 0.5.11 → 0.6.0
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 +127 -0
- data/README.md +76 -35
- data/lib/squared/common/base.rb +1 -22
- data/lib/squared/common/format.rb +33 -25
- data/lib/squared/common/prompt.rb +58 -36
- data/lib/squared/common/shell.rb +44 -11
- data/lib/squared/common/system.rb +69 -36
- data/lib/squared/common/utils.rb +29 -6
- data/lib/squared/config.rb +17 -21
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +87 -91
- data/lib/squared/workspace/project/base.rb +548 -378
- data/lib/squared/workspace/project/docker.rb +393 -290
- data/lib/squared/workspace/project/git.rb +328 -312
- data/lib/squared/workspace/project/node.rb +545 -280
- data/lib/squared/workspace/project/python.rb +329 -200
- data/lib/squared/workspace/project/ruby.rb +672 -343
- data/lib/squared/workspace/project/support/class.rb +166 -68
- data/lib/squared/workspace/repo.rb +39 -35
- data/lib/squared/workspace/series.rb +6 -6
- data/lib/squared/workspace/support/base.rb +3 -29
- data/lib/squared/workspace/support/variables.rb +48 -0
- data/lib/squared/workspace/support.rb +1 -1
- data/lib/squared/workspace.rb +1 -1
- metadata +4 -7
- data/lib/squared/workspace/support/data.rb +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed078210213186745643650b4a73f7f376b5aba7033643c850b48d555c198501
|
|
4
|
+
data.tar.gz: d4d8c0e6308f3bdc3aca66891980259ad52ce11f3a53112c7a22ae4de9e31f40
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fcf308f894ee49566103575561b74459afc1aa7e03af8d5c5397c7bb7432dfce996cbb1291f4f81af792d5b1dd8ed6a9075ce7b2fab6f41dca0c56431e38b78c
|
|
7
|
+
data.tar.gz: 19f25542363b33fa567cbfcb0267c79fbc55a313ce0fba8ab25ec17dd43f276b004b00304e8bfe38dba1338a2e554170a8f1535d1bdc5981407fae6e9bff2bf8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,129 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.0] - 2025-10-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Docker command compose action create was implemented.
|
|
8
|
+
- Docker command compose action ps was implemented.
|
|
9
|
+
- Docker command compose action ps is interactive.
|
|
10
|
+
- Project base asdf commands [latest|where|update] were implemented.
|
|
11
|
+
- Pip command options were updated to 25.2.
|
|
12
|
+
- Command line programs who do not assign with equals are supported.
|
|
13
|
+
- Docker command ls with column formatting was implemented.
|
|
14
|
+
- Git command stash action staged and worktree were implemented.
|
|
15
|
+
- Git command diff action files can output to a patch file.
|
|
16
|
+
- Repo task init with REPO_Y can auto-accept overwrite confirmation.
|
|
17
|
+
- Caller locations for errors can be excluded using ARG[:BACKTRACE].
|
|
18
|
+
- Node command package action reinstall was implemented.
|
|
19
|
+
- Node class method and command tsc was implemented.
|
|
20
|
+
- Python command pip action reinstall was implemented.
|
|
21
|
+
- Project command options can be stored by class ref and project name.
|
|
22
|
+
- Bundler command config is interactive.
|
|
23
|
+
- Ruby method bundle supports stored command options.
|
|
24
|
+
- Ruby method rake supports stored command options.
|
|
25
|
+
- Ruby method ruby supports stored command options.
|
|
26
|
+
- Ruby method gem supports stored command options.
|
|
27
|
+
- Python method pip supports stored command options.
|
|
28
|
+
- Python command pip action wheel was implemented.
|
|
29
|
+
- Ruby method irb supports stored command options.
|
|
30
|
+
- Ruby command gem action command was implemented.
|
|
31
|
+
- ENV supplementary command options can be space delimited.
|
|
32
|
+
- Project command options can extend other stored options.
|
|
33
|
+
- Ruby command gem action outdated can update without being interactive.
|
|
34
|
+
- Ruby command gem action update system can accept a specific version.
|
|
35
|
+
- Ruby command gem action outdated supports threading.
|
|
36
|
+
- Git command grep was implemented.
|
|
37
|
+
- Common format bright colors fallback to standard colors when not enabled.
|
|
38
|
+
- Project base command unpack action gz was implemented.
|
|
39
|
+
- Common format defined String instance method subhint.
|
|
40
|
+
- Application readers [exception|pipe|verbose|warning] were converted into accessors.
|
|
41
|
+
- Node private projects can publish entire workspace with tags.
|
|
42
|
+
- Node command outdated can select a range of packages to update.
|
|
43
|
+
- Gem command outdated can select a range of packages to update.
|
|
44
|
+
- Python command outdated can select a range of packages to update.
|
|
45
|
+
- Node command outdated option diff was implemented.
|
|
46
|
+
- Bundler command outdated can select a range of packages to update.
|
|
47
|
+
- Common prompt method choice can select all items with "\*".
|
|
48
|
+
- Node command bump can auto-commit package.json using GIT_MESSAGE.
|
|
49
|
+
- Git command options were updated to version 2.51.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- Git method source will raise error when checking exit status.
|
|
54
|
+
- Date gem is no longer globally required.
|
|
55
|
+
- Global task git:all was removed.
|
|
56
|
+
- Common base method as_a was relocated to Utils.
|
|
57
|
+
- Python command build and publish detects only one backend.
|
|
58
|
+
- Docker command compose action ps was renamed service.
|
|
59
|
+
- Docker command image action list was renamed ls.
|
|
60
|
+
- Project base method success? conditionally calls print_success method.
|
|
61
|
+
- Error classes were not specified for invalid operation.
|
|
62
|
+
- Common format methods stripstyle and stripext are String instance methods.
|
|
63
|
+
- Common format method alias puts_oe was removed.
|
|
64
|
+
- Git commands without a valid action will exit with error status.
|
|
65
|
+
- Errno exceptions are used in place of SystemCallError.
|
|
66
|
+
- Common format method raise_error defaults to RuntimeError.
|
|
67
|
+
- OptionPartition delegator method delete_at was renamed remove_at.
|
|
68
|
+
- Node event name "publish" was renamed to "npm:publish".
|
|
69
|
+
- Project task run with a Method passes self as first argument.
|
|
70
|
+
- Ruby command check was removed.
|
|
71
|
+
- Ruby method gem! was renamed gem.
|
|
72
|
+
- Ruby methods ruby and irb first argument was converted into kwargs.
|
|
73
|
+
- Ruby method rake executes all tasks in one run command.
|
|
74
|
+
- Ruby project file methods return nil instead of false.
|
|
75
|
+
- Ruby commands [exec|cache|config] were relocated under bundle namespace.
|
|
76
|
+
- Ruby command gem action update without arguments is not modified.
|
|
77
|
+
- Ruby command install was replaced with reinstall under bundle namespace.
|
|
78
|
+
- Ruby command update was relocated under bundle namespace.
|
|
79
|
+
- Common prompt confirm timeout was revised for non-immediate responses.
|
|
80
|
+
- Project relative paths are stripped from banner when context is displayed.
|
|
81
|
+
- Workspace module Support extend submodules private methods.
|
|
82
|
+
- Workspace method add passes parent through Project constructor.
|
|
83
|
+
- Project base method run_s uses last argument for ENV hash.
|
|
84
|
+
- Project base method inject does not exit program when raised.
|
|
85
|
+
- Reline gem is installed only when using at least Ruby 3.0.
|
|
86
|
+
- Python method install arguments strategy and user were removed.
|
|
87
|
+
- Project command outdated does not support threading when interactive.
|
|
88
|
+
- Project base accessor global was converted into a reader and setter.
|
|
89
|
+
- Repo build can simultaneously use script and run through REPO_BUILD.
|
|
90
|
+
- Repo static method read_manifest was made an instance method named repo_manifest.
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
|
|
94
|
+
- Node task update did not check equivalent ENV install options.
|
|
95
|
+
|
|
96
|
+
## [0.5.12] - 2025-10-31
|
|
97
|
+
|
|
98
|
+
### Changed
|
|
99
|
+
|
|
100
|
+
- Ruby task depend does not override bundle config without setting.
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
|
|
104
|
+
- Node command run did nothing at all when called upon.
|
|
105
|
+
|
|
106
|
+
## [0.4.26] - 2025-10-31
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
|
|
110
|
+
- Docker command options were updated to 28.5.
|
|
111
|
+
|
|
112
|
+
### Changed
|
|
113
|
+
|
|
114
|
+
- Node package manager does not override package.json with NODE_INSTALL.
|
|
115
|
+
- Node workspaces can specify more than one package manager through NODE_INSTALL.
|
|
116
|
+
|
|
117
|
+
### Fixed
|
|
118
|
+
|
|
119
|
+
- Node command add did not provide optional save argument.
|
|
120
|
+
- Python command outdated did not detect synchronous output.
|
|
121
|
+
- Node command outdated auto-commit was completely dysfunctional.
|
|
122
|
+
- Project workspaces caused a complete meltdown on TruffleRuby.
|
|
123
|
+
- Project build initialization global flag was always incoherent.
|
|
124
|
+
- Project base setters did not accept direct values.
|
|
125
|
+
- Project base global graph tasks are not definable by a sub-project.
|
|
126
|
+
|
|
3
127
|
## [0.5.11] - 2025-10-18
|
|
4
128
|
|
|
5
129
|
### Fixed
|
|
@@ -1153,6 +1277,8 @@
|
|
|
1153
1277
|
|
|
1154
1278
|
- Changelog was created.
|
|
1155
1279
|
|
|
1280
|
+
[0.6.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.0
|
|
1281
|
+
[0.5.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.12
|
|
1156
1282
|
[0.5.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.11
|
|
1157
1283
|
[0.5.10]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.10
|
|
1158
1284
|
[0.5.9]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.9
|
|
@@ -1165,6 +1291,7 @@
|
|
|
1165
1291
|
[0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
|
|
1166
1292
|
[0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
|
|
1167
1293
|
[0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
|
|
1294
|
+
[0.4.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.26
|
|
1168
1295
|
[0.4.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.25
|
|
1169
1296
|
[0.4.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.24
|
|
1170
1297
|
[0.4.23]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.23
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# squared 0.
|
|
1
|
+
# squared 0.6
|
|
2
2
|
|
|
3
3
|
* [source](https://github.com/anpham6/squared-ruby)
|
|
4
4
|
* [docs](https://squared.readthedocs.io)
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
| 2025-06-16 | 0.5.0 | 2.5.0 | 3.4.3 |
|
|
15
15
|
| ---------- | ----- | ----- | ----- |
|
|
16
16
|
| 2025-08-23 | 0.5.5 | | 3.4.5 |
|
|
17
|
+
| 2025-10-31 | 0.6.0 | | 3.4.7 |
|
|
17
18
|
|
|
18
19
|
The range chart indicates the latest Ruby tested against at the time of release.
|
|
19
20
|
|
|
@@ -142,20 +143,59 @@ Workspace::Application
|
|
|
142
143
|
# android = /workspaces/android-docs
|
|
143
144
|
# chrome = /workspaces/chrome-docs
|
|
144
145
|
|
|
146
|
+
# ...symbol?, string, ...string?, ...symbol?
|
|
147
|
+
# extend name args project
|
|
148
|
+
|
|
149
|
+
Node = Workspace::Project::Node # tsc
|
|
150
|
+
Node.options("build:dev", "target=es2022", project: "tsconfig.json") # :node (ref)
|
|
151
|
+
Node.options("build:dev", "outDir=tmp", :squared) # squared (project name)
|
|
152
|
+
|
|
153
|
+
Ruby = Workspace::Project::Ruby # ruby | gem | rake | bundle | irb
|
|
154
|
+
Ruby.options("lint", "rubocop", opts: ["gemfile=Gemfile"]) # :ruby
|
|
155
|
+
Ruby.options("lint", "--parallel", :squared)
|
|
156
|
+
|
|
157
|
+
Python = Workspace::Project::Python # pip
|
|
158
|
+
Python.options("build", opts: ["r=requirements.txt"]) # :python
|
|
159
|
+
Python.options(:build, "build:dev", opts: ["no-deps"])
|
|
160
|
+
|
|
145
161
|
Workspace::Application
|
|
146
|
-
.new(ENV["SQUARED_HOME"], prefix: "rb", common: false)
|
|
162
|
+
.new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
|
|
147
163
|
.group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
|
|
148
164
|
pathname: {
|
|
149
|
-
run: "rake compile"
|
|
165
|
+
run: "rake compile" # rake rb:pathname:build
|
|
150
166
|
}
|
|
151
167
|
})
|
|
152
|
-
.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
168
|
+
.add("squared") do
|
|
169
|
+
apply :run, proc { # rake rb:squared:build
|
|
170
|
+
tsc(with: scriptname || "build:dev", verbose: true) # Repo (global)
|
|
171
|
+
# OR
|
|
172
|
+
tsc("target=es2022", "outDir=tmp", project: "tsconfig.json") # 1
|
|
173
|
+
tsc("clean=true", "./sqd/tsconfig.json", build: true) # 2
|
|
174
|
+
run("npm run build:dev", { "RUBYOPT" => "-W2" }, from: :run) # 3
|
|
175
|
+
|
|
176
|
+
# Parallel
|
|
177
|
+
[
|
|
178
|
+
Thread.new { tsc(sync: false) },
|
|
179
|
+
Thread.new { tsc(sync: false) },
|
|
180
|
+
Thread.new { run(sync: false) }
|
|
181
|
+
]
|
|
182
|
+
.each(&:join)
|
|
183
|
+
}
|
|
184
|
+
apply :lint, proc {
|
|
185
|
+
bundle("exec", "-A --cache=true", with: "lint", verbose: true) # bundle exec --gemfile='/squared/Gemfile' rubocop --parallel -A --cache=true
|
|
186
|
+
}
|
|
187
|
+
end
|
|
188
|
+
.with(:python, editable: false) do # ref=Symbol | group=String
|
|
189
|
+
banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
|
|
190
|
+
doc("make html") # rake rb:doc:python
|
|
191
|
+
run(false) # rake rb:build:python (disabled)
|
|
192
|
+
exclude(%i[base git]) # Project::Git.ref (superclass)
|
|
193
|
+
add("android-docs", "android") # rake rb:android:doc
|
|
194
|
+
add("chrome-docs", "chrome") do # rake rb:chrome:doc
|
|
195
|
+
apply :run, proc {
|
|
196
|
+
pip("wheel", with: "build:dev") # pip wheel -r '/chrome-docs/requirements.txt' --no-deps
|
|
197
|
+
}
|
|
198
|
+
end
|
|
159
199
|
end
|
|
160
200
|
.style("inline", "bold")
|
|
161
201
|
.build
|
|
@@ -496,28 +536,28 @@ Non-task:
|
|
|
496
536
|
|
|
497
537
|
Most project classes will inherit from `Git` which enables these tasks:
|
|
498
538
|
|
|
499
|
-
| Task | Git | Command
|
|
500
|
-
| :--------- | :--------------- |
|
|
501
|
-
| branch | branch | create track delete move copy list current
|
|
502
|
-
| checkout | checkout | commit branch track detach path
|
|
503
|
-
| commit | commit | add all amend amend-orig fixup
|
|
504
|
-
| diff | diff | head branch files view between contain
|
|
505
|
-
| fetch | fetch | origin remote all
|
|
506
|
-
| files | ls-files | cached modified deleted others
|
|
507
|
-
| git | | add blame clean mv revert rm status
|
|
508
|
-
| log | log | view between contain
|
|
509
|
-
| merge | merge | commit no-commit send
|
|
510
|
-
| pull | pull | origin remote all
|
|
511
|
-
| rebase | rebase | branch onto send
|
|
512
|
-
| refs | ls-remote --refs | heads tags remote
|
|
513
|
-
| reset | reset | commit index patch mode undo
|
|
514
|
-
| restore | restore | source staged worktree
|
|
515
|
-
| rev | rev | commit build output
|
|
516
|
-
| show | show | format oneline textconv
|
|
517
|
-
| stash | stash | push pop apply branch drop clear list all
|
|
518
|
-
| submodule | submodule | status update branch url sync
|
|
519
|
-
| switch | switch | branch create detach
|
|
520
|
-
| tag | tag | add sign delete list
|
|
539
|
+
| Task | Git | Command |
|
|
540
|
+
| :--------- | :--------------- | :-------------------------------------------------------- |
|
|
541
|
+
| branch | branch | create track delete move copy list current |
|
|
542
|
+
| checkout | checkout | commit branch track detach path |
|
|
543
|
+
| commit | commit | add all amend amend-orig fixup |
|
|
544
|
+
| diff | diff | head branch files view between contain |
|
|
545
|
+
| fetch | fetch | origin remote all |
|
|
546
|
+
| files | ls-files | cached modified deleted others |
|
|
547
|
+
| git | | add blame clean grep mv revert rm status |
|
|
548
|
+
| log | log | view between contain |
|
|
549
|
+
| merge | merge | commit no-commit send |
|
|
550
|
+
| pull | pull | origin remote all |
|
|
551
|
+
| rebase | rebase | branch onto send |
|
|
552
|
+
| refs | ls-remote --refs | heads tags remote |
|
|
553
|
+
| reset | reset | commit index patch mode undo |
|
|
554
|
+
| restore | restore | source staged worktree |
|
|
555
|
+
| rev | rev | commit build output |
|
|
556
|
+
| show | show | format oneline textconv |
|
|
557
|
+
| stash | stash | push pop apply branch drop clear list all staged worktree |
|
|
558
|
+
| submodule | submodule | status update branch url sync |
|
|
559
|
+
| switch | switch | branch create detach |
|
|
560
|
+
| tag | tag | add sign delete list |
|
|
521
561
|
|
|
522
562
|
You can disable all of them at once using the `exclude` property.
|
|
523
563
|
|
|
@@ -632,7 +672,7 @@ LOG_LEVEL # See gem "logger"
|
|
|
632
672
|
|
|
633
673
|
### Git
|
|
634
674
|
|
|
635
|
-
* Version: [2.
|
|
675
|
+
* Version: [2.51](https://github.com/git/git/blob/v2.51.0/Documentation/RelNotes/2.51.0.adoc)
|
|
636
676
|
|
|
637
677
|
```sh
|
|
638
678
|
GIT_OPTIONS=q,strategy=ort # all
|
|
@@ -688,7 +728,7 @@ GIT_AUTOSTASH_${NAME}=0 # rebase (project only)
|
|
|
688
728
|
|
|
689
729
|
### Docker
|
|
690
730
|
|
|
691
|
-
* Version: [28.
|
|
731
|
+
* Version: [28.5](https://docs.docker.com/engine/release-notes/28)
|
|
692
732
|
|
|
693
733
|
```sh
|
|
694
734
|
DOCKER_OPTIONS=q,no-cache # all
|
|
@@ -735,7 +775,7 @@ These global options also can target the application main suffix `${NAME}`. (e.g
|
|
|
735
775
|
```sh
|
|
736
776
|
REPO_ROOT # parent dir
|
|
737
777
|
REPO_HOME # project dir (main)
|
|
738
|
-
REPO_BUILD # run,
|
|
778
|
+
REPO_BUILD # script,run (e.g. build:dev | build:dev,make install | make)
|
|
739
779
|
REPO_GROUP # string
|
|
740
780
|
REPO_REF # e.g. ruby,node
|
|
741
781
|
REPO_DEV # pattern,0,1
|
|
@@ -747,6 +787,7 @@ REPO_MANIFEST # e.g. latest,nightly,prod
|
|
|
747
787
|
REPO_GROUPS # e.g. base,prod,docs
|
|
748
788
|
REPO_STAGE # 0,1,2,3,4
|
|
749
789
|
REPO_SUBMODULLES # 0,1
|
|
790
|
+
REPO_Y # 0,1
|
|
750
791
|
REPO_TIMEOUT # confirm dialog (seconds)
|
|
751
792
|
```
|
|
752
793
|
|
data/lib/squared/common/base.rb
CHANGED
|
@@ -17,6 +17,7 @@ module Squared
|
|
|
17
17
|
GRAPH: ['|', '-', '|', '\\', '-'].freeze,
|
|
18
18
|
BORDER: ['|', '-', '-', '-', '-', '-', '|', '|', '-', '-'].freeze,
|
|
19
19
|
VIEW: 'view',
|
|
20
|
+
BACKTRACE: $DEBUG || !$VERBOSE.nil?,
|
|
20
21
|
LEVEL: ENV.fetch('LOG_LEVEL', 0).to_i,
|
|
21
22
|
COLOR: ENV.fetch('NO_COLOR', '').empty?
|
|
22
23
|
}
|
|
@@ -97,27 +98,5 @@ module Squared
|
|
|
97
98
|
VAR[:theme].each_value { |val| val.freeze.each_value(&:freeze) }
|
|
98
99
|
VAR.freeze
|
|
99
100
|
end
|
|
100
|
-
|
|
101
|
-
module_function
|
|
102
|
-
|
|
103
|
-
def as_a(obj, *meth, flat: nil, compact: false, &blk)
|
|
104
|
-
return [] if obj.nil?
|
|
105
|
-
|
|
106
|
-
unless obj.is_a?(::Array)
|
|
107
|
-
obj = if obj.respond_to?(:to_ary)
|
|
108
|
-
obj.to_ary
|
|
109
|
-
elsif obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
|
|
110
|
-
val
|
|
111
|
-
else
|
|
112
|
-
[obj]
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
obj = flat.is_a?(::Numeric) ? obj.flatten(flat) : obj.flatten if flat
|
|
116
|
-
obj = obj.compact if compact
|
|
117
|
-
obj = obj.map(&meth.shift) until meth.empty?
|
|
118
|
-
return obj unless block_given?
|
|
119
|
-
|
|
120
|
-
obj.select(&blk)
|
|
121
|
-
end
|
|
122
101
|
end
|
|
123
102
|
end
|
|
@@ -39,6 +39,10 @@ module Squared
|
|
|
39
39
|
TEXT_STYLE = [:bold, :dim, :italic, :underline, :blinking, nil, :inverse, :hidden, :strikethrough].freeze
|
|
40
40
|
private_constant :AIX_TERM, :BOX_GRAPH, :BOX_BORDER, :TEXT_STYLE
|
|
41
41
|
|
|
42
|
+
String.define_method(:stripstyle) { gsub(/\x1B\[(?:\d+;?)+m/, '') }
|
|
43
|
+
String.define_method(:stripext) { File.basename(self, '.*') }
|
|
44
|
+
String.define_method(:subhint) { |s| s.nil? || (s.is_a?(::String) && s.empty?) ? self : "#{self} (#{s})" }
|
|
45
|
+
|
|
42
46
|
def enable_aixterm
|
|
43
47
|
unless (colors = __get__(:colors)).frozen?
|
|
44
48
|
colors.update(AIX_TERM)
|
|
@@ -85,7 +89,7 @@ module Squared
|
|
|
85
89
|
end
|
|
86
90
|
else
|
|
87
91
|
t = type.to_sym
|
|
88
|
-
if (c = __get__(:colors)[t])
|
|
92
|
+
if (c = __get__(:colors)[t] || __get__(:colors)[t.to_s.sub('bright_', '').to_sym])
|
|
89
93
|
if index == -1
|
|
90
94
|
s = wrap.call(s, [c])
|
|
91
95
|
else
|
|
@@ -94,7 +98,7 @@ module Squared
|
|
|
94
98
|
else
|
|
95
99
|
next unless (n = TEXT_STYLE.index(t))
|
|
96
100
|
|
|
97
|
-
s = "\x1B[#{n
|
|
101
|
+
s = "\x1B[#{n.succ}m#{s}\x1B[#{n == 0 ? 22 : n + 21}m"
|
|
98
102
|
end
|
|
99
103
|
end
|
|
100
104
|
if index == -1
|
|
@@ -108,7 +112,7 @@ module Squared
|
|
|
108
112
|
ret = wrap.call(ret, code) unless code.empty?
|
|
109
113
|
return ret unless data
|
|
110
114
|
|
|
111
|
-
out = ''
|
|
115
|
+
out = +''
|
|
112
116
|
data.to_a.each_with_index do |group, i|
|
|
113
117
|
next if i == 0
|
|
114
118
|
|
|
@@ -126,8 +130,8 @@ module Squared
|
|
|
126
130
|
colors = __get__(:colors)
|
|
127
131
|
Array(args).flatten.compact.each do |val|
|
|
128
132
|
if !val.is_a?(::Numeric)
|
|
129
|
-
|
|
130
|
-
ret <<
|
|
133
|
+
k = val.to_sym
|
|
134
|
+
ret << k if colors.key?(k) || colors.key?(k.to_s.sub('bright_', '').to_sym) || TEXT_STYLE.include?(k)
|
|
131
135
|
elsif val.between?(0, 256)
|
|
132
136
|
ret << val
|
|
133
137
|
elsif val < 0 && (b = val.to_s.split('.')[1])
|
|
@@ -151,6 +155,10 @@ module Squared
|
|
|
151
155
|
end
|
|
152
156
|
end
|
|
153
157
|
|
|
158
|
+
def opt_style(styles, pat = nil, index = 1)
|
|
159
|
+
{ styles: styles, pat: pat, index: index }
|
|
160
|
+
end
|
|
161
|
+
|
|
154
162
|
def log_sym(level)
|
|
155
163
|
if level.is_a?(::Numeric)
|
|
156
164
|
case level
|
|
@@ -188,8 +196,12 @@ module Squared
|
|
|
188
196
|
end
|
|
189
197
|
if (args.size > 1 && !hint) || hint == false
|
|
190
198
|
title = log_title(level, color: false)
|
|
191
|
-
|
|
192
|
-
|
|
199
|
+
emphasize(args,
|
|
200
|
+
title: title + (subject ? " #{subject}" : ''),
|
|
201
|
+
pipe: -1,
|
|
202
|
+
sub: if color
|
|
203
|
+
opt_style(__get__(:theme)[:logger][log_sym(level)], /\A(#{Regexp.escape(title)})(.*)\z/m)
|
|
204
|
+
end)
|
|
193
205
|
else
|
|
194
206
|
msg = [log_title(level, color: color)]
|
|
195
207
|
msg << (color ? sub_style(subject.to_s, styles: (@theme && @theme[:subject]) || :bold) : subject) if subject
|
|
@@ -205,7 +217,7 @@ module Squared
|
|
|
205
217
|
begin
|
|
206
218
|
File.open(pipe, 'a') do |f|
|
|
207
219
|
br = File::SEPARATOR == '\\' ? "\r\n" : "\n"
|
|
208
|
-
args.flatten.each { |val| f.write(
|
|
220
|
+
args.flatten.each { |val| f.write(val.chomp.stripstyle + br) }
|
|
209
221
|
end
|
|
210
222
|
return
|
|
211
223
|
rescue StandardError
|
|
@@ -215,13 +227,12 @@ module Squared
|
|
|
215
227
|
(pipe == 2 ? $stderr : $stdout).puts(*args)
|
|
216
228
|
end
|
|
217
229
|
|
|
218
|
-
alias puts_oe log_console
|
|
219
|
-
|
|
220
230
|
module_function
|
|
221
231
|
|
|
222
232
|
def message(*args, hint: nil, empty: false, space: ARG[:SPACE])
|
|
223
233
|
(empty ? args.reject { |val| val.nil? || (val.respond_to?(:empty?) && val.empty?) } : args)
|
|
224
|
-
.join(space)
|
|
234
|
+
.join(space)
|
|
235
|
+
.subhint(hint)
|
|
225
236
|
end
|
|
226
237
|
|
|
227
238
|
def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, pipe: nil,
|
|
@@ -237,7 +248,7 @@ module Squared
|
|
|
237
248
|
lines = val.to_s.lines(chomp: true)
|
|
238
249
|
lines[0] = "#{val.class}: #{lines.first}" if (err = val.is_a?(::StandardError))
|
|
239
250
|
end
|
|
240
|
-
n = cols || max.call(lines)
|
|
251
|
+
n = (cols.is_a?(::Array) ? cols.map(&:size).max : cols) || max.call(lines)
|
|
241
252
|
if $stdout.tty?
|
|
242
253
|
require 'io/console'
|
|
243
254
|
(n = [n, $stdout.winsize[1] - 4].min) rescue nil
|
|
@@ -255,14 +266,14 @@ module Squared
|
|
|
255
266
|
sub.each { |h| s = sub_style(s, **h) }
|
|
256
267
|
s = "#{b0} #{s} #{b0}"
|
|
257
268
|
if border
|
|
258
|
-
s = sub_style(s,
|
|
259
|
-
s = sub_style(s,
|
|
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))
|
|
260
271
|
end
|
|
261
272
|
s
|
|
262
273
|
end
|
|
263
274
|
out << draw.call(b2, b3)
|
|
264
275
|
if title
|
|
265
|
-
out.concat(title.map { |t| pr.call(t) })
|
|
276
|
+
out.concat(title.map! { |t| pr.call(t) })
|
|
266
277
|
out << draw.call(b6, b7)
|
|
267
278
|
end
|
|
268
279
|
lines.each { |line| out << pr.call(line) }
|
|
@@ -296,16 +307,13 @@ module Squared
|
|
|
296
307
|
end
|
|
297
308
|
end
|
|
298
309
|
|
|
299
|
-
def
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
def raise_error(*args, hint: nil, kind: ArgumentError)
|
|
308
|
-
raise kind, message(*args, hint: hint, empty: true), caller_locations(1).map(&:to_s)
|
|
310
|
+
def raise_error(*args, hint: nil, kind: RuntimeError, start: 0)
|
|
311
|
+
kind = args.shift if args.first.is_a?(::Class) && args.first < ::Exception
|
|
312
|
+
raise kind, message(*args, hint: hint, empty: true), if ARG[:BACKTRACE]
|
|
313
|
+
caller(start.succ)
|
|
314
|
+
else
|
|
315
|
+
caller_locations(start.succ, 1).first&.base_label
|
|
316
|
+
end
|
|
309
317
|
end
|
|
310
318
|
end
|
|
311
319
|
end
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
unless defined?(Readline)
|
|
4
|
+
if RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.7'
|
|
5
|
+
require 'readline'
|
|
6
|
+
else
|
|
7
|
+
begin
|
|
8
|
+
require 'reline'
|
|
9
|
+
Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
|
|
10
|
+
Readline = Reline
|
|
11
|
+
rescue LoadError
|
|
12
|
+
require 'readline'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
3
17
|
module Squared
|
|
4
18
|
module Common
|
|
5
19
|
module Prompt
|
|
6
20
|
module_function
|
|
7
21
|
|
|
8
|
-
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts:
|
|
9
|
-
require 'readline'
|
|
22
|
+
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 3, timeout: 60)
|
|
10
23
|
require 'timeout'
|
|
11
24
|
if agree == 'Y' && cancel == 'N' && !msg.match?(%r{\[(?:Yn|nY|Y/n|y/N)\]})
|
|
12
25
|
case default
|
|
@@ -38,9 +51,8 @@ module Squared
|
|
|
38
51
|
end
|
|
39
52
|
end
|
|
40
53
|
|
|
41
|
-
def choice(msg, list = nil, min: 1, max: 1, multiple: false,
|
|
42
|
-
attempts:
|
|
43
|
-
require 'readline'
|
|
54
|
+
def choice(msg, list = nil, min: 1, max: 1, multiple: false, index: false, grep: nil, border: nil, auto: true,
|
|
55
|
+
force: true, attempts: 3, timeout: 0)
|
|
44
56
|
require 'timeout'
|
|
45
57
|
if list
|
|
46
58
|
grep &&= Array(grep).map { |val| Regexp.new(val) }
|
|
@@ -52,40 +64,51 @@ module Squared
|
|
|
52
64
|
puts '%2d. %s' % [items.size, val]
|
|
53
65
|
end
|
|
54
66
|
max = items.size
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
raise ArgumentError, 'empty selection list' if max == 0
|
|
68
|
+
|
|
69
|
+
min = grep ? 1 : [min, max].min
|
|
57
70
|
if auto
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
auto.times { puts } if auto.is_a?(::Numeric)
|
|
72
|
+
if border == true
|
|
73
|
+
puts print_footer
|
|
74
|
+
elsif border
|
|
75
|
+
puts print_footer(border: border)
|
|
76
|
+
end
|
|
77
|
+
msg = "#{msg + (force ? ':' : '?')} [#{min}-#{max}#{if (n = multiple)
|
|
78
|
+
"|,#{n.is_a?(::Numeric) ? "{#{n}}" : '*'}"
|
|
79
|
+
end}] "
|
|
61
80
|
end
|
|
62
81
|
end
|
|
63
|
-
|
|
82
|
+
between = ->(s) { s.match?(/^\d+$/) && s.to_i.between?(min, max) }
|
|
64
83
|
Timeout.timeout(timeout) do
|
|
65
84
|
while (ch = Readline.readline(msg))
|
|
66
85
|
unless (ch = ch.strip).empty?
|
|
67
86
|
if multiple
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
k = if ch == '*'
|
|
88
|
+
(min..max).to_a
|
|
89
|
+
else
|
|
90
|
+
ch.split(/\s*,\s*/).map! do |s|
|
|
91
|
+
if s =~ /^(\d+)-(\d+)$/
|
|
92
|
+
next unless between.call($1) && between.call($2)
|
|
72
93
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
i = $1.to_i
|
|
95
|
+
j = $2.to_i
|
|
96
|
+
next (i..j).to_a if i < j
|
|
97
|
+
elsif between.call(s)
|
|
98
|
+
s.to_i
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
unless k.include?(nil)
|
|
103
|
+
k.flatten!
|
|
104
|
+
k.uniq!
|
|
105
|
+
k.sort!
|
|
106
|
+
unless multiple.is_a?(::Numeric) && multiple != k.size
|
|
107
|
+
return index || !items ? k : k.map! { |i| items[i.pred] }
|
|
78
108
|
end
|
|
79
109
|
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
b.uniq!
|
|
83
|
-
b.sort!
|
|
84
|
-
return b unless items
|
|
85
|
-
return b.map! { |i| items[i - 1] } unless multiple.is_a?(::Numeric) && multiple != b.size
|
|
86
|
-
end
|
|
87
|
-
elsif valid.call(ch)
|
|
88
|
-
return items ? items[ch.to_i - 1] : ch.to_i
|
|
110
|
+
elsif between.call(ch)
|
|
111
|
+
return index || !items ? ch.to_i : items[ch.to_i.pred]
|
|
89
112
|
end
|
|
90
113
|
end
|
|
91
114
|
attempts -= 1
|
|
@@ -98,12 +121,11 @@ module Squared
|
|
|
98
121
|
puts
|
|
99
122
|
exit 0
|
|
100
123
|
else
|
|
101
|
-
|
|
124
|
+
[] if multiple
|
|
102
125
|
end
|
|
103
126
|
end
|
|
104
127
|
|
|
105
128
|
def readline(msg, history = false, force: nil, multiline: nil, &blk)
|
|
106
|
-
require 'readline'
|
|
107
129
|
multiline = if multiline && Readline.respond_to?(:readmultiline)
|
|
108
130
|
multiline.is_a?(::Enumerable) || block_given? ? multiline : [multiline.to_s]
|
|
109
131
|
end
|
|
@@ -118,11 +140,11 @@ module Squared
|
|
|
118
140
|
end
|
|
119
141
|
case force
|
|
120
142
|
when ::TrueClass, ::FalseClass
|
|
121
|
-
msg = "#{msg}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
143
|
+
msg = "#{msg}%s%s " % if multiline
|
|
144
|
+
[' ', multiline.is_a?(::Enumerable) ? "{#{multiline.to_a.join('|')}}" : multiline]
|
|
145
|
+
else
|
|
146
|
+
[force ? ':' : '?', '']
|
|
147
|
+
end
|
|
126
148
|
ret = (prompt.call || '').strip
|
|
127
149
|
multiline.each { |val| break if ret.delete_suffix!(val.to_s) } if multiline.is_a?(::Enumerable)
|
|
128
150
|
exit 1 if force && ret.empty?
|