squared 0.4.8 → 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 483002a469a23461dcee07ded3610011d831f2c737142cd4b464899fbdf70cde
4
- data.tar.gz: 4601b03b61f6270e8b3841777effd420b47c752ddbe96924ca329ee92c98ee4c
3
+ metadata.gz: ba613d7ba02a664fb4581573f6ee04d705f6bb2d1cb165c30c49d97eb259cbec
4
+ data.tar.gz: 764888100c6a6560478e99ed1451f1593a86e120799e25400708d81be934102c
5
5
  SHA512:
6
- metadata.gz: 5767519e7f0150a753c0cbf97aa59292ad59a29b4f78c6e7596e5bd369b035258339d062b896c59d37496ccdcd4224179a745065f1dc41a35f876a507f30e171
7
- data.tar.gz: c457cbd60b4865aea1e218ce9609c4094f618cc4b404eac309c8235b3bc116599487d1c641151cd99bceab6d28a03b48abd1774e447017afb2d28439aca40298
6
+ metadata.gz: 1cf6f1f10babf7bfbbe665fe5fc97527cf1df4093a3e6b8b906a4bf8cf87f538c601faee86f40decb79455de340e1d8f510fb45d0acc17694cd97a4051010539
7
+ data.tar.gz: 2b537c2c6a30a17191f32eb1012b225bc29fff9e9102b663a6dcf3ffd05465f4e8a0790f4cbdd6c63b21bd64c762e85dff1d22b4eb35053702a6692e92c994cc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,98 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.10] - 2025-05-08
4
+
5
+ ### Added
6
+
7
+ - Git command pull and fetch action remote is interactive.
8
+ - Ruby command script uses multiline input when available.
9
+ - Ruby command file is interactive.
10
+ - Node command publish can accept access option levels.
11
+ - Docker command image action rm when called empty is interactive.
12
+
13
+ ### Fixed
14
+
15
+ - Disabled batch and alias tasks were not hidden.
16
+ - Docker tags from ENV were appended twice.
17
+ - Git events were not always registered.
18
+ - Git revbuild did not write lock data file with parallel tasks.
19
+
20
+ ### Changed
21
+
22
+ - Choice selection default was set to no timeout.
23
+ - Git command add can accept a file search pattern.
24
+
25
+ ## [0.4.9] - 2025-04-27
26
+
27
+ ### Added
28
+
29
+ - Git command reset action commit is interactive.
30
+ - Git command commit action all is interactive.
31
+ - Git command log and diff commit based actions are interactive.
32
+ - Git command branch action move and copy are interactive.
33
+ - Git command rebase and merge are interactive.
34
+ - Git command checkout action detach is interactive.
35
+ - Git command branch action delete for remotes is interactive.
36
+ - Git command restore action source was created.
37
+ - Git command tag actions can choose a remote to push.
38
+ - Git command switch was implemented.
39
+ - Git command branch action create is interactive.
40
+ - Git command reset action mode and patch are interactive.
41
+ - Git command restore action staged and worktree are interactive.
42
+ - Git command log and checkout commit based actions are interactive.
43
+ - Ruby command ruby action script is interactive.
44
+ - Ruby command irb is interactive.
45
+ - Git command commit action fixup was implemented.
46
+ - Git command commit action all can accept add command options.
47
+ - Git command branch action create and track can upload tracking.
48
+ - Git command add was implemented.
49
+ - Python command venv action run is interactive.
50
+
51
+ ### Changed
52
+
53
+ - Ruby depend with bundler excludes development group in production.
54
+ - OptionPartition class first and pass parameters were combined.
55
+ - Git command stash action list can accept log options.
56
+ - Git command branch action set was renamed track.
57
+ - Ruby autodetect can specify version manager for local project.
58
+ - Git pattern matching for HEAD was revised.
59
+
60
+ ### Removed
61
+
62
+ - Git command branch action edit is not commonly used.
63
+ - Git command rev action branch only echoed valid branches.
64
+ - Git command rev action parseopt is not relevant to a workspace.
65
+
66
+ ## [0.3.10] - 2025-04-27
67
+
68
+ ### Fixed
69
+
70
+ - Git command reset action commit used invalid delimeter.
71
+ - Git single option values were not merged as per specification.
72
+ - Project script task did not fire first and last callbacks.
73
+ - Git checkout action commit did not include options.
74
+
75
+ ### Removed
76
+
77
+ - Git command files action ignored could not be used alone.
78
+
79
+ ## [0.2.10] - 2025-04-27
80
+
81
+ ### Fixed
82
+
83
+ - Project run and script tasks did not fire first and last callbacks.
84
+ - Git command clone did not read booleans for recurse-submodules.
85
+
86
+ ## [0.1.7] - 2025-04-27
87
+
88
+ ### Fixed
89
+
90
+ - Project directory context method option pass was inverted.
91
+ - Shell options with spaces and without quotes were not escaped.
92
+ - Git task status did not display branch information.
93
+ - Ruby copy method argument include was ignored when used directly.
94
+ - Git commit could not push branch without same name as remote.
95
+
3
96
  ## [0.4.8] - 2025-04-21
4
97
 
5
98
  ### Added
@@ -483,7 +576,7 @@
483
576
  - Node tasks without any action are not displayed.
484
577
  - Git fetch commands that do not apply to pull are rejected.
485
578
 
486
- ## [0.1.3] - 2024-01-02
579
+ ## [0.1.3] - 2025-01-02
487
580
 
488
581
  ### Fixed
489
582
 
@@ -562,6 +655,8 @@
562
655
 
563
656
  - Changelog was created.
564
657
 
658
+ [0.4.10]: https://github.com/anpham6/squared/releases/tag/v0.4.10-ruby
659
+ [0.4.9]: https://github.com/anpham6/squared/releases/tag/v0.4.9-ruby
565
660
  [0.4.8]: https://github.com/anpham6/squared/releases/tag/v0.4.8-ruby
566
661
  [0.4.7]: https://github.com/anpham6/squared/releases/tag/v0.4.7-ruby
567
662
  [0.4.6]: https://github.com/anpham6/squared/releases/tag/v0.4.6-ruby
@@ -571,6 +666,7 @@
571
666
  [0.4.2]: https://github.com/anpham6/squared/releases/tag/v0.4.2-ruby
572
667
  [0.4.1]: https://github.com/anpham6/squared/releases/tag/v0.4.1-ruby
573
668
  [0.4.0]: https://github.com/anpham6/squared/releases/tag/v0.4.0-ruby
669
+ [0.3.10]: https://github.com/anpham6/squared/releases/tag/v0.3.10-ruby
574
670
  [0.3.9]: https://github.com/anpham6/squared/releases/tag/v0.3.9-ruby
575
671
  [0.3.8]: https://github.com/anpham6/squared/releases/tag/v0.3.8-ruby
576
672
  [0.3.7]: https://github.com/anpham6/squared/releases/tag/v0.3.7-ruby
@@ -581,6 +677,7 @@
581
677
  [0.3.2]: https://github.com/anpham6/squared/releases/tag/v0.3.2-ruby
582
678
  [0.3.1]: https://github.com/anpham6/squared/releases/tag/v0.3.1-ruby
583
679
  [0.3.0]: https://github.com/anpham6/squared/releases/tag/v0.3.0-ruby
680
+ [0.2.10]: https://github.com/anpham6/squared/releases/tag/v0.2.10-ruby
584
681
  [0.2.9]: https://github.com/anpham6/squared/releases/tag/v0.2.9-ruby
585
682
  [0.2.8]: https://github.com/anpham6/squared/releases/tag/v0.2.8-ruby
586
683
  [0.2.7]: https://github.com/anpham6/squared/releases/tag/v0.2.7-ruby
@@ -591,6 +688,7 @@
591
688
  [0.2.2]: https://github.com/anpham6/squared/releases/tag/v0.2.2-ruby
592
689
  [0.2.1]: https://github.com/anpham6/squared/releases/tag/v0.2.1-ruby
593
690
  [0.2.0]: https://github.com/anpham6/squared/releases/tag/v0.2.0-ruby
691
+ [0.1.7]: https://github.com/anpham6/squared/releases/tag/v0.1.7-ruby
594
692
  [0.1.6]: https://github.com/anpham6/squared/releases/tag/v0.1.6-ruby
595
693
  [0.1.5]: https://github.com/anpham6/squared/releases/tag/v0.1.5-ruby
596
694
  [0.1.4]: https://github.com/anpham6/squared/releases/tag/v0.1.4-ruby
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # squared 5.4
1
+ # squared 5.5
2
2
 
3
3
  ## Documentation
4
4
 
@@ -15,10 +15,11 @@
15
15
  * [squared-express](https://github.com/anpham6/squared-express#readme)
16
16
  * [E-mc](https://github.com/anpham6/e-mc#readme)
17
17
  * [Pi-r](https://github.com/anpham6/pi-r#readme)
18
+ * [Pi-r2](https://github.com/anpham6/pi-r2#readme)
18
19
 
19
20
  ## Installation
20
21
 
21
- * NodeJS 16 LTS
22
+ * NodeJS 18
22
23
 
23
24
  ### NPX
24
25
 
@@ -131,26 +132,22 @@ rake clone # node + docs
131
132
 
132
133
  ```sh
133
134
  # NODE_TAG=latest
134
- # RUBY_VERSION=2.4.0-3.3.0
135
- # MANIFEST=nightly,staging,prod,android
135
+ # RUBY_VERSION=2.4.0-3.4.0
136
+ # MANIFEST=nightly,prod,latest,android
136
137
  # BUILD={dev,prod}
137
138
  # DEV={0,1,local}
138
139
  # DOCS=any
139
140
  # PIPE_FAIL={0,1}
140
141
  # PORT=3000
141
- docker build -t squared --build-arg MANIFEST=prod --build-arg SQUARED=prod .
142
- docker build -t node --build-arg NODE_TAG=20 --build-arg NODE_INSTALL=pnpm -f Dockerfile.slim . # no docs
143
- docker buildx bake node
142
+ docker build -t squared --build-arg MANIFEST=prod --build-arg NODE_ENV=production .
143
+ docker build -t node --build-arg NODE_TAG=22 --build-arg NODE_INSTALL=pnpm -f Dockerfile.slim .
144
+ NODE=22 docker buildx bake node
144
145
  # OR
145
- # RUBY_TAG=latest
146
- # NODE_VERSION=22.x
147
- docker build -t ruby --build-arg RUBY_TAG=3.0.0 --build-arg NODE_VERSION=20.x --build-arg PIPE_FAIL=0 -f Dockerfile.ruby .
148
- docker buildx bake ruby
146
+ docker build -t ruby --build-arg RUBY_TAG=3.4.0 --build-arg NODE_VERSION=22 --build-arg PIPE_FAIL=0 -f Dockerfile.ruby .
147
+ RUBY=3.4.0 docker buildx bake ruby
149
148
  # OR
150
- # NGINX_VERSION=1.27
151
- # NGINX_VARIANT=bookworm
152
- docker build -t nginx --build-arg NGINX_VERSION=1.27 --build-arg PORT=3000 --build-arg NODE_VERSION=18.x -f Dockerfile.nginx .
153
- docker buildx bake nginx
149
+ docker build -t nginx --build-arg NGINX_VERSION=1.27 --build-arg PORT=3000 --build-arg NODE_VERSION=20 -f Dockerfile.nginx .
150
+ NGINX=1.27 docker buildx bake nginx
154
151
 
155
152
  # Express
156
153
  docker run -it --name express --rm -p 3000:3000 \
@@ -521,6 +518,7 @@ squared.settings = {
521
518
  ],
522
519
  compressImages: false, // TinyPNG API Key <https://tinypng.com/developers>
523
520
  compressImages: "****************", // API key
521
+ compressImages: [{ plugin: "imagemin-pngquant", format: "png", options: { quality: [0.6, 0.8] } }], // v5.5
524
522
  convertImages: "", // png | jpeg | webp | gif | bmp
525
523
  showAttributes: true,
526
524
  showAttributes: {
@@ -541,7 +539,7 @@ squared.settings = {
541
539
  showErrorMessages: false,
542
540
  convertPixels: "dp", // "sp" | "pt" | "in" | "mm"
543
541
  convertLineHeight: "sp", // "dp" | "pt" | "in" | "mm"
544
- convertEntities: ["numeric"], // v5.4
542
+ convertEntities: ["numeric"],
545
543
  convertEntities: ["codepoints", {/* JSON (last) */}], // https://html.spec.whatwg.org/entities.json
546
544
  insertSpaces: 4,
547
545
  outputDocumentHandler: "android",
@@ -1361,4 +1359,4 @@ NOTE: Defining an element "**id**" will prevent it from being removed during the
1361
1359
 
1362
1360
  ## LICENSE
1363
1361
 
1364
- BSD 3-Clause
1362
+ BSD 3-Clause
data/README.ruby.md CHANGED
@@ -83,7 +83,7 @@ Workspace::Application
83
83
  "CFLAGS" => "-fPIC -O1"
84
84
  })
85
85
  .add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
86
- .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.4.0/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
86
+ .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.4.0/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true | "rvm" | "rbenv" | "asdf" | "bundler"
87
87
  .add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
88
88
  .add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
89
89
  .add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
@@ -98,6 +98,9 @@ Workspace::Application
98
98
  with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
99
99
  # OR
100
100
  add(["publish/sqd-cli", "publish/sqd-serve"], true, exclude: [:base]) # rake squared:sqd-serve:build
101
+
102
+ # Git
103
+ revbuild(include: %w[src/ framework/ types/]) # Synchronous is recommended
101
104
  end
102
105
  .add("squared/sqd", exclude: :git, pass: [:node, "checkout", "bump"]) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
103
106
  variable_set :script, "build:sqd" # Override detection
@@ -116,9 +119,9 @@ Workspace::Application
116
119
  end
117
120
  end
118
121
  end
119
- .pass("pull", group: "default") { test? || doc? } # pathname:pull | optparse:pull
122
+ .pass("pull", group: "default") { test? || doc? } # rake pathname:pull | rake optparse:pull
120
123
  .style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
121
- .build(default: "build", parallel: ["pull", "fetch", "rebase", "archive", "copy", "clean", /^outdated:/], pass: ["publish"]) do |workspace|
124
+ .build(default: "build", parallel: ["pull", "fetch", "rebase", "archive", "clean", /^outdated:/], pass: ["publish"]) do |workspace|
122
125
  workspace
123
126
  .enable_aixterm
124
127
  .style({
@@ -194,9 +197,9 @@ Workspace::Application
194
197
  "pir": { # rake pir:clone
195
198
  uri: "https://github.com/anpham6/pi-r", #
196
199
  options: { #
197
- "origin": "github", # --origin='github'
200
+ "origin": "github", # --origin=github
198
201
  "recurse-submodules": false, # --no-recurse-submodules
199
- "shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude='v0.0.1' --shallow-exclude='v0.0.2'
202
+ "shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude=v0.0.1 --shallow-exclude=v0.0.2
200
203
  }
201
204
  }
202
205
  )
@@ -238,7 +241,7 @@ Workspace::Application
238
241
  .new(main: "squared")
239
242
  .graph(["depend"], ref: :git) # Optional
240
243
  .with(:python) do
241
- doc(windows? ? '.\make.bat html' : 'make html')
244
+ doc(windows? ? ".\make.bat html" : "make html") # rake android-docs:doc | rake doc:python
242
245
  add("android-docs", "android", venv: "/home/user/.venv") # rake android-docs:depend
243
246
  add("chrome-docs", "chrome", graph: "android", venv: ".venv") do # /workspaces/chrome-docs/.venv
244
247
  variable_set :dependindex, 2 # Use Poetry for dependencies (optional)
@@ -282,6 +285,10 @@ Workspace::Application
282
285
  p "1"
283
286
  end
284
287
  # OR
288
+ run(on: { first: -> { p "pass" }, last: -> { p "pass" } }) do
289
+ p "1"
290
+ end
291
+ # OR
285
292
  run(["gem build", "--force", { "RUBY_VERSION" => "3.4.0" }]) # RUBY_VERSION="3.4.0" gem build --force
286
293
  # OR
287
294
  run({ #
@@ -433,20 +440,21 @@ Most project classes will inherit from `Git` which enables these tasks:
433
440
  | :--------- | :--------------- | :-------------------------------------------- |
434
441
  | branch | branch | create set delete move copy list edit current |
435
442
  | checkout | checkout | commit branch track detach path |
436
- | commit | commit | add all amend amend-orig |
443
+ | commit | commit | add all amend amend-orig fixup |
437
444
  | diff | diff | head cached branch files between contain |
438
445
  | fetch | fetch | origin remote |
439
- | files | ls-files | cached modified deleted others ignored |
440
- | git | | clean mv rm |
446
+ | files | ls-files | cached modified deleted others |
447
+ | git | | add clean mv rm revert |
441
448
  | merge | merge | commit no-commit send |
442
449
  | pull | pull | origin remote |
443
450
  | rebase | rebase | branch onto send |
444
451
  | refs | ls-remote --refs | heads tags remote |
445
452
  | reset | reset | commit index patch mode |
446
453
  | restore | restore | staged worktree |
447
- | rev | rev | commit branch output parseopt |
454
+ | rev | rev | commit output |
448
455
  | show | show | format oneline |
449
456
  | stash | stash | push pop apply drop list |
457
+ | switch | switch | create detach merge |
450
458
  | tag | tag | add sign delete list |
451
459
 
452
460
  You can disable all of them at once using the `exclude` property.
@@ -470,11 +478,12 @@ Workspace::Application
470
478
 
471
479
  ### Commit Hash
472
480
 
473
- Commands which use commit hashes are parsed using string interpolation format as to not be confused for an option.
481
+ Commands which use commit hashes are parsed using a ":" prefix as to not be confused for an option.
474
482
 
475
483
  ```sh
476
- rake squared:log:view[#{af012345}] # git log af012345
477
- rake squared:log:view[H1,H5,all,lib,./H12345] # git log --all HEAD~1 HEAD~5 -- 'lib' 'H12345'
484
+ rake squared:log:view[:af012345] # git log af012345
485
+ rake squared:log:view[#{af012345}] # deprecated
486
+ rake squared:log:view[H1,HEAD^5,all,lib,./H12345] # git log --all @~1 @^5 -- 'lib' 'H12345'
478
487
  ```
479
488
 
480
489
  ## Environment
@@ -484,7 +493,7 @@ rake squared:log:view[H1,H5,all,lib,./H12345] # git log --all HEAD~1 HEAD~5 --
484
493
  All project binary programs can have their executable path set to a non-global alias.
485
494
 
486
495
  ```ruby
487
- Common::PATH.merge!({
496
+ Common::PATH.update({
488
497
  GIT: "/usr/bin/git", # PATH_GIT=/usr/bin/git
489
498
  TAR: "/opt/archivers/tar", # PATH_TAR=/opt/archivers/tar
490
499
  UNZIP: "/opt/archivers/unzip",
@@ -566,39 +575,47 @@ GIT_AUTOSTASH_${NAME}=0 # rebase (project only)
566
575
 
567
576
  | Command | Flag | ENV |
568
577
  | :--------- | :---------------- | :-------------------------------------------------------------------- |
578
+ | branch | create | TRACK=0,1,s FORCE |
579
+ | branch | move copy | FORCE |
580
+ | branch | set delete | COUNT=n |
581
+ | branch | global | SYNC |
582
+ | checkout | branch | DETACH TRACK=s COUNT=n |
583
+ | checkout | detach | REFLOG=1 |
584
+ | checkout | track | COUNT=n |
585
+ | checkout | global path | HEAD=s PATHSPEC=s |
586
+ | checkout | * | FORCE MERGE |
587
+ | clone | * | DEPTH=n ORIGIN=s BRANCH=s LOCAL=0,1 |
588
+ | commit | * | UPSTREAM=s DRY_RUN EDIT=0 M|MESSAGE=s |
589
+ | diff | -between -contain | MERGE_BASE |
590
+ | diff | head branch | INDEX=n |
591
+ | diff | * | PATHSPEC=s |
592
+ | fetch | -remote | ALL |
593
+ | fetch | remote | REFSPEC=s |
594
+ | fetch | * | FORCE RECURSE_SUBMODULES=0,1,s |
595
+ | git | rm | PATHSPEC=s |
596
+ | log | * | PATHSPEC=s |
569
597
  | pull | rebase | AUTOSTASH |
570
598
  | pull | remote | REFSPEC=s |
599
+ | pull | -remote | ALL |
571
600
  | pull | * | REBASE=0,1 FORCE RECURSE_SUBMODULES=0,1,s |
572
601
  | rebase | branch | HEAD=s |
573
602
  | rebase | onto | INTERACTIVE I HEAD=s |
574
- | fetch | -remote | ALL |
575
- | fetch | remote | REFSPEC=s |
576
- | fetch | * | FORCE RECURSE_SUBMODULES=0,1,s |
577
- | clone | * | DEPTH=n ORIGIN=s BRANCH=s LOCAL=0,1 |
578
- | stash | push | PATHSPEC=s |
579
- | stash | global | ALL=0,1 KEEP_INDEX=0,1 INCLUDE_UNTRACKED=0,1 STAGED=0,1 MESSAGE=s M=s |
580
- | status | global | LONG IGNORE_SUBMODULES=s,0-3 PATHSPEC=s |
581
- | revbuild | global | UNTRACKED_FILES=s IGNORE_SUBMODULES=s IGNORED=s (status) |
582
603
  | reset | mode (mixed) | N REFRESH=0 |
583
604
  | reset | index | PATHSPEC=s |
605
+ | reset | commit | COUNT=n REFLOG=1 |
584
606
  | reset | -commit | HEAD=s |
585
- | checkout | branch | DETACH TRACK=s |
586
- | checkout | global path | HEAD=s PATHSPEC=s |
587
- | checkout | * | FORCE MERGE |
588
- | tag | add | SIGN FORCE HEAD=s |
589
- | tag | sign | FORCE HEAD=s |
590
- | log | * | PATHSPEC=s |
591
- | diff | -between -contain | MERGE_BASE |
592
- | diff | head branch | INDEX=n |
593
- | diff | * | PATHSPEC=s |
594
- | commit | * | MESSAGE=s M=s REPOSITORY=s DRY_RUN EDIT=0 |
595
- | branch | create | TRACK=0,1,s FORCE |
596
- | branch | move copy | FORCE |
597
- | branch | global | SYNC |
598
607
  | restore | * | PATHSPEC=s |
599
- | show | -online | ABBREV=n |
608
+ | revbuild | global | UNTRACKED_FILES=s IGNORE_SUBMODULES=s IGNORED=s (status) |
609
+ | stash | push | PATHSPEC=s |
610
+ | stash | global | ALL=0,1 KEEP_INDEX=0,1 INCLUDE_UNTRACKED=0,1 STAGED=0,1 M|MESSAGE=s |
611
+ | status | global | BRANCH LONG IGNORE_SUBMODULES=s,0-3 PATHSPEC=s |
612
+ | switch | detach | REFLOG=1 |
613
+ | switch | -detach | HEAD=s |
614
+ | switch | * | FORCE |
615
+ | tag | add | SIGN FORCE HEAD=s M|MESSAGE=s |
616
+ | tag | sign | FORCE HEAD=s M|MESSAGE=s |
617
+ | tag | delete | COUNT=n |
600
618
  | rev | commit branch | HEAD=s |
601
- | git | rm | PATHSPEC=s |
602
619
 
603
620
  ### Docker
604
621
 
@@ -608,6 +625,7 @@ DOCKER_OPTIONS_${NAME}=v,no-cache=false # project only (override)
608
625
  DOCKER_TAG=latest # all
609
626
  DOCKER_TAG_${NAME}=v0.1.0 # project only (override)
610
627
  DOCKER_ALL=1 # list every image/container
628
+ DOCKER_Y=1 # confirm all
611
629
  ```
612
630
 
613
631
  | Command | Flag | ENV |
@@ -616,6 +634,7 @@ DOCKER_ALL=1 # list every image/container
616
634
  | buildx | bake | SERVICE=s |
617
635
  | compose | build | TARGET=s |
618
636
  | container | commit | REGISTRY=s PLATFORM=s DISABLE_CONTENT_TRUST=0,1 |
637
+ | image | rm | Y=0,1 |
619
638
  | image | push | TAG=s REGISTRY=s |
620
639
 
621
640
  ### Repo
@@ -61,7 +61,7 @@ module Squared
61
61
  end
62
62
  wrap = ->(s, n) { "\x1B[#{n.join(';')}m#{s}\x1B[0m" }
63
63
  code = []
64
- args.concat(as_a(styles)).each_with_index do |type, i|
64
+ args.concat(as_a(styles)).flatten.each_with_index do |type, i|
65
65
  next unless type
66
66
 
67
67
  if index == -1
@@ -146,19 +146,12 @@ module Squared
146
146
  def log_sym(level)
147
147
  if level.is_a?(::Numeric)
148
148
  case level
149
- when Logger::DEBUG
150
- :debug
151
- when Logger::INFO
152
- :info
153
- when Logger::WARN
154
- :warn
155
- when Logger::ERROR
156
- :error
157
- when Logger::FATAL
158
- :fatal
159
- else
160
- :unknown
161
- end
149
+ when Logger::DEBUG then :debug
150
+ when Logger::INFO then :info
151
+ when Logger::WARN then :warn
152
+ when Logger::ERROR then :error
153
+ when Logger::FATAL then :fatal
154
+ else :unknown end
162
155
  else
163
156
  level.to_s.downcase.to_sym
164
157
  end
@@ -185,7 +178,7 @@ module Squared
185
178
  end
186
179
  if args.size > 1 && !hint
187
180
  title = log_title(level, color: false)
188
- sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
181
+ sub = { pat: /\A(#{Regexp.escape(title)})(.*)\z/m, styles: __get__(:theme)[:logger][log_sym(level)] } if color
189
182
  emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub)
190
183
  else
191
184
  msg = [log_title(level, color: color)]
@@ -246,7 +239,7 @@ module Squared
246
239
  ret = sub_style(ret, styles: border) if border
247
240
  ret
248
241
  end
249
- sub = as_a(sub)
242
+ sub = as_a sub
250
243
  pr = lambda do |line|
251
244
  s = line.ljust(n)
252
245
  sub.each { |h| s = sub_style(s, **h) }
@@ -296,7 +289,7 @@ module Squared
296
289
  end
297
290
 
298
291
  def stripext(val)
299
- File.basename(val, File.extname(val))
292
+ File.basename(val, '.*')
300
293
  end
301
294
 
302
295
  def raise_error(*args, hint: nil, kind: ArgumentError)
@@ -5,14 +5,14 @@ module Squared
5
5
  module Prompt
6
6
  module_function
7
7
 
8
- def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
8
+ def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 30)
9
9
  require 'readline'
10
10
  require 'timeout'
11
- agree = /^#{agree}$/i if agree.is_a?(::String)
12
- cancel = /^#{cancel}$/i if cancel.is_a?(::String)
11
+ agree = /^#{Regexp.escape(agree)}$/i if agree.is_a?(::String)
12
+ cancel = /^#{Regexp.escape(cancel)}$/i if cancel.is_a?(::String)
13
13
  Timeout.timeout(timeout) do
14
14
  begin
15
- while (ch = Readline.readline(msg, true))
15
+ while (ch = Readline.readline(msg))
16
16
  ch = ch.chomp
17
17
  case (ch.empty? ? default : ch)
18
18
  when agree
@@ -32,34 +32,50 @@ module Squared
32
32
  end
33
33
  end
34
34
 
35
- def choice(msg, list = nil, min: 1, max: 1, multiple: false, attempts: 5, timeout: 60)
35
+ def choice(msg, list = nil, min: 1, max: 1, multiple: false, force: true, grep: nil, auto: true,
36
+ attempts: 5, timeout: 0)
36
37
  require 'readline'
37
38
  require 'timeout'
38
39
  if list
40
+ grep &&= (grep.is_a?(::Enumerable) ? grep : [grep]).map { |val| Regexp.new(val) }
39
41
  items = []
40
- list.each_with_index do |val, index|
41
- puts "#{index.succ.to_s.rjust(2)}. #{val}"
42
+ list.each do |val|
43
+ next if grep&.none? { |pat| pat.match?(line) }
44
+
42
45
  items << val.chomp
46
+ puts "#{items.size.to_s.rjust(2)}. #{val}"
43
47
  end
44
48
  max = items.size
45
- msg = "#{msg}: [1-#{max}#{multiple ? '|,' : ''}] "
49
+ raise_error 'empty selection list' if max == 0
50
+ min = [min, max].min
51
+ if auto
52
+ msg = "#{msg}: [1-#{max}#{if multiple
53
+ "|,#{multiple.is_a?(Numeric) ? "{#{multiple}}" : ''}"
54
+ end}] "
55
+ end
46
56
  end
47
- return unless max >= min
48
-
49
57
  valid = ->(s) { s.match?(/^-?\d+$/) && s.to_i.between?(min, max) }
50
58
  Timeout.timeout(timeout) do
51
59
  begin
52
- while (ch = Readline.readline(msg, true))
53
- ch = ch.strip
54
- if multiple
55
- a = ch.split(/\s*,\s*/)
56
- b = a.select { |s| valid.call(s) }.map!(&:to_i)
57
- return items ? b.map! { |i| items[i - 1] } : b if a.size == b.size
58
- elsif valid.call(ch)
59
- return items ? items[ch.to_i - 1] : ch.to_i
60
+ while (ch = Readline.readline(msg))
61
+ unless (ch = ch.strip).empty?
62
+ if multiple
63
+ a = ch.split(/\s*,\s*/)
64
+ b = a.select { |s| valid.call(s) }.map!(&:to_i).sort
65
+ next unless a.size == b.size
66
+ return b unless items
67
+ next if multiple.is_a?(::Numeric) && multiple != b.size
68
+
69
+ return b.map! { |i| items[i - 1] }
70
+ elsif valid.call(ch)
71
+ return items ? items[ch.to_i - 1] : ch.to_i
72
+ end
60
73
  end
61
74
  attempts -= 1
62
- exit 1 unless attempts > 0
75
+ next if attempts > 0
76
+ break unless force
77
+
78
+ exit 1
63
79
  end
64
80
  rescue Interrupt
65
81
  puts
@@ -69,6 +85,36 @@ module Squared
69
85
  end
70
86
  end
71
87
  end
88
+
89
+ def readline(msg, history = false, force: nil, multiline: nil, &blk)
90
+ require 'readline'
91
+ multiline = if multiline && Readline.respond_to?(:readmultiline)
92
+ multiline.is_a?(::Enumerable) || block_given? ? multiline : [multiline.to_s]
93
+ end
94
+ prompt = lambda do
95
+ if !multiline
96
+ Readline.readline(msg, history)
97
+ elsif block_given?
98
+ Readline.readmultiline(msg, history, &blk)
99
+ else
100
+ Readline.readmultiline(msg, history) { |line| multiline.any? { |val| line.split.last.end_with?(val) } }
101
+ end
102
+ end
103
+ case force
104
+ when ::TrueClass, ::FalseClass
105
+ msg = "#{msg} %s " % if multiline
106
+ multiline.is_a?(::Enumerable) ? "{#{multiline.join('|')}}" : multiline
107
+ else
108
+ "(#{force ? 'required' : 'optional'}):"
109
+ end
110
+ ret = (prompt.call || '').strip
111
+ multiline.each { |val| break if ret.delete_suffix!(val) } if multiline.is_a?(::Enumerable)
112
+ raise_error 'user cancelled' if force && ret.empty?
113
+ ret
114
+ else
115
+ prompt.call
116
+ end
117
+ end
72
118
  end
73
119
  end
74
120
  end