squared 0.0.10 → 0.0.11

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