squared 0.5.16 → 0.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +87 -64
- data/README.md +75 -34
- data/lib/squared/common/base.rb +1 -22
- data/lib/squared/common/format.rb +34 -26
- data/lib/squared/common/prompt.rb +57 -34
- data/lib/squared/common/shell.rb +70 -49
- data/lib/squared/common/system.rb +69 -36
- data/lib/squared/common/utils.rb +29 -6
- data/lib/squared/config.rb +23 -26
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +80 -81
- data/lib/squared/workspace/project/base.rb +517 -354
- data/lib/squared/workspace/project/docker.rb +376 -273
- data/lib/squared/workspace/project/git.rb +329 -314
- data/lib/squared/workspace/project/node.rb +494 -265
- data/lib/squared/workspace/project/python.rb +328 -199
- data/lib/squared/workspace/project/ruby.rb +655 -347
- data/lib/squared/workspace/project/support/class.rb +189 -169
- data/lib/squared/workspace/repo.rb +43 -41
- data/lib/squared/workspace/series.rb +6 -6
- data/lib/squared/workspace/support/base.rb +3 -24
- data/lib/squared/workspace/support/variables.rb +48 -0
- data/lib/squared/workspace/support.rb +1 -1
- data/lib/squared/workspace.rb +1 -1
- metadata +2 -2
- data/lib/squared/workspace/support/data.rb +0 -11
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
unless defined?(Readline)
|
|
4
|
+
if RUBY_ENGINE == 'ruby' && RUBY_VERSION < '2.7'
|
|
5
|
+
require 'readline'
|
|
6
|
+
else
|
|
7
|
+
begin
|
|
8
|
+
require 'reline'
|
|
9
|
+
Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
|
|
10
|
+
Readline = Reline
|
|
11
|
+
rescue LoadError
|
|
12
|
+
require 'readline'
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
3
17
|
module Squared
|
|
4
18
|
module Common
|
|
5
19
|
module Prompt
|
|
6
20
|
module_function
|
|
7
21
|
|
|
8
|
-
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts:
|
|
9
|
-
require 'readline'
|
|
22
|
+
def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 3, timeout: 60)
|
|
10
23
|
require 'timeout'
|
|
11
24
|
if agree == 'Y' && cancel == 'N' && !msg.match?(%r{\[(?:Yn|nY|Y/n|y/N)\]})
|
|
12
25
|
case default
|
|
@@ -38,9 +51,8 @@ module Squared
|
|
|
38
51
|
end
|
|
39
52
|
end
|
|
40
53
|
|
|
41
|
-
def choice(msg, list = nil, min: 1, max: 1, multiple: false,
|
|
42
|
-
attempts:
|
|
43
|
-
require 'readline'
|
|
54
|
+
def choice(msg, list = nil, min: 1, max: 1, multiple: false, index: false, grep: nil, border: nil, auto: true,
|
|
55
|
+
force: true, attempts: 3, timeout: 0)
|
|
44
56
|
require 'timeout'
|
|
45
57
|
if list
|
|
46
58
|
grep &&= Array(grep).map { |val| Regexp.new(val) }
|
|
@@ -52,39 +64,51 @@ module Squared
|
|
|
52
64
|
puts '%2d. %s' % [items.size, val]
|
|
53
65
|
end
|
|
54
66
|
max = items.size
|
|
55
|
-
|
|
67
|
+
raise ArgumentError, 'empty selection list' if max == 0
|
|
68
|
+
|
|
56
69
|
min = grep ? 1 : [min, max].min
|
|
57
70
|
if auto
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
auto.times { puts } if auto.is_a?(::Numeric)
|
|
72
|
+
if border == true
|
|
73
|
+
puts print_footer
|
|
74
|
+
elsif border
|
|
75
|
+
puts print_footer(border: border)
|
|
76
|
+
end
|
|
77
|
+
msg = "#{msg + (force ? ':' : '?')} [#{min}-#{max}#{if (n = multiple)
|
|
78
|
+
"|,#{n.is_a?(::Numeric) ? "{#{n}}" : '*'}"
|
|
79
|
+
end}] "
|
|
61
80
|
end
|
|
62
81
|
end
|
|
63
|
-
|
|
82
|
+
between = ->(s) { s.match?(/^\d+$/) && s.to_i.between?(min, max) }
|
|
64
83
|
Timeout.timeout(timeout) do
|
|
65
84
|
while (ch = Readline.readline(msg))
|
|
66
85
|
unless (ch = ch.strip).empty?
|
|
67
86
|
if multiple
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
k = if ch == '*'
|
|
88
|
+
(min..max).to_a
|
|
89
|
+
else
|
|
90
|
+
ch.split(/\s*,\s*/).map! do |s|
|
|
91
|
+
if s =~ /^(\d+)-(\d+)$/
|
|
92
|
+
next unless between.call($1) && between.call($2)
|
|
72
93
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
i = $1.to_i
|
|
95
|
+
j = $2.to_i
|
|
96
|
+
next (i..j).to_a if i < j
|
|
97
|
+
elsif between.call(s)
|
|
98
|
+
s.to_i
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
unless k.include?(nil)
|
|
103
|
+
k.flatten!
|
|
104
|
+
k.uniq!
|
|
105
|
+
k.sort!
|
|
106
|
+
unless multiple.is_a?(::Numeric) && multiple != k.size
|
|
107
|
+
return index || !items ? k : k.map! { |i| items[i.pred] }
|
|
78
108
|
end
|
|
79
109
|
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
b.uniq!
|
|
83
|
-
b.sort!
|
|
84
|
-
return items ? b.map! { |i| items[i - 1] } : b unless multiple.is_a?(::Numeric) && multiple != b.size
|
|
85
|
-
end
|
|
86
|
-
elsif valid.call(ch)
|
|
87
|
-
return items ? items[ch.to_i - 1] : ch.to_i
|
|
110
|
+
elsif between.call(ch)
|
|
111
|
+
return index || !items ? ch.to_i : items[ch.to_i.pred]
|
|
88
112
|
end
|
|
89
113
|
end
|
|
90
114
|
attempts -= 1
|
|
@@ -97,12 +121,11 @@ module Squared
|
|
|
97
121
|
puts
|
|
98
122
|
exit 0
|
|
99
123
|
else
|
|
100
|
-
|
|
124
|
+
[] if multiple
|
|
101
125
|
end
|
|
102
126
|
end
|
|
103
127
|
|
|
104
128
|
def readline(msg, history = false, force: nil, multiline: nil, &blk)
|
|
105
|
-
require 'readline'
|
|
106
129
|
multiline = if multiline && Readline.respond_to?(:readmultiline)
|
|
107
130
|
multiline.is_a?(::Enumerable) || block_given? ? multiline : [multiline.to_s]
|
|
108
131
|
end
|
|
@@ -117,11 +140,11 @@ module Squared
|
|
|
117
140
|
end
|
|
118
141
|
case force
|
|
119
142
|
when ::TrueClass, ::FalseClass
|
|
120
|
-
msg = "#{msg}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
143
|
+
msg = "#{msg}%s%s " % if multiline
|
|
144
|
+
[' ', multiline.is_a?(::Enumerable) ? "{#{multiline.to_a.join('|')}}" : multiline]
|
|
145
|
+
else
|
|
146
|
+
[force ? ':' : '?', '']
|
|
147
|
+
end
|
|
125
148
|
ret = (prompt.call || '').strip
|
|
126
149
|
multiline.each { |val| break if ret.delete_suffix!(val.to_s) } if multiline.is_a?(::Enumerable)
|
|
127
150
|
exit 1 if force && ret.empty?
|
data/lib/squared/common/shell.rb
CHANGED
|
@@ -6,14 +6,11 @@ require 'shellwords'
|
|
|
6
6
|
module Squared
|
|
7
7
|
module Common
|
|
8
8
|
module Shell
|
|
9
|
-
QUOTE_VALUE = /\A(["'])(.*)\1\z/m.freeze
|
|
10
|
-
private_constant :QUOTE_VALUE
|
|
11
|
-
|
|
12
9
|
module_function
|
|
13
10
|
|
|
14
11
|
def shell_escape(val, quote: false, force: false, double: false, option: false, override: false)
|
|
15
|
-
if (r = /\A(--?)([
|
|
16
|
-
if (data = r[2].match(
|
|
12
|
+
if (r = /\A(--?)([^= ]+)((=|\s+)(["'])?(?(5)(.*)\5|(.*)))?\z/m.match(val = val.to_s))
|
|
13
|
+
if (data = r[2].match(/\A(["'])(.+)\1\z/))
|
|
17
14
|
double = data[1] == '"'
|
|
18
15
|
override = true
|
|
19
16
|
elsif !r[3] || r[6]
|
|
@@ -28,9 +25,9 @@ module Squared
|
|
|
28
25
|
|
|
29
26
|
r[7]
|
|
30
27
|
end
|
|
31
|
-
r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt,
|
|
32
|
-
elsif option && val =~ /\A(
|
|
33
|
-
return val if $2.match?(
|
|
28
|
+
r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt, double: double, force: force, override: override)
|
|
29
|
+
elsif option && val =~ /\A([^=]+)=(.+)\z/m
|
|
30
|
+
return val if $2.match?(/\A(["']).+\1\z/m)
|
|
34
31
|
|
|
35
32
|
"#{$1}=%s" % if $2.include?(' ')
|
|
36
33
|
shell_quote($2, option: false)
|
|
@@ -40,7 +37,7 @@ module Squared
|
|
|
40
37
|
Shellwords.escape($2)
|
|
41
38
|
end
|
|
42
39
|
elsif Rake::Win32.windows?
|
|
43
|
-
quote ? shell_quote(val,
|
|
40
|
+
quote ? shell_quote(val, double: double, force: force) : val
|
|
44
41
|
elsif val.empty?
|
|
45
42
|
''
|
|
46
43
|
else
|
|
@@ -48,56 +45,46 @@ module Squared
|
|
|
48
45
|
end
|
|
49
46
|
end
|
|
50
47
|
|
|
51
|
-
def shell_quote(val, option: true, force: true, double: false,
|
|
48
|
+
def shell_quote(val, option: true, force: true, double: false, override: false)
|
|
52
49
|
val = val.to_s
|
|
53
50
|
return val if (!force && !val.include?(' ')) || val.empty?
|
|
54
51
|
|
|
55
|
-
if option
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
q = ->(s) { s.gsub("'\\\\''", "'") }
|
|
60
|
-
if val =~ QUOTE_VALUE
|
|
61
|
-
return val if $1 == '"' && Rake::Win32.windows? && val.match?(/(?:[#{File::SEPARATOR} ]|\\")/o)
|
|
62
|
-
|
|
63
|
-
base = $2 unless preserve
|
|
64
|
-
end
|
|
65
|
-
if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
|
66
|
-
"\"#{q.call(base || val).gsub(/(?<!\\)"/, '\\"')}\""
|
|
52
|
+
if option && val.match?(/(?:\A|\A[^=\s]+(?:=|\s+)|#{Rake::Win32.windows? ? '[\\\/]' : '\/'})(["']).+\1\z/mo)
|
|
53
|
+
val
|
|
54
|
+
elsif double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
|
|
55
|
+
"\"#{val.gsub(/(?<!\\)"/, '\\"')}\""
|
|
67
56
|
else
|
|
68
|
-
|
|
57
|
+
"'#{val.gsub("'", "'\\\\''")}'"
|
|
69
58
|
end
|
|
70
59
|
end
|
|
71
60
|
|
|
72
|
-
def shell_option(flag, val = nil,
|
|
73
|
-
|
|
61
|
+
def shell_option(flag, val = nil, sep: '=', escape: true, quote: true, force: true, double: false, merge: false,
|
|
62
|
+
override: false)
|
|
74
63
|
flag = flag.to_s
|
|
75
|
-
if flag =~
|
|
64
|
+
if flag =~ /\A(["'])(.+)\1\z/
|
|
76
65
|
double = $1 == '"'
|
|
77
66
|
flag = $2
|
|
78
67
|
escape = false
|
|
79
68
|
override = true
|
|
80
69
|
end
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
end}"
|
|
100
|
-
end}"
|
|
70
|
+
b = if flag[0] == '-'
|
|
71
|
+
flag[1] == '-' ? sep : ' '
|
|
72
|
+
elsif flag.size == 1
|
|
73
|
+
a = '-'
|
|
74
|
+
merge ? '' : ' '
|
|
75
|
+
else
|
|
76
|
+
a = '--'
|
|
77
|
+
sep
|
|
78
|
+
end
|
|
79
|
+
"#{a}#{flag}#{unless val.nil?
|
|
80
|
+
"#{b}#{if escape
|
|
81
|
+
shell_escape(val, quote: quote, double: double, override: override)
|
|
82
|
+
elsif quote
|
|
83
|
+
shell_quote(val, option: false, force: force, double: double, override: override)
|
|
84
|
+
else
|
|
85
|
+
val
|
|
86
|
+
end}"
|
|
87
|
+
end}"
|
|
101
88
|
end
|
|
102
89
|
|
|
103
90
|
def shell_split(val, join: nil, **kwargs)
|
|
@@ -107,10 +94,45 @@ module Squared
|
|
|
107
94
|
ret.join(join.is_a?(::String) ? join : ' ')
|
|
108
95
|
end
|
|
109
96
|
|
|
97
|
+
def shell_parse(val, escape: false, force: true, **kwargs)
|
|
98
|
+
a = []
|
|
99
|
+
b = []
|
|
100
|
+
c = []
|
|
101
|
+
d = []
|
|
102
|
+
e = [a, b]
|
|
103
|
+
j = -1
|
|
104
|
+
val.shellsplit.each_with_index do |opt, i|
|
|
105
|
+
if opt == '--'
|
|
106
|
+
e = [c, d]
|
|
107
|
+
elsif opt =~ /\A--?[^=]+(=|\z)/
|
|
108
|
+
j = $1 == '=' ? -1 : i
|
|
109
|
+
e[0] << [opt]
|
|
110
|
+
elsif j >= 0
|
|
111
|
+
e[0][j] << opt
|
|
112
|
+
else
|
|
113
|
+
e[1] << shell_quote(opt, option: false, force: force)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
ret = [[a, b], [], [c, d]].flat_map do |e, f|
|
|
117
|
+
next '--' unless e
|
|
118
|
+
|
|
119
|
+
e.flat_map do |item|
|
|
120
|
+
if item.size == 1
|
|
121
|
+
fill_option(item.first)
|
|
122
|
+
else
|
|
123
|
+
flag = item.shift
|
|
124
|
+
item.map! { |s| shell_option(flag, s, escape: escape, force: force, **kwargs) }
|
|
125
|
+
end
|
|
126
|
+
end.concat(f)
|
|
127
|
+
end
|
|
128
|
+
ret.pop if ret.last == '--'
|
|
129
|
+
ret
|
|
130
|
+
end
|
|
131
|
+
|
|
110
132
|
def shell_bin(name, env: true)
|
|
111
133
|
key = name.upcase
|
|
112
|
-
shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
|
|
113
|
-
|
|
134
|
+
shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name, option: false, force: false,
|
|
135
|
+
double: true)
|
|
114
136
|
end
|
|
115
137
|
|
|
116
138
|
def line_width(lines)
|
|
@@ -119,7 +141,6 @@ module Squared
|
|
|
119
141
|
end
|
|
120
142
|
|
|
121
143
|
def fill_option(val, **kwargs)
|
|
122
|
-
return val unless val.is_a?(::String)
|
|
123
144
|
return "-#{val}" if val.match?(/\A(?:[a-z]\d*|\d)\z/i)
|
|
124
145
|
|
|
125
146
|
shell_escape(val.start_with?('-') ? val : "--#{val}", **kwargs)
|
|
@@ -6,6 +6,25 @@ require 'rake'
|
|
|
6
6
|
module Squared
|
|
7
7
|
module Common
|
|
8
8
|
module System
|
|
9
|
+
class << self
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def parse_link(val)
|
|
13
|
+
case val
|
|
14
|
+
when ::TrueClass, 's'
|
|
15
|
+
1
|
|
16
|
+
when 'r'
|
|
17
|
+
2
|
|
18
|
+
when 'h'
|
|
19
|
+
3
|
|
20
|
+
else
|
|
21
|
+
raise ArgumentError, "unrecognized 'link' flag: #{val}" if val
|
|
22
|
+
|
|
23
|
+
0
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
9
28
|
module_function
|
|
10
29
|
|
|
11
30
|
def shell(*args, name: :system, **kwargs)
|
|
@@ -29,11 +48,11 @@ module Squared
|
|
|
29
48
|
raise $?.to_s
|
|
30
49
|
end
|
|
31
50
|
|
|
32
|
-
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil,
|
|
33
|
-
|
|
51
|
+
def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, preserve: nil, force: false, verbose: true,
|
|
52
|
+
pass: nil, hidden: false)
|
|
34
53
|
base = Pathname.new(src)
|
|
35
54
|
target = Pathname.new(dest)
|
|
36
|
-
raise
|
|
55
|
+
raise Errno::ENOENT, dest.cleanpath.to_s unless create || target.parent.exist?
|
|
37
56
|
|
|
38
57
|
subdir = {}
|
|
39
58
|
target.mkpath if create
|
|
@@ -57,53 +76,67 @@ module Squared
|
|
|
57
76
|
end
|
|
58
77
|
count = 0
|
|
59
78
|
soft = 0
|
|
79
|
+
type = System.send :parse_link, link
|
|
60
80
|
subdir.each do |dir, files|
|
|
61
|
-
|
|
62
|
-
files.dup
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
if link == 'hard'
|
|
73
|
-
FileUtils.ln(file, dir, force: force, verbose: false)
|
|
74
|
-
else
|
|
75
|
-
FileUtils.ln_s(file, dir, force: force, verbose: false)
|
|
81
|
+
unless type == 0
|
|
82
|
+
items = files.dup
|
|
83
|
+
files.clear
|
|
84
|
+
items.each do |file|
|
|
85
|
+
if file.exist?
|
|
86
|
+
if !file.symlink?
|
|
87
|
+
files << file
|
|
88
|
+
elsif !force
|
|
89
|
+
next
|
|
76
90
|
end
|
|
77
|
-
soft += 1
|
|
78
91
|
end
|
|
92
|
+
case type
|
|
93
|
+
when 1
|
|
94
|
+
FileUtils.ln_s(file, dir, force: force, verbose: false)
|
|
95
|
+
when 2
|
|
96
|
+
FileUtils.ln_s(file.relative_path_from(dir), dir, force: force, verbose: false)
|
|
97
|
+
else
|
|
98
|
+
FileUtils.ln(file, dir, force: force, verbose: false)
|
|
99
|
+
end
|
|
100
|
+
soft += 1
|
|
79
101
|
end
|
|
80
102
|
end
|
|
81
103
|
next if files.empty?
|
|
82
104
|
|
|
83
|
-
out = FileUtils.cp(files, dir, verbose: false)
|
|
105
|
+
out = FileUtils.cp(files, dir, preserve: preserve, verbose: false)
|
|
84
106
|
count += out.size
|
|
85
107
|
end
|
|
86
108
|
puts [target.realpath, subdir.size, soft > 0 ? "#{count}+#{soft}" : count].join(' => ') if verbose
|
|
87
109
|
end
|
|
88
110
|
|
|
89
|
-
def copy_guard(src, dest, link: nil, force: false, verbose: true)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
111
|
+
def copy_guard(*src, dest, base: '.', create: false, link: nil, preserve: nil, force: false, verbose: true)
|
|
112
|
+
src = src.compact.flatten
|
|
113
|
+
dest = Pathname.new(dest).realdirpath
|
|
114
|
+
base = Pathname.new(base).realpath
|
|
115
|
+
dir = if dest.directory?
|
|
116
|
+
true
|
|
117
|
+
elsif src.size > 1
|
|
118
|
+
raise Errno::ENOENT, dest.cleanpath.to_s unless create && !dest.exist?
|
|
119
|
+
|
|
120
|
+
dest.mkpath
|
|
121
|
+
true
|
|
122
|
+
end
|
|
123
|
+
targets = src.map! { |file| [base + file, dir ? dest + File.basename(file) : dest] }
|
|
124
|
+
return if !force && (targets = targets.reject { |to| to[1].exist? }).empty?
|
|
125
|
+
|
|
126
|
+
type = System.send :parse_link, link
|
|
127
|
+
targets.each do |file, to|
|
|
128
|
+
case type
|
|
129
|
+
when 0
|
|
130
|
+
FileUtils.cp(file, to, preserve: preserve, verbose: verbose)
|
|
131
|
+
when 1
|
|
132
|
+
FileUtils.ln_s(file, to, force: force, verbose: verbose)
|
|
133
|
+
when 2
|
|
134
|
+
FileUtils.ln_s(file.relative_path_from(dir ? to.dirname : to), to, force: force, verbose: verbose)
|
|
135
|
+
else
|
|
136
|
+
FileUtils.ln(file, to, force: force, verbose: verbose)
|
|
97
137
|
end
|
|
98
138
|
end
|
|
99
|
-
|
|
100
|
-
when 'hard', 1
|
|
101
|
-
FileUtils.ln(src, dest, force: force, verbose: verbose)
|
|
102
|
-
when ::TrueClass, 'soft', 0
|
|
103
|
-
FileUtils.ln_s(src, dest, force: force, verbose: verbose)
|
|
104
|
-
else
|
|
105
|
-
FileUtils.cp(src, dest, verbose: verbose)
|
|
106
|
-
end
|
|
139
|
+
nil
|
|
107
140
|
end
|
|
108
141
|
end
|
|
109
142
|
end
|
data/lib/squared/common/utils.rb
CHANGED
|
@@ -9,21 +9,44 @@ module Squared
|
|
|
9
9
|
module Utils
|
|
10
10
|
module_function
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
|
|
12
|
+
def as_a(obj, *meth, flat: nil, compact: false, &blk)
|
|
13
|
+
return [] if obj.nil?
|
|
14
|
+
|
|
15
|
+
unless obj.is_a?(::Array)
|
|
16
|
+
obj = if obj.respond_to?(:to_ary)
|
|
17
|
+
obj.to_ary
|
|
18
|
+
elsif obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
|
|
19
|
+
val
|
|
20
|
+
else
|
|
21
|
+
[obj]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
obj = flat.is_a?(::Numeric) ? obj.flatten(flat) : obj.flatten if flat
|
|
25
|
+
obj = obj.compact if compact
|
|
26
|
+
obj = obj.map(&meth.shift) until meth.empty?
|
|
27
|
+
return obj unless block_given?
|
|
28
|
+
|
|
29
|
+
obj.select(&blk)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def split_escape(val, char: ',', &blk)
|
|
33
|
+
ret = val.split(/\s*(?<!\\)#{char}\s*/)
|
|
34
|
+
return ret unless block_given?
|
|
35
|
+
|
|
36
|
+
ret.each(&blk)
|
|
14
37
|
end
|
|
15
38
|
|
|
16
39
|
def split_option(val)
|
|
17
40
|
val = val.strip
|
|
18
41
|
return [val, '', ''] unless (i = val.index('='))
|
|
19
42
|
|
|
20
|
-
last = val[
|
|
43
|
+
last = val[i.succ..-1].strip
|
|
21
44
|
quote = ''
|
|
22
45
|
if last =~ /\A(["'])(.+)\1\z/
|
|
23
46
|
last = $2
|
|
24
47
|
quote = $1
|
|
25
48
|
end
|
|
26
|
-
[val[0..
|
|
49
|
+
[val[0..i.pred], last, quote]
|
|
27
50
|
end
|
|
28
51
|
|
|
29
52
|
def task_invoke(*cmd, args: [], exception: true, warning: true)
|
|
@@ -105,9 +128,9 @@ module Squared
|
|
|
105
128
|
end
|
|
106
129
|
end
|
|
107
130
|
|
|
108
|
-
def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil)
|
|
131
|
+
def env(key, default = nil, suffix: nil, strict: false, equals: nil, ignore: nil, **)
|
|
109
132
|
ret = env_value(key, suffix: suffix, strict: strict)
|
|
110
|
-
return
|
|
133
|
+
return Array(equals).any? { |val| val.to_s == ret } unless equals.nil?
|
|
111
134
|
|
|
112
135
|
ret.empty? || (ignore && Array(ignore).any? { |val| val.to_s == ret }) ? default : ret
|
|
113
136
|
end
|
data/lib/squared/config.rb
CHANGED
|
@@ -12,14 +12,15 @@ module Squared
|
|
|
12
12
|
include Rake::DSL
|
|
13
13
|
|
|
14
14
|
class << self
|
|
15
|
-
def parse(gem, namespace, ext = [
|
|
15
|
+
def parse(gem, namespace, ext = [pkg])
|
|
16
16
|
require gem
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
end
|
|
17
|
+
obj = eval namespace
|
|
18
|
+
Array(ext).each { |val| @@mime_obj[val] = [obj, ext] }
|
|
20
19
|
rescue LoadError, NameError => e
|
|
21
20
|
warn e
|
|
22
21
|
nil
|
|
22
|
+
else
|
|
23
|
+
@@mime_obj[ext.first]
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def link(project, main = project.dependfile.basename, name = nil, **kwargs, &blk)
|
|
@@ -85,7 +86,7 @@ module Squared
|
|
|
85
86
|
['path not found', realpath]
|
|
86
87
|
else
|
|
87
88
|
@required = true
|
|
88
|
-
project ? [project, '
|
|
89
|
+
project ? [project, 'missing'] : %w[name missing]
|
|
89
90
|
end
|
|
90
91
|
warn log_message(Logger::WARN, msg, subject: self.class, hint: hint)
|
|
91
92
|
end
|
|
@@ -105,7 +106,7 @@ module Squared
|
|
|
105
106
|
next unless (data = Viewer.parse(type, type.upcase, ext))
|
|
106
107
|
end
|
|
107
108
|
obj, ext = data
|
|
108
|
-
target = file ||
|
|
109
|
+
target = file || (realpath if target?)
|
|
109
110
|
|
|
110
111
|
task_desc(command, *ext, target: target)
|
|
111
112
|
task type, [:keys] do |_, args|
|
|
@@ -204,14 +205,14 @@ module Squared
|
|
|
204
205
|
|
|
205
206
|
def read_keys(reader, type, file, keys, ext: [type], opts: {})
|
|
206
207
|
if file && (mime = mimetype(file)) && basepath(file).exist?
|
|
207
|
-
raise_error
|
|
208
|
+
raise_error file, mime, hint: 'invalid' unless ext.include?(mime)
|
|
208
209
|
else
|
|
209
210
|
if ext.include?(mime)
|
|
210
211
|
alt = file
|
|
211
212
|
file = nil
|
|
212
213
|
ext[0] = mime
|
|
213
214
|
elsif file
|
|
214
|
-
keys.
|
|
215
|
+
keys.unshift(file)
|
|
215
216
|
alt = basepath "#{main}.{#{ext.join(',')}}"
|
|
216
217
|
file = Dir[alt].first
|
|
217
218
|
else
|
|
@@ -219,7 +220,7 @@ module Squared
|
|
|
219
220
|
args = { hint: 'no keys' }
|
|
220
221
|
end
|
|
221
222
|
unless file
|
|
222
|
-
args ||= {
|
|
223
|
+
args ||= { kind: Errno::ENOENT }
|
|
223
224
|
raise_error(reader.name, "#{File.basename(alt, '.*')}.#{ext.first}", **args)
|
|
224
225
|
end
|
|
225
226
|
end
|
|
@@ -236,22 +237,18 @@ module Squared
|
|
|
236
237
|
title = Pathname.new(file)
|
|
237
238
|
.realpath
|
|
238
239
|
.to_s
|
|
239
|
-
.sub(
|
|
240
|
+
.sub(/^#{Regexp.escape(File.join(Dir.pwd, ''))}/, '')
|
|
240
241
|
emphasize(lines, title: title, sub: unless stdin?
|
|
241
242
|
[
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
{ pat: /\A((?~: ): )(true|false)(\s*)\z/m, styles: theme[:boolean],
|
|
252
|
-
index: 2 },
|
|
253
|
-
{ pat: /\A((?~: ): (?!undefined))([^"\[{].*)\z/m, styles: theme[:value],
|
|
254
|
-
index: 2 }
|
|
243
|
+
opt_style(theme[:banner], /\A((?:[^:]|(?<! ):(?! ))+)\z/),
|
|
244
|
+
opt_style(theme[:undefined], /\A(.*?)(<[^>]+>)(.+)\z/m, 2),
|
|
245
|
+
opt_style(theme[:key], /\A((?~ : ))( : (?!undefined).+)\z/m),
|
|
246
|
+
opt_style(theme[:number], /\A((?~: ): )(-?[\d.]+)(\s*)\z/m, 2),
|
|
247
|
+
opt_style(theme[:string], /\A((?~: ): ")(.+)("\s*)\z/m, 2),
|
|
248
|
+
opt_style(theme[:hash], /\A((?~: ): \{)(.+)(\}\s*)\z/m, 2),
|
|
249
|
+
opt_style(theme[:array], /\A((?~: ): \[)(.+)(\]\s*)\z/m, 2),
|
|
250
|
+
opt_style(theme[:boolean], /\A((?~: ): )(true|false)(\s*)\z/m, 2),
|
|
251
|
+
opt_style(theme[:value], /\A((?~: ): (?!undefined))([^"\[{].*)\z/m, 2)
|
|
255
252
|
]
|
|
256
253
|
end, border: theme[:border])
|
|
257
254
|
end
|
|
@@ -262,7 +259,7 @@ module Squared
|
|
|
262
259
|
symbolize = opts[:symbolize_names]
|
|
263
260
|
keys.each do |key|
|
|
264
261
|
begin
|
|
265
|
-
items = key.split('.')
|
|
262
|
+
items = key.split('.')
|
|
266
263
|
items = items.map(&:to_sym) if symbolize
|
|
267
264
|
val = data.dig(*items)
|
|
268
265
|
if val.nil?
|
|
@@ -308,8 +305,8 @@ module Squared
|
|
|
308
305
|
def task_desc(command, *ext, target: nil)
|
|
309
306
|
return unless Rake::TaskManager.record_task_metadata
|
|
310
307
|
|
|
311
|
-
val = "#{ext.first}[#{
|
|
312
|
-
args = *name.split(':').
|
|
308
|
+
val = "#{ext.first}[#{"file?=#{File.basename(main)}.#{ext.last}," if target}keys+]"
|
|
309
|
+
args = *name.split(':').push(command, val)
|
|
313
310
|
if project
|
|
314
311
|
project.workspace.task_desc(*args)
|
|
315
312
|
else
|
data/lib/squared/version.rb
CHANGED