squared 0.2.14 → 0.3.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 ADDED
@@ -0,0 +1,466 @@
1
+ # squared 0.3
2
+
3
+ * [source](https://github.com/anpham6/squared)
4
+ * [manifest](https://github.com/anpham6/squared-repo)
5
+ * [docs](https://squared.readthedocs.io)
6
+
7
+ ## Version Compatibility
8
+
9
+ | Date | squared | Min | Max | Git |
10
+ | :--------: | ------: | -----: | -----: | -----: |
11
+ | 2024-12-07 | 0.1.0 | 2.4.0 | 3.3.6 | 2.39 |
12
+ | 2025-01-07 | 0.2.0 | 2.4.0 | 3.4.0 | 2.39 |
13
+ | 2025-02-07 | 0.3.0 | 2.4.0 | 3.4.1 | 2.39 |
14
+
15
+ The range chart indicates the latest Ruby tested against at the time of release.
16
+
17
+ ## Installation
18
+
19
+ ```sh
20
+ gem install squared
21
+ ```
22
+
23
+ ### Optional
24
+
25
+ * [Repo](https://source.android.com/docs/setup/reference/repo)
26
+ * Python 3.6
27
+ * Not compatible with Windows
28
+
29
+ ```sh
30
+ mkdir -p ~/.bin
31
+ PATH="${HOME}/.bin:${PATH}"
32
+ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
33
+ chmod a+rx ~/.bin/repo
34
+ ```
35
+
36
+ ## Example - Rakefile
37
+
38
+ Projects from any accessible folder can be added relative to the parent directory (e.g. *REPO_ROOT*) or absolutely. The same Rakefile can also manage other similarly cloned `Repo` repositories remotely by setting the `REPO_ROOT` environment variable to the location. Missing projects will simply be excluded from the task runner.
39
+
40
+ ```ruby
41
+ require "squared"
42
+
43
+ require "squared/workspace"
44
+ require "squared/workspace/repo" # Optional
45
+ require "squared/workspace/project/node" #
46
+ require "squared/workspace/project/python" #
47
+ require "squared/workspace/project/ruby" #
48
+ # OR
49
+ require "squared/app" # All workspace related modules
50
+
51
+ # NODE_ENV = production
52
+
53
+ # REPO_ROOT = /workspaces #
54
+ # REPO_HOME = /workspaces/squared # Dir.pwd
55
+ # rake = /workspaces/squared/Rakefile # main?
56
+ # OR
57
+ # REPO_ROOT = /workspaces # Dir.pwd
58
+ # rake = /workspaces/Rakefile #
59
+ # REPO_HOME = /workspaces/squared # main: "squared"
60
+
61
+ # pathname = /workspaces/pathname
62
+ # optparse = /workspaces/optparse
63
+ # log = /workspaces/logger
64
+ # emc = /workspaces/e-mc
65
+ # pir = /workspaces/pi-r
66
+ # squared = /workspaces/squared
67
+ # cli = /workspaces/squared/publish/sqd-cli
68
+ # sqd-serve = /workspaces/squared/publish/sqd-serve
69
+ # sqd = /workspaces/squared/sqd
70
+
71
+ Workspace::Application
72
+ .new(Dir.pwd, main: "squared") # Dir.pwd? (main? is implicitly basename)
73
+ .banner("group", "project", styles: ["yellow", "black"], border: "bold") # name | project | path | ref | group? | parent? | version?
74
+ .repo("https://github.com/anpham6/squared-repo", "nightly", script: ["build:dev", "build:prod"], ref: :node) # Repo (optional)
75
+ .run("rake install", ref: :ruby)
76
+ .depend(false, group: "default")
77
+ .clean("rake clean", group: "default")
78
+ .clean(["build/"], group: "app")
79
+ .log({ file: "tmp/%Y-%m-%d.log", level: "debug" }, group: "app")
80
+ .add("pathname", run: "rake compile", copy: "rake install", test: "rake test", group: "default", env: { # Ruby (with C extensions)
81
+ "CFLAGS" => "-fPIC -O1"
82
+ })
83
+ .add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
84
+ .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.4.0/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
85
+ .add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
86
+ .add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
87
+ .add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
88
+ # Repo (global)
89
+ as(:run, "build:dev", "dev") # npm run build:dev -> npm run dev
90
+ as(:run, { "build:dev": "dev", "build:prod": "prod" })
91
+
92
+ add("publish/sqd-cli", "cli", exclude: [:git]) # rake cli:build
93
+ add("publish/sqd-serve") # rake sqd-serve:build
94
+ add("publish/sqd-admin", group: "sqd", exclude: [:base])
95
+ # OR
96
+ with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
97
+ # OR
98
+ add(["publish/sqd-cli", "publish/sqd-serve", "publish/sqd-admin"], true, exclude: [:base]) # rake squared:sqd-serve:build
99
+ 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
+ variable_set :depend, false
103
+ variable_set :clean, ["build/sqd/"]
104
+ end
105
+ .pass("pull", group: "default") { test? || doc? } # pathname:pull | optparse:pull
106
+ .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|
108
+ workspace
109
+ .enable_aixterm
110
+ .style({
111
+ banner: ["bright_cyan", "bold", "bright_black!"],
112
+ border: "bright_white"
113
+ })
114
+ end
115
+
116
+ # default = /workspaces/ruby/*
117
+ # pathname = /workspaces/ruby/pathname
118
+ # optparse = /workspaces/ruby/optparse
119
+ # logger = /workspaces/ruby/logger
120
+ # android = /workspaces/android-docs
121
+ # chrome = /workspaces/chrome-docs
122
+
123
+ Workspace::Application
124
+ .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
125
+ .group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
126
+ pathname: {
127
+ run: "rake compile" # rake rb:pathname:build
128
+ }
129
+ })
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
137
+ end
138
+ .style("inline", "bold")
139
+ .build
140
+ ```
141
+
142
+ **NOTE**: The use of "**ref**" (class name) is only necessary when initializing an empty directory (e.g. *rake repo:init*).
143
+
144
+ ### Clone
145
+
146
+ The task is only active when the project directory is empty or does not exist.
147
+
148
+ ```ruby
149
+ Workspace::Application
150
+ .new(main: "squared")
151
+ .git(
152
+ "emc": "https://github.com/anpham6/e-mc", # rake emc:clone
153
+ "pir": { # rake pir:clone
154
+ uri: "https://github.com/anpham6/pi-r", #
155
+ options: { #
156
+ "origin": "github", # --origin='github'
157
+ "recurse-submodules": false, # --no-recurse-submodules
158
+ "shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude='v0.0.1' --shallow-exclude='v0.0.2'
159
+ }
160
+ }
161
+ )
162
+ .git("squared", "/path/to/squared", options: { local: true }) # Relative paths resolve from workspace root
163
+ .git(
164
+ {
165
+ emc: { uri: "e-mc", options: { "depth": 2 } }, # https://github.com/anpham6/e-mc
166
+ pir: "pi-r" # Maps task alias to repository folder
167
+ },
168
+ base: "https://github.com/anpham6", # Required
169
+ repo: ["squared", "android-docs", "chrome-docs"], # https://github.com/anpham6/squared
170
+ options: { # Only "repo"
171
+ "depth": 1,
172
+ "quiet": true
173
+ }
174
+ )
175
+ .with(:node) do # rake clone:node
176
+ add("e-mc", "emc") # https://github.com/anpham6/e-mc
177
+ add("pi-r", "pir") # https://github.com/anpham6/pi-r
178
+ add("squared") # https://github.com/anpham6/squared
179
+ end
180
+ .with(:python) do # rake clone:python
181
+ add("android-docs")
182
+ add("chrome-docs")
183
+ end
184
+ .git("https://github.com/anpham6") # Uses already defined root projects
185
+ .git("https://github.com/anpham6", ["emc", "pir"]) # Targets any defined project
186
+ .build(parallel: ["clone"]) # rake clone + rake clone:sync
187
+ ```
188
+
189
+ ### Graph
190
+
191
+ ```ruby
192
+ Workspace::Application
193
+ .new(main: "squared")
194
+ .graph(["depend"], ref: :git) # Optional
195
+ .with(:python) do
196
+ add("android-docs", "android")
197
+ add("chrome-docs", "chrome", graph: "android")
198
+ end
199
+ .with(:node) do
200
+ graph(["build", "copy"], on: { # Overrides "git"
201
+ first: proc { puts "1" },
202
+ last: proc { puts "2" }
203
+ })
204
+ script("build:dev") # npm run build:dev
205
+ # OR
206
+ run([nil, "build:dev", { "PATH" => "~/.bin" }, "--workspace", "--silent"]) # PATH="~/.bin" npm run build:dev --workspace -- --silent
207
+
208
+ 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 } #
212
+ end
213
+ add("pi-r", "pir", graph: "emc", first: {
214
+ build: proc { puts self.name } # puts "pir"
215
+ })
216
+ add("squared-express", "express", graph: "pir")
217
+ add("squared", graph: ["chrome", "express"]) do
218
+ first("git:ls-files") { puts path }
219
+ last("git:ls-files") { puts workspace.root }
220
+ end
221
+ end
222
+ .with(:ruby) do
223
+ run("gem build") # gem build
224
+ # OR
225
+ run(["gem build", "--force", { "RUBY_VERSION" => "3.4.0" }]) # RUBY_VERSION="3.4.0" gem build --force
226
+ # OR
227
+ run(["gem pristine", ["gem build", "gem cleanup"], nil, "--debug"]) # gem pristine --debug && gem build --debug && gem cleanup --debug
228
+ # 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
232
+ ])
233
+
234
+ add("pathname", test: ["rake test", { jobs: ENV["RAKE_JOBS"] }]) # rake test --jobs 4
235
+ add("fileutils", graph: "pathname")
236
+ add("optparse", run: "gem build", env: { "PATH" => "~/.bin" }, opts: "-v") # PATH="~/.bin" gem build -v
237
+ add("rake", graph: ["fileutils", "optparse"])
238
+ banner(command: false) # Always hide banner
239
+ end
240
+ .build
241
+ ```
242
+
243
+ ```sh
244
+ rake pir:graph # emc + pir
245
+ rake express:graph # emc + pir + express
246
+ rake chrome:graph # android + chrome
247
+ rake graph:python # same
248
+ rake squared:graph # android + chrome + emc + pir + express + squared
249
+ rake graph:node # same
250
+ rake rake:graph # pathname + fileutils + optparse + rake
251
+ rake graph:ruby # same
252
+ rake graph # graph:node + graph:ruby
253
+
254
+ rake squared:graph:run[express,pir] # emc + pir + express + squared
255
+ rake squared:graph:run[node,-emc] # pir + express + squared
256
+ ```
257
+
258
+ ### Batch
259
+
260
+ ```ruby
261
+ Workspace::Series.batch(:ruby, :node, {
262
+ stage: %i[graph test],
263
+ reset: %i[stash pull]
264
+ })
265
+ ```
266
+
267
+ ### Rename
268
+
269
+ ```ruby
270
+ Workspace::Series.rename("depend", "install")
271
+ ```
272
+
273
+ ## Usage
274
+
275
+ ```sh
276
+ rake -T # List tasks
277
+ rake # rake status (usually "build")
278
+
279
+ # GIT_OPTIONS=rebase
280
+ rake pull # All except "default" + "app"
281
+ rake pull:ruby # pathname + optparse + logger
282
+ rake pull:default # pathname + optparse
283
+ rake pull:app # squared
284
+ rake pull:node # emc + pir + squared
285
+
286
+ rake build # All except "android"
287
+ rake doc # optparse + android
288
+ rake depend # All except "default"
289
+
290
+ rake build:ruby # rake compile + rake install + rake install
291
+
292
+ rake clean # All except "default" + "app"
293
+ rake clean:ruby # rake clean + rake clean + ["tmp/"]
294
+ rake clean:default # rake clean + rake clean + skip
295
+ rake clean:app # none + skip + ["build/"]
296
+ rake clean:node # none + ["publish/**/*.js", "tmp/"] + ["build/"]
297
+
298
+ rake squared:run[#] # List scripts (node)
299
+ rake squared:rake[#] # List tasks (ruby)
300
+ ```
301
+
302
+ ```sh
303
+ rake build:app # squared + cli + sqd-serve
304
+ rake squared:build:workspace # cli + sqd-serve
305
+ rake pull:sqd # sqd-admin
306
+ rake squared:pull:workspace # sqd-serve + sqd-admin
307
+ rake squared:outdated:workspace # cli + sqd-serve + sqd-admin
308
+ ```
309
+
310
+ ## Methods
311
+
312
+ Task:
313
+
314
+ * run
315
+ * script
316
+ * depend
317
+ * graph
318
+ * doc
319
+ * lint
320
+ * test
321
+ * clean
322
+
323
+ Non-task:
324
+
325
+ * log
326
+ * exclude
327
+
328
+ ## Styles
329
+
330
+ * banner
331
+ * border
332
+ * header
333
+ * active
334
+ * inline
335
+ * current
336
+ * major
337
+ * red
338
+ * yellow
339
+ * green
340
+
341
+ ## Environment
342
+
343
+ ### Path
344
+
345
+ All project executable programs can have their binary path set to a non-global alias.
346
+
347
+ ```ruby
348
+ 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"
355
+ })
356
+ ```
357
+
358
+ ### Build
359
+
360
+ ```ruby
361
+ Workspace::Application
362
+ .new
363
+ .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
+
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
384
+ ```
385
+
386
+ ### Graph
387
+
388
+ ```ruby
389
+ GRAPH_${NAME} # depend,build => squared:depend + squared:build
390
+ GRAPH_${NAME}_PASS # -emc,pir,express => pir + express
391
+ ```
392
+
393
+ ### Logger
394
+
395
+ These global options also can target the project suffix `${NAME}`. (e.g. LOG_FILE_EMC)
396
+
397
+ ```ruby
398
+ LOG_FILE # %Y-%m-%d.log
399
+ # OR
400
+ LOG_AUTO # year,y,month,m,day,d,1
401
+ # Optional
402
+ LOG_DIR # exist?
403
+ LOG_LEVEL # See gem "logger"
404
+ LOG_COLUMNS # terminal width (default: 80)
405
+ ```
406
+
407
+ ### Repo
408
+
409
+ These global options also can target the application main suffix `${NAME}`. (e.g. REPO_ROOT_SQUARED)
410
+
411
+ ```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)
423
+ ```
424
+
425
+ ## Git
426
+
427
+ Most project classes will inherit from `Git` which enables these tasks:
428
+
429
+ | Task | Git | Command |
430
+ | :--------- | :--------------- | :-------------------------------------------- |
431
+ | branch | branch | create set delete move copy list edit current |
432
+ | checkout | checkout | commit branch track detach path |
433
+ | commit | commit | add all amend amend-orig |
434
+ | diff | diff | head cached branch files between contain |
435
+ | fetch | fetch | origin remote |
436
+ | files | ls-files | cached modified deleted others ignored |
437
+ | pull | pull | origin remote |
438
+ | rebase | rebase | branch onto send |
439
+ | refs | ls-remote --refs | heads tags remote |
440
+ | reset | reset | commit index patch mode |
441
+ | restore | restore | source worktree staged overlay |
442
+ | rev | rev | commit branch output parseopt |
443
+ | show | show | format oneline |
444
+ | stash | stash | push pop apply drop list |
445
+ | tag | tag | add delete list |
446
+
447
+ You can disable all of them at once using the `exclude` property.
448
+
449
+ ```ruby
450
+ Workspace::Application
451
+ .new
452
+ .add("squared", exclude: :git)
453
+ ```
454
+
455
+ You can disable one or more of them using the `pass` property as a *string*.
456
+
457
+ ```ruby
458
+ Workspace::Application
459
+ .new
460
+ .add("squared", pass: ["pull"], ref: :node)
461
+ .pass("pull", ref: :node) { read_packagemanager(:private) }
462
+ ```
463
+
464
+ ## LICENSE
465
+
466
+ BSD 3-Clause
@@ -6,10 +6,12 @@ module Squared
6
6
  ARG = {
7
7
  PIPE: 1,
8
8
  OUT: nil,
9
- VERBOSE: nil,
10
9
  FAIL: false,
10
+ HOME: nil,
11
11
  COMMON: true,
12
+ VERBOSE: nil,
12
13
  BANNER: true,
14
+ QUOTE: "'",
13
15
  SPACE: ' => ',
14
16
  GRAPH: ['│', '─', '├', '└', '┬'],
15
17
  VIEW: 'view',
@@ -53,7 +55,6 @@ module Squared
53
55
  hash: %i[green black!],
54
56
  array: %i[blue black!],
55
57
  number: [:magenta],
56
- boolean: [:magenta],
57
58
  undefined: %i[red italic]
58
59
  },
59
60
  logger: {
@@ -84,7 +85,7 @@ module Squared
84
85
  PATH.freeze
85
86
  ARG.freeze
86
87
  VAR.each_value(&:freeze)
87
- VAR[:theme].each_value { |val| val.freeze.each_value(&:freeze) }
88
+ VAR[:theme].each_value(&:freeze)
88
89
  VAR.freeze
89
90
  end
90
91
 
@@ -94,15 +95,13 @@ module Squared
94
95
  return [] if obj.nil?
95
96
 
96
97
  unless obj.is_a?(::Array)
97
- obj = if obj.respond_to?(:to_ary)
98
- obj.to_ary
99
- elsif obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
98
+ obj = if obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
100
99
  val
101
100
  else
102
101
  [obj]
103
102
  end
104
103
  end
105
- obj = flat.is_a?(::Numeric) ? obj.flatten(flat) : obj.flatten if flat
104
+ obj = obj.flatten(flat.is_a?(::Numeric) ? flat : nil) if flat
106
105
  obj = obj.compact if compact
107
106
  obj = obj.map(&meth) if meth
108
107
  block_given? ? obj.select(&blk) : obj
@@ -9,7 +9,7 @@ module Squared
9
9
  extend Forwardable
10
10
 
11
11
  def self.to_s
12
- super.match(/[^:]+\z/)[0]
12
+ super[/[^:]+\z/, 0]
13
13
  end
14
14
 
15
15
  def_delegators :@data, :+, :each, :each_with_index, :entries, :to_a, :include?
@@ -31,7 +31,7 @@ module Squared
31
31
 
32
32
  class JoinSet < Set
33
33
  def self.to_s
34
- super.match(/[^:]+\z/)[0]
34
+ super[/[^:]+\z/, 0]
35
35
  end
36
36
 
37
37
  attr_reader :delim
@@ -41,8 +41,33 @@ module Squared
41
41
  @delim = delim
42
42
  end
43
43
 
44
+ def last(val, pat)
45
+ (@last ||= []).push([val, pat, $1]) if val =~ pat
46
+ self << val
47
+ end
48
+
44
49
  def pass(&blk)
45
50
  ret = to_a.map!(&:to_s).reject(&:empty?)
51
+ @last&.each do |val, pat, key|
52
+ i = []
53
+ j = nil
54
+ ret.each_with_index do |opt, index|
55
+ if opt == val
56
+ j = index
57
+ elsif j && opt =~ pat && $1 == key
58
+ i << index
59
+ end
60
+ end
61
+ next unless j && !i.empty?
62
+
63
+ val = ret[j]
64
+ cur = j
65
+ i.each do |k|
66
+ ret[cur] = ret[k]
67
+ cur = k
68
+ end
69
+ ret[i.last] = val
70
+ end
46
71
  block_given? ? ret.reject(&blk) : ret
47
72
  end
48
73
 
@@ -53,7 +53,7 @@ module Squared
53
53
  end
54
54
  wrap = ->(s, n) { "\x1B[#{n.join(';')}m#{s}\x1B[0m" }
55
55
  code = []
56
- args.concat(as_a(styles)).flatten.each_with_index do |type, i|
56
+ args.concat(as_a(styles)).each_with_index do |type, i|
57
57
  next unless type
58
58
 
59
59
  if index == -1
@@ -66,7 +66,7 @@ module Squared
66
66
  f, b = type.to_s.split('.')
67
67
  s = wrap.(s, ['38', '5', f]) if f[0] != '-' && f.to_i <= 255
68
68
  if b
69
- b = b[0..2]
69
+ b = b[0, 3]
70
70
  s = wrap.(s, ['48', '5', b]) unless b.to_i > 255
71
71
  end
72
72
  else
@@ -114,10 +114,10 @@ module Squared
114
114
  if !val.is_a?(::Numeric)
115
115
  val = val.to_sym
116
116
  ret << val if colors.key?(val) || TEXT_STYLE.include?(val)
117
- elsif val.between?(0, 256)
117
+ elsif val >= 0 && val <= 256
118
118
  ret << val
119
119
  elsif val < 0 && (b = val.to_s.split('.')[1])
120
- b = b[0..2]
120
+ b = b[0, 3]
121
121
  ret << "-0.#{b}".to_f unless b.to_i > 255
122
122
  end
123
123
  end
@@ -127,11 +127,11 @@ module Squared
127
127
  def apply_style(data, key, args, empty: true)
128
128
  return if data.is_a?(::Symbol) && (data = __get__(:theme)[data]).nil?
129
129
 
130
- set = ->(k, v) { data[k.to_sym] = check_style(v, empty: empty) }
130
+ set = ->(k, v) { data[k] = check_style(v, empty: empty) }
131
131
  if key.is_a?(::Hash)
132
132
  key.each { |k, v| set.(k, v || args) }
133
133
  else
134
- set.(key, args)
134
+ set.(key.to_sym, args)
135
135
  end
136
136
  end
137
137
 
@@ -171,11 +171,15 @@ module Squared
171
171
  if args.size > 1
172
172
  title = log_title(level, color: false)
173
173
  sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
174
- emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub, pipe: -1)
174
+ emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub)
175
175
  else
176
176
  msg = [log_title(level, color: color)]
177
- msg << (color ? sub_style(subject, :underline) : subject) if subject
178
- msg << args.shift if msg.size == 1
177
+ if subject
178
+ msg << (color ? sub_style(subject, :underline) : subject)
179
+ else
180
+ msg += args
181
+ args.clear
182
+ end
179
183
  message(msg.join(' '), *args, hint: hint)
180
184
  end
181
185
  end
@@ -185,7 +189,7 @@ module Squared
185
189
  begin
186
190
  File.open(pipe, 'a') do |f|
187
191
  br = File::SEPARATOR == '\\' ? "\r\n" : "\n"
188
- args.flatten.each { |val| f.write("#{strip_style(val.chomp)}#{br}") }
192
+ args.flatten.each { |val| f.write(strip_style(val.chomp) + br) }
189
193
  end
190
194
  return
191
195
  rescue StandardError
@@ -257,8 +261,6 @@ module Squared
257
261
  yield out
258
262
  elsif pipe
259
263
  case pipe
260
- when -1
261
- return out
262
264
  when 0
263
265
  pipe = $stdin
264
266
  when 2
@@ -276,12 +278,8 @@ module Squared
276
278
  val.gsub(/\x1B\[(\d+;?)+m/, '')
277
279
  end
278
280
 
279
- def stripext(val)
280
- File.basename(val, File.extname(val))
281
- end
282
-
283
281
  def raise_error(*args, hint: nil, kind: ArgumentError)
284
- raise kind, message(*args, hint: hint, empty: true), caller_locations(1).map(&:to_s)
282
+ raise kind, message(*args, hint: hint, empty: true), caller_locations(1)
285
283
  end
286
284
  end
287
285
  end
@@ -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