squared 0.3.10 → 0.4.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.
data/README.ruby.md CHANGED
@@ -1,4 +1,4 @@
1
- # squared 0.3
1
+ # squared 0.4
2
2
 
3
3
  * [source](https://github.com/anpham6/squared)
4
4
  * [manifest](https://github.com/anpham6/squared-repo)
@@ -11,6 +11,7 @@
11
11
  | 2024-12-07 | 0.1.0 | 2.4.0 | 3.3.6 | 2.39 |
12
12
  | 2025-01-07 | 0.2.0 | 2.4.0 | 3.4.0 | 2.39 |
13
13
  | 2025-02-07 | 0.3.0 | 2.4.0 | 3.4.1 | 2.39 |
14
+ | 2025-03-06 | 0.4.0 | 2.4.0 | 3.4.2 | 2.39 |
14
15
 
15
16
  The range chart indicates the latest Ruby tested against at the time of release.
16
17
 
@@ -45,18 +46,19 @@ require "squared/workspace/repo" # Optional
45
46
  require "squared/workspace/project/node" #
46
47
  require "squared/workspace/project/python" #
47
48
  require "squared/workspace/project/ruby" #
49
+ require "squared/workspace/project/docker" #
48
50
  # OR
49
51
  require "squared/app" # All workspace related modules
50
52
 
51
53
  # NODE_ENV = production
52
54
 
53
- # REPO_ROOT = /workspaces #
54
- # REPO_HOME = /workspaces/squared # Dir.pwd
55
- # rake = /workspaces/squared/Rakefile # main?
55
+ # REPO_ROOT = /workspaces |
56
+ # REPO_HOME = /workspaces/squared | Dir.pwd
57
+ # rake = /workspaces/squared/Rakefile | main?
56
58
  # OR
57
- # REPO_ROOT = /workspaces # Dir.pwd
58
- # rake = /workspaces/Rakefile #
59
- # REPO_HOME = /workspaces/squared # main: "squared"
59
+ # REPO_ROOT = /workspaces | Dir.pwd
60
+ # rake = /workspaces/Rakefile |
61
+ # REPO_HOME = /workspaces/squared | main: "squared"
60
62
 
61
63
  # pathname = /workspaces/pathname
62
64
  # optparse = /workspaces/optparse
@@ -86,25 +88,34 @@ Workspace::Application
86
88
  .add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
87
89
  .add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
88
90
  # Repo (global)
89
- as(:run, "build:dev", "dev") # npm run build:dev -> npm run dev
91
+ as(:run, "build:dev", "dev") # npm run build:dev -> npm run dev
90
92
  as(:run, { "build:dev": "dev", "build:prod": "prod" })
91
93
 
92
- add("publish/sqd-cli", "cli", exclude: [:git]) # rake cli:build
93
- add("publish/sqd-serve") # rake sqd-serve:build
94
+ add("publish/sqd-cli", "cli", exclude: [:git]) # rake cli:build
95
+ add("publish/sqd-serve") # rake sqd-serve:build
94
96
  add("publish/sqd-admin", group: "sqd", exclude: [:base])
95
97
  # OR
96
- with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
98
+ with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
97
99
  # OR
98
- add(["publish/sqd-cli", "publish/sqd-serve", "publish/sqd-admin"], true, exclude: [:base]) # rake squared:sqd-serve:build
100
+ add(["publish/sqd-cli", "publish/sqd-serve"], true, exclude: [:base]) # rake squared:sqd-serve:build
99
101
  end
100
- .add("squared/sqd", exclude: :git, pass: [:node, 'checkout', 'bump']) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
101
- variable_set :script, "build:sqd" # Override detection
102
+ .add("squared/sqd", exclude: :git, pass: [:node, "checkout", "bump"]) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
103
+ variable_set :script, "build:sqd" # Override detection
102
104
  variable_set :depend, false
103
105
  variable_set :clean, ["build/sqd/"]
104
106
  end
107
+ .with(:docker, pass: ["unpack"]) do
108
+ .add("squared", "docker", file: "Dockerfile", context: ".", tag: "latest", args: "--ssh=default", secrets: ["id=github,env=GITHUB_TOKEN"]) do # Docker
109
+ series(:clean) do # run | depend | doc | lint | test | copy | clean
110
+ File.read(basepath("docker-bake.hcl"))
111
+ .scan(/\btags\s+=\s+\["([^"]+)"\]/)
112
+ .each { |val| image(:rm, tag: val.first) }
113
+ end
114
+ end
115
+ end
105
116
  .pass("pull", group: "default") { test? || doc? } # pathname:pull | optparse:pull
106
117
  .style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
107
- .build(default: "build", parallel: ["pull", "fetch", "rebase", "copy", "clean", /^outdated:/], pass: ['publish']) do |workspace|
118
+ .build(default: "build", parallel: ["pull", "fetch", "rebase", "archive", "copy", "clean", /^outdated:/], pass: ["publish"]) do |workspace|
108
119
  workspace
109
120
  .enable_aixterm
110
121
  .style({
@@ -121,19 +132,19 @@ Workspace::Application
121
132
  # chrome = /workspaces/chrome-docs
122
133
 
123
134
  Workspace::Application
124
- .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
135
+ .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
125
136
  .group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
126
137
  pathname: {
127
- run: "rake compile" # rake rb:pathname:build
138
+ run: "rake compile" # rake rb:pathname:build
128
139
  }
129
140
  })
130
- .with(:python) do # ref=Symbol | group=String
131
- banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
132
- doc("make html") # rake rb:doc:python
133
- run(false) # rake rb:build:python (disabled)
134
- exclude(%i[base git]) # Project::Git.ref (superclass)
135
- add("android-docs", "android") # rake rb:android:doc
136
- add("chrome-docs", "chrome") # rake rb:chrome:doc
141
+ .with(:python) do # ref=Symbol | group=String
142
+ banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
143
+ doc("make html") # rake rb:doc:python
144
+ run(false) # rake rb:build:python (disabled)
145
+ exclude(%i[base git]) # Project::Git.ref (superclass)
146
+ add("android-docs", "android") # rake rb:android:doc
147
+ add("chrome-docs", "chrome") # rake rb:chrome:doc
137
148
  end
138
149
  .style("inline", "bold")
139
150
  .build
@@ -141,6 +152,33 @@ Workspace::Application
141
152
 
142
153
  **NOTE**: The use of "**ref**" (class name) is only necessary when initializing an empty directory (e.g. *rake repo:init*).
143
154
 
155
+ ## Archive
156
+
157
+ ```ruby
158
+ # HEADERS={"Authorization":"Bearer RANDOM-TOKEN"} (hash/json)
159
+ # ZIP_DEPTH=0 | default=1
160
+ # TAR_DEPTH=0 | TAR_DEPTH_SQUARED
161
+ # UNPACK_FORCE=1 | Remove target directory
162
+
163
+ Workspace::Application
164
+ .new(main: "squared")
165
+ .with(:python) do
166
+ add("android-docs", "android", archive: "https://github.com/anpham6/android-docs/archive/refs/tags/v0.3.0.zip")
167
+ add("chrome-docs", "chrome", archive: {
168
+ uri: "https://github.com/anpham6/chrome-docs/archive/refs/tags/v0.5.0.tar.gz", # URI.open (required)
169
+ digest: "e3d55d2004d4770dd663254c9272dc3baad0d57a5bd14ca767de6546cdf14680", # SHA1 | SHA256 | SHA384 | SHA512 | MD5
170
+ digest: "rmd160:47b7790a511eed675fec1a3e742845fef058799b", # RMD160
171
+ ext: "tar.gz", # zip | tar | tar.gz | tgz | tar.xz | txz
172
+ depth: 1, # nested directories (e.g. --strip-components)
173
+ headers: { # URI.open
174
+ "Authorization" => "Bearer RANDOM-TOKEN"
175
+ }
176
+ })
177
+ end
178
+ .add("squared", release: "https://github.com/anpham6/squared/archive/refs/tags/??") # squared:unpack:zip[v5.4.0,/tmp/squared]
179
+ end
180
+ ```
181
+
144
182
  ### Clone
145
183
 
146
184
  The task is only active when the project directory is empty or does not exist.
@@ -179,10 +217,14 @@ Workspace::Application
179
217
  end
180
218
  .with(:python) do # rake clone:python
181
219
  add("android-docs")
182
- add("chrome-docs")
220
+ add("chrome-docs") do
221
+ revbuild(include: "source/", exclude: ["source/conf.py"]) # Limit files being watched
222
+ end
183
223
  end
184
- .git("https://github.com/anpham6") # Uses already defined root projects
185
224
  .git("https://github.com/anpham6", ["emc", "pir"]) # Targets any defined project
225
+ .git("https://github.com/anpham6", cache: true) # Uses already defined root projects + revbuild
226
+ .revbuild # Enables task revbuild (squared.revb)
227
+ .revbuild(file: "../build.json") # $ROOT/build.json
186
228
  .build(parallel: ["clone"]) # rake clone + rake clone:sync
187
229
  ```
188
230
 
@@ -197,45 +239,75 @@ Workspace::Application
197
239
  add("chrome-docs", "chrome", graph: "android")
198
240
  end
199
241
  .with(:node) do
200
- graph(["build", "copy"], on: { # Overrides "git"
242
+ graph(["build", "copy"], on: { # Overrides "git"
201
243
  first: proc { puts "1" },
202
244
  last: proc { puts "2" }
203
245
  })
204
- script("build:dev") # npm run build:dev
246
+ script("build:dev") # npm run build:dev
205
247
  # OR
206
- run([nil, "build:dev", { "PATH" => "~/.bin" }, "--workspace", "--silent"]) # PATH="~/.bin" npm run build:dev --workspace -- --silent
248
+ run([nil, "build:dev", { "PATH" => "~/.bin" }, "--workspace", "--silent"]) # PATH="~/.bin" npm run build:dev --workspace -- --silent
249
+ # OR
250
+ run({ # Same
251
+ script: "build:dev", #
252
+ env: { "PATH" => "~/.bin" }, #
253
+ opts: "--workspace", #
254
+ args: "--silent" #
255
+ })
207
256
 
208
257
  add("e-mc", "emc") do
209
- first("build", "emc:clean", "emc:depend") # rake emc:clean && rake emc:depend && rake emc:build && echo "123"
210
- last("build", out: "123") { |out: nil| puts out } #
211
- error("build") { |err: nil| log.debug err } #
258
+ first("build", "emc:clean", "emc:depend") # rake emc:clean && rake emc:depend && rake emc:build && echo "123"
259
+ last("build", out: "123") { |out: nil| puts out } #
260
+ error("build") { |err: nil| log.debug err } #
212
261
  end
213
262
  add("pi-r", "pir", graph: "emc", first: {
214
- build: proc { puts self.name } # puts "pir"
263
+ build: proc { puts self.name } # puts "pir"
215
264
  })
216
265
  add("squared-express", "express", graph: "pir")
217
266
  add("squared", graph: ["chrome", "express"]) do
218
- first("git:ls-files") { puts path }
219
- last("git:ls-files") { puts workspace.root }
267
+ first("git:ls-files") { puts "1" } # skipped
268
+ first("git:ls-files", override: true) { puts "2" } # puts "2"
269
+ last("git:ls-files") { puts workspace.root } # puts "/workspaces"
220
270
  end
221
271
  end
222
272
  .with(:ruby) do
223
- run("gem build") # gem build
273
+ run("gem build") # gem build
224
274
  # OR
225
- run(["gem build", "--force", { "RUBY_VERSION" => "3.4.0" }]) # RUBY_VERSION="3.4.0" gem build --force
275
+ run(["gem build", "--force", { "RUBY_VERSION" => "3.4.0" }]) # RUBY_VERSION="3.4.0" gem build --force
276
+ # OR
277
+ run({ #
278
+ command: "gem build", # RUBY_VERSION="3.4.0" gem build --silent --force
279
+ opts: "--force", # composable
280
+ env: { "PATH" => "~/.bin" }, #
281
+ args: { silent: true } #
282
+ })
226
283
  # OR
227
- run(["gem pristine", ["gem build", "gem cleanup"], nil, "--debug"]) # gem pristine --debug && gem build --debug && gem cleanup --debug
284
+ run(["gem pristine", ["gem build", "gem cleanup"], nil, "--debug"]) # gem pristine --debug && gem build --debug && gem cleanup --debug
285
+ #
286
+ # All commands are either Array or Hash
287
+ #
288
+ run([ # PATH="~/.bin" GEM_HOME="~/.gems/ruby-3.4.0" (merged)
289
+ ["gem pristine", "--all", { "PATH" => "~/.bin" }, "--silent"], # gem pristine --silent --all
290
+ ["gem build", { strict: true }, { "GEM_HOME" => "~/.gems/ruby-3.4.0" }] # gem build --strict
291
+ ]) #
228
292
  # OR
229
- run([ # PATH="~/.bin" GEM_HOME="~/.gems/ruby-3.4.0" (merged)
230
- ["gem pristine", "--all", { "PATH" => "~/.bin" }, "--silent"], # gem pristine --silent --all
231
- ["gem build", { strict: true }, { "GEM_HOME" => "~/.gems/ruby-3.4.0" }] # gem build --strict
293
+ run([ # Same
294
+ { #
295
+ env: { "PATH" => "~/.bin" }, #
296
+ command: "gem pristine", #
297
+ opts: "--all", args: "--silent" #
298
+ }, #
299
+ { #
300
+ env: { "GEM_HOME" => "~/.gems/ruby-3.4.0" }, #
301
+ command: "gem build", #
302
+ opts: { strict: true } #
303
+ } #
232
304
  ])
233
305
 
234
- add("pathname", test: ["rake test", { jobs: ENV["RAKE_JOBS"] }]) # rake test --jobs 4
306
+ add("pathname", test: ["rake test", { jobs: ENV["RAKE_JOBS"] }]) # rake test --jobs 4
235
307
  add("fileutils", graph: "pathname")
236
- add("optparse", run: "gem build", env: { "PATH" => "~/.bin" }, opts: "-v") # PATH="~/.bin" gem build -v
308
+ add("optparse", run: "gem build", env: { "PATH" => "~/.bin" }, opts: "-v") # PATH="~/.bin" gem build -v
237
309
  add("rake", graph: ["fileutils", "optparse"])
238
- banner(command: false) # Always hide banner
310
+ banner(command: false) # Always hide banner
239
311
  end
240
312
  .build
241
313
  ```
@@ -314,6 +386,7 @@ Task:
314
386
  * run
315
387
  * script
316
388
  * depend
389
+ * archive
317
390
  * graph
318
391
  * doc
319
392
  * lint
@@ -332,7 +405,10 @@ Non-task:
332
405
  * header
333
406
  * active
334
407
  * inline
408
+ * subject
409
+ * caution
335
410
  * current
411
+ * extra
336
412
  * major
337
413
  * red
338
414
  * yellow
@@ -346,12 +422,14 @@ All project executable programs can have their binary path set to a non-global a
346
422
 
347
423
  ```ruby
348
424
  Common::PATH.merge!({
349
- GIT: '/usr/bin/git',
350
- GEM: '~/.rvm/rubies/ruby-3.4.0/bin/gem',
351
- BUNDLE: '~/.rvm/gems/ruby-3.4.0/bin/bundle',
352
- RAKE: '~/.rvm/gems/ruby-3.4.0/bin/rake',
353
- NPM: '/opt/node/v22.0.0/bin/npm',
354
- PYTHON: "#{ENV['PYTHONPATH']}/bin/python"
425
+ GIT: "/usr/bin/git",
426
+ TAR: "/opt/archivers/tar",
427
+ UNZIP: "/opt/archivers/unzip",
428
+ GEM: "~/.rvm/gems/ruby-3.4.0/bin/gem",
429
+ BUNDLE: "~/.rvm/gems/ruby-3.4.0/bin/bundle",
430
+ RAKE: "~/.rvm/gems/ruby-3.4.0/bin/rake",
431
+ NPM: "/opt/node/v22.0.0/bin/npm",
432
+ PYTHON: "#{ENV["PYTHONPATH"]}/bin/python"
355
433
  })
356
434
  ```
357
435
 
@@ -362,32 +440,32 @@ Workspace::Application
362
440
  .new
363
441
  .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
364
442
 
365
- BUILD_TYPE # global
366
-
367
- # :env :run :opts :type
368
- # LD_LIBRARY_PATH="path/to/lib" CFLAGS="-Wall" gcc a.c -o a.o -g -O2
369
- BUILD_${NAME} # gcc a.c -o a.o
370
- BUILD_${NAME}_OPTS # -g
371
- BUILD_${NAME}_ENV # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (hash/json)
372
- BUILD_${NAME}_TYPE # debug
373
-
374
- # :env :opts :script :args
375
- # NODE_ENV="production" NO_COLOR="1" npm run --loglevel=error --workspaces=false build:dev -- --quiet
376
- BUILD_${NAME} # build:dev
377
- BUILD_${NAME}_OPTS # --loglevel=error --workspaces=false
378
- BUILD_${NAME}_ENV # {"NODE_ENV":"production","NO_COLOR":"1"} (hash/json)
379
- BUILD_${NAME}_DEV # pattern,0,1 (:dev)
380
- BUILD_${NAME}_PROD # pattern,0,1 (:prod)
381
- SCRIPT_${NAME}_OPTS # --quiet
382
-
383
- BUILD_${NAME}=0 # skip project
443
+ BUILD_TYPE # global
444
+
445
+ # :env :run :args :opts :type
446
+ # LD_LIBRARY_PATH="path/to/lib" CFLAGS="-Wall" gcc a.c -o a.o -g -O2
447
+ BUILD_${NAME} # gcc a.c -o a.o
448
+ BUILD_${NAME}_OPTS # -g
449
+ BUILD_${NAME}_ENV # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (hash/json)
450
+ BUILD_${NAME}_TYPE # debug
451
+
452
+ # :env :script :opts :args
453
+ # NODE_ENV="production" NO_COLOR="1" npm run build:dev --loglevel=error --workspaces=false -- --quiet
454
+ BUILD_${NAME} # build:dev
455
+ BUILD_${NAME}_OPTS # --loglevel=error --workspaces=false
456
+ BUILD_${NAME}_ENV # {"NODE_ENV":"production","NO_COLOR":"1"} (hash/json)
457
+ BUILD_${NAME}_DEV # pattern,0,1 (:dev)
458
+ BUILD_${NAME}_PROD # pattern,0,1 (:prod)
459
+ ${REF}_${NAME}_OPTS # --quiet (e.g. NODE_SQUARED_OPTS)
460
+
461
+ BUILD_${NAME}=0 # skip project
384
462
  ```
385
463
 
386
464
  ### Graph
387
465
 
388
466
  ```ruby
389
- GRAPH_${NAME} # depend,build => squared:depend + squared:build
390
- GRAPH_${NAME}_PASS # -emc,pir,express => pir + express
467
+ GRAPH_${NAME} # depend,build => squared:depend + squared:build
468
+ GRAPH_${NAME}_PASS # -emc,pir,express => pir + express
391
469
  ```
392
470
 
393
471
  ### Logger
@@ -395,13 +473,13 @@ GRAPH_${NAME}_PASS # -emc,pir,express => pir + express
395
473
  These global options also can target the project suffix `${NAME}`. (e.g. LOG_FILE_EMC)
396
474
 
397
475
  ```ruby
398
- LOG_FILE # %Y-%m-%d.log
476
+ LOG_FILE # %Y-%m-%d.log
399
477
  # OR
400
- LOG_AUTO # year,y,month,m,day,d,1
478
+ LOG_AUTO # year,y,month,m,day,d,1
401
479
  # Optional
402
- LOG_DIR # exist?
403
- LOG_LEVEL # See gem "logger"
404
- LOG_COLUMNS # terminal width (default: 80)
480
+ LOG_DIR # exist?
481
+ LOG_LEVEL # See gem "logger"
482
+ LOG_COLUMNS # terminal width (default: 80)
405
483
  ```
406
484
 
407
485
  ### Repo
@@ -409,17 +487,18 @@ LOG_COLUMNS # terminal width (default: 80)
409
487
  These global options also can target the application main suffix `${NAME}`. (e.g. REPO_ROOT_SQUARED)
410
488
 
411
489
  ```ruby
412
- REPO_ROOT # parent dir
413
- REPO_HOME # project dir (main)
414
- REPO_BUILD # run,script
415
- REPO_GROUP # string
416
- REPO_REF # e.g. ruby,node
417
- REPO_DEV # pattern,0,1
418
- REPO_PROD # pattern,0,1
419
- REPO_WARN # 0,1
420
- REPO_SYNC # 0,1
421
- REPO_MANIFEST # e.g. latest,nightly,prod
422
- REPO_TIMEOUT # confirm dialog (seconds)
490
+ REPO_ROOT # parent dir
491
+ REPO_HOME # project dir (main)
492
+ REPO_BUILD # run,script
493
+ REPO_GROUP # string
494
+ REPO_REF # e.g. ruby,node
495
+ REPO_DEV # pattern,0,1
496
+ REPO_PROD # pattern,0,1
497
+ REPO_WARN # 0,1
498
+ REPO_SYNC # 0,1
499
+ REPO_MANIFEST # e.g. latest,nightly,prod
500
+ REPO_DRYRUN # 0,1,2
501
+ REPO_TIMEOUT # confirm dialog (seconds)
423
502
  ```
424
503
 
425
504
  ## Git
@@ -433,12 +512,13 @@ Most project classes will inherit from `Git` which enables these tasks:
433
512
  | commit | commit | add all amend amend-orig |
434
513
  | diff | diff | head cached branch files between contain |
435
514
  | fetch | fetch | origin remote |
436
- | files | ls-files | cached modified deleted others |
515
+ | files | ls-files | cached modified deleted others ignored |
516
+ | git | | clean mv restore rm |
517
+ | merge | merge | commit no-commit send |
437
518
  | pull | pull | origin remote |
438
519
  | rebase | rebase | branch onto send |
439
520
  | refs | ls-remote --refs | heads tags remote |
440
521
  | reset | reset | commit index patch mode |
441
- | restore | restore | source worktree staged overlay |
442
522
  | rev | rev | commit branch output parseopt |
443
523
  | show | show | format oneline |
444
524
  | stash | stash | push pop apply drop list |
data/lib/squared/app.rb CHANGED
@@ -5,4 +5,5 @@ require_relative 'workspace/repo'
5
5
  require_relative 'workspace/project/node'
6
6
  require_relative 'workspace/project/python'
7
7
  require_relative 'workspace/project/ruby'
8
+ require_relative 'workspace/project/docker'
8
9
  require_relative 'config'
@@ -13,8 +13,10 @@ module Squared
13
13
  BANNER: true,
14
14
  QUOTE: "'",
15
15
  SPACE: ' => ',
16
- GRAPH: ['', '', '', '', ''],
16
+ GRAPH: ['|', '-', '|', '\\', '-'].freeze,
17
+ BORDER: ['|', '-', '-', '-', '-', '-', '|', '|', '-', '-'].freeze,
17
18
  VIEW: 'view',
19
+ LEVEL: ENV.fetch('LOG_LEVEL', 0).to_i,
18
20
  COLOR: ENV.fetch('NO_COLOR', '').empty?
19
21
  }
20
22
  VAR = {
@@ -42,7 +44,10 @@ module Squared
42
44
  header: [:bold],
43
45
  active: [:bold],
44
46
  inline: [:bold],
47
+ subject: [:bold],
48
+ caution: [:red],
45
49
  current: nil,
50
+ extra: nil,
46
51
  major: [:bold]
47
52
  },
48
53
  project: {},
@@ -54,7 +54,7 @@ module Squared
54
54
  ret.each_with_index do |opt, index|
55
55
  if opt == val
56
56
  j = index
57
- elsif j && opt =~ pat && $1 == key
57
+ elsif j && opt[pat, 1] == key
58
58
  i << index
59
59
  end
60
60
  end
@@ -28,12 +28,16 @@ module Squared
28
28
  bright_cyan!: '106',
29
29
  bright_white!: '107'
30
30
  }.freeze
31
+ AIX_GRAPH = ['│', '─', '├', '└', '┬'].freeze
32
+ AIX_BORDER = ['│', '─', '╭', '╮', '╯', '╰', '├', '┤', '┬', '┴'].freeze
31
33
  TEXT_STYLE = [:bold, :dim, :italic, :underline, :blinking, nil, :inverse, :hidden, :strikethrough].freeze
32
- private_constant :AIX_TERM, :TEXT_STYLE
34
+ private_constant :AIX_TERM, :AIX_GRAPH, :AIX_BORDER, :TEXT_STYLE
33
35
 
34
36
  def enable_aixterm
35
37
  unless (colors = __get__(:colors)).frozen?
36
38
  colors.merge!(AIX_TERM)
39
+ ARG[:GRAPH] = AIX_GRAPH
40
+ ARG[:BORDER] = AIX_BORDER
37
41
  end
38
42
  block_given? ? yield(self) : self
39
43
  end
@@ -53,7 +57,7 @@ module Squared
53
57
  end
54
58
  wrap = ->(s, n) { "\x1B[#{n.join(';')}m#{s}\x1B[0m" }
55
59
  code = []
56
- args.concat(as_a(styles)).flatten.each_with_index do |type, i|
60
+ args.concat(as_a(styles)).each_with_index do |type, i|
57
61
  next unless type
58
62
 
59
63
  if index == -1
@@ -114,7 +118,7 @@ module Squared
114
118
  if !val.is_a?(::Numeric)
115
119
  val = val.to_sym
116
120
  ret << val if colors.key?(val) || TEXT_STYLE.include?(val)
117
- elsif val.between?(0, 256)
121
+ elsif val >= 0 && val <= 256
118
122
  ret << val
119
123
  elsif val < 0 && (b = val.to_s.split('.')[1])
120
124
  b = b[0, 3]
@@ -166,21 +170,29 @@ module Squared
166
170
  color ? sub_style(ret, *styles) : ret
167
171
  end
168
172
 
169
- def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR])
173
+ def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR], pass: false)
174
+ return false if !pass && level.is_a?(::Numeric) && level < ARG[:LEVEL]
175
+
170
176
  args = args.map(&:to_s)
171
- if args.size > 1
177
+ if args.size > 1 && !hint
172
178
  title = log_title(level, color: false)
173
179
  sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
174
180
  emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub)
175
181
  else
176
182
  msg = [log_title(level, color: color)]
177
- msg << (color ? sub_style(subject, :underline) : subject) if subject
178
- msg << args.shift if msg.size == 1
183
+ if subject
184
+ msg << (color ? sub_style(subject, styles: (@theme && @theme[:subject]) || :bold) : subject)
185
+ else
186
+ msg += args
187
+ args.clear
188
+ end
179
189
  message(msg.join(' '), *args, hint: hint)
180
190
  end
181
191
  end
182
192
 
183
193
  def puts_oe(*args, pipe: 1)
194
+ return if args.first == false && args.size == 1
195
+
184
196
  if pipe.is_a?(Pathname)
185
197
  begin
186
198
  File.open(pipe, 'a') do |f|
@@ -222,27 +234,31 @@ module Squared
222
234
  require 'io/console'
223
235
  (n = [n, $stdout.winsize[1] - 4].min) rescue nil
224
236
  end
237
+ b0, b1, b2, b3, b4, b5, b6, b7 = ARG[:BORDER]
225
238
  out = []
226
- bord = '-' * (n + 4)
227
- bord = sub_style(bord, styles: border) if border
239
+ draw = lambda do |a, b|
240
+ ret = a + (b1 * (n + 2)) + b
241
+ ret = sub_style(ret, styles: border) if border
242
+ ret
243
+ end
228
244
  sub = as_a(sub)
229
245
  pr = lambda do |line|
230
246
  s = line.ljust(n)
231
247
  sub.each { |h| s = sub_style(s, **h) }
232
- s = "| #{s} |"
248
+ s = "#{b0} #{s} #{b0}"
233
249
  if border
234
- s = sub_style(s, pat: /\A(\|)(.+)\z/m, styles: border)
235
- s = sub_style(s, pat: /\A(.+)(\|)\z/m, styles: border, index: 2)
250
+ s = sub_style(s, pat: /\A(#{Regexp.escape(b0)})(.+)\z/m, styles: border)
251
+ s = sub_style(s, pat: /\A(.+)(#{Regexp.escape(b0)})\z/m, styles: border, index: 2)
236
252
  end
237
253
  s
238
254
  end
239
- out << bord
255
+ out << draw.(b2, b3)
240
256
  if title
241
257
  out += title.map { |t| pr.(t) }
242
- out << bord
258
+ out << draw.(b6, b7)
243
259
  end
244
260
  lines.each { |line| out << pr.(line) }
245
- out << bord
261
+ out << draw.(b5, b4)
246
262
  if footer
247
263
  unless sub.empty? && !right
248
264
  footer.map! do |s|
@@ -274,10 +290,6 @@ module Squared
274
290
  val.gsub(/\x1B\[(\d+;?)+m/, '')
275
291
  end
276
292
 
277
- def stripext(val)
278
- File.basename(val, File.extname(val))
279
- end
280
-
281
293
  def raise_error(*args, hint: nil, kind: ArgumentError)
282
294
  raise kind, message(*args, hint: hint, empty: true), caller_locations(1).map(&:to_s)
283
295
  end
@@ -8,8 +8,8 @@ module Squared
8
8
  def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
9
9
  require 'readline'
10
10
  require 'timeout'
11
- agree = /\A#{agree}\z/i if agree.is_a?(::String)
12
- cancel = /\A#{cancel}\z/i if cancel.is_a?(::String)
11
+ agree = /^#{agree}$/i if agree.is_a?(::String)
12
+ cancel = /^#{cancel}$/i if cancel.is_a?(::String)
13
13
  Timeout.timeout(timeout) do
14
14
  begin
15
15
  while (ch = Readline.readline(msg, true))
@@ -21,7 +21,7 @@ module Squared
21
21
  return false
22
22
  end
23
23
  attempts -= 1
24
- exit 1 unless attempts > 0
24
+ exit 1 unless attempts >= 0
25
25
  end
26
26
  rescue Interrupt
27
27
  puts