squared 0.0.12 → 0.1.1

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.
@@ -12,12 +12,11 @@ module Squared
12
12
  include System
13
13
  include Shell
14
14
  include Utils
15
- include ::Rake::DSL
15
+ include Rake::DSL
16
16
 
17
+ VAR_SET = %i[parent global envname dependfile theme run script env].freeze
17
18
  SEM_VER = /(\d+)(?:(\.)(\d+))?(?:(\.)(\d+)(\S+)?)?/.freeze
18
-
19
- VAR_SET = %i[parent global envname dependfile theme run script env depend graph doc test copy clean].freeze
20
- private_constant :VAR_SET
19
+ private_constant :VAR_SET, :SEM_VER
21
20
 
22
21
  class << self
23
22
  def populate(*); end
@@ -26,14 +25,14 @@ module Squared
26
25
  def bannerargs(*); end
27
26
 
28
27
  def tasks
29
- [].freeze
28
+ %i[build depend graph doc test copy clean].freeze
30
29
  end
31
30
 
32
31
  def as_path(val)
33
32
  case val
34
- when ::Pathname
33
+ when Pathname
35
34
  val
36
- when ::String
35
+ when String
37
36
  Pathname.new(val)
38
37
  end
39
38
  end
@@ -42,13 +41,13 @@ module Squared
42
41
  @ref ||= to_s.downcase.to_sym
43
42
  end
44
43
 
45
- def to_s
46
- super.match(/[^:]+$/)[0]
47
- end
48
-
49
44
  def config?(*)
50
45
  false
51
46
  end
47
+
48
+ def to_s
49
+ super.match(/[^:]+$/)[0]
50
+ end
52
51
  end
53
52
 
54
53
  @@tasks = {
@@ -151,7 +150,7 @@ module Squared
151
150
  def initialize_logger(log: nil, **)
152
151
  return if @log
153
152
 
154
- log = log.is_a?(::Hash) ? log.dup : { file: log }
153
+ log = log.is_a?(Hash) ? log.dup : { file: log }
155
154
  unless (file = env('LOG_FILE'))
156
155
  file = case env('LOG_AUTO')
157
156
  when 'y', 'year'
@@ -171,7 +170,7 @@ module Squared
171
170
  raise if @exception
172
171
 
173
172
  file = nil
174
- warn log_message(::Logger::WARN, e) if warning?
173
+ warn log_message(Logger::WARN, e) if warning?
175
174
  end
176
175
  end
177
176
  log[:progname] ||= @name
@@ -187,13 +186,13 @@ module Squared
187
186
  @dev = env_match("#{pre}_DEV", dev)
188
187
  @prod = env_match("#{pre}_PROD", prod)
189
188
  cmd = @output[0]
190
- unless cmd == false || cmd.is_a?(::Array) || (val = env('BUILD', suffix: 'OPTS')).nil?
189
+ unless cmd == false || cmd.is_a?(Array) || (val = env('BUILD', suffix: 'OPTS')).nil?
191
190
  @output[cmd ? 1 : 3] = shell_split(val, join: true)
192
191
  end
193
192
  unless @output[2] == false || (val = env('BUILD', suffix: 'ENV')).nil?
194
193
  begin
195
194
  data = JSON.parse(val)
196
- raise_error('invalid JSON object', val, hint: "#{prefix}_ENV") unless data.is_a?(::Hash)
195
+ raise_error('invalid JSON object', val, hint: "#{prefix}_ENV") unless data.is_a?(Hash)
197
196
  @output[2] = data
198
197
  rescue StandardError => e
199
198
  log.warn e
@@ -241,22 +240,34 @@ module Squared
241
240
  when :graph
242
241
  next unless graph?
243
242
 
243
+ check = lambda do |args|
244
+ next args if (args = args.to_a).empty?
245
+
246
+ guard_params(action, flag, args: args.reject { |val| name == val.to_s })
247
+ end
248
+
249
+ desc format_desc(action, flag, 'project*')
244
250
  if flag == :run
245
- desc format_desc(action, flag, 'pass*')
246
- task flag, [:pass] do |_, args|
247
- graph(pass: args.to_a)
251
+ task flag, [:project] do |_, args|
252
+ graph check.(args)
248
253
  end
249
254
  else
250
- desc format_desc(action, flag)
251
- task flag do
252
- out = graph(out: [])
253
- emphasize(out, title: path, right: true, border: borderstyle,
254
- footer: "dependencies: #{out.size - 1}",
255
- sub: [
256
- { pat: /^(#{Regexp.escape(path.to_s)})(.*)$/, styles: theme[:header] },
257
- { pat: /^(#{Regexp.escape(name)})(.*)$/, styles: theme[:active] },
258
- { pat: /^(\s*)([a-z]+: )(\d+)$/, styles: theme[:inline], index: 3 }
259
- ])
255
+ task flag, [:project] do |_, args|
256
+ out, done = graph(check.(args), out: [])
257
+ out.map! do |val|
258
+ done.each_with_index do |proj, i|
259
+ next unless val.end_with?(" #{proj.name}")
260
+
261
+ val += " (#{i.succ})"
262
+ break
263
+ end
264
+ val
265
+ end
266
+ emphasize(out, title: path, right: true, border: borderstyle, sub: [
267
+ { pat: /^(#{Regexp.escape(path.to_s)})(.*)$/, styles: theme[:header] },
268
+ { pat: /^(#{Regexp.escape(name)})(.*)$/, styles: theme[:active] },
269
+ { pat: /^(.+ )(\()(\d+)(\))(.*)$/, styles: theme[:inline], index: 3 }
270
+ ])
260
271
  end
261
272
  end
262
273
  end
@@ -276,18 +287,28 @@ module Squared
276
287
  end
277
288
 
278
289
  def add(path, name = nil, **kwargs, &blk)
279
- if path.is_a?(::String) && (data = %r{^(.+)[\\/]\*+$}.match(path))
280
- path = basepath(data[1]).children.select(&:directory?)
290
+ checkdir = lambda do |val|
291
+ if val.directory? && !val.empty?
292
+ true
293
+ else
294
+ log.warn "workspace \"#{val}\" (#{val.empty? ? 'empty' : 'not found'})"
295
+ false
296
+ end
281
297
  end
282
- if path.is_a?(::Array)
298
+ if path.is_a?(String) && (data = %r{^(.+)[\\/]\*+$}.match(path))
299
+ return self unless checkdir.(path = basepath(data[1]))
300
+
301
+ path = path.children.select { |val| checkdir.(val) }
302
+ end
303
+ if path.is_a?(Array)
283
304
  name = @name if name == true
284
305
  path.each { |val| add(val, name && task_join(name, File.basename(val)), **kwargs, &blk) }
285
306
  return self
286
- elsif !projectpath?(path = basepath(path))
307
+ elsif !projectpath?(path = basepath(path)) || !checkdir.(path)
287
308
  return self
288
- elsif name.is_a?(::Symbol)
309
+ elsif name.is_a?(Symbol)
289
310
  name = name.to_s
290
- elsif !name.is_a?(::String)
311
+ elsif !name.is_a?(String)
291
312
  name = nil
292
313
  end
293
314
  if @withargs
@@ -319,9 +340,9 @@ module Squared
319
340
  end
320
341
  if cmd
321
342
  case opts
322
- when ::String
343
+ when String
323
344
  cmd = "#{cmd} #{opts}"
324
- when ::Array
345
+ when Array
325
346
  cmd = cmd.join(' && ')
326
347
  else
327
348
  cmd = [cmd, compose(opts, script: false)].compact.join(' ') unless opts == false || !respond_to?(:compose)
@@ -352,9 +373,9 @@ module Squared
352
373
 
353
374
  def clean(*)
354
375
  case @clean
355
- when ::String
376
+ when String
356
377
  run_s(@clean, sync: invoked_sync?('clean'))
357
- when ::Enumerable
378
+ when Enumerable
358
379
  as_a(@clean).each do |val|
359
380
  if (val = val.to_s) =~ %r{[\\/]$}
360
381
  dir = Pathname.new(val)
@@ -362,7 +383,7 @@ module Squared
362
383
  next unless dir.directory?
363
384
 
364
385
  log.warn "rm -rf #{dir}"
365
- dir.rmtree(verbose: true)
386
+ dir.rmtree
366
387
  else
367
388
  files = val.include?('*') ? Dir[basepath(val)] : [basepath(val)]
368
389
  files.each do |file|
@@ -377,40 +398,28 @@ module Squared
377
398
  end
378
399
  end
379
400
 
380
- def graph(*, sync: invoked_sync?('graph'), pass: [], out: nil)
381
- data = graph_collect(self)
382
- data[name] << self unless out
383
- run_graph(data, name, out, sync: sync, pass: pass)
384
- out
385
- end
386
-
387
- def log
388
- return @log unless @log.is_a?(::Array)
389
-
390
- @log = Logger.new(enabled? ? @log[0] : nil, **@log[1])
391
- end
392
-
393
- def basepath(*args, ascend: nil)
394
- ret = path.join(*args)
395
- return ret unless ascend && !ret.exist?
396
-
397
- path.parent.ascend.each do |dir|
398
- target = dir.join(*args)
399
- return target if target.exist?
400
- break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
401
+ def graph(start = [], tasks = nil, sync: invoked_sync?('graph'), pass: [], out: nil)
402
+ if (val = env('GRAPH', strict: true))
403
+ tasks ||= []
404
+ split_escape(val).each do |task|
405
+ if ref?(task.to_sym) && (script = workspace.script_get(:graph, ref: task.to_sym))
406
+ tasks += script[:graph]
407
+ else
408
+ tasks << task
409
+ end
410
+ end
401
411
  end
402
- ret
403
- end
404
-
405
- def color(val)
406
- ret = theme[val]
407
- ret && !ret.empty? ? ret : [val]
412
+ pass.concat(split_escape(val)) if (val = env('GRAPH_PASS', strict: true))
413
+ data = graph_collect(self, start)
414
+ data[name] << self unless out
415
+ done = run_graph(data, name, tasks, out, sync: sync, pass: pass)
416
+ [out, done] if out
408
417
  end
409
418
 
410
419
  def variable_set(key, *val, **kwargs)
411
420
  if variables.include?(key)
412
421
  case key
413
- when :run
422
+ when :build, :run
414
423
  run_set(*val, **kwargs)
415
424
  when :script
416
425
  script_set(*val, **kwargs)
@@ -435,28 +444,6 @@ module Squared
435
444
  end
436
445
  end
437
446
 
438
- def allref
439
- @ref.reverse_each
440
- end
441
-
442
- def dependtype(*)
443
- @dependindex ? @dependindex.succ : 0
444
- end
445
-
446
- def version(*); end
447
-
448
- def inspect
449
- "#<#{self.class}: #{name} => #{self}>"
450
- end
451
-
452
- def to_s
453
- path.to_s
454
- end
455
-
456
- def to_sym
457
- name.to_sym
458
- end
459
-
460
447
  def enabled?(ref = nil)
461
448
  return false if ref && !ref?(ref)
462
449
 
@@ -486,7 +473,7 @@ module Squared
486
473
  end
487
474
 
488
475
  def graph?
489
- @graph.is_a?(::Array) && !@graph.empty?
476
+ @graph.is_a?(Array) && !@graph.empty?
490
477
  end
491
478
 
492
479
  def copy?
@@ -513,28 +500,63 @@ module Squared
513
500
  @prod != false && workspace.prod?(pat: @prod, **scriptargs)
514
501
  end
515
502
 
516
- private
503
+ def version(*); end
517
504
 
518
- def variables
519
- VAR_SET
505
+ def dependtype(*)
506
+ @dependindex ? @dependindex.succ : 0
507
+ end
508
+
509
+ def log
510
+ return @log unless @log.is_a?(Array)
511
+
512
+ @log = Logger.new(enabled? ? @log[0] : nil, **@log[1])
513
+ end
514
+
515
+ def allref
516
+ @ref.reverse_each
517
+ end
518
+
519
+ def basepath(*args, ascend: nil)
520
+ ret = path.join(*args)
521
+ return ret unless ascend && !ret.exist?
522
+
523
+ path.parent.ascend.each do |dir|
524
+ target = dir.join(*args)
525
+ return target if target.exist?
526
+ break if (ascend.is_a?(String) && dir.join(ascend).exist?) || workspace.root == dir || parent&.path == dir
527
+ end
528
+ ret
529
+ end
530
+
531
+ def inspect
532
+ "#<#{self.class}: #{name} => #{self}>"
533
+ end
534
+
535
+ def to_s
536
+ path.to_s
520
537
  end
521
538
 
539
+ def to_sym
540
+ name.to_sym
541
+ end
542
+
543
+ private
544
+
522
545
  def puts(*args)
523
546
  puts_oe(*args, pipe: pipe)
524
547
  end
525
548
 
526
- def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, **)
549
+ def run(cmd = @session, var = nil, exception: @exception, sync: true, banner: true, chdir: path, **)
527
550
  cmd = session_done(cmd)
528
551
  log.info cmd
529
552
  begin
530
- if cmd =~ /^\S+:(\S+:?)+$/ && workspace.task_defined?(cmd)
531
- print_item if sync
553
+ if cmd =~ /^[^:]+:[^:]/ && workspace.task_defined?(cmd)
532
554
  log.warn "ENV was discarded: #{var}" if var
533
555
  task_invoke(cmd, exception: exception, warning: warning?)
534
556
  else
535
557
  print_item format_banner(cmd, banner: banner) if sync
536
- args = var.is_a?(::Hash) ? [var, cmd] : [cmd]
537
- shell(*args, chdir: path, exception: exception)
558
+ args = var.is_a?(Hash) ? [var, cmd] : [cmd]
559
+ shell(*args, chdir: chdir, exception: exception)
538
560
  end
539
561
  rescue StandardError => e
540
562
  log.error e
@@ -546,9 +568,25 @@ module Squared
546
568
  cmd.each { |val| run(val, env, banner: banner, **kwargs) }
547
569
  end
548
570
 
549
- def run_graph(data, start, out = nil, sync: true, pass: [], done: [], depth: 0, last: false)
571
+ def run_graph(data, start, tasks = nil, out = nil, sync: true, pass: [], done: [], depth: 0, last: false,
572
+ single: false)
550
573
  check = ->(deps) { deps.reject { |val| done.include?(val) } }
551
- items = check.(data[start])
574
+ dedupe = lambda do |name|
575
+ next [] unless (ret = data[name])
576
+
577
+ ret.dup.each do |proj|
578
+ next if proj.name == name
579
+
580
+ data[proj.name]&.each { |dep| ret.delete(dep) if ret.include?(dep) }
581
+ end
582
+ ret
583
+ end
584
+ if depth == 0
585
+ items = check.(dedupe.(start))
586
+ single = items.size == 1
587
+ else
588
+ items = check.(data[start])
589
+ end
552
590
  if out
553
591
  a, b, c, d, e = ARG[:GRAPH]
554
592
  out << case depth
@@ -561,22 +599,30 @@ module Squared
561
599
  "#{last ? d : c}#{b * 3}#{e} #{start}"
562
600
  end
563
601
  else
564
- "#{a}#{' ' * (depth - 1)}#{d}#{b * 2}#{items.empty? ? b : e} #{start}"
602
+ "#{single ? ' ' : a}#{' ' * (depth - 1)}#{last ? d : c}#{b * 3}#{items.empty? ? b : e} #{start}"
565
603
  end
566
604
  end
567
605
  items.each_with_index do |proj, i|
568
606
  next if done.include?(proj)
569
607
 
570
- j = out ? i == items.size - 1 || check.(items[i + 1..-1]).empty? : false
571
608
  s = proj.name
572
- unless start == s || (none = check.(data.fetch(s, [])).empty?)
573
- run_graph(data, s, out, sync: sync, pass: pass, done: done, depth: depth.succ, last: j)
609
+ t = dedupe.(s)
610
+ j = if out
611
+ if i == items.size - 1 || check.(post = items[i + 1..-1]).empty?
612
+ true
613
+ elsif !t.empty? && depth > 0
614
+ post.reject { |pr| t.include?(pr) }.empty?
615
+ end
616
+ end
617
+ unless start == s || (none = check.(t).empty?)
618
+ run_graph(data, s, tasks, out, sync: sync, pass: pass, done: done, depth: depth.succ, single: single,
619
+ last: j == true)
574
620
  end
575
621
  if !out
576
- if (script = workspace.script_get(group: proj.group, ref: proj.ref))
577
- tasks = script[:graph]
622
+ unless tasks || !(script = workspace.script_get(:graph, group: proj.group, ref: proj.allref))
623
+ group = script[:graph]
578
624
  end
579
- (tasks || (dev? ? %w[build copy] : %w[depend build])).each do |meth|
625
+ (tasks || group || (dev? ? ['build', 'copy'] : ['depend', 'build'])).each do |meth|
580
626
  next if pass.include?(meth)
581
627
 
582
628
  if workspace.task_defined?(cmd = task_join(s, meth))
@@ -590,17 +636,24 @@ module Squared
590
636
  out << if depth == 0
591
637
  "#{i == items.size - 1 ? d : c}#{b * 4} #{s}"
592
638
  else
593
- "#{last && depth == 1 ? ' ' : a}#{' ' * depth}#{j ? d : c}#{b * 3} #{s}"
639
+ f = ''.dup
640
+ k = 0
641
+ while k < depth
642
+ f += "#{(last && !j) || (j && k > 0 && k == depth - 1) || single ? ' ' : a} "
643
+ k += 1
644
+ end
645
+ f + "#{j ? d : c}#{b * 3} #{s}"
594
646
  end
595
647
  end
596
648
  done << proj
597
649
  end
650
+ done
598
651
  end
599
652
 
600
- def graph_collect(target, data: {})
653
+ def graph_collect(target, start = [], data: {})
601
654
  deps = []
602
- target.instance_variable_get(:@graph)&.each do |val|
603
- next unless (proj = workspace.find(name: val))
655
+ (start.empty? ? target.instance_variable_get(:@graph) : start)&.each do |val|
656
+ next unless (proj = workspace.find(name: val)) && proj.enabled?
604
657
 
605
658
  deps << proj
606
659
  graph_collect(proj, data: data) if proj.graph? && !data.key?(proj.name)
@@ -614,9 +667,11 @@ module Squared
614
667
  a = "#{key}_#{@envname}"
615
668
  ret = if suffix
616
669
  ENV.fetch("#{a}_#{suffix}", '')
670
+ elsif strict
671
+ ENV[a].to_s
617
672
  else
618
- ignore = ['0'].freeze if ignore.nil? && !strict
619
- ENV[a] || (strict ? '' : ENV.fetch(key, ''))
673
+ ignore = ['0'].freeze if ignore.nil?
674
+ ENV[a] || ENV.fetch(key, '')
620
675
  end
621
676
  return ret == equals.to_s unless equals.nil?
622
677
 
@@ -694,7 +749,7 @@ module Squared
694
749
  end
695
750
 
696
751
  def format_desc(action, flag, opts = nil, req: nil, arg: 'opts*')
697
- opts = "#{arg}=#{opts.join(',')}" if opts.is_a?(::Array)
752
+ opts = "#{arg}=#{opts.join(',')}" if opts.is_a?(Array)
698
753
  out = [@desc]
699
754
  if flag
700
755
  out << action
@@ -718,11 +773,11 @@ module Squared
718
773
  out = []
719
774
  out << cmd.sub(/^\S+/, &:upcase) if data[:command]
720
775
  data[:order].each do |val|
721
- if val.is_a?(::Array)
776
+ if val.is_a?(Array)
722
777
  s = ' '
723
778
  found = false
724
779
  val = val.map do |meth|
725
- if meth.is_a?(::String)
780
+ if meth.is_a?(String)
726
781
  s = ''
727
782
  meth
728
783
  elsif respond_to?(meth)
@@ -781,8 +836,13 @@ module Squared
781
836
  opts.each { |val| @session << "--#{flag}=#{shell_escape(val, quote: true)}" }
782
837
  end
783
838
 
784
- def append_value(opts)
785
- opts.each { |val| @session << val }
839
+ def append_value(opts, delim: false)
840
+ @session << '--' if delim && !opts.empty?
841
+ opts.each { |val| @session << shell_escape(val) }
842
+ end
843
+
844
+ def append_option(list, **kwargs)
845
+ list.each { |val| @session << "--#{val}" if option(val, **kwargs) }
786
846
  end
787
847
 
788
848
  def append_nocolor(flag = nil)
@@ -796,23 +856,61 @@ module Squared
796
856
 
797
857
  @session = nil
798
858
  raise_error(action, "#{flag}[#{key}]", hint: val.nil? ? 'missing' : 'invalid')
799
- elsif args.is_a?(::Array) && args.empty?
859
+ elsif args.is_a?(Array) && args.empty?
800
860
  @session = nil
801
861
  raise_error(action, "#{flag}+", hint: 'empty')
802
862
  end
803
863
  args
804
864
  end
805
865
 
806
- def pwd_set(done = nil, &blk)
866
+ def projectmap(files, parent: false)
867
+ files = files.select { |val| projectpath?(val) } unless parent
868
+ files.map { |val| val == '.' ? '.' : shell_quote(basepath(val.strip)) }
869
+ end
870
+
871
+ def semver(val)
872
+ return val if val[3]
873
+
874
+ val[3] = '.'
875
+ val[4] = '0'
876
+ unless val[1]
877
+ val[1] = '.'
878
+ val[2] = '0'
879
+ end
880
+ val
881
+ end
882
+
883
+ def semscan(val, fill: true)
884
+ ret = val.scan(SEM_VER).first
885
+ fill ? semver(ret) : ret
886
+ end
887
+
888
+ def indexitem(val)
889
+ return unless (data = /\A\^(\d+)(:.+)?\z/.match(val))
890
+
891
+ [data[1].to_i, data[2] ? data[2][1..-1] : nil]
892
+ end
893
+
894
+ def indexerror(val, list = nil)
895
+ raise_error("requested index #{val}", hint: list && "of #{list.size}")
896
+ end
897
+
898
+ def color(val)
899
+ ret = theme[val]
900
+ ret && !ret.empty? ? ret : [val]
901
+ end
902
+
903
+ def pwd_set(done = nil, pass: false, &blk)
807
904
  pwd = Pathname.pwd
808
905
  if block_given?
809
- if path == pwd
810
- instance_eval(&blk)
906
+ if path == pwd || pass == true || (pass.is_a?(String) && semscan(pass).join >= RUBY_VERSION)
907
+ ret = instance_eval(&blk)
811
908
  else
812
909
  Dir.chdir(path)
813
- instance_eval(&blk)
910
+ ret = instance_eval(&blk)
814
911
  Dir.chdir(pwd)
815
912
  end
913
+ ret
816
914
  elsif @pwd == pwd
817
915
  @pwd = nil
818
916
  pwd unless done
@@ -837,7 +935,7 @@ module Squared
837
935
  end
838
936
  end
839
937
  unless @output[2] == false
840
- if val.is_a?(::Hash)
938
+ if val.is_a?(Hash)
841
939
  @output[2] = val
842
940
  elsif val == false
843
941
  @output[2] = false
@@ -850,7 +948,7 @@ module Squared
850
948
  return if @output[1] == false && @output[0].nil?
851
949
 
852
950
  @output[0] = nil
853
- @output[1] = if @global && cmd.is_a?(::Array)
951
+ @output[1] = if @global && cmd.is_a?(Array)
854
952
  cmd[prod == true ? 1 : 0]
855
953
  else
856
954
  cmd
@@ -867,10 +965,10 @@ module Squared
867
965
 
868
966
  def runnable?(val)
869
967
  case val
870
- when ::String
968
+ when String
871
969
  true
872
- when ::Enumerable
873
- !val.is_a?(::Hash)
970
+ when Enumerable
971
+ !val.is_a?(Hash)
874
972
  else
875
973
  false
876
974
  end
@@ -905,31 +1003,14 @@ module Squared
905
1003
  workspace.warning
906
1004
  end
907
1005
 
908
- def projectmap(files, parent: false)
909
- files = files.select { |val| projectpath?(val) } unless parent
910
- files.map { |val| val == '.' ? '.' : shell_quote(basepath(val.strip)) }
911
- end
912
-
913
- def semver(val)
914
- return val if val[3]
915
-
916
- val[3] = '.'
917
- val[4] = '0'
918
- unless val[1]
919
- val[1] = '.'
920
- val[2] = '0'
921
- end
922
- val
923
- end
924
-
925
- def semscan(val)
926
- val.scan(SEM_VER).first
1006
+ def variables
1007
+ Base.tasks + VAR_SET
927
1008
  end
928
1009
 
929
1010
  def borderstyle
930
- if (data = workspace.banner_get(*@ref, group: group))
931
- data[:border]
932
- end
1011
+ return unless (data = workspace.banner_get(*@ref, group: group))
1012
+
1013
+ data[:border]
933
1014
  end
934
1015
 
935
1016
  def headerstyle
@@ -939,19 +1020,9 @@ module Squared
939
1020
  def scriptargs
940
1021
  { target: script? ? @output[1] : @output[0], ref: ref, group: group, global: @global }
941
1022
  end
942
-
943
- def indexdata(val)
944
- if (data = /\A\^(\d+)(:.+)?\z/.match(val))
945
- [data[1].to_i, data[2] ? data[2][1..-1] : nil]
946
- end
947
- end
948
-
949
- def indexerror(val, list = nil)
950
- raise_error("requested index #{val}", hint: list && "of #{list.size}")
951
- end
952
1023
  end
953
1024
 
954
- Application.impl_project = Base
1025
+ Application.implement(Base, base: true)
955
1026
  Application.attr_banner = Common::SymSet.new(%i[name project path ref group parent])
956
1027
  end
957
1028
  end