squared 0.6.16 → 0.7.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.
@@ -6,35 +6,26 @@ module Squared
6
6
  include Enumerable
7
7
  include Common::Format
8
8
  include Utils
9
- include Support::Variables
10
9
  include Rake::DSL
11
10
 
12
11
  TASK_METADATA = Rake::TaskManager.record_task_metadata
13
12
  private_constant :TASK_METADATA
14
13
 
15
14
  class << self
16
- def implement(*objs, base: false)
17
- return if base && objs.size > 1
18
-
19
- objs.each do |obj|
20
- next unless base || obj < impl_project
21
-
22
- if base
23
- self.impl_project = obj
24
- impl_series.base_set(obj)
25
- else
26
- kind_project.unshift(obj)
27
- impl_series.extend_set(obj)
28
- end
29
- if (args = obj.batchargs)
30
- impl_series.batch(*args)
31
- end
32
- if (args = obj.aliasargs)
33
- impl_series.alias(*args)
34
- end
35
- if (args = obj.bannerargs)
36
- attr_banner.merge(args)
15
+ def implement(*objs, base: nil)
16
+ objs.each_with_index do |obj, index|
17
+ if base && index == 0
18
+ case base
19
+ when 0, true
20
+ @kind_extend[0] = obj
21
+ next
22
+ when 1
23
+ @kind_extend.insert(1, obj)
24
+ else
25
+ @kind_extend.push(obj)
26
+ end
37
27
  end
28
+ kind_project.unshift(obj) if extends(obj)
38
29
  end
39
30
  end
40
31
 
@@ -42,17 +33,14 @@ module Squared
42
33
  if ref && (ret = kind_project.find { |proj| proj.ref == ref })
43
34
  ret
44
35
  elsif path
45
- kind_project.find { |proj| proj.config?(path) }
36
+ (kind_project - @kind_extend).find { |proj| proj.config?(path) } ||
37
+ @kind_extend.find { |proj| proj.config?(path) }
46
38
  end
47
39
  end
48
40
 
49
- def exclude(*args)
50
- @task_exclude.merge(args.map!(&:to_sym))
51
- end
52
-
53
- def register(app)
41
+ def register(app, base, exclude: [])
54
42
  @session << app
55
- impl_series.new(app, exclude: @task_exclude.to_a)
43
+ impl_series.new(app, (@kind_extend + base).uniq, exclude: exclude.map(&:to_sym))
56
44
  end
57
45
 
58
46
  def load_ref(path, gem: nil)
@@ -65,14 +53,23 @@ module Squared
65
53
  break
66
54
  end
67
55
  end
68
- dir = if gem.match?(/-\d+(?:\.|$)/)
56
+ dir = if gem.match?(/-\d+(\.|$)/)
69
57
  gem
70
58
  else
71
59
  Dir.glob("#{gem}-*", base: @gemsdir).pop
72
60
  end
73
61
  path = File.join(@gemsdir, dir, path) if dir
74
62
  end
75
- @load_project.unshift(path.cleanpath.to_s) if (path = Pathname.new(path)).absolute? && path.exist?
63
+ path = Pathname.new(path)
64
+ @load_project.unshift(path.cleanpath.to_s) if path.absolute? && path.exist?
65
+ end
66
+
67
+ def extends(obj)
68
+ @kind_extend.any? { |impl| obj < impl }
69
+ end
70
+
71
+ def impl_project
72
+ @kind_extend.first
76
73
  end
77
74
 
78
75
  def baseref
@@ -83,46 +80,42 @@ module Squared
83
80
  super[/[^:]+\z/, 0]
84
81
  end
85
82
 
86
- alias series_wrap register
87
-
88
- attr_reader :kind_project, :load_project, :session
89
- attr_accessor :impl_series, :impl_project, :attr_banner
83
+ attr_reader :kind_project, :load_project, :attr_banner, :session
84
+ attr_accessor :impl_series
90
85
  end
91
86
 
92
87
  @kind_project = []
93
88
  @load_project = [File.expand_path('project', __dir__)]
89
+ @attr_banner = Set.new
90
+ @kind_extend = []
94
91
  @session = []
95
- @task_exclude = Set.new
96
92
 
97
93
  attr_reader :root, :home, :main, :prefix, :theme, :series, :closed
98
94
  attr_accessor :exception, :pipe, :verbose, :warning
99
95
 
100
96
  def initialize(home = (ARG[:HOME] && ENV[ARG[:HOME]]) || Dir.pwd, *, main: nil, prefix: nil,
101
97
  verbose: ARG[:VERBOSE], common: ARG[:COMMON], pipe: ARG[:PIPE], exception: ARG[:FAIL], **)
102
- @home = Pathname.new(home).realdirpath
103
- basename = @home.basename.to_s
98
+ home = Pathname.new(home)
99
+ basename = home.basename.to_s
104
100
  if main
105
101
  @main = main.to_s.freeze
106
- @home += @main unless @main == basename || (windows? && @main.casecmp?(basename))
102
+ home += @main unless @main == basename || (windows? && @main.casecmp?(basename))
107
103
  else
108
104
  @main = basename.freeze
109
105
  end
110
- @home.mkpath rescue nil
111
- @root = @home.parent
112
106
  @prefix = prefix
113
- @series = Application.register(self)
114
107
  @project = {}
115
- @kind = hashlist
116
- @extensions = []
108
+ @base = Set.new
109
+ @kind = Support.hashlist
110
+ @config = {}
111
+ @extensions = Set.new
112
+ @finalize = Set.new([:__chain__])
117
113
  @envname = env_key(@main).freeze
114
+ @closed = false
115
+ @stage = Support.hashlist
116
+ self.home = home
118
117
  self.exception = env_bool exception
119
- self.pipe = if $DEBUG
120
- 2
121
- elsif (out = ARG[:OUT]) && out.include?(File::SEPARATOR)
122
- env_pipe(out, pipe, root: home)
123
- else
124
- env_pipe(pipe, (out && env(out)) || 1, root: home)
125
- end
118
+ self.pipe = $DEBUG ? 2 : env_pipe(pipe, (ARG[:OUT] && env(ARG[:OUT])) || 1, root: home)
126
119
  self.verbose = if $VERBOSE.nil?
127
120
  false
128
121
  elsif verbose.nil?
@@ -131,102 +124,93 @@ module Squared
131
124
  env_bool(verbose, verbose.is_a?(String) ? @pipe != 0 : verbose, index: true)
132
125
  end
133
126
  self.warning = @verbose != false
134
- @closed = false
135
- @theme = if common
136
- ARG[:COLOR] = false if @pipe == 0 || @pipe.is_a?(Pathname)
137
- __get__(:theme)[:workspace]
138
- else
139
- {}
140
- end
141
- @chain = hashlist
142
- @script = {
143
- group: hashobj,
144
- ref: hashobj,
145
- group!: {},
146
- ref!: {}
147
- }.freeze
148
- @events = {
149
- group: hashobj,
150
- ref: hashobj
151
- }.freeze
152
- @pass = {
153
- group: hashobj,
154
- ref: hashobj,
155
- global: {},
156
- pattern: []
157
- }.freeze
158
- @banner = {
159
- group: {},
160
- ref: {}
161
- }.freeze
127
+ @theme = common ? __get__(:theme)[:workspace] : {}
128
+ @chain = Support.hashlist
129
+ @script = Struct::SessionData.new
130
+ @events = Struct::SessionData.new
131
+ @pass = Struct::SessionData.new
132
+ @banner = Struct::SessionData.new
133
+ @timeout = Struct::SessionData.new
134
+ @global = Hash.new do |data, key|
135
+ data[key] = { group: {}, ref: {}, exclude: [], extras: {}, module: nil, script: nil }
136
+ end
162
137
  initialize_session
163
138
  end
164
139
 
165
- def initialize_session
166
- return unless @pipe.is_a?(Pathname)
167
-
168
- msg = "Session started on #{Time.now} by #{@main}"
169
- bord = '#' * msg.size
170
- puts bord, msg, bord
171
- end
172
-
173
140
  def each(&blk)
174
141
  return to_enum(:each) unless block_given?
175
142
 
176
143
  @project.each_value(&blk)
177
144
  end
178
145
 
179
- def build(parallel: [], pass: nil, **kwargs)
146
+ def build(parallel: [], **kwargs)
180
147
  return self unless enabled? && !@closed
181
148
 
149
+ self.closed = 'init'
182
150
  kwargs[:parallel] = if kwargs[:pattern].is_a?(Array)
183
151
  parallel.map(&:to_s)
184
152
  else
185
153
  kwargs[:pattern] = []
186
- parallel.reject { |val| kwargs[:pattern] << val if val.is_a?(Regexp) }.map!(&:to_s)
154
+ parallel.reject { |val| kwargs[:pattern] << val if val.is_a?(Regexp) }.map(&:to_s)
187
155
  end
188
- @pass[:pattern].concat(pass.map { |val| val.is_a?(Regexp) ? val : val.to_s }) if pass
189
- series.reset
156
+ @pass.items.concat(kwargs[:pass].map { |val| val.is_a?(Regexp) ? val : val.to_s }) if kwargs[:pass]
157
+ @series = Application.register(self, @base.to_a, exclude: kwargs.fetch(:exclude, []))
158
+ self.closed = 'begin'
159
+ pb = @stage.key?('project:begin')
160
+ pe = @stage.key?('project:end')
161
+ keys = @series.keys
190
162
  each do |proj|
163
+ self.closed = ['project:begin', proj] if pb
191
164
  if proj.enabled?
192
- proj.populate(series.keys.dup, **kwargs)
165
+ proj.populate(keys.dup, **kwargs)
193
166
  elsif proj.enabled?(base: false)
194
167
  proj.generate([], **kwargs)
195
168
  else
196
169
  next
197
170
  end
198
- series.populate(proj, **kwargs)
171
+ @series.populate(proj, **kwargs)
172
+ self.closed = ['project:end', proj] if pe
199
173
  end
200
- Application.kind_project.each { |obj| obj.populate(self, **kwargs) }
201
- @extensions.uniq.each { |ext| __send__(ext, **kwargs) }
202
- series.build(**kwargs)
174
+ self.closed = 'populate'
175
+ @base.each { |obj| obj.populate(self, **kwargs) }
176
+ self.closed = 'extensions'
177
+ @extensions.each { |ext| __send__(ext, **kwargs) }
178
+ self.closed = 'series'
179
+ @series.build(**kwargs)
203
180
  __build__(**kwargs)
204
- yield self if block_given?
205
- __chain__(**kwargs)
181
+ if block_given?
182
+ self.closed = 'yield:begin'
183
+ yield self
184
+ self.closed = 'yield:end'
185
+ end
186
+ self.closed = 'finalize'
187
+ @finalize.each { |ext| __send__(ext, **kwargs) }
188
+ self.closed = 'end'
206
189
  @closed = true
207
190
  self
208
191
  end
209
192
 
210
- def with(*val, hide: nil, group: nil, **kwargs, &blk)
211
- if hide.nil? && kwargs.key?(:pass)
212
- pass = kwargs[:pass]
213
- case pass
214
- when true, false
215
- hide = pass
216
- kwargs.delete(:pass)
217
- else
218
- hide, pass = Array(pass).partition { |s| respond_to?(s) || s.to_s.end_with?('?') }
219
- if pass.empty?
220
- kwargs.delete(:pass)
221
- elsif hide.empty?
222
- hide = nil
223
- else
224
- kwargs[:pass] = pass
193
+ def with(*val, hide: false, group: nil, **kwargs, &blk)
194
+ if hide
195
+ return self if hide == true
196
+
197
+ Array(hide).each do |args|
198
+ if args.is_a?(Array)
199
+ if respond_to?(hint = args.first)
200
+ next unless __send__(*args)
201
+
202
+ return self
203
+ end
204
+ elsif respond_to?(args)
205
+ next unless __send__(args)
206
+
207
+ return self
225
208
  end
209
+ raise_error 'method not found'
210
+ rescue => e
211
+ warn log_message(Logger::WARN, e, subject: main, hint: hint || args)
226
212
  end
227
213
  end
228
- return self if hide == true || (hide && Array(hide).any? { |s| respond_to?(s) && __send__(s) rescue nil })
229
-
230
214
  @group = nil
231
215
  @ref = nil
232
216
  @withargs = unless kwargs.empty?
@@ -242,7 +226,7 @@ module Squared
242
226
  when Symbol
243
227
  @ref = val
244
228
  else
245
- raise_error ArgumentError, 'missing group or ref' if block_given?
229
+ raise_error TypeError, "not a group/ref: #{kind || 'nil'}" if block_given?
246
230
  end
247
231
  if block_given?
248
232
  instance_eval(&blk)
@@ -259,18 +243,18 @@ module Squared
259
243
 
260
244
  def chain(task, *action, project: nil, step: 0, with: nil, before: nil, after: nil, sync: false,
261
245
  group: @group, ref: @ref)
262
- if project
263
- action.map! { |val| task_join(project.name, val) }
264
- elsif (target = group || ref)
265
- action.map! { |val| task_name(task_join(val, target)) }
266
- else
267
- action.map! { |val| task_name(val) }
268
- keys = @project.keys unless prefix
269
- end
246
+ tasks = if project
247
+ action.map { |val| task_join(project.name, val) }
248
+ elsif (target = group || ref)
249
+ action.map { |val| task_name(task_join(val, target)) }
250
+ else
251
+ keys = @project.keys unless prefix
252
+ action.map { |val| task_name(val) }
253
+ end
270
254
  ns = lambda do |val|
271
255
  return if (ret = as_a(val, :to_s, flat: true)).empty?
272
256
 
273
- ret.map! do |arg|
257
+ ret.map do |arg|
274
258
  if arg.include?(':') || (keys && !keys.include?(arg))
275
259
  task_name(arg)
276
260
  else
@@ -278,7 +262,7 @@ module Squared
278
262
  end
279
263
  end
280
264
  end
281
- data = Struct::ChainData.new(action, step, ns.call(with), ns.call(before), ns.call(after), sync)
265
+ data = Struct::ChainData.new(tasks, step, ns.call(with), ns.call(before), ns.call(after), sync)
282
266
  @chain[task_name(task.to_s)] << data
283
267
  self
284
268
  end
@@ -321,18 +305,18 @@ module Squared
321
305
 
322
306
  def pass(name, group: @group, ref: @ref, &blk)
323
307
  data = if group
324
- @pass[:group][group.to_s]
308
+ @pass.group[group.to_s]
325
309
  elsif ref
326
- @pass[:ref][ref.to_sym]
310
+ @pass.ref[ref.to_sym]
327
311
  else
328
- @pass[:global]
312
+ @pass.store
329
313
  end
330
314
  data[name.to_sym] = blk
331
315
  self
332
316
  end
333
317
 
334
318
  def banner(*args, command: true, styles: nil, border: nil, group: @group, ref: @ref)
335
- data = Struct::BannerData.new(command, [], check_style(styles, empty: false), check_style(border))
319
+ data = Struct::BannerData.new(command, check_style(styles, empty: false), check_style(border))
336
320
  args.each do |meth|
337
321
  if meth.is_a?(Array)
338
322
  found = false
@@ -340,7 +324,7 @@ module Squared
340
324
  case val
341
325
  when Symbol
342
326
  found = true
343
- Application.attr_banner.include?(val)
327
+ banner_include?(val)
344
328
  when String
345
329
  true
346
330
  else
@@ -352,7 +336,7 @@ module Squared
352
336
  elsif meth.size == 1
353
337
  meth = meth.first
354
338
  end
355
- elsif !Application.attr_banner.include?(meth = meth.to_sym)
339
+ elsif !banner_include?(meth = meth.to_sym)
356
340
  next
357
341
  end
358
342
  data.order << meth
@@ -367,8 +351,29 @@ module Squared
367
351
  self
368
352
  end
369
353
 
354
+ def timeout(data, group: @group, ref: @ref)
355
+ if group
356
+ @timeout.group[group.to_s].update(data)
357
+ elsif ref
358
+ @timeout.ref[ref.to_sym].update(data)
359
+ else
360
+ @timeout.store.update(data)
361
+ end
362
+ self
363
+ end
364
+
365
+ def batch(*args)
366
+ (@config[:batch] ||= []) << args
367
+ self
368
+ end
369
+
370
+ def rename(task, val)
371
+ (@config[:rename] ||= {})[task.to_sym] = val.to_s
372
+ self
373
+ end
374
+
370
375
  def add(path, project = nil, **kwargs, &blk)
371
- kwargs = hashdup(@withargs).update(kwargs) if @withargs
376
+ kwargs = Support.hashdup(@withargs).update(kwargs) if @withargs
372
377
  ref = kwargs.key?(:ref) ? kwargs.delete(:ref) : @ref
373
378
  kwargs[:group] = @group if @group && !kwargs.key?(:group)
374
379
  path = rootpath path
@@ -379,12 +384,20 @@ module Squared
379
384
  index += 1
380
385
  name = task_name "#{project}-#{index}"
381
386
  end
382
- proj = ((if !ref.is_a?(Class)
383
- require_project ref
384
- Application.find(ref, path: path)
385
- elsif ref < Application.impl_project
387
+ unless ref.is_a?(Symbol) && (proj = @base.find { |item| item.ref == ref })
388
+ proj = if !ref.is_a?(Class)
389
+ require_project(ref) || Application.find(ref, path: path)
390
+ elsif Application.extends(ref)
386
391
  ref
387
- end) || @kind[name]&.last || Application.impl_project).new(self, path, name, **kwargs)
392
+ end || @kind[name]&.last
393
+ if proj
394
+ @base << proj
395
+ @banner.items.concat(Array(proj.bannerargs))
396
+ else
397
+ proj = Application.impl_project
398
+ end
399
+ end
400
+ proj = proj.new(self, path, name, **kwargs)
388
401
  proj.__send__(:index_set, size)
389
402
  @project[name] = proj
390
403
  __get__(:project)[name] = proj unless kwargs[:private]
@@ -393,7 +406,7 @@ module Squared
393
406
  end
394
407
 
395
408
  def group(path, val, override: {}, **kwargs, &blk)
396
- rootpath(path).children.map! do |dir|
409
+ rootpath(path).children.map do |dir|
397
410
  next unless dir.directory?
398
411
 
399
412
  basename = dir.basename.to_s
@@ -417,6 +430,18 @@ module Squared
417
430
  self
418
431
  end
419
432
 
433
+ def stage(val, first: false, &blk)
434
+ data = @stage[val]
435
+ if first == true
436
+ data.unshift(blk)
437
+ elsif first.is_a?(Numeric) && first < data.size
438
+ data.insert(first, blk)
439
+ else
440
+ data.push(blk)
441
+ end
442
+ self
443
+ end
444
+
420
445
  def style(obj, *args, target: nil, empty: false)
421
446
  data = nil
422
447
  if target
@@ -431,7 +456,7 @@ module Squared
431
456
  if obj.is_a?(String)
432
457
  obj = begin
433
458
  JSON.parse(homepath(obj).read, { symbolize_names: true })
434
- rescue StandardError => e
459
+ rescue => e
435
460
  warn log_message(Logger::ERROR, e)
436
461
  end
437
462
  end
@@ -447,7 +472,7 @@ module Squared
447
472
  }
448
473
  data.each do |key, val|
449
474
  key = key.to_s
450
- if key.start_with?(/(\\A|\^)/) || key.match?(/(\\z|\$)\z/)
475
+ if key.start_with?('\A', '^') || key.end_with?('\z', '$')
451
476
  @describe[:replace] << [Regexp.new(key), val]
452
477
  else
453
478
  @describe[val.is_a?(Regexp) ? :pattern : :alias][key] = val
@@ -489,7 +514,7 @@ module Squared
489
514
  end
490
515
 
491
516
  def find_base(obj)
492
- Application.kind_project.find { |proj| obj.instance_of?(proj) }
517
+ @base.find { |proj| obj.instance_of?(proj) }
493
518
  end
494
519
 
495
520
  def task_name(val)
@@ -530,7 +555,7 @@ module Squared
530
555
  break
531
556
  end
532
557
  end
533
- args = split_escape(val, char: ':').map! { |s| s.gsub('\\:', ':') } if found
558
+ args = split_escape(val, char: ':').map { |s| s.gsub('\\:', ':') } if found
534
559
  end
535
560
  desc message(*args, **kwargs)
536
561
  end
@@ -547,7 +572,7 @@ module Squared
547
572
  tasks << key if obj.has?(key, baseref)
548
573
  elsif (batch = series.batch_get(key))
549
574
  obj.allref do |ref|
550
- next unless obj.has?(key, ref) && (data = batch[ref])
575
+ next unless obj.has?(key, ref, missing: series.missing?(ref, key)) && (data = batch[ref])
551
576
 
552
577
  data.each do |val|
553
578
  if (items = task_resolve(obj, val)).empty?
@@ -607,29 +632,55 @@ module Squared
607
632
  out ? message(*val) : task_desc(*val)
608
633
  end
609
634
 
610
- def script_find(*args)
635
+ def script_find(*args, name: nil)
636
+ target = @global[name || '_']
637
+ group, ref, exclude = target.fetch_values(:group, :ref, :exclude)
638
+ ret = nil
611
639
  args.reverse_each do |val|
612
- if val && (ret = val.is_a?(Symbol) ? @script[:ref!][val] : @script[:group!][val.to_sym])
613
- return ret
640
+ next unless val
641
+
642
+ if exclude.include?(val)
643
+ ret = nil
644
+ break
645
+ elsif ret
646
+ next
647
+ elsif (ret = val.is_a?(Symbol) ? ref[val] : group[val]) && exclude.empty?
648
+ break
614
649
  end
615
650
  end
616
- @script[:ref!][:''] ||= scriptobj
651
+ ret || (target[:script] ||= scriptobj)
617
652
  end
618
653
 
619
654
  def script_get(*args, group: nil, ref: nil)
620
- data_get(*args, group: group, ref: ref, target: @script)
655
+ data_get(*args, target: @script, group: group, ref: ref)
621
656
  end
622
657
 
623
658
  def events_get(*args, group: nil, ref: nil)
624
- data_get(*args, group: group, ref: ref, target: @events)
659
+ data_get(*args, target: @events, group: group, ref: ref)
625
660
  end
626
661
 
627
662
  def banner_get(*ref, group: nil)
628
- ret = nil
629
- return ret if group && (ret = @banner[:group][group.to_sym])
663
+ if group && @banner.group.key?(group = group.to_sym)
664
+ @banner.group[group]
665
+ else
666
+ ref.reverse_each do |val|
667
+ next unless @banner.ref.key?(val)
630
668
 
631
- ref.reverse_each { |val| return ret if (ret = @banner[:ref][val]) }
632
- @banner[:ref][:_]
669
+ return @banner.ref[val]
670
+ end
671
+ @banner.ref[:_] if @banner.ref.key?(:_)
672
+ end
673
+ end
674
+
675
+ def timeout_get(*ref, group: nil)
676
+ ret = @timeout.store.dup
677
+ ref.each { |val| ret.update(@timeout.ref[val]) if @timeout.ref.key?(val) }
678
+ ret.update(@timeout.group[group]) if group && @timeout.group.key?(group)
679
+ ret
680
+ end
681
+
682
+ def config_get(key, default = nil, &blk)
683
+ @config.fetch(key, block_given? ? blk : default)
633
684
  end
634
685
 
635
686
  def enabled?
@@ -652,13 +703,13 @@ module Squared
652
703
 
653
704
  def task_exclude?(key, obj = nil)
654
705
  if obj
655
- data = obj.group ? @pass[:group][obj.group] : @pass[:ref][obj.ref]
656
- blk = (data && data[key.to_sym]) || @pass[:global][key.to_sym]
706
+ data = obj.group ? @pass.group[obj.group] : @pass.ref[obj.ref]
707
+ blk = (data && data[key.to_sym]) || @pass.store[key.to_sym]
657
708
  return true if blk && obj.instance_eval(&blk)
658
709
 
659
710
  key = task_join(task_localname(obj.name), key)
660
711
  end
661
- @pass[:pattern].any? { |item| item.is_a?(Regexp) ? key.to_s.match?(item) : key == item }
712
+ @pass.items.any? { |item| item.is_a?(Regexp) ? item.match?(key) : item == key }
662
713
  end
663
714
 
664
715
  def task_defined?(*key)
@@ -745,18 +796,43 @@ module Squared
745
796
 
746
797
  private
747
798
 
748
- def __build__(default: nil, **)
749
- unless task_defined?('squared:version')
750
- task 'squared:version' do
751
- puts Squared::VERSION
752
- end
753
- end
754
- if default && task_defined?(out = task_name(default))
755
- task Rake.application.default_task_name => out
799
+ def initialize_session
800
+ return unless @pipe.is_a?(Pathname)
801
+
802
+ msg = "Session started on #{Time.now} by #{@main}"
803
+ bord = '#' * msg.size
804
+ puts bord, msg, bord
805
+ end
806
+
807
+ def home=(val)
808
+ return if @closed
809
+
810
+ @home = Pathname.new(val).realdirpath
811
+ @root = @home.parent
812
+ @home.mkpath rescue nil
813
+ end
814
+
815
+ def closed=(val)
816
+ if val.is_a?(Array)
817
+ val, target = val
818
+ else
819
+ target = self
756
820
  end
821
+ @closed = val
822
+ @stage[val].each { |blk| target.instance_eval(&blk) } if @stage.key?(val)
823
+ end
824
+
825
+ def __build__(*, default: nil, **)
826
+ self.closed = 'build:begin'
827
+ task('squared:version') { puts Squared::VERSION } unless task_defined?('squared:version')
828
+ task Rake.application.default_task_name => task_name(default) if default && task_defined?(task_name(default))
829
+ self.closed = 'build:end'
757
830
  end
758
831
 
759
832
  def __chain__(*)
833
+ return if @chain.empty?
834
+
835
+ self.closed = 'chain:begin'
760
836
  @chain.each do |key, group|
761
837
  level = []
762
838
  sync = []
@@ -867,13 +943,14 @@ module Squared
867
943
  end
868
944
  end
869
945
  end
946
+ self.closed = 'chain:end'
870
947
  end
871
948
 
872
949
  def puts(*args, **kwargs)
873
950
  log_console(*args, pipe: kwargs[:pipe] || pipe)
874
951
  end
875
952
 
876
- def script_command(task, val, group, ref, on = nil, &blk)
953
+ def script_command(task, val, group, ref, on, &blk)
877
954
  if block_given?
878
955
  val = Struct::RunData.new(val, blk)
879
956
  elsif !val
@@ -884,7 +961,7 @@ module Squared
884
961
  as_a group, :to_sym
885
962
  else
886
963
  label = :ref
887
- as_a(ref || :_, :to_sym)
964
+ as_a ref, :to_sym
888
965
  end.each do |name|
889
966
  @script[label][name][task] = val
890
967
  @events[label][name][task] = on if on.is_a?(Hash)
@@ -892,18 +969,39 @@ module Squared
892
969
  self
893
970
  end
894
971
 
895
- def script_set(data, group: nil, ref: nil)
972
+ def script_set(from, data, name: nil, extras: nil, group: nil, ref: nil)
973
+ target = @global[name || '_']
974
+ target[:module] = from
975
+ target[:extras].update(extras) if extras
896
976
  data.freeze
897
977
  if group
898
- Array(group).each { |val| @script[:group!][val.to_sym] = data }
978
+ Array(group).each do |val|
979
+ val = val.to_s
980
+ if val.start_with?('-')
981
+ target[:exclude] << val[1..-1]
982
+ else
983
+ target[:group][val] = data
984
+ end
985
+ end
899
986
  elsif ref
900
- Array(ref).each { |val| @script[:ref!][val.to_sym] = data }
987
+ Array(ref).each do |val|
988
+ val = val.to_s
989
+ if val.start_with?('-')
990
+ target[:exclude] << val[1..-1].to_sym
991
+ else
992
+ target[:ref][val.to_sym] = data
993
+ end
994
+ end
901
995
  else
902
- @script[:ref!][:''] = data
996
+ target[:script] = data
903
997
  end
904
998
  end
905
999
 
906
- def data_get(*args, group: nil, ref: nil, target: nil)
1000
+ def script_each(from, &blk)
1001
+ @global.select { |_, data| data[:module] == from }.each(&blk)
1002
+ end
1003
+
1004
+ def data_get(*args, target:, group: nil, ref: nil)
907
1005
  if group && target[:group].key?(key = group.to_sym)
908
1006
  target[:group][key]
909
1007
  elsif ref.is_a?(Enumerable)
@@ -916,39 +1014,37 @@ module Squared
916
1014
  nil
917
1015
  elsif ref && target[:ref].key?(ref)
918
1016
  target[:ref][ref]
919
- else
920
- target[:ref][:_]
921
1017
  end
922
1018
  end
923
1019
 
924
1020
  def require_project(ref)
925
- return unless ref.is_a?(Symbol) && Application.kind_project.none? { |proj| proj.ref == ref }
1021
+ ret = Application.kind_project.find { |proj| proj.ref == ref }
1022
+ return ret if ret
926
1023
 
927
- name = ref.to_s
928
- Application.load_project.each do |val|
929
- next unless File.exist?("#{rb = File.join(val, name)}.rb")
1024
+ Application.load_project.each do |dir|
1025
+ next unless File.exist?("#{rb = File.join(dir, ref.to_s)}.rb")
930
1026
 
931
1027
  require_relative rb
932
1028
  break
933
1029
  end
934
- nil
935
1030
  end
936
1031
 
937
1032
  def root?(path, pass: [])
938
1033
  return false unless path.directory?
939
1034
 
940
- path.each_child do |c|
941
- name = c.basename.to_s
942
- unless c.to_s == __FILE__ || (@main == name && c.directory? && c.empty?) || pass.any? { |val| val == name }
1035
+ path.each_child do |file|
1036
+ s = file.basename.to_s
1037
+ unless file.to_s == __FILE__ || (@main == s && file.directory? && file.empty?) || pass.any? { |val| val == s }
943
1038
  return false
944
1039
  end
945
1040
  end
946
1041
  true
947
1042
  end
948
1043
 
949
- def script?(state, target: nil, pat: nil, group: nil, ref: baseref, global: false, script: true)
950
- data = script_find ref, group
951
- type = script ? :script : :run
1044
+ def script?(state, name: nil, target: nil, pat: nil, group: nil, ref: baseref, type: nil, script: true,
1045
+ global: false)
1046
+ data = script_find(ref, group, name: name)
1047
+ type ||= script ? :script : :run
952
1048
  if global
953
1049
  target = data[type] if target.nil?
954
1050
  pat = data[state] if pat.nil?
@@ -958,13 +1054,23 @@ module Squared
958
1054
  target && pat.is_a?(Regexp) ? Array(target).any?(pat) : pat == true
959
1055
  end
960
1056
 
1057
+ def banner_include?(val)
1058
+ Application.attr_banner.include?(val) || @banner.items.include?(val)
1059
+ end
1060
+
961
1061
  def scriptobj
962
1062
  {
963
1063
  run: nil,
964
1064
  script: nil,
965
1065
  dev: nil,
966
1066
  prod: nil,
967
- global: {},
1067
+ global: {
1068
+ script: false,
1069
+ run: false,
1070
+ doc: false,
1071
+ lint: false,
1072
+ test: false
1073
+ },
968
1074
  env: {}
969
1075
  }
970
1076
  end