squared 0.4.6 → 0.4.8
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 +77 -0
- data/README.ruby.md +52 -32
- data/lib/squared/common/base.rb +1 -0
- data/lib/squared/common/class.rb +20 -5
- data/lib/squared/common/format.rb +30 -22
- data/lib/squared/common/prompt.rb +39 -1
- data/lib/squared/common/shell.rb +14 -10
- data/lib/squared/common/system.rb +3 -3
- data/lib/squared/common/utils.rb +17 -10
- data/lib/squared/config.rb +1 -2
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +39 -23
- data/lib/squared/workspace/project/base.rb +242 -243
- data/lib/squared/workspace/project/docker.rb +119 -72
- data/lib/squared/workspace/project/git.rb +252 -214
- data/lib/squared/workspace/project/node.rb +65 -67
- data/lib/squared/workspace/project/python.rb +69 -57
- data/lib/squared/workspace/project/ruby.rb +297 -98
- data/lib/squared/workspace/project/support/class.rb +199 -0
- data/lib/squared/workspace/project/support.rb +3 -0
- data/lib/squared/workspace/project.rb +1 -0
- data/lib/squared/workspace/repo.rb +6 -8
- data/lib/squared/workspace/series.rb +7 -6
- data/lib/squared/workspace.rb +1 -8
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 483002a469a23461dcee07ded3610011d831f2c737142cd4b464899fbdf70cde
|
4
|
+
data.tar.gz: 4601b03b61f6270e8b3841777effd420b47c752ddbe96924ca329ee92c98ee4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5767519e7f0150a753c0cbf97aa59292ad59a29b4f78c6e7596e5bd369b035258339d062b896c59d37496ccdcd4224179a745065f1dc41a35f876a507f30e171
|
7
|
+
data.tar.gz: c457cbd60b4865aea1e218ce9609c4094f618cc4b404eac309c8235b3bc116599487d1c641151cd99bceab6d28a03b48abd1774e447017afb2d28439aca40298
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,77 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.4.8] - 2025-04-21
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Workspace project tasks can be executed with a block.
|
8
|
+
- Gem command outdated supports semantic version upgrades.
|
9
|
+
- Project task unpack supports "gem" extension.
|
10
|
+
- Ruby command version was implemented.
|
11
|
+
- Ruby command file and script were implemented.
|
12
|
+
- Git global command autostash was created.
|
13
|
+
- Workspace static method exclude for global tasks was created.
|
14
|
+
- Git command checkout action branch and track are interactive.
|
15
|
+
- Git command branch action set and delete are interactive.
|
16
|
+
- Git command tag action delete is interactive.
|
17
|
+
- Docker command image run and container exec are interactive.
|
18
|
+
- Docker command network connect and disconnect are interactive.
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
|
22
|
+
- Project methods with conflicting names were given "!" suffix.
|
23
|
+
- Docker exec args are run without escape protection.
|
24
|
+
- Format method enable_aixterm no longer accepts a block.
|
25
|
+
|
26
|
+
### Fixed
|
27
|
+
|
28
|
+
- Git command log action view did not parse options.
|
29
|
+
- Project task unpack did not use custom extensions.
|
30
|
+
- Docker did not append secrets when given a string.
|
31
|
+
|
32
|
+
## [0.4.7] - 2025-04-17
|
33
|
+
|
34
|
+
### Added
|
35
|
+
|
36
|
+
- Project support class OptionPartition was created.
|
37
|
+
- Git command tag action sign was implemented.
|
38
|
+
- Gem command uninstall was implemented.
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
|
42
|
+
- DateTime instances was replaced with Time.
|
43
|
+
- Utils method time_offset was renamed time_since.
|
44
|
+
- Ruby gem command build will search project for gemspec.
|
45
|
+
|
46
|
+
### Fixed
|
47
|
+
|
48
|
+
- Project task archive was not enabled.
|
49
|
+
|
50
|
+
## [0.3.9] - 2025-04-17
|
51
|
+
|
52
|
+
### Fixed
|
53
|
+
|
54
|
+
- Project option parser did not separate custom values.
|
55
|
+
|
56
|
+
## [0.2.9] - 2025-04-17
|
57
|
+
|
58
|
+
### Changed
|
59
|
+
|
60
|
+
- Project log file naming supports more date formats.
|
61
|
+
|
62
|
+
### Fixed
|
63
|
+
|
64
|
+
- Environment options did not always pass session object.
|
65
|
+
- Git command pull actions used unknown flags.
|
66
|
+
- Workspace describe did not merge multiple invocations.
|
67
|
+
|
68
|
+
## [0.1.6] - 2025-04-17
|
69
|
+
|
70
|
+
### Fixed
|
71
|
+
|
72
|
+
- User-defined program paths were not reduced to bare name.
|
73
|
+
- Project path validation did not include separator.
|
74
|
+
|
3
75
|
## [0.4.6] - 2025-04-12
|
4
76
|
|
5
77
|
### Added
|
@@ -490,6 +562,8 @@
|
|
490
562
|
|
491
563
|
- Changelog was created.
|
492
564
|
|
565
|
+
[0.4.8]: https://github.com/anpham6/squared/releases/tag/v0.4.8-ruby
|
566
|
+
[0.4.7]: https://github.com/anpham6/squared/releases/tag/v0.4.7-ruby
|
493
567
|
[0.4.6]: https://github.com/anpham6/squared/releases/tag/v0.4.6-ruby
|
494
568
|
[0.4.5]: https://github.com/anpham6/squared/releases/tag/v0.4.5-ruby
|
495
569
|
[0.4.4]: https://github.com/anpham6/squared/releases/tag/v0.4.4-ruby
|
@@ -497,6 +571,7 @@
|
|
497
571
|
[0.4.2]: https://github.com/anpham6/squared/releases/tag/v0.4.2-ruby
|
498
572
|
[0.4.1]: https://github.com/anpham6/squared/releases/tag/v0.4.1-ruby
|
499
573
|
[0.4.0]: https://github.com/anpham6/squared/releases/tag/v0.4.0-ruby
|
574
|
+
[0.3.9]: https://github.com/anpham6/squared/releases/tag/v0.3.9-ruby
|
500
575
|
[0.3.8]: https://github.com/anpham6/squared/releases/tag/v0.3.8-ruby
|
501
576
|
[0.3.7]: https://github.com/anpham6/squared/releases/tag/v0.3.7-ruby
|
502
577
|
[0.3.6]: https://github.com/anpham6/squared/releases/tag/v0.3.6-ruby
|
@@ -506,6 +581,7 @@
|
|
506
581
|
[0.3.2]: https://github.com/anpham6/squared/releases/tag/v0.3.2-ruby
|
507
582
|
[0.3.1]: https://github.com/anpham6/squared/releases/tag/v0.3.1-ruby
|
508
583
|
[0.3.0]: https://github.com/anpham6/squared/releases/tag/v0.3.0-ruby
|
584
|
+
[0.2.9]: https://github.com/anpham6/squared/releases/tag/v0.2.9-ruby
|
509
585
|
[0.2.8]: https://github.com/anpham6/squared/releases/tag/v0.2.8-ruby
|
510
586
|
[0.2.7]: https://github.com/anpham6/squared/releases/tag/v0.2.7-ruby
|
511
587
|
[0.2.6]: https://github.com/anpham6/squared/releases/tag/v0.2.6-ruby
|
@@ -515,6 +591,7 @@
|
|
515
591
|
[0.2.2]: https://github.com/anpham6/squared/releases/tag/v0.2.2-ruby
|
516
592
|
[0.2.1]: https://github.com/anpham6/squared/releases/tag/v0.2.1-ruby
|
517
593
|
[0.2.0]: https://github.com/anpham6/squared/releases/tag/v0.2.0-ruby
|
594
|
+
[0.1.6]: https://github.com/anpham6/squared/releases/tag/v0.1.6-ruby
|
518
595
|
[0.1.5]: https://github.com/anpham6/squared/releases/tag/v0.1.5-ruby
|
519
596
|
[0.1.4]: https://github.com/anpham6/squared/releases/tag/v0.1.4-ruby
|
520
597
|
[0.1.3]: https://github.com/anpham6/squared/releases/tag/v0.1.3-ruby
|
data/README.ruby.md
CHANGED
@@ -278,6 +278,10 @@ Workspace::Application
|
|
278
278
|
.with(:ruby) do
|
279
279
|
run("gem build") # gem build
|
280
280
|
# OR
|
281
|
+
run("gem build", on: { first: -> { p "2" }, last: -> { p "4" } }) do # run | depend | graph | clean | doc | lint | test
|
282
|
+
p "1"
|
283
|
+
end
|
284
|
+
# OR
|
281
285
|
run(["gem build", "--force", { "RUBY_VERSION" => "3.4.0" }]) # RUBY_VERSION="3.4.0" gem build --force
|
282
286
|
# OR
|
283
287
|
run({ #
|
@@ -443,11 +447,13 @@ Most project classes will inherit from `Git` which enables these tasks:
|
|
443
447
|
| rev | rev | commit branch output parseopt |
|
444
448
|
| show | show | format oneline |
|
445
449
|
| stash | stash | push pop apply drop list |
|
446
|
-
| tag | tag | add delete list
|
450
|
+
| tag | tag | add sign delete list |
|
447
451
|
|
448
452
|
You can disable all of them at once using the `exclude` property.
|
449
453
|
|
450
454
|
```ruby
|
455
|
+
Workspace::Application.exclude('autostash', 'rebase')
|
456
|
+
|
451
457
|
Workspace::Application
|
452
458
|
.new
|
453
459
|
.add("squared", exclude: :git)
|
@@ -462,11 +468,20 @@ Workspace::Application
|
|
462
468
|
.pass("pull", ref: :node) { read_packagemanager(:private) }
|
463
469
|
```
|
464
470
|
|
471
|
+
### Commit Hash
|
472
|
+
|
473
|
+
Commands which use commit hashes are parsed using string interpolation format as to not be confused for an option.
|
474
|
+
|
475
|
+
```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'
|
478
|
+
```
|
479
|
+
|
465
480
|
## Environment
|
466
481
|
|
467
482
|
### Path
|
468
483
|
|
469
|
-
All project
|
484
|
+
All project binary programs can have their executable path set to a non-global alias.
|
470
485
|
|
471
486
|
```ruby
|
472
487
|
Common::PATH.merge!({
|
@@ -483,44 +498,47 @@ Common::PATH.merge!({
|
|
483
498
|
|
484
499
|
### Build
|
485
500
|
|
486
|
-
```
|
501
|
+
```ruby
|
487
502
|
Workspace::Application
|
488
503
|
.new
|
489
504
|
.add("squared", run: "gcc a.c -o a.o", opts: { __debug__: { g: true, O2: true, c: nil }, c: true, j: 4 }) # gcc a.c -o a.o -c -j4
|
505
|
+
```
|
490
506
|
|
491
|
-
|
507
|
+
```sh
|
508
|
+
BUILD_TYPE # global
|
509
|
+
${PROG}_COLOR=0 # --no-color (e.g. GIT_COLOR)
|
492
510
|
|
493
511
|
# :env :run :args :opts :type
|
494
512
|
# LD_LIBRARY_PATH="path/to/lib" CFLAGS="-Wall" gcc a.c -o a.o -g -O2
|
495
|
-
BUILD_${NAME}
|
496
|
-
BUILD_${NAME}_OPTS
|
497
|
-
BUILD_${NAME}_ENV
|
498
|
-
BUILD_${NAME}_TYPE
|
513
|
+
BUILD_${NAME} # gcc a.c -o a.o
|
514
|
+
BUILD_${NAME}_OPTS # -g
|
515
|
+
BUILD_${NAME}_ENV # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (hash/json)
|
516
|
+
BUILD_${NAME}_TYPE # debug
|
499
517
|
|
500
518
|
# :env :script :opts :args
|
501
519
|
# NODE_ENV="production" NO_COLOR="1" npm run build:dev --loglevel=error --workspaces=false -- --quiet
|
502
|
-
BUILD_${NAME}
|
503
|
-
BUILD_${NAME}_OPTS
|
504
|
-
BUILD_${NAME}_ENV
|
505
|
-
BUILD_${NAME}_DEV
|
506
|
-
BUILD_${NAME}_PROD
|
507
|
-
${REF}_${NAME}_OPTS
|
520
|
+
BUILD_${NAME} # build:dev
|
521
|
+
BUILD_${NAME}_OPTS # --loglevel=error --workspaces=false
|
522
|
+
BUILD_${NAME}_ENV # {"NODE_ENV":"production","NO_COLOR":"1"} (hash/json)
|
523
|
+
BUILD_${NAME}_DEV # pattern,0,1 (:dev)
|
524
|
+
BUILD_${NAME}_PROD # pattern,0,1 (:prod)
|
525
|
+
${REF}_${NAME}_OPTS # --quiet (e.g. NODE_SQUARED_OPTS)
|
508
526
|
|
509
|
-
BUILD_${NAME}=0
|
510
|
-
BUILD_${NAME}_VERSION=0.1.0
|
527
|
+
BUILD_${NAME}=0 # skip project
|
528
|
+
BUILD_${NAME}_VERSION=0.1.0 # publish + detection
|
511
529
|
|
512
|
-
BANNER=0
|
513
|
-
BANNER_${NAME}=0
|
530
|
+
BANNER=0 # hide banner
|
531
|
+
BANNER_${NAME}=0 #
|
514
532
|
|
515
|
-
REVBUILD_FORCE=1
|
516
|
-
REVBUILD_FORCE_${NAME}=1
|
533
|
+
REVBUILD_FORCE=1 # Rebuild all targets
|
534
|
+
REVBUILD_FORCE_${NAME}=1 # Rebuild project
|
517
535
|
```
|
518
536
|
|
519
537
|
### Graph
|
520
538
|
|
521
539
|
```sh
|
522
|
-
GRAPH_${NAME}
|
523
|
-
GRAPH_${NAME}_PASS
|
540
|
+
GRAPH_${NAME} # depend,build => squared:depend + squared:build
|
541
|
+
GRAPH_${NAME}_PASS # -emc,pir,express => pir + express
|
524
542
|
```
|
525
543
|
|
526
544
|
### Logger
|
@@ -528,22 +546,22 @@ GRAPH_${NAME}_PASS # -emc,pir,express => pir + express
|
|
528
546
|
These global options also can target the project suffix `${NAME}`. (e.g. LOG_FILE_EMC)
|
529
547
|
|
530
548
|
```sh
|
531
|
-
LOG_FILE
|
549
|
+
LOG_FILE # %Y-%m-%d.log
|
532
550
|
# OR
|
533
|
-
LOG_AUTO
|
551
|
+
LOG_AUTO # year,y,month,m,day,d,1
|
534
552
|
# Optional
|
535
|
-
LOG_DIR
|
536
|
-
LOG_LEVEL
|
537
|
-
LOG_COLUMNS
|
553
|
+
LOG_DIR # exist?
|
554
|
+
LOG_LEVEL # See gem "logger"
|
555
|
+
LOG_COLUMNS # terminal width (default: 80)
|
538
556
|
```
|
539
557
|
|
540
558
|
### Git
|
541
559
|
|
542
560
|
```sh
|
543
|
-
GIT_OPTIONS=q,strategy=ort
|
544
|
-
GIT_OPTIONS_${NAME}=v,ff
|
545
|
-
GIT_AUTOSTASH=1
|
546
|
-
GIT_AUTOSTASH_${NAME}=0
|
561
|
+
GIT_OPTIONS=q,strategy=ort # all
|
562
|
+
GIT_OPTIONS_${NAME}=v,ff # project only
|
563
|
+
GIT_AUTOSTASH=1 # rebase (all)
|
564
|
+
GIT_AUTOSTASH_${NAME}=0 # rebase (project only)
|
547
565
|
```
|
548
566
|
|
549
567
|
| Command | Flag | ENV |
|
@@ -567,7 +585,8 @@ GIT_AUTOSTASH_${NAME}=0 # rebase (project only)
|
|
567
585
|
| checkout | branch | DETACH TRACK=s |
|
568
586
|
| checkout | global path | HEAD=s PATHSPEC=s |
|
569
587
|
| checkout | * | FORCE MERGE |
|
570
|
-
| tag | add | SIGN HEAD=s
|
588
|
+
| tag | add | SIGN FORCE HEAD=s |
|
589
|
+
| tag | sign | FORCE HEAD=s |
|
571
590
|
| log | * | PATHSPEC=s |
|
572
591
|
| diff | -between -contain | MERGE_BASE |
|
573
592
|
| diff | head branch | INDEX=n |
|
@@ -588,6 +607,7 @@ DOCKER_OPTIONS=q,no-cache # all
|
|
588
607
|
DOCKER_OPTIONS_${NAME}=v,no-cache=false # project only (override)
|
589
608
|
DOCKER_TAG=latest # all
|
590
609
|
DOCKER_TAG_${NAME}=v0.1.0 # project only (override)
|
610
|
+
DOCKER_ALL=1 # list every image/container
|
591
611
|
```
|
592
612
|
|
593
613
|
| Command | Flag | ENV |
|
data/lib/squared/common/base.rb
CHANGED
data/lib/squared/common/class.rb
CHANGED
@@ -12,7 +12,7 @@ module Squared
|
|
12
12
|
super[/[^:]+\z/, 0]
|
13
13
|
end
|
14
14
|
|
15
|
-
def_delegators :@data, :+, :each, :each_with_index, :entries, :
|
15
|
+
def_delegators :@data, :+, :each, :each_with_index, :entries, :merge, :include?
|
16
16
|
|
17
17
|
def initialize(data = [])
|
18
18
|
@data = Set.new(data)
|
@@ -22,6 +22,10 @@ module Squared
|
|
22
22
|
@data.add(val.to_sym)
|
23
23
|
end
|
24
24
|
|
25
|
+
def to_a
|
26
|
+
@data.to_a.freeze
|
27
|
+
end
|
28
|
+
|
25
29
|
def to_s
|
26
30
|
@data.to_s.sub('Set', SymSet.to_s)
|
27
31
|
end
|
@@ -71,13 +75,24 @@ module Squared
|
|
71
75
|
block_given? ? ret.reject(&blk) : ret
|
72
76
|
end
|
73
77
|
|
78
|
+
def and(*args)
|
79
|
+
self << '&&'
|
80
|
+
merge(args)
|
81
|
+
end
|
82
|
+
|
83
|
+
def or(*args)
|
84
|
+
self << '||'
|
85
|
+
merge(args)
|
86
|
+
end
|
87
|
+
|
88
|
+
def with(*args, &blk)
|
89
|
+
temp('&&', *args, &blk)
|
90
|
+
end
|
91
|
+
|
74
92
|
def temp(*args, &blk)
|
75
93
|
args.compact!
|
76
94
|
ret = pass(&blk)
|
77
|
-
unless args.empty?
|
78
|
-
ret += args
|
79
|
-
ret = Set.new(ret).to_a
|
80
|
-
end
|
95
|
+
ret = Set.new(ret.concat(args)).to_a unless args.empty?
|
81
96
|
ret.join(@delim)
|
82
97
|
end
|
83
98
|
|
@@ -28,18 +28,22 @@ module Squared
|
|
28
28
|
bright_cyan!: '106',
|
29
29
|
bright_white!: '107'
|
30
30
|
}.freeze
|
31
|
-
|
32
|
-
|
31
|
+
BOX_GRAPH = ['│', '─', '├', '└', '┬'].freeze
|
32
|
+
BOX_BORDER = ['│', '─', '╭', '╮', '╯', '╰', '├', '┤', '┬', '┴'].freeze
|
33
33
|
TEXT_STYLE = [:bold, :dim, :italic, :underline, :blinking, nil, :inverse, :hidden, :strikethrough].freeze
|
34
|
-
private_constant :AIX_TERM, :
|
34
|
+
private_constant :AIX_TERM, :BOX_GRAPH, :BOX_BORDER, :TEXT_STYLE
|
35
35
|
|
36
36
|
def enable_aixterm
|
37
37
|
unless (colors = __get__(:colors)).frozen?
|
38
38
|
colors.merge!(AIX_TERM)
|
39
|
-
ARG[:GRAPH] = AIX_GRAPH
|
40
|
-
ARG[:BORDER] = AIX_BORDER
|
41
39
|
end
|
42
|
-
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def enable_drawing
|
44
|
+
ARG[:GRAPH] = BOX_GRAPH
|
45
|
+
ARG[:BORDER] = BOX_BORDER
|
46
|
+
self
|
43
47
|
end
|
44
48
|
|
45
49
|
private
|
@@ -68,16 +72,16 @@ module Squared
|
|
68
72
|
end
|
69
73
|
if type.is_a?(::Numeric)
|
70
74
|
f, b = type.to_s.split('.')
|
71
|
-
s = wrap.(s, ['38', '5', f]) if f[0] != '-' && f.to_i <= 255
|
75
|
+
s = wrap.call(s, ['38', '5', f]) if f[0] != '-' && f.to_i <= 255
|
72
76
|
if b
|
73
77
|
b = b[0, 3]
|
74
|
-
s = wrap.(s, ['48', '5', b]) unless b.to_i > 255
|
78
|
+
s = wrap.call(s, ['48', '5', b]) unless b.to_i > 255
|
75
79
|
end
|
76
80
|
else
|
77
81
|
t = type.to_sym
|
78
82
|
if (c = __get__(:colors)[t])
|
79
83
|
if index == -1
|
80
|
-
s = wrap.(s, [c])
|
84
|
+
s = wrap.call(s, [c])
|
81
85
|
else
|
82
86
|
code << c
|
83
87
|
end
|
@@ -95,7 +99,7 @@ module Squared
|
|
95
99
|
end
|
96
100
|
return ret.join if index == -1
|
97
101
|
|
98
|
-
ret = wrap.(ret, code) unless code.empty?
|
102
|
+
ret = wrap.call(ret, code) unless code.empty?
|
99
103
|
return ret unless data
|
100
104
|
|
101
105
|
out = ''.dup
|
@@ -133,9 +137,9 @@ module Squared
|
|
133
137
|
|
134
138
|
set = ->(k, v) { data[k] = check_style(v, empty: empty) }
|
135
139
|
if key.is_a?(::Hash)
|
136
|
-
key.each { |k, v| set.(k, v || args) }
|
140
|
+
key.each { |k, v| set.call(k, v || args) }
|
137
141
|
else
|
138
|
-
set.(key.to_sym, args)
|
142
|
+
set.call(key.to_sym, args)
|
139
143
|
end
|
140
144
|
end
|
141
145
|
|
@@ -219,18 +223,18 @@ module Squared
|
|
219
223
|
max = ->(v) { n = [n, v.max_by(&:size).size].max }
|
220
224
|
set = lambda do |v|
|
221
225
|
ret = as_a(v, :to_s)
|
222
|
-
max.(ret)
|
226
|
+
max.call(ret)
|
223
227
|
ret
|
224
228
|
end
|
225
|
-
title &&= set.(title)
|
226
|
-
footer &&= set.(footer)
|
229
|
+
title &&= set.call(title)
|
230
|
+
footer &&= set.call(footer)
|
227
231
|
if val.is_a?(::Array)
|
228
232
|
lines = val.map(&:to_s)
|
229
233
|
else
|
230
234
|
lines = val.to_s.lines(chomp: true)
|
231
235
|
lines[0] = "#{val.class}: #{lines.first}" if (err = val.is_a?(StandardError))
|
232
236
|
end
|
233
|
-
n = cols || max.(lines)
|
237
|
+
n = cols || max.call(lines)
|
234
238
|
if $stdout.tty?
|
235
239
|
require 'io/console'
|
236
240
|
(n = [n, $stdout.winsize[1] - 4].min) rescue nil
|
@@ -253,13 +257,13 @@ module Squared
|
|
253
257
|
end
|
254
258
|
s
|
255
259
|
end
|
256
|
-
out << draw.(b2, b3)
|
260
|
+
out << draw.call(b2, b3)
|
257
261
|
if title
|
258
|
-
out
|
259
|
-
out << draw.(b6, b7)
|
262
|
+
out.concat(title.map { |t| pr.call(t) })
|
263
|
+
out << draw.call(b6, b7)
|
260
264
|
end
|
261
|
-
lines.each { |line| out << pr.(line) }
|
262
|
-
out << draw.(b5, b4)
|
265
|
+
lines.each { |line| out << pr.call(line) }
|
266
|
+
out << draw.call(b5, b4)
|
263
267
|
if footer
|
264
268
|
unless sub.empty? && !right
|
265
269
|
footer.map! do |s|
|
@@ -268,7 +272,7 @@ module Squared
|
|
268
272
|
s
|
269
273
|
end
|
270
274
|
end
|
271
|
-
out
|
275
|
+
out.concat(footer)
|
272
276
|
end
|
273
277
|
if block_given?
|
274
278
|
yield out
|
@@ -291,6 +295,10 @@ module Squared
|
|
291
295
|
val.gsub(/\x1B\[(\d+;?)+m/, '')
|
292
296
|
end
|
293
297
|
|
298
|
+
def stripext(val)
|
299
|
+
File.basename(val, File.extname(val))
|
300
|
+
end
|
301
|
+
|
294
302
|
def raise_error(*args, hint: nil, kind: ArgumentError)
|
295
303
|
raise kind, message(*args, hint: hint, empty: true), caller_locations(1).map(&:to_s)
|
296
304
|
end
|
@@ -21,7 +21,7 @@ module Squared
|
|
21
21
|
return false
|
22
22
|
end
|
23
23
|
attempts -= 1
|
24
|
-
exit 1 unless attempts
|
24
|
+
exit 1 unless attempts > 0
|
25
25
|
end
|
26
26
|
rescue Interrupt
|
27
27
|
puts
|
@@ -31,6 +31,44 @@ module Squared
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
+
|
35
|
+
def choice(msg, list = nil, min: 1, max: 1, multiple: false, attempts: 5, timeout: 60)
|
36
|
+
require 'readline'
|
37
|
+
require 'timeout'
|
38
|
+
if list
|
39
|
+
items = []
|
40
|
+
list.each_with_index do |val, index|
|
41
|
+
puts "#{index.succ.to_s.rjust(2)}. #{val}"
|
42
|
+
items << val.chomp
|
43
|
+
end
|
44
|
+
max = items.size
|
45
|
+
msg = "#{msg}: [1-#{max}#{multiple ? '|,' : ''}] "
|
46
|
+
end
|
47
|
+
return unless max >= min
|
48
|
+
|
49
|
+
valid = ->(s) { s.match?(/^-?\d+$/) && s.to_i.between?(min, max) }
|
50
|
+
Timeout.timeout(timeout) do
|
51
|
+
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
|
+
end
|
61
|
+
attempts -= 1
|
62
|
+
exit 1 unless attempts > 0
|
63
|
+
end
|
64
|
+
rescue Interrupt
|
65
|
+
puts
|
66
|
+
exit 0
|
67
|
+
else
|
68
|
+
multiple ? [] : nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
34
72
|
end
|
35
73
|
end
|
36
74
|
end
|
data/lib/squared/common/shell.rb
CHANGED
@@ -13,7 +13,7 @@ module Squared
|
|
13
13
|
return val if !r[3] || (!r[5] && r[6].match?(/\s/))
|
14
14
|
|
15
15
|
combine = lambda do |opt|
|
16
|
-
if r[2] =~
|
16
|
+
if r[2] =~ /\A(["'])(.+)\1\z/
|
17
17
|
double = $1 == '"'
|
18
18
|
r[2] = $2
|
19
19
|
override = true
|
@@ -21,11 +21,13 @@ module Squared
|
|
21
21
|
r[1] + r[2] + r[4] + shell_quote(opt, double: double, force: force, override: override)
|
22
22
|
end
|
23
23
|
if r[5] == r[7]
|
24
|
-
r[5] ? val : combine.(r[6])
|
24
|
+
r[5] ? val : combine.call(r[6])
|
25
25
|
else
|
26
26
|
force = true
|
27
|
-
combine.(r[5] + r[6] + r[7])
|
27
|
+
combine.call(r[5] + r[6] + r[7])
|
28
28
|
end
|
29
|
+
elsif val.empty?
|
30
|
+
''
|
29
31
|
elsif Rake::Win32.windows?
|
30
32
|
quote ? shell_quote(val, double: double, force: force) : val
|
31
33
|
else
|
@@ -35,7 +37,7 @@ module Squared
|
|
35
37
|
|
36
38
|
def shell_quote(val, option: true, force: true, double: false, override: false)
|
37
39
|
val = val.to_s
|
38
|
-
return val if !force && !val.include?(' ')
|
40
|
+
return val if val.empty? || (!force && !val.include?(' '))
|
39
41
|
return val if option && val.match?(/(?:\A|\S=|[^=]\s+|#{Rake::Win32.windows? ? '[\\\/]' : '\/'})(["']).+\1\z/m)
|
40
42
|
|
41
43
|
if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
@@ -45,10 +47,10 @@ module Squared
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def shell_option(flag, val = nil, escape: true, quote: true,
|
49
|
-
merge: false)
|
50
|
+
def shell_option(flag, val = nil, escape: true, quote: true, option: true, force: true, double: false,
|
51
|
+
merge: false, override: false)
|
50
52
|
flag = flag.to_s
|
51
|
-
if flag =~
|
53
|
+
if flag =~ /\A(["'])(.+)\1\z/
|
52
54
|
double = $1 == '"'
|
53
55
|
flag = $2
|
54
56
|
escape = false
|
@@ -66,8 +68,10 @@ module Squared
|
|
66
68
|
"#{a}#{flag}#{if val
|
67
69
|
"#{b}#{if escape
|
68
70
|
shell_escape(val, quote: quote, double: double, override: override)
|
71
|
+
elsif quote
|
72
|
+
shell_quote(val, option: option, force: force, double: double, override: override)
|
69
73
|
else
|
70
|
-
|
74
|
+
val
|
71
75
|
end}"
|
72
76
|
end}"
|
73
77
|
end
|
@@ -88,8 +92,8 @@ module Squared
|
|
88
92
|
shell_escape(val.start_with?('-') ? val : "--#{val}", double: double)
|
89
93
|
end
|
90
94
|
|
91
|
-
def quote_option(flag, val, double: false)
|
92
|
-
shell_option(flag, val, escape: false, double: double)
|
95
|
+
def quote_option(flag, val, option: true, double: false, merge: false)
|
96
|
+
shell_option(flag, val, escape: false, option: option, double: double, merge: merge)
|
93
97
|
end
|
94
98
|
|
95
99
|
def basic_option(flag, val, merge: false)
|
@@ -23,14 +23,14 @@ module Squared
|
|
23
23
|
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, force: false, pass: nil, verbose: true)
|
24
24
|
src = Pathname.new(src)
|
25
25
|
dest = Pathname.new(dest)
|
26
|
-
raise "#{dest} (not found)" if !create && !dest.parent.exist?
|
26
|
+
raise "#{dest.cleanpath} (not found)" if !create && !dest.parent.exist?
|
27
27
|
|
28
28
|
subdir = {}
|
29
29
|
dest.mkpath if create
|
30
30
|
if pass
|
31
31
|
exclude = []
|
32
32
|
pass = [pass] unless pass.is_a?(::Array)
|
33
|
-
pass.each { |val| exclude
|
33
|
+
pass.each { |val| exclude.concat(Dir.glob(src.join(val))) }
|
34
34
|
end
|
35
35
|
(glob.is_a?(::Array) ? glob : [glob]).each do |val|
|
36
36
|
Dir.glob(src.join(val)) do |path|
|
@@ -89,7 +89,7 @@ module Squared
|
|
89
89
|
case link
|
90
90
|
when 'hard', 1
|
91
91
|
FileUtils.ln(src, dest, force: force, verbose: verbose)
|
92
|
-
when
|
92
|
+
when TrueClass, 'soft', 0
|
93
93
|
FileUtils.ln_s(src, dest, force: force, verbose: verbose)
|
94
94
|
else
|
95
95
|
FileUtils.cp(src, dest, verbose: verbose)
|