squared 0.3.6 → 0.4.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.
@@ -28,12 +28,16 @@ module Squared
28
28
  bright_cyan!: '106',
29
29
  bright_white!: '107'
30
30
  }.freeze
31
+ AIX_GRAPH = ['│', '─', '├', '└', '┬'].freeze
32
+ AIX_BORDER = ['│', '─', '╭', '╮', '╯', '╰', '├', '┤', '┬', '┴'].freeze
31
33
  TEXT_STYLE = [:bold, :dim, :italic, :underline, :blinking, nil, :inverse, :hidden, :strikethrough].freeze
32
- private_constant :AIX_TERM, :TEXT_STYLE
34
+ private_constant :AIX_TERM, :AIX_GRAPH, :AIX_BORDER, :TEXT_STYLE
33
35
 
34
36
  def enable_aixterm
35
37
  unless (colors = __get__(:colors)).frozen?
36
38
  colors.merge!(AIX_TERM)
39
+ ARG[:GRAPH] = AIX_GRAPH
40
+ ARG[:BORDER] = AIX_BORDER
37
41
  end
38
42
  block_given? ? yield(self) : self
39
43
  end
@@ -114,7 +118,7 @@ module Squared
114
118
  if !val.is_a?(::Numeric)
115
119
  val = val.to_sym
116
120
  ret << val if colors.key?(val) || TEXT_STYLE.include?(val)
117
- elsif val >= 0 && val <= 256
121
+ elsif val.between?(0, 256)
118
122
  ret << val
119
123
  elsif val < 0 && (b = val.to_s.split('.')[1])
120
124
  b = b[0, 3]
@@ -166,16 +170,23 @@ module Squared
166
170
  color ? sub_style(ret, *styles) : ret
167
171
  end
168
172
 
169
- def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR])
173
+ def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR], append: true, pass: false)
170
174
  args = args.map(&:to_s)
171
- if args.size > 1
175
+ if level.is_a?(::Numeric)
176
+ if append && respond_to?(:log)
177
+ ref = log rescue nil
178
+ ref.add(level, message(subject, *args, hint: hint, space: ', ')) if ref.is_a?(Logger)
179
+ end
180
+ return false if !pass && level < ARG[:LEVEL]
181
+ end
182
+ if args.size > 1 && !hint
172
183
  title = log_title(level, color: false)
173
184
  sub = { pat: /^(#{title})(.+)$/, styles: __get__(:theme)[:logger][log_sym(level)] } if color
174
185
  emphasize(args, title: title + (subject ? " #{subject}" : ''), sub: sub)
175
186
  else
176
187
  msg = [log_title(level, color: color)]
177
188
  if subject
178
- msg << (color ? sub_style(subject, :underline) : subject)
189
+ msg << (color ? sub_style(subject, styles: (@theme && @theme[:subject]) || :bold) : subject)
179
190
  else
180
191
  msg += args
181
192
  args.clear
@@ -185,6 +196,8 @@ module Squared
185
196
  end
186
197
 
187
198
  def puts_oe(*args, pipe: 1)
199
+ return if args.first == false && args.size == 1
200
+
188
201
  if pipe.is_a?(Pathname)
189
202
  begin
190
203
  File.open(pipe, 'a') do |f|
@@ -201,8 +214,8 @@ module Squared
201
214
 
202
215
  module_function
203
216
 
204
- def message(*args, hint: nil, empty: false)
205
- (empty ? args.reject { |val| val.nil? || val.empty? } : args).join(ARG[:SPACE]) + (hint ? " (#{hint})" : '')
217
+ def message(*args, hint: nil, empty: false, space: ARG[:SPACE])
218
+ (empty ? args.reject { |val| val.nil? || val.empty? } : args).join(space) + (hint ? " (#{hint})" : '')
206
219
  end
207
220
 
208
221
  def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, border: nil, pipe: nil)
@@ -226,27 +239,31 @@ module Squared
226
239
  require 'io/console'
227
240
  (n = [n, $stdout.winsize[1] - 4].min) rescue nil
228
241
  end
242
+ b0, b1, b2, b3, b4, b5, b6, b7 = ARG[:BORDER]
229
243
  out = []
230
- bord = '-' * (n + 4)
231
- bord = sub_style(bord, styles: border) if border
244
+ draw = lambda do |a, b|
245
+ ret = a + (b1 * (n + 2)) + b
246
+ ret = sub_style(ret, styles: border) if border
247
+ ret
248
+ end
232
249
  sub = as_a(sub)
233
250
  pr = lambda do |line|
234
251
  s = line.ljust(n)
235
252
  sub.each { |h| s = sub_style(s, **h) }
236
- s = "| #{s} |"
253
+ s = "#{b0} #{s} #{b0}"
237
254
  if border
238
- s = sub_style(s, pat: /\A(\|)(.+)\z/m, styles: border)
239
- s = sub_style(s, pat: /\A(.+)(\|)\z/m, styles: border, index: 2)
255
+ s = sub_style(s, pat: /\A(#{Regexp.escape(b0)})(.+)\z/m, styles: border)
256
+ s = sub_style(s, pat: /\A(.+)(#{Regexp.escape(b0)})\z/m, styles: border, index: 2)
240
257
  end
241
258
  s
242
259
  end
243
- out << bord
260
+ out << draw.(b2, b3)
244
261
  if title
245
262
  out += title.map { |t| pr.(t) }
246
- out << bord
263
+ out << draw.(b6, b7)
247
264
  end
248
265
  lines.each { |line| out << pr.(line) }
249
- out << bord
266
+ out << draw.(b5, b4)
250
267
  if footer
251
268
  unless sub.empty? && !right
252
269
  footer.map! do |s|
@@ -8,8 +8,8 @@ module Squared
8
8
  def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
9
9
  require 'readline'
10
10
  require 'timeout'
11
- agree = /\A#{agree}\z/i if agree.is_a?(::String)
12
- cancel = /\A#{cancel}\z/i if cancel.is_a?(::String)
11
+ agree = /^#{agree}$/i if agree.is_a?(::String)
12
+ cancel = /^#{cancel}$/i if cancel.is_a?(::String)
13
13
  Timeout.timeout(timeout) do
14
14
  begin
15
15
  while (ch = Readline.readline(msg, true))
@@ -8,78 +8,91 @@ module Squared
8
8
  module Shell
9
9
  module_function
10
10
 
11
- def shell_escape(val, quote: false, force: false)
12
- if (data = /\A(--?[^= ]+)((=|\s+)(["'])?(.+?)(["'])?)?\z/m.match(val = val.to_s))
13
- return val if !data[2] || (!data[4] && data[5] =~ /\s/)
14
-
15
- join = ->(opt) { data[1] + data[3] + shell_quote(opt) }
16
- if data[4] == data[6]
17
- data[4] ? val : join.(data[5])
11
+ def shell_escape(val, quote: false, force: false, double: false, override: false)
12
+ if (r = /\A(--?)([^= ]+)((=|\s+)(["'])?(.+?)(["'])?)?\z/m.match(val = val.to_s))
13
+ return val if !r[3] || (!r[5] && r[6].match?(/\s/))
14
+
15
+ combine = lambda do |opt|
16
+ if r[2] =~ /^(["'])(.+)\1$/
17
+ double = $1 == '"'
18
+ r[2] = $2
19
+ override = true
20
+ end
21
+ r[1] + r[2] + r[4] + shell_quote(opt, double: double, force: force, override: override)
22
+ end
23
+ if r[5] == r[7]
24
+ r[5] ? val : combine.(r[6])
18
25
  else
19
- join.(data[4] + data[5] + data[6])
26
+ force = true
27
+ combine.(r[5] + r[6] + r[7])
20
28
  end
21
29
  elsif Rake::Win32.windows?
22
- quote ? shell_quote(val, force: force) : val
30
+ quote ? shell_quote(val, double: double, force: force) : val
23
31
  else
24
32
  Shellwords.escape(val)
25
33
  end
26
34
  end
27
35
 
28
- def shell_quote(val, force: true)
36
+ def shell_quote(val, option: true, force: true, double: false, override: false)
29
37
  val = val.to_s
30
- return val if (!force && !val.include?(' ')) || val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m)
31
-
32
- Rake::Win32.windows? || ARG[:QUOTE] == '"' ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
33
- end
34
-
35
- def shell_split(val, escape: true, quote: false, join: nil)
36
- val = Shellwords.split(val)
37
- val = val.map { |opt| shell_escape(opt, quote: quote) } if escape
38
- return val unless join
38
+ return val if (!force && !val.include?(' ')) || (option && val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m))
39
39
 
40
- val.join(join.is_a?(::String) ? join : ' ')
40
+ if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
41
+ "\"#{val.gsub(/(?<!\\)"/, '\\"')}\""
42
+ else
43
+ "'#{val.gsub("'", "'\\\\''")}'"
44
+ end
41
45
  end
42
46
 
43
- def shell_option(flag, val = nil, escape: true, quote: true, force: true)
47
+ def shell_option(flag, val = nil, escape: true, quote: true, force: true, double: false, override: false,
48
+ merge: false)
44
49
  flag = flag.to_s
50
+ if flag =~ /^(["'])(.+)\1$/
51
+ double = $1 == '"'
52
+ flag = $2
53
+ escape = false
54
+ override = true
55
+ end
45
56
  if flag[0] == '-'
46
57
  b = flag[1] == '-' ? '=' : ' '
58
+ elsif flag.size == 1
59
+ a = '-'
60
+ b = merge ? '' : ' '
47
61
  else
48
- a, b = flag.size == 1 ? ['-', ' '] : ['--', '=']
62
+ a = '--'
63
+ b = '='
49
64
  end
50
65
  "#{a}#{flag}#{if val
51
66
  "#{b}#{if escape
52
- shell_escape(val, quote: quote)
67
+ shell_escape(val, quote: quote, double: double, override: override)
53
68
  else
54
- quote ? shell_quote(val, force: force) : val
69
+ quote ? shell_quote(val, force: force, double: double, override: override) : val
55
70
  end}"
56
71
  end}"
57
72
  end
58
73
 
59
- def fill_option(val)
60
- return "-#{val}" if val =~ /\A[a-z](?:\d*)\z/i
74
+ def shell_split(val, escape: true, quote: false, join: nil)
75
+ ret = Shellwords.split(val)
76
+ return ret if join == false
61
77
 
62
- shell_escape(val.start_with?('-') ? val : "--#{val}")
63
- end
78
+ ret = ret.map { |opt| shell_escape(opt, quote: quote) } if escape
79
+ return ret unless join
64
80
 
65
- def quote_option(flag, val)
66
- shell_option(flag, val, escape: false)
81
+ ret.join(join.is_a?(::String) ? join : ' ')
67
82
  end
68
83
 
69
- def basic_option(flag, val)
70
- shell_option(flag, val, escape: false, force: false)
71
- end
84
+ def fill_option(val, double: false)
85
+ return "-#{val}" if val.match?(/^[a-z]\d*$/i)
72
86
 
73
- def single_quote(val)
74
- val.gsub("'", "'\\\\''")
87
+ shell_escape(val.start_with?('-') ? val : "--#{val}", double: double)
75
88
  end
76
89
 
77
- def double_quote(val)
78
- val.gsub(/(?<!\\)"/, '\\"')
90
+ def quote_option(flag, val, double: false)
91
+ shell_option(flag, val, escape: false, double: double)
79
92
  end
80
93
 
81
- def split_escape(val, char: ',')
82
- val.split(/\s*(?<!\\)#{char}\s*/o)
94
+ def basic_option(flag, val, merge: false)
95
+ shell_option(flag, val, escape: false, force: false, merge: merge)
83
96
  end
84
97
  end
85
98
  end
@@ -8,6 +8,23 @@ module Squared
8
8
  module Utils
9
9
  module_function
10
10
 
11
+ def split_escape(val, char: ',')
12
+ val.split(/\s*(?<!\\)#{char}\s*/o)
13
+ end
14
+
15
+ def split_option(val)
16
+ val = val.strip
17
+ return [val, '', ''] unless (i = val.index('='))
18
+
19
+ last = val[i + 1..-1].strip
20
+ quote = ''
21
+ if last =~ /^(["'])(.+)\1$/
22
+ last = $2
23
+ quote = $1
24
+ end
25
+ [val[0..i - 1], last, quote]
26
+ end
27
+
11
28
  def task_invoke(*cmd, args: [], exception: true, warning: true)
12
29
  cmd.each { |name| Rake::Task[name].invoke(*args) }
13
30
  rescue StandardError => e
@@ -31,8 +48,57 @@ module Squared
31
48
  Rake::Task.tasks.any? do |obj|
32
49
  next unless obj.already_invoked
33
50
 
34
- args.any? { |val| val.is_a?(::Regexp) ? obj.name =~ val : val == obj.name }
51
+ args.any? { |val| val.is_a?(::Regexp) ? obj.name.match?(val) : val == obj.name }
52
+ end
53
+ end
54
+
55
+ def time_format(epoch, clock: false, pass: [])
56
+ ss = 1000
57
+ mm = 60 * ss
58
+ hh = 60 * mm
59
+ dd = 24 * hh
60
+ hm = pass.include?('s')
61
+ time = []
62
+ if !clock && (d = epoch / dd) > 0
63
+ time << "#{d}d"
64
+ epoch -= d * dd
65
+ end
66
+ if (h = epoch / hh) > 0
67
+ time << (clock ? h.to_s : "#{h}h")
68
+ epoch -= h * hh
35
69
  end
70
+ if (m = epoch / mm) > 0
71
+ time << (clock ? m.to_s.rjust(2, '0') : "#{m}m")
72
+ epoch -= m * mm
73
+ elsif clock
74
+ time << '00'
75
+ end
76
+ unless hm
77
+ if (s = epoch / ss) > 0
78
+ time << (clock ? s.to_s.rjust(2, '0') : "#{s}s")
79
+ epoch -= s * ss
80
+ elsif clock
81
+ time << '00'
82
+ end
83
+ end
84
+ if clock
85
+ time.join(':')
86
+ else
87
+ time << "#{epoch}ms" unless hm || pass.include?('ms')
88
+ time.join(' ')
89
+ end
90
+ end
91
+
92
+ def time_offset(val = nil)
93
+ val = DateTime.parse(val) if val.is_a?(::String)
94
+ cur = DateTime.now
95
+ ret = 0
96
+ if (r = /^([+-])(\d+):(\d+):(\d+)$/.match((val || cur).strftime('%::z')))
97
+ ret += (r[1] == '+' ? -1 : 1) * ((r[2].to_i * 60 * 60) + (r[3].to_i * 60) + r[4].to_i) * 1000
98
+ end
99
+ return ret unless val
100
+
101
+ (cur.strftime('%Q').to_i + time_offset) - (val.strftime('%Q').to_i + ret)
36
102
  end
37
103
 
38
104
  def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil)
@@ -88,7 +154,7 @@ module Squared
88
154
  return ret.to_i
89
155
  end
90
156
  when ::Numeric
91
- return key if key >= 0 && key <= 2
157
+ return key if key.between?(0, 2)
92
158
  end
93
159
  default
94
160
  end
@@ -90,7 +90,7 @@ module Squared
90
90
  @required = true
91
91
  project ? [project, 'not found'] : ['name', 'missing']
92
92
  end
93
- warn log_message(Logger::WARN, msg, subject: self.class, hint: hint)
93
+ warn log_message(Logger::WARN, msg, subject: self.class, hint: hint, pass: true)
94
94
  end
95
95
 
96
96
  def build
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.3.6'
4
+ VERSION = '0.4.1'
5
5
  end
@@ -173,7 +173,7 @@ module Squared
173
173
  when Symbol
174
174
  @ref = val
175
175
  else
176
- raise_error('group{Symbol} | ref{String}', hint: 'missing') if block_given?
176
+ raise_error 'missing group or ref' if block_given?
177
177
  end
178
178
  if block_given?
179
179
  instance_eval(&blk)
@@ -357,7 +357,7 @@ module Squared
357
357
  }
358
358
  data.each do |key, val|
359
359
  key = key.to_s
360
- if /\A(\\A|\^)/ =~ key || /(\\z|\$)\z/ =~ key
360
+ if key.match?(/\A(\\A|\^)/) || key.match?(/(\\z|\$)\z/)
361
361
  @describe[:replace] << [Regexp.new(key), val]
362
362
  else
363
363
  @describe[val.is_a?(Regexp) ? :pattern : :alias][key.to_s] = val
@@ -415,15 +415,14 @@ module Squared
415
415
  val = name || task_join(*args)
416
416
  found = false
417
417
  replace = lambda do |data, out|
418
- if (index = data.size) > 0
419
- data.to_a.reverse_each { |group| out.sub!("%#{index -= 1}", group) }
420
- end
418
+ index = data.size
419
+ data.to_a.reverse_each { |group| out.sub!("%#{index -= 1}", group) }
421
420
  out
422
421
  end
423
- @describe[:replace].each do |pat, key|
424
- next unless (data = pat.match(val))
422
+ @describe[:replace].each do |pat, tmpl|
423
+ next unless val =~ pat
425
424
 
426
- val = replace.(data, key.dup)
425
+ val = replace.($~, tmpl.dup)
427
426
  found = true
428
427
  end
429
428
  if (out = @describe[:alias][val])
@@ -431,14 +430,14 @@ module Squared
431
430
  found = true
432
431
  else
433
432
  @describe[:pattern].each do |key, pat|
434
- next unless (data = pat.match(val))
433
+ next unless val =~ pat
435
434
 
436
- val = replace.(data, key.dup)
435
+ val = replace.($~, key.dup)
437
436
  found = true
438
437
  break
439
438
  end
440
439
  end
441
- args = Shell.split_escape(val, char: ':').map! { |s| s.gsub('\\:', ':') } if found
440
+ args = split_escape(val, char: ':').map! { |s| s.gsub('\\:', ':') } if found
442
441
  end
443
442
  desc message(*args, **kwargs)
444
443
  end
@@ -564,7 +563,7 @@ module Squared
564
563
 
565
564
  key = task_join(task_localname(obj.name), key)
566
565
  end
567
- @pass[:pattern].any? { |item| item.is_a?(Regexp) ? key =~ item : key == item }
566
+ @pass[:pattern].any? { |item| item.is_a?(Regexp) ? key.to_s.match?(item) : key == item }
568
567
  end
569
568
 
570
569
  def task_defined?(*key)
@@ -587,6 +586,10 @@ module Squared
587
586
  Rake::Win32.windows?
588
587
  end
589
588
 
589
+ def docker?
590
+ File.exist?('/.dockerenv')
591
+ end
592
+
590
593
  def rootpath(*args)
591
594
  root.join(*args)
592
595
  end
@@ -693,7 +696,7 @@ module Squared
693
696
  end
694
697
  return false if state == :prod && data[:dev] == true && data[:global]
695
698
 
696
- target && pat.is_a?(Regexp) ? as_a(target).any? { |val| val =~ pat } : pat == true
699
+ target && pat.is_a?(Regexp) ? as_a(target).any? { |val| val.match?(pat) } : pat == true
697
700
  end
698
701
 
699
702
  def scriptobj