squared 0.0.10 → 0.0.12

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.
@@ -3,8 +3,8 @@
3
3
  module Squared
4
4
  module Workspace
5
5
  class Application
6
- include Common
7
- include Format
6
+ include Common::Format
7
+ include Utils
8
8
  include ::Rake::DSL
9
9
 
10
10
  SCRIPT_OBJ = {
@@ -20,54 +20,63 @@ module Squared
20
20
  class << self
21
21
  def implement(*objs)
22
22
  objs.each do |obj|
23
- if obj < Project::Base
24
- @impl_project.unshift(obj)
25
- obj.tasks&.each { |task| @impl_series.add(task, obj) }
26
- elsif obj < Workspace::Series
27
- @impl_series = obj
23
+ next unless obj < impl_project
24
+
25
+ kind_project.unshift(obj)
26
+ obj.tasks&.each { |task| impl_series.add(task, obj) }
27
+ if (args = obj.batchargs)
28
+ impl_series.batch(*args)
29
+ end
30
+ if (args = obj.aliasargs)
31
+ impl_series.alias(*args)
32
+ end
33
+ if (args = obj.bannerargs)
34
+ @attr_banner += args
28
35
  end
29
36
  end
30
37
  end
31
38
 
32
39
  def find(ref = nil, path: nil)
33
- if ref && (ret = impl_project.find { |proj| proj.ref == ref.to_sym })
40
+ if ref && (ret = kind_project.find { |proj| proj.ref == ref })
34
41
  ret
35
42
  elsif path
36
- impl_project.find { |proj| proj.is_a?(path) }
43
+ kind_project.find { |proj| proj.config?(path) }
37
44
  end
38
45
  end
39
46
 
47
+ def baseref
48
+ impl_project.ref
49
+ end
50
+
40
51
  def to_s
41
- super.to_s.match(/[^:]+$/)[0]
52
+ super.match(/[^:]+$/)[0]
42
53
  end
43
54
 
44
- attr_reader :impl_project, :impl_series
55
+ attr_reader :kind_project
56
+ attr_accessor :impl_series, :impl_project, :attr_banner
45
57
  end
46
58
 
47
- @impl_project = []
48
- @impl_series = Workspace::Series
59
+ @kind_project = []
49
60
 
50
- attr_reader :root, :home, :main, :prefix, :series, :theme
51
- attr_accessor :exception, :pipe, :verbose, :warning
61
+ attr_reader :root, :home, :main, :prefix, :exception, :warning, :pipe, :verbose, :theme, :series, :closed
52
62
 
53
- def initialize(home = Dir.pwd, *,
54
- main: nil, prefix: nil, verbose: nil,
55
- common: Common::KEY[:COMMON], pipe: Common::KEY[:PIPE], exception: Common::KEY[:FAIL], **)
56
- @home = (home = Pathname.new(home)).realdirpath
57
- @main = (main || home.basename).to_s
63
+ def initialize(home = Dir.pwd, *, main: nil, prefix: nil,
64
+ verbose: ARG[:VERBOSE], common: ARG[:COMMON], pipe: ARG[:PIPE], exception: ARG[:FAIL], **)
65
+ @home = Pathname.new(home).realdirpath
58
66
  @root = @home.parent
67
+ @main = (main || @home.basename).to_s.freeze
59
68
  @prefix = prefix
60
69
  @series = Application.impl_series.new(self)
61
70
  @project = {}
62
71
  @extensions = []
63
- @pipe = env_pipe(pipe)
72
+ @pipe = env_pipe(pipe, (ARG[:OUT] && env(ARG[:OUT])) || 1, root: @home)
64
73
  @exception = env_bool(exception)
65
- @verbose = verbose.nil? ? @pipe > 0 : verbose
74
+ @verbose = env_bool(verbose, verbose.nil? || verbose.is_a?(::String) ? @pipe != 0 : verbose)
66
75
  @warning = @verbose != false
67
- @envname = @main.gsub(/[^\w]+/, '_').upcase
76
+ @closed = false
68
77
  if common
69
78
  @theme = __get__(:theme)[:workspace]
70
- __set__(:no_color, true) if @pipe == 0
79
+ ARG[:COLOR] = false if @pipe == 0 || @pipe.is_a?(::Pathname)
71
80
  else
72
81
  @theme = {}
73
82
  end
@@ -81,46 +90,59 @@ module Squared
81
90
  group: {},
82
91
  ref: {}
83
92
  }.freeze
93
+ initialize_session
84
94
  end
85
95
 
86
- def build(**kwargs)
87
- kwargs[:parallel] = kwargs.fetch(:parallel, []).map(&:to_s)
88
- return unless enabled?
96
+ def initialize_session
97
+ @envname = @main.gsub(/[^\w]+/, '_').upcase.freeze
98
+ return unless @pipe.is_a?(::Pathname)
99
+
100
+ bord = '#' * Project.line_width
101
+ puts bord, format('Session started on %s by %s', Time.now.to_s, @main), bord
102
+ end
89
103
 
104
+ def build(parallel: [], **kwargs)
105
+ return self unless enabled? && !@closed
106
+
107
+ kwargs[:parallel] = parallel.map(&:to_s)
90
108
  @project.each_value do |proj|
91
109
  next unless proj.enabled?
92
110
 
93
111
  proj.populate(**kwargs)
94
- series.__populate__(proj)
112
+ series.populate(proj)
95
113
  end
96
114
 
97
- Application.impl_project.each { |obj| obj.populate(self, **kwargs) }
115
+ Application.kind_project.each { |obj| obj.populate(self, **kwargs) }
98
116
  @extensions.each { |ext| __send__(ext, **kwargs) }
99
117
 
100
- series.__build__(**kwargs)
118
+ series.build(**kwargs)
101
119
  __build__(**kwargs)
102
120
 
103
121
  yield self if block_given?
122
+ @closed = true
123
+ self
104
124
  end
105
125
 
106
- def with(*val, &blk)
126
+ def with(*val, group: nil, **kwargs, &blk)
107
127
  @group = nil
108
128
  @ref = nil
129
+ @withargs = kwargs.empty? ? nil : kwargs
130
+ val = as_a(group || kwargs[:ref], flat: true, compact: true) if val.empty?
109
131
  kind = val.first
110
132
  val = kind if val.size == 1
111
133
  case kind
112
134
  when ::String
113
135
  @group = val
114
- if block_given?
115
- instance_eval(&blk)
116
- @group = nil
117
- end
118
136
  when ::Symbol
119
137
  @ref = val
120
- if block_given?
121
- instance_eval(&blk)
122
- @ref = nil
123
- end
138
+ else
139
+ raise_error('group{Symbol} | ref{String}', hint: 'missing') if block_given?
140
+ end
141
+ if block_given?
142
+ instance_eval(&blk)
143
+ @group = nil
144
+ @ref = nil
145
+ @withargs = nil
124
146
  end
125
147
  self
126
148
  end
@@ -133,6 +155,10 @@ module Squared
133
155
  script_command :depend, script, group, ref
134
156
  end
135
157
 
158
+ def graph(script, group: @group, ref: @ref)
159
+ script_command :graph, as_a(script, :to_s).freeze, group, ref
160
+ end
161
+
136
162
  def clean(script, group: @group, ref: @ref)
137
163
  script_command :clean, script, group, ref
138
164
  end
@@ -153,48 +179,97 @@ module Squared
153
179
  script_command :exclude, as_a(base, :to_sym).freeze, group, ref
154
180
  end
155
181
 
156
- def add(path, name = nil, **kwargs, &blk)
182
+ def banner(*args, command: true, styles: nil, border: nil, group: @group, ref: @ref)
183
+ data = { command: command, order: [], styles: check_style(styles, empty: false), border: check_style(border) }
184
+ args.each do |meth|
185
+ if meth.is_a?(::Array)
186
+ found = false
187
+ meth = meth.select do |val|
188
+ case val
189
+ when ::Symbol
190
+ found = true
191
+ Application.attr_banner.include?(val)
192
+ when ::String
193
+ true
194
+ else
195
+ false
196
+ end
197
+ end
198
+ if !found
199
+ next
200
+ elsif meth.size == 1
201
+ meth = meth.first
202
+ end
203
+ elsif !Application.attr_banner.include?(meth = meth.to_sym)
204
+ next
205
+ end
206
+ data[:order] << meth
207
+ end
208
+ unless !command && data[:order].empty?
209
+ if group
210
+ label = :group
211
+ items = as_a(group)
212
+ else
213
+ label = :ref
214
+ items = ref ? as_a(ref) : %i[_]
215
+ end
216
+ items.each { |val| @banner[label][val.to_sym] = data }
217
+ end
218
+ self
219
+ end
220
+
221
+ def add(path, project = nil, **kwargs, &blk)
222
+ if @withargs
223
+ data = @withargs.dup
224
+ data.merge!(kwargs)
225
+ kwargs = data
226
+ end
157
227
  ref = if kwargs.key?(:ref)
228
+ kwargs = kwargs.dup unless @withargs
158
229
  kwargs.delete(:ref)
159
230
  elsif @ref.is_a?(::Symbol)
160
231
  @ref
161
232
  end
162
- kwargs[:group] = @group if !kwargs.key?(:group) && @group.is_a?(::String)
163
- path = root_path(path)
164
- name ||= path.basename.to_s
233
+ if @group.is_a?(::String) && !kwargs.key?(:group)
234
+ kwargs = kwargs.dup unless @withargs
235
+ kwargs[:group] = @group
236
+ end
237
+ path = rootpath(path)
238
+ project = (project || path.basename).to_s
239
+ name = task_name(project)
240
+ index = 0
241
+ while @project[name]
242
+ index += 1
243
+ name = "#{project}-#{index}"
244
+ end
165
245
  proj = ((if !ref.is_a?(::Class)
166
246
  Application.find(ref, path: path)
167
247
  elsif ref < Project::Base
168
248
  ref
169
- end) || Project::Base).new(task_name(name), path, self, **kwargs)
170
- @project[name = name.to_sym] = proj
249
+ end) || Project::Base).new(self, path, name, **kwargs)
250
+ @project[name] = proj
171
251
  __get__(:project)[name] = proj unless kwargs[:private]
172
252
  proj.instance_eval(&blk) if block_given?
173
253
  self
174
254
  end
175
255
 
176
- def group(path, name, override: {}, **kwargs)
177
- root_path(path).children.map do |ent|
178
- next unless (dir = Pathname.new(ent)).directory?
256
+ def group(path, val, override: {}, **kwargs, &blk)
257
+ rootpath(path).children.map do |dir|
258
+ next unless dir.directory?
179
259
 
180
- index = 0
181
- basename = dir.basename.to_s.to_sym
182
- while @project[basename]
183
- index += 1
184
- basename = :"#{basename}-#{index}"
185
- end
186
- [basename, dir, override[basename]]
260
+ basename = dir.basename.to_s
261
+ [dir, basename, override[basename.to_sym]]
187
262
  end
188
- .each do |basename, dir, opts|
263
+ .each do |dir, basename, opts|
189
264
  args = kwargs.dup
190
265
  args.merge!(opts) if opts
191
- add(basename, dir, group: name, **args)
266
+ add(dir, basename, group: val, **args, &blk)
192
267
  end
193
268
  self
194
269
  end
195
270
 
196
271
  def compose(name, &blk)
197
- namespace(task_name(name), &blk)
272
+ namespace(task_name(name), &blk) if block_given?
198
273
  self
199
274
  end
200
275
 
@@ -203,7 +278,7 @@ module Squared
203
278
  self
204
279
  end
205
280
 
206
- def style(name, *args, target: nil, empty: false)
281
+ def style(obj, *args, target: nil, empty: false)
207
282
  data = nil
208
283
  if target
209
284
  as_a(target).each_with_index do |key, i|
@@ -214,79 +289,103 @@ module Squared
214
289
  end
215
290
  end
216
291
  end
217
- apply_style(data || theme, name, *args, empty: empty) unless target && !data
292
+ apply_style(data || theme, obj, args, empty: empty) unless target && !data
218
293
  self
219
294
  end
220
295
 
221
- def banner(*order, command: true, styles: [], border: [], group: nil, ref: nil)
222
- if order.empty?
223
- return (group && @banner[:group][group.to_sym]) || (ref && @banner[:ref][ref]) || @banner[:ref][:_]
224
- end
296
+ def find(path = nil, name: nil)
297
+ path &&= rootpath(path)
298
+ name &&= name.to_s
299
+ ret = @project.find { |_, item| (path && item.path == path) || (name && item.name == name) }&.last
300
+ return ret unless block_given?
225
301
 
226
- data = { command: command, order: [], styles: check_style(styles, empty: false), border: check_style(border) }
227
- order.flatten.each do |val|
228
- case (val = val.to_sym)
229
- when :name, :project, :path, :ref, :group
230
- data[:order] << val
231
- end
232
- end
233
- if command || !data[:order].empty?
234
- if group ||= @group
235
- label = :group
236
- items = as_a(group)
237
- else
238
- label = :ref
239
- items = as_a(ref || @ref || :_)
240
- end
241
- items.each { |val| @banner[label][val.to_sym] = data }
242
- end
302
+ yield ret if ret
243
303
  self
244
304
  end
245
305
 
246
- def script(*args, group: nil, ref: nil)
247
- return @script[:group][group.to_sym] if group
248
- return @script[:ref][ref] if ref
249
-
250
- args.reverse_each do |val|
251
- next unless val && (ret = val.is_a?(::Symbol) ? @script[:ref!][val] : @script[:group!][val.to_sym])
306
+ def find_base(obj)
307
+ Application.kind_project.find { |proj| obj.instance_of?(proj) }
308
+ end
252
309
 
253
- return ret
254
- end
255
- @script[:ref][:_] || SCRIPT_OBJ
310
+ def task_name(val, desc: false)
311
+ ret = @prefix ? task_join(@prefix, val) : val.to_s
312
+ desc ? ret.split(':').join(ARG[:SPACE]) : ret
256
313
  end
257
314
 
258
- def env(key, default = nil, equals: nil, ignore: nil)
259
- ret = (ENV["#{key}_#{@envname}"] || ENV[key]).to_s
260
- return ret == equals.to_s unless equals.nil?
315
+ def task_namespace(val, first: false)
316
+ return nil unless (ret = val.to_s.split(':')).size > 1
261
317
 
262
- ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
318
+ first ? ret.first : task_join(*ret[0..-2])
263
319
  end
264
320
 
265
- def root_path(*args)
266
- root.join(*args)
267
- end
321
+ def task_resolve(obj, key)
322
+ tasks = []
323
+ if (base = task_base?(key))
324
+ tasks << key if obj.has?(key, baseref)
325
+ elsif (batch = series.batch_get(key))
326
+ obj.allref.each do |ref|
327
+ next unless (data = batch[ref])
268
328
 
269
- def home_path(*args)
270
- home.join(*args)
329
+ data.each do |val|
330
+ if (items = task_resolve(obj, val)).empty?
331
+ tasks.clear
332
+ break
333
+ end
334
+ tasks += items
335
+ end
336
+ return tasks unless tasks.empty?
337
+ end
338
+ elsif task_extend?(obj, key)
339
+ tasks << key
340
+ end
341
+ ret = []
342
+ if tasks.empty?
343
+ return [] if (base && !obj.ref?(baseref)) || !(data = series.alias_get(key))
344
+
345
+ obj.allref.each do |ref|
346
+ next unless (alt = data[ref])
347
+
348
+ ret = task_resolve(obj, alt)
349
+ break unless ret.empty?
350
+ end
351
+ else
352
+ tasks.each do |val|
353
+ target = task_join(obj.name, series.name_get(val))
354
+ return [] unless task_defined?(target)
355
+
356
+ ret << target
357
+ end
358
+ end
359
+ ret
271
360
  end
272
361
 
273
- def find_base(obj)
274
- Application.impl_project.find { |proj| obj.instance_of?(proj) }
362
+ def script_find(*args)
363
+ args.reverse_each do |val|
364
+ next unless val && (ret = val.is_a?(::Symbol) ? @script[:ref!][val] : @script[:group!][val.to_sym])
365
+
366
+ return ret
367
+ end
368
+ @script[:ref!][:_] || SCRIPT_OBJ
275
369
  end
276
370
 
277
- def task_name(val, desc: false)
278
- ret = @prefix ? "#{@prefix}:#{val}" : val.to_s
279
- desc ? ret.split(':').join(' => ') : ret
371
+ def script_get(group: nil, ref: nil)
372
+ if group
373
+ @script[:group][group.to_sym]
374
+ elsif ref
375
+ @script[:ref][ref]
376
+ end
280
377
  end
281
378
 
282
- def task_namespace(val, first: false)
283
- return nil unless (ret = val.to_s.split(':')).size > 1
379
+ def banner_get(*ref, group: nil)
380
+ ret = nil
381
+ return ret if group && (ret = @banner[:group][group.to_sym])
284
382
 
285
- first ? ret.first : ret[0..-2].join(':')
383
+ ref.reverse_each { |val| return ret if (ret = @banner[:ref][val]) }
384
+ @banner[:ref][:_]
286
385
  end
287
386
 
288
387
  def to_s
289
- root.to_s
388
+ (home? ? home : root).to_s
290
389
  end
291
390
 
292
391
  def inspect
@@ -297,12 +396,20 @@ module Squared
297
396
  !@extensions.empty? || @project.values.any?(&:enabled?)
298
397
  end
299
398
 
399
+ def task_base?(key)
400
+ series.base?(key)
401
+ end
402
+
300
403
  def task_extend?(obj, key)
301
404
  series.extend?(obj, key)
302
405
  end
303
406
 
304
- def task_defined?(key, *)
305
- ::Rake::Task.task_defined?(key)
407
+ def task_include?(obj, key, ref = nil)
408
+ task_base?(key) ? obj.has?(key, ref || baseref) : task_extend?(obj, key)
409
+ end
410
+
411
+ def task_defined?(*key)
412
+ ::Rake::Task.task_defined?(key.size == 1 ? key.first : task_join(*key))
306
413
  end
307
414
 
308
415
  def dev?(**kwargs)
@@ -313,25 +420,38 @@ module Squared
313
420
  script?(:prod, **kwargs)
314
421
  end
315
422
 
316
- private
423
+ def home?
424
+ !(proj = find(home)).nil? && proj.enabled?
425
+ end
317
426
 
318
- def __build__(default: nil, **)
319
- if !task_defined?('default') && default && task_defined?(target = task_name(default))
320
- task 'default' => target
321
- end
322
- return unless series.some?(:build)
427
+ def rootpath(*args)
428
+ root.join(*args)
429
+ end
430
+
431
+ def homepath(*args)
432
+ home.join(*args)
433
+ end
434
+
435
+ def baseref
436
+ Application.baseref
437
+ end
438
+
439
+ def invokeargs
440
+ { exception: exception, warning: warning }
441
+ end
323
442
 
324
- init = [task_name('depend'), task_name(dev?(global: true) && series.some?(:refresh) ? 'refresh' : 'build')]
443
+ public :task_join
325
444
 
326
- task 'default' => init[1] unless default || task_defined?('default')
327
- return unless series.some?(:depend) && !task_defined?(key = task_name('init'))
445
+ private
328
446
 
329
- desc key
330
- task key => init
447
+ def __build__(default: nil, **)
448
+ if default && task_defined?(t = task_name(default)) && !task_defined?(n = ::Rake.application.default_task_name)
449
+ task n => t
450
+ end
331
451
  end
332
452
 
333
453
  def puts(*args)
334
- @pipe == 2 ? $stderr.puts(*args) : $stdout.puts(*args)
454
+ puts_oe(*args, pipe: pipe)
335
455
  end
336
456
 
337
457
  def script_command(task, val, group, ref)
@@ -353,7 +473,7 @@ module Squared
353
473
  elsif ref
354
474
  as_a(ref).each { |val| @script[:ref!][val.to_sym] = data }
355
475
  else
356
- @script[:ref][:_] = data
476
+ @script[:ref!][:_] = data
357
477
  end
358
478
  end
359
479
 
@@ -361,8 +481,8 @@ module Squared
361
481
  SCRIPT_OBJ.dup
362
482
  end
363
483
 
364
- def script?(state, target: nil, pat: nil, group: nil, ref: Project::Base.ref, global: false)
365
- data = script(ref, group)
484
+ def script?(state, target: nil, pat: nil, group: nil, ref: baseref, global: false)
485
+ data = script_find(ref, group)
366
486
  if global
367
487
  target = data[:script] || data[:run] if target.nil?
368
488
  pat = data[state] if pat.nil?