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.
@@ -10,38 +10,36 @@ module Squared
10
10
 
11
11
  def shell_escape(val, quote: false, force: false)
12
12
  if (data = /\A(--?[^= ]+)((=|\s+)(["'])?(.+?)(["'])?)?\z/m.match(val = val.to_s))
13
- return val if !data[2] || (!data[4] && !data[5].match?(/\s/))
13
+ return val unless data[2]
14
14
 
15
15
  join = ->(opt) { data[1] + data[3] + shell_quote(opt) }
16
16
  if data[4] == data[6]
17
17
  data[4] ? val : join.(data[5])
18
18
  else
19
- join.("#{data[4]}#{data[5]}#{data[6]}")
19
+ join.(data[4] + data[5] + data[6])
20
20
  end
21
21
  elsif Rake::Win32.windows?
22
22
  quote ? shell_quote(val, force: force) : val
23
23
  else
24
- val.empty? ? '' : Shellwords.escape(val)
24
+ Shellwords.escape(val)
25
25
  end
26
26
  end
27
27
 
28
28
  def shell_quote(val, force: true)
29
29
  val = val.to_s
30
- return val if !force && !val.include?(' ')
31
- return val if option && val =~ /(?:^|\S=|[^=]\s+|#{Rake::Win32.windows? ? '[\\\/]' : '\/'})(["']).+\1\z/m
30
+ return val if (!force && !val.include?(' ')) || val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m)
32
31
 
33
- Rake::Win32.windows? ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
32
+ Rake::Win32.windows? || ARG[:QUOTE] == '"' ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
34
33
  end
35
34
 
36
- def shell_split(val, escape: true, quote: false, join: nil)
37
- val = Shellwords.split(val)
38
- val = val.map { |opt| shell_escape(opt, quote: quote) } if escape
35
+ def shell_split(val, quote: false, join: nil)
36
+ val = Shellwords.split(val).map { |opt| shell_escape(opt, quote: quote) }
39
37
  return val unless join
40
38
 
41
39
  val.join(join.is_a?(::String) ? join : ' ')
42
40
  end
43
41
 
44
- def shell_option(flag, val = nil, escape: true, quote: true)
42
+ def shell_option(flag, val = nil, escape: true, quote: true, force: true)
45
43
  flag = flag.to_s
46
44
  if flag[0] == '-'
47
45
  b = flag[1] == '-' ? '=' : ' '
@@ -52,7 +50,7 @@ module Squared
52
50
  "#{b}#{if escape
53
51
  shell_escape(val, quote: quote)
54
52
  else
55
- quote ? shell_quote(val) : val
53
+ quote ? shell_quote(val, force: force) : val
56
54
  end}"
57
55
  end}"
58
56
  end
@@ -68,7 +66,7 @@ module Squared
68
66
  end
69
67
 
70
68
  def basic_option(flag, val)
71
- shell_option(flag, val, escape: false, quote: false)
69
+ shell_option(flag, val, escape: false, force: false)
72
70
  end
73
71
 
74
72
  def single_quote(val)
@@ -80,7 +78,7 @@ module Squared
80
78
  end
81
79
 
82
80
  def split_escape(val, char: ',')
83
- val.split(/\s*(?<!\\)#{char}\s*/)
81
+ val.split(/\s*(?<!\\)#{char}\s*/o)
84
82
  end
85
83
  end
86
84
  end
@@ -1,32 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'pathname'
4
- require 'rake'
4
+ require 'fileutils'
5
5
 
6
6
  module Squared
7
7
  module Common
8
8
  module System
9
9
  module_function
10
10
 
11
- def shell(*args, name: :system, **kwargs)
12
- if RUBY_ENGINE == 'jruby' && Rake::Win32.windows?
13
- e = kwargs[:exception]
14
- if (dir = kwargs[:chdir]) && ((pwd = Dir.pwd) != dir)
15
- Dir.chdir(dir)
16
- ret = Kernel.send(name, *args)
17
- Dir.chdir(pwd)
18
- else
19
- ret = Kernel.send(name, *args)
20
- end
21
- elsif RUBY_VERSION < '2.6'
22
- e = kwargs.delete(:exception)
23
- ret = Kernel.send(name, *args, **kwargs)
11
+ def shell(*args, **kwargs)
12
+ if RUBY_VERSION < '2.6'
13
+ exception = kwargs.delete(:exception)
14
+ ret = system(*args, **kwargs)
15
+ return ret if ret || !exception
16
+
17
+ raise $?.to_s
24
18
  else
25
- return Kernel.send(name, *args, **kwargs)
19
+ system(*args, **kwargs)
26
20
  end
27
- return ret unless e && !ret && name == :system
28
-
29
- raise $?.to_s
30
21
  end
31
22
 
32
23
  def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, force: false, pass: nil, verbose: true)
@@ -38,9 +29,10 @@ module Squared
38
29
  dest.mkpath if create
39
30
  if pass
40
31
  exclude = []
41
- Array(pass).each { |val| exclude += Dir.glob(src.join(val)) }
32
+ pass = [pass] unless pass.is_a?(::Array)
33
+ pass.each { |val| exclude += Dir.glob(src.join(val)) }
42
34
  end
43
- Array(glob).each do |val|
35
+ (glob.is_a?(::Array) ? glob : [glob]).each do |val|
44
36
  Dir.glob(src.join(val)) do |path|
45
37
  next if exclude&.include?(path) || (path = Pathname.new(path)).directory?
46
38
 
@@ -87,7 +79,8 @@ module Squared
87
79
  def copy_guard(src, dest, link: nil, force: false, verbose: true)
88
80
  unless force
89
81
  if (path = Pathname.new(dest)).directory?
90
- src = Array(src).reject { |val| path.join(File.basename(val)).exist? }
82
+ src = [src] unless src.is_a?(::Array)
83
+ src = src.reject { |val| path.join(File.basename(val)).exist? }
91
84
  return if src.empty?
92
85
  elsif path.exist?
93
86
  return
@@ -35,33 +35,44 @@ module Squared
35
35
  end
36
36
  end
37
37
 
38
- def env(key, default = nil, suffix: @envname, equals: nil, ignore: nil)
39
- ret = env_value(key, suffix: suffix)
38
+ def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil)
39
+ ret = env_value(key, suffix: suffix, strict: strict)
40
40
  return ret == equals.to_s unless equals.nil?
41
41
 
42
42
  ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
43
43
  end
44
44
 
45
- def env_value(key, default = '', suffix: nil)
46
- suffix && (ret = ENV["#{key}_#{suffix}"]) ? ret : ENV.fetch(key, default)
45
+ def env_value(key, default = '', suffix: nil, strict: false)
46
+ if suffix
47
+ if (ret = ENV["#{key}#{@envname ? "_#{@envname}" : ''}_#{suffix}"])
48
+ return ret
49
+ elsif strict
50
+ return default
51
+ end
52
+ end
53
+ if @envname
54
+ return ret if (ret = ENV["#{key}_#{@envname}"])
55
+ return default if strict
56
+ end
57
+ ENV.fetch(key, default)
47
58
  end
48
59
 
49
- def env_bool(key, default = false, suffix: nil)
60
+ def env_bool(key, default = false, suffix: nil, strict: false, index: false)
50
61
  if key.is_a?(::String)
51
- case env_value(key, suffix: suffix)
62
+ case (val = env_value(key, suffix: suffix, strict: strict))
52
63
  when ''
53
64
  default
54
65
  when '0', 'false'
55
66
  false
56
67
  else
57
- true
68
+ index && val.to_i > 0 ? val.to_i : true
58
69
  end
59
70
  else
60
71
  key.nil? ? default : key
61
72
  end
62
73
  end
63
74
 
64
- def env_pipe(key, default = 1, suffix: nil, root: nil)
75
+ def env_pipe(key, default = 1, suffix: nil, strict: false, root: nil)
65
76
  if default.is_a?(::String)
66
77
  begin
67
78
  default = (root ? root.join(default) : Pathname.new(default)).realdirpath
@@ -72,18 +83,18 @@ module Squared
72
83
  end
73
84
  case key
74
85
  when ::String
75
- case (ret = env_value(key, suffix: suffix))
86
+ case (ret = env_value(key, suffix: suffix, strict: strict))
76
87
  when '0', '1', '2'
77
88
  return ret.to_i
78
89
  end
79
90
  when ::Numeric
80
- return key if key.between?(0, 2)
91
+ return key if key >= 0 && key <= 2
81
92
  end
82
93
  default
83
94
  end
84
95
 
85
- def env_match(key, default = nil, suffix: nil, options: 0, timeout: nil)
86
- case (ret = env_value(key, suffix: suffix))
96
+ def env_match(key, default = nil, suffix: nil, strict: false, options: 0, timeout: nil)
97
+ case (val = env_value(key, suffix: suffix, strict: strict))
87
98
  when ''
88
99
  default
89
100
  when '0'
@@ -91,7 +102,7 @@ module Squared
91
102
  when '1'
92
103
  true
93
104
  else
94
- Regexp.new(ret, options, timeout: timeout)
105
+ Regexp.new(val, options, timeout: timeout)
95
106
  end
96
107
  end
97
108
  end
@@ -33,7 +33,7 @@ module Squared
33
33
  end
34
34
 
35
35
  def to_s
36
- super.match(/[^:]+\z/)[0]
36
+ super[/[^:]+\z/, 0]
37
37
  end
38
38
  end
39
39
 
@@ -48,6 +48,7 @@ module Squared
48
48
  if project && (project.respond_to?(:workspace) || (project = __get__(:project)[project.to_s]))
49
49
  main = project.basepath(main).to_s
50
50
  @project = project
51
+ @envname = project.instance_variable_get(:@envname)
51
52
  @required = true
52
53
  end
53
54
  @name = name || @project&.name
@@ -89,7 +90,7 @@ module Squared
89
90
  @required = true
90
91
  project ? [project, 'not found'] : ['name', 'missing']
91
92
  end
92
- warn log_message(:warn, msg, subject: self.class, hint: hint)
93
+ warn log_message(Logger::WARN, msg, subject: self.class, hint: hint)
93
94
  end
94
95
 
95
96
  def build
@@ -238,7 +239,7 @@ module Squared
238
239
  title = Pathname.new(file)
239
240
  .realpath
240
241
  .to_s
241
- .sub(Regexp.new("\\A#{Regexp.escape(File.join(Dir.pwd, ''))}"), '')
242
+ .sub(/\A#{Regexp.escape(File.join(Dir.pwd, ''))}/, '')
242
243
  emphasize(lines, title: title, sub: unless stdin?
243
244
  [
244
245
  { pat: /\A((?:[^:]|(?<! ):(?! ))+)\z/, styles: theme[:banner] },
@@ -249,8 +250,6 @@ module Squared
249
250
  { pat: /\A(.+ : ")(.+)("\s*)\z/m, styles: theme[:string], index: 2 },
250
251
  { pat: /\A(.+ : \{)(.+)(\}\s*)\z/m, styles: theme[:hash], index: 2 },
251
252
  { pat: /\A(.+ : \[)(.+)(\]\s*)\z/m, styles: theme[:array], index: 2 },
252
- { pat: /\A(.+ : )(true|false)(\s*)\z/m, styles: theme[:boolean],
253
- index: 2 },
254
253
  { pat: /\A(.+ : (?!undefined))([^"\[{].*)\z/m, styles: theme[:value],
255
254
  index: 2 }
256
255
  ]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.2.14'
4
+ VERSION = '0.3.0'
5
5
  end
@@ -56,7 +56,7 @@ module Squared
56
56
  end
57
57
 
58
58
  def to_s
59
- super.match(/[^:]+\z/)[0]
59
+ super[/[^:]+\z/, 0]
60
60
  end
61
61
 
62
62
  attr_reader :kind_project
@@ -68,7 +68,7 @@ module Squared
68
68
 
69
69
  attr_reader :root, :home, :main, :prefix, :exception, :warning, :pipe, :verbose, :theme, :series, :closed
70
70
 
71
- def initialize(home = Dir.pwd, *, main: nil, prefix: nil,
71
+ def initialize(home = (ARG[:HOME] && ENV[ARG[:HOME]]) || Dir.pwd, *, main: nil, prefix: nil,
72
72
  verbose: ARG[:VERBOSE], common: ARG[:COMMON], pipe: ARG[:PIPE], exception: ARG[:FAIL], **)
73
73
  @home = Pathname.new(home).realdirpath
74
74
  basename = @home.basename.to_s
@@ -78,15 +78,17 @@ module Squared
78
78
  else
79
79
  @main = basename.freeze
80
80
  end
81
+ @home.mkpath rescue nil
81
82
  @root = @home.parent
82
83
  @prefix = prefix
83
84
  @series = Application.impl_series.new(self)
84
85
  @project = {}
85
86
  @kind = {}
86
87
  @extensions = []
88
+ @envname = @main.gsub(/[^\w]+/, '_').upcase.freeze
87
89
  @pipe = env_pipe(pipe, (ARG[:OUT] && env(ARG[:OUT])) || 1, root: @home)
88
90
  @exception = env_bool(exception)
89
- @verbose = env_bool(verbose, verbose.nil? || verbose.is_a?(String) ? @pipe != 0 : verbose)
91
+ @verbose = env_bool(verbose, verbose.nil? || verbose.is_a?(String) ? @pipe != 0 : verbose, index: true)
90
92
  @warning = @verbose != false
91
93
  @closed = false
92
94
  if common
@@ -105,6 +107,12 @@ module Squared
105
107
  group: {},
106
108
  ref: {}
107
109
  }.freeze
110
+ @pass = {
111
+ group: {},
112
+ ref: {},
113
+ global: {},
114
+ pattern: []
115
+ }.freeze
108
116
  @banner = {
109
117
  group: {},
110
118
  ref: {}
@@ -113,14 +121,13 @@ module Squared
113
121
  end
114
122
 
115
123
  def initialize_session
116
- @envname = @main.gsub(/[^\w]+/, '_').upcase.freeze
117
124
  return unless @pipe.is_a?(Pathname)
118
125
 
119
126
  bord = '#' * Project.line_width
120
127
  puts bord, format('Session started on %s by %s', Time.now.to_s, @main), bord
121
128
  end
122
129
 
123
- def build(parallel: [], **kwargs)
130
+ def build(parallel: [], pass: nil, **kwargs)
124
131
  return self unless enabled? && !@closed
125
132
 
126
133
  if kwargs[:pattern].is_a?(Array)
@@ -130,6 +137,7 @@ module Squared
130
137
  kwargs[:parallel] = parallel.reject { |val| val.is_a?(Regexp) && (kwargs[:pattern] << val) }
131
138
  .map(&:to_s)
132
139
  end
140
+ @pass[:pattern].concat(pass.map { |val| val.is_a?(Regexp) ? val : val.to_s }) if pass
133
141
  @project.each_value do |proj|
134
142
  if proj.enabled?
135
143
  proj.populate(series.keys.dup, **kwargs)
@@ -138,7 +146,7 @@ module Squared
138
146
  else
139
147
  next
140
148
  end
141
- series.populate(proj)
149
+ series.populate(proj, **kwargs)
142
150
  end
143
151
 
144
152
  Application.kind_project.each { |obj| obj.populate(self, **kwargs) }
@@ -180,6 +188,10 @@ module Squared
180
188
  script_command :run, script, group, ref, on
181
189
  end
182
190
 
191
+ def script(script, group: @group, ref: @ref, on: nil)
192
+ script_command :script, script, group, ref, on
193
+ end
194
+
183
195
  def depend(script, group: @group, ref: @ref, on: nil)
184
196
  script_command :depend, script, group, ref, on
185
197
  end
@@ -196,6 +208,10 @@ module Squared
196
208
  script_command :doc, script, group, ref, on
197
209
  end
198
210
 
211
+ def lint(script, group: @group, ref: @ref, on: nil)
212
+ script_command :lint, script, group, ref, on
213
+ end
214
+
199
215
  def test(script, group: @group, ref: @ref, on: nil)
200
216
  script_command :test, script, group, ref, on
201
217
  end
@@ -208,6 +224,18 @@ module Squared
208
224
  script_command :exclude, as_a(base, :to_sym).freeze, group, ref
209
225
  end
210
226
 
227
+ def pass(name, group: @group, ref: @ref, &blk)
228
+ data = if group
229
+ @pass[:group][group] ||= {}
230
+ elsif ref
231
+ @pass[:ref][ref] ||= {}
232
+ else
233
+ @pass[:global]
234
+ end
235
+ data[name.to_sym] = blk
236
+ self
237
+ end
238
+
211
239
  def banner(*args, command: true, styles: nil, border: nil, group: @group, ref: @ref)
212
240
  data = { command: command, order: [], styles: check_style(styles, empty: false), border: check_style(border) }
213
241
  args.each do |meth|
@@ -268,7 +296,7 @@ module Squared
268
296
  index = 0
269
297
  while @project[name]
270
298
  index += 1
271
- name = task_name "#{project}-#{index}"
299
+ name = "#{project}-#{index}"
272
300
  end
273
301
  proj = ((if !ref.is_a?(Class)
274
302
  Application.find(ref, path: path)
@@ -322,7 +350,7 @@ module Squared
322
350
  end
323
351
 
324
352
  def describe(data)
325
- @describe ||= {
353
+ @describe = {
326
354
  alias: {},
327
355
  replace: [],
328
356
  pattern: {}
@@ -376,7 +404,7 @@ module Squared
376
404
  end
377
405
 
378
406
  def task_localname(val)
379
- prefix && val.is_a?(String) ? val.sub(/\A#{Regexp.escape(prefix)}:/, '') : val.to_s
407
+ prefix && val.is_a?(String) ? val.sub(/\A#{Regexp.escape(prefix)}:/o, '') : val.to_s
380
408
  end
381
409
 
382
410
  def task_desc(*args, **kwargs)
@@ -427,7 +455,7 @@ module Squared
427
455
  tasks << key if obj.has?(key, baseref)
428
456
  elsif (batch = series.batch_get(key))
429
457
  obj.allref.each do |ref|
430
- next unless obj.has?(key, ref) && (data = batch[ref])
458
+ next unless (data = batch[ref])
431
459
 
432
460
  data.each do |val|
433
461
  if (items = task_resolve(obj, val)).empty?
@@ -446,7 +474,7 @@ module Squared
446
474
  return [] if (base && !obj.ref?(baseref)) || !(data = series.alias_get(key))
447
475
 
448
476
  obj.allref.each do |ref|
449
- next unless obj.has?(key, ref) && (alt = data[ref])
477
+ next unless (alt = data[ref])
450
478
 
451
479
  ret = task_resolve(obj, alt)
452
480
  break unless ret.empty?
@@ -528,6 +556,17 @@ module Squared
528
556
  task_base?(key) ? obj.has?(key, ref || baseref) : task_extend?(obj, key)
529
557
  end
530
558
 
559
+ def task_exclude?(key, obj = nil)
560
+ if obj
561
+ data = obj.group ? @pass[:group][obj.group] : @pass[:ref][obj.ref]
562
+ blk = (data && data[key.to_sym]) || @pass[:global][key.to_sym]
563
+ return true if blk && obj.instance_eval(&blk)
564
+
565
+ key = task_join(task_localname(obj.name), key)
566
+ end
567
+ @pass[:pattern].any? { |item| item.is_a?(Regexp) ? key =~ item : key == item }
568
+ end
569
+
531
570
  def task_defined?(*key)
532
571
  Rake::Task.task_defined?(key.size == 1 ? key.first : task_join(*key))
533
572
  end
@@ -548,14 +587,6 @@ module Squared
548
587
  Rake::Win32.windows?
549
588
  end
550
589
 
551
- def jruby?
552
- RUBY_ENGINE == 'jruby'
553
- end
554
-
555
- def jruby_win?
556
- jruby? && windows?
557
- end
558
-
559
590
  def rootpath(*args)
560
591
  root.join(*args)
561
592
  end
@@ -589,14 +620,9 @@ module Squared
589
620
  private
590
621
 
591
622
  def __build__(default: nil, **)
592
- unless task_defined?('squared:version')
593
- task 'squared:version' do
594
- puts Squared::VERSION
595
- end
596
- end
597
- if default && task_defined?(out = task_name(default))
598
- task Rake.application.default_task_name => out
599
- end
623
+ return unless default && task_defined?(out = task_name(default))
624
+
625
+ task Rake.application.default_task_name => out
600
626
  end
601
627
 
602
628
  def puts(*args)
@@ -613,9 +639,7 @@ module Squared
613
639
  end
614
640
  items.each do |name|
615
641
  (@script[label][name] ||= {})[task] = val
616
- next unless on.is_a?(Hash)
617
-
618
- (@events[label][name] ||= {})[task] = on
642
+ (@events[label][name] ||= {})[task] = on if on.is_a?(Hash)
619
643
  end
620
644
  self
621
645
  end
@@ -632,34 +656,33 @@ module Squared
632
656
  end
633
657
 
634
658
  def data_get(*args, group: nil, ref: nil, target: nil)
635
- if group && (ret = target[:group][group.to_sym])
636
- ret
637
- elsif ref
638
- if ref.is_a?(Enumerable)
639
- ref.each do |key|
640
- next unless (ret = target[:ref][key])
659
+ if group
660
+ target[:group][group.to_sym]
661
+ elsif ref.is_a?(Array)
662
+ ref = ref.each
663
+ end
664
+ if ref.instance_of?(Enumerator)
665
+ ref.each do |key|
666
+ next unless (ret = target[:ref][key])
641
667
 
642
- return ret if args.empty? || args.any? { |val| ret.key?(val) }
643
- end
644
- nil
645
- else
646
- target[:ref][ref]
668
+ return ret if args.empty? || args.any? { |val| ret.key?(val) }
647
669
  end
670
+ nil
671
+ elsif ref
672
+ target[:ref][ref]
648
673
  end
649
674
  end
650
675
 
651
676
  def root?(path, pass: [])
652
677
  return false unless path.directory?
653
678
 
654
- case path.children.size
655
- when 0
656
- true
657
- when 1
658
- target = path.children.first
659
- target.to_s == __FILE__ || pass.any? { |val| val == target.basename.to_s }
660
- else
661
- false
679
+ path.children.each do |c|
680
+ name = c.basename.to_s
681
+ next if c.to_s == __FILE__ || (@main == name && c.directory? && c.empty?) || pass.any? { |val| val == name }
682
+
683
+ return false
662
684
  end
685
+ true
663
686
  end
664
687
 
665
688
  def script?(state, target: nil, pat: nil, group: nil, ref: baseref, global: false)