squared 0.8.5 → 0.9.0.pre1
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 +43 -1
- data/README.md +157 -116
- data/exe/sqd +224 -0
- data/lib/squared/common/base.rb +7 -3
- data/lib/squared/common/format.rb +8 -3
- data/lib/squared/common/prompt.rb +64 -30
- data/lib/squared/common/shell.rb +3 -1
- data/lib/squared/common/system.rb +2 -9
- data/lib/squared/config.rb +3 -3
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +24 -13
- data/lib/squared/workspace/project/base.rb +101 -46
- data/lib/squared/workspace/project/docker.rb +93 -44
- data/lib/squared/workspace/project/git.rb +53 -76
- data/lib/squared/workspace/project/node.rb +13 -11
- data/lib/squared/workspace/project/python.rb +58 -19
- data/lib/squared/workspace/project/ruby.rb +39 -28
- data/lib/squared/workspace/project/support/class.rb +1 -1
- data/lib/squared/workspace/project/support/optionpartition.rb +15 -14
- data/lib/squared/workspace/repo.rb +5 -5
- data/lib/squared/workspace/series.rb +4 -2
- data/squared.gemspec +7 -5
- metadata +20 -4
data/exe/sqd
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$:.unshift(File.expand_path('../lib', __dir__)) if File.exist?(File.expand_path('../squared.gemspec', __dir__))
|
|
5
|
+
|
|
6
|
+
require 'squared'
|
|
7
|
+
require 'rake'
|
|
8
|
+
require 'optparse'
|
|
9
|
+
|
|
10
|
+
class SqdParser < OptionParser
|
|
11
|
+
include Squared::Common::Format
|
|
12
|
+
include Utils
|
|
13
|
+
|
|
14
|
+
attr_reader :options, :global
|
|
15
|
+
|
|
16
|
+
def initialize(*)
|
|
17
|
+
super
|
|
18
|
+
@options = { 'project-args': [], 'project-env': [] }
|
|
19
|
+
@global = []
|
|
20
|
+
@program_name = 'squared'
|
|
21
|
+
@raise_unknown = false
|
|
22
|
+
@require_exact = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def parse_global(list, assert:)
|
|
26
|
+
raise ArgumentError, "cannot be used with --#{assert}" if options.key?(assert)
|
|
27
|
+
|
|
28
|
+
ARGV.each_with_index do |val, index|
|
|
29
|
+
if val == '--'
|
|
30
|
+
separator!(index: index)
|
|
31
|
+
break
|
|
32
|
+
end
|
|
33
|
+
next if val.start_with?('-') || val.include?(':') || val.empty?
|
|
34
|
+
|
|
35
|
+
global.concat(list.map { |name| "#{val}:#{name}" })
|
|
36
|
+
ARGV[index] = ''
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def parse_common(list, session:, arg:)
|
|
41
|
+
if list && !list.include?('*')
|
|
42
|
+
session[arg].merge!(list.to_h { |key| [key, 'true'] })
|
|
43
|
+
else
|
|
44
|
+
session[arg] = Hash.new('true')
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def banner_set(val, session:)
|
|
49
|
+
session[:BANNER] = val
|
|
50
|
+
ENV['BANNER'] = val ? 'true' : 'false'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def color_set(val, session:)
|
|
54
|
+
if (session[:COLOR] = val)
|
|
55
|
+
enable_aixterm
|
|
56
|
+
enable_drawing
|
|
57
|
+
else
|
|
58
|
+
enable_drawing false
|
|
59
|
+
Squared::Common.const_get(:VAR)[:colors].freeze
|
|
60
|
+
end
|
|
61
|
+
ENV['NO_COLOR'] = val ? nil : '1'
|
|
62
|
+
ENV['FORCE_COLOR'] = val ? '2' : '0'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def run
|
|
66
|
+
parse!(into: options)
|
|
67
|
+
if (project = options[:project])
|
|
68
|
+
pattern, project = project.partition do |val|
|
|
69
|
+
next true if val == '*'
|
|
70
|
+
|
|
71
|
+
val = ".#{val}" if val.start_with?('*')
|
|
72
|
+
val.match?(/[*+\[(]|(?<!\\)\.\.|\{\d+\}/) && Regexp.new(val)
|
|
73
|
+
rescue RegexpError
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
pattern.each do |val|
|
|
77
|
+
val = if val == '*'
|
|
78
|
+
'[^:]+'
|
|
79
|
+
else
|
|
80
|
+
val.sub(/^\*/, '.*')
|
|
81
|
+
.sub(/(?<!\.)\*$/, '.*')
|
|
82
|
+
.gsub(/\.([*+])/, '[^:]\1?')
|
|
83
|
+
end
|
|
84
|
+
IO.popen("rake -T \"^#{val}:\"").each { |line| project << $1 if line =~ /\Arake (#{val}):/o }
|
|
85
|
+
end
|
|
86
|
+
exit 1 if project.empty? && !pattern.empty?
|
|
87
|
+
project.uniq!
|
|
88
|
+
options[:'project-env'].each do |val|
|
|
89
|
+
n = val.index('=')
|
|
90
|
+
key = val[...n]
|
|
91
|
+
val = val[n.succ..].stripquote
|
|
92
|
+
project.each { |name| ENV["#{key}_#{env_key(name.split(':').first)}"] = val }
|
|
93
|
+
end
|
|
94
|
+
ARGV.each_with_index do |val, index|
|
|
95
|
+
if val == '--'
|
|
96
|
+
separator!(index: index)
|
|
97
|
+
break
|
|
98
|
+
end
|
|
99
|
+
next unless val.start_with?(':')
|
|
100
|
+
|
|
101
|
+
args = options[:'project-args'].shift
|
|
102
|
+
global.concat(project.map { |name| "#{name}#{val}#{"[#{args}]" if args}" })
|
|
103
|
+
ARGV[index] = ''
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
ARGV.reject!(&:empty?)
|
|
107
|
+
Rake.application.run(global.concat(ARGV))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def separator!(index:)
|
|
111
|
+
ARGV[index] = '' if ARGV.grep('--').size > 1
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def error_exit(*val, hint)
|
|
115
|
+
raise OptionParser::InvalidArgument, message(*val, hint: hint)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
SqdParser.new do |sqd|
|
|
120
|
+
session = Squared::Common::ARG
|
|
121
|
+
sqd.banner = 'Usage: sqd [options] [rake options] [global...] [:targets...] -- [rake targets...]'
|
|
122
|
+
sqd.separator ''
|
|
123
|
+
sqd.on('-R', '--ref STR,STR', Array, 'Run global commands by class reference') do |val|
|
|
124
|
+
sqd.parse_global(val, assert: :group)
|
|
125
|
+
session[:APP][:series_ref_min] = 1
|
|
126
|
+
end
|
|
127
|
+
sqd.on('-G', '--group STR,STR', Array, 'Run global commands by project group') do |val|
|
|
128
|
+
sqd.parse_global(val, assert: :ref)
|
|
129
|
+
end
|
|
130
|
+
sqd.separator ''
|
|
131
|
+
sqd.on('-P', '--project STR,PAT', Array, 'Run project commands with common arguments')
|
|
132
|
+
sqd.on('-a', '--project-args STR,STR', 'Provide command arguments for :targets (multiple)') do |val|
|
|
133
|
+
sqd.options[:'project-args'] << val
|
|
134
|
+
end
|
|
135
|
+
sqd.on('-e', '--project-env KEY=STR', 'Provide command ENV variables for :targets (multiple)') do |val|
|
|
136
|
+
sqd.error_exit('missing value', "#{val}=") unless val.include?('=')
|
|
137
|
+
|
|
138
|
+
sqd.options[:'project-env'] << val
|
|
139
|
+
end
|
|
140
|
+
sqd.separator ''
|
|
141
|
+
sqd.on('-s', '--[no-]strict', 'Do not run commands with invalid arguments') do |val|
|
|
142
|
+
session[:STRICT] = val
|
|
143
|
+
ENV['STRICT'] = val ? 'true' : 'false'
|
|
144
|
+
end
|
|
145
|
+
sqd.on('--update', 'Use update strategy for applicable commands') do
|
|
146
|
+
ENV['UPDATE'] = 'true'
|
|
147
|
+
end
|
|
148
|
+
sqd.on('-F', '--force [STR,STR]', Array, 'Enable force through ENV by application') do |val|
|
|
149
|
+
sqd.parse_common(val, session: session, arg: :FORCE)
|
|
150
|
+
end
|
|
151
|
+
sqd.on('-y', '--yes [STR,STR]', Array, 'Enable auto-approve through ENV by application') do |val|
|
|
152
|
+
sqd.parse_common(val, session: session, arg: :YES)
|
|
153
|
+
end
|
|
154
|
+
sqd.on('-d', '--dry-run', 'Run commands without any modifying actions') do
|
|
155
|
+
ENV['DRY_RUN'] = 'true'
|
|
156
|
+
end
|
|
157
|
+
sqd.separator ''
|
|
158
|
+
sqd.on('-S', '--select PAGE:CHOICE', 'Prompt menu selection pagination limits') do |val|
|
|
159
|
+
page, choice = val.split(/\D/, 2).map(&:to_i)
|
|
160
|
+
sqd.error_exit('not an integer', val) if choice.nil? ? page == 0 : choice == 0
|
|
161
|
+
|
|
162
|
+
session[:PAGE] = page if page > 0
|
|
163
|
+
session[:CHOICE] = choice if choice.to_i > 0
|
|
164
|
+
ENV['SELECT'] = "#{page}:#{choice}"
|
|
165
|
+
end
|
|
166
|
+
sqd.separator ''
|
|
167
|
+
sqd.on('-p', '--pipe 0|1|2', Integer, 'Set file descriptor for communication') do |val|
|
|
168
|
+
sqd.error_exit('out of range', val) unless val.between?(0, 2)
|
|
169
|
+
|
|
170
|
+
session[:PIPE] = val
|
|
171
|
+
end
|
|
172
|
+
sqd.on('-o', '--pipe-out FILE', 'Write command data stream to a file') do |val|
|
|
173
|
+
sqd.error_exit("missing an explicit \".#{File::SEPARATOR}\"", val) unless val.include?(File::SEPARATOR)
|
|
174
|
+
|
|
175
|
+
session[:OUT] = val
|
|
176
|
+
end
|
|
177
|
+
sqd.on('--fail 0..4', Integer, 'Set application exception level') do |val|
|
|
178
|
+
sqd.error_exit('out of range', val) unless val.between?(0, 4)
|
|
179
|
+
|
|
180
|
+
session[:FAIL] = val
|
|
181
|
+
end
|
|
182
|
+
%i[debug info warn error fatal].then do |state|
|
|
183
|
+
values = state + (0..4).map(&:to_s)
|
|
184
|
+
sqd.on('--log-level SEVERITY', values, "Set logger and exception state (#{state.join(', ')})") do |val|
|
|
185
|
+
require 'logger'
|
|
186
|
+
severity = case val
|
|
187
|
+
when :debug then Logger::DEBUG
|
|
188
|
+
when :info then Logger::INFO
|
|
189
|
+
when :warn then Logger::WARN
|
|
190
|
+
when :error then Logger::ERROR
|
|
191
|
+
when :fatal then Logger::FATAL
|
|
192
|
+
else
|
|
193
|
+
val.to_i
|
|
194
|
+
end
|
|
195
|
+
session[:LEVEL] = severity
|
|
196
|
+
ENV['LOG_LEVEL'] = severity.to_s
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
sqd.separator ''
|
|
200
|
+
sqd.on('--[no-]banner', 'Display executing command attributes') do |val|
|
|
201
|
+
sqd.banner_set(val, session: session)
|
|
202
|
+
end
|
|
203
|
+
sqd.on('-x', '--[no-]color', 'Use enhanced styling for terminal output') do |val|
|
|
204
|
+
sqd.color_set(val, session: session)
|
|
205
|
+
end
|
|
206
|
+
sqd.on('-X', '--plain', 'Disable banner and styling for all commands') do
|
|
207
|
+
sqd.banner_set(false, session: session)
|
|
208
|
+
sqd.color_set(false, session: session)
|
|
209
|
+
end
|
|
210
|
+
sqd.on('-v', '--verbose', 'Increase output verbosity (multiple)') do
|
|
211
|
+
unless session[:VERBOSE]
|
|
212
|
+
session[:VERBOSE] = $VERBOSE ? 1 : 0
|
|
213
|
+
sqd.global.unshift('--verbose')
|
|
214
|
+
end
|
|
215
|
+
ENV['VERBOSE'] = (session[:VERBOSE] += 1).to_s
|
|
216
|
+
end
|
|
217
|
+
sqd.on('--version', 'Print the current version') do
|
|
218
|
+
puts Squared::VERSION
|
|
219
|
+
exit 0
|
|
220
|
+
end
|
|
221
|
+
sqd.on('-h', '--help', 'Print the command line options') do
|
|
222
|
+
sqd.help_exit
|
|
223
|
+
end
|
|
224
|
+
end.run
|
data/lib/squared/common/base.rb
CHANGED
|
@@ -11,13 +11,17 @@ module Squared
|
|
|
11
11
|
COMMON: true,
|
|
12
12
|
VERBOSE: nil,
|
|
13
13
|
STRICT: false,
|
|
14
|
+
FORCE: {},
|
|
15
|
+
YES: {},
|
|
16
|
+
APP: {},
|
|
14
17
|
BANNER: true,
|
|
15
|
-
|
|
18
|
+
PAGE: 20,
|
|
19
|
+
CHOICE: 100,
|
|
16
20
|
QUOTE: "'",
|
|
17
21
|
SPACE: ' => ',
|
|
18
22
|
SUCCESS: 'Success',
|
|
19
|
-
GRAPH: %w[| - | \\ -]
|
|
20
|
-
BORDER: %w[| - - - - - | | - -]
|
|
23
|
+
GRAPH: %w[| - | \\ -],
|
|
24
|
+
BORDER: %w[| - - - - - | | - -],
|
|
21
25
|
VIEW: 'view',
|
|
22
26
|
LEVEL: ENV.fetch('LOG_LEVEL', 0).to_i,
|
|
23
27
|
COLOR: ENV.fetch('NO_COLOR', '').empty?
|
|
@@ -50,9 +50,14 @@ module Squared
|
|
|
50
50
|
self
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
def enable_drawing
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
def enable_drawing(state = true)
|
|
54
|
+
if state
|
|
55
|
+
ARG[:GRAPH] = BOX_GRAPH unless ARG[:GRAPH].frozen?
|
|
56
|
+
ARG[:BORDER] = BOX_BORDER unless ARG[:BORDER].frozen?
|
|
57
|
+
else
|
|
58
|
+
ARG[:GRAPH].freeze
|
|
59
|
+
ARG[:BORDER].freeze
|
|
60
|
+
end
|
|
56
61
|
self
|
|
57
62
|
end
|
|
58
63
|
|
|
@@ -1,27 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'timeout'
|
|
4
|
+
|
|
3
5
|
module Squared
|
|
4
6
|
module Common
|
|
5
7
|
module Prompt
|
|
6
8
|
def self.reline
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
require 'reline'
|
|
13
|
-
Reline
|
|
14
|
-
rescue LoadError
|
|
15
|
-
require 'readline'
|
|
16
|
-
Readline
|
|
17
|
-
end
|
|
18
|
-
end
|
|
9
|
+
require 'reline'
|
|
10
|
+
Reline
|
|
11
|
+
rescue LoadError
|
|
12
|
+
require 'readline'
|
|
13
|
+
Readline
|
|
19
14
|
end
|
|
20
15
|
|
|
21
16
|
module_function
|
|
22
17
|
|
|
23
18
|
def confirm(msg, accept = nil, agree: 'Y', cancel: 'N', force: false, attempts: 3, timeout: 60)
|
|
24
|
-
require 'timeout'
|
|
25
19
|
if agree == 'Y' && cancel == 'N' && !msg.match?(%r{\[(Yn|nY|Y/n|y/N)\]})
|
|
26
20
|
case accept
|
|
27
21
|
when 'Y'
|
|
@@ -34,7 +28,7 @@ module Squared
|
|
|
34
28
|
cancel = /^#{Regexp.escape(cancel)}$/i if cancel.is_a?(::String)
|
|
35
29
|
Timeout.timeout(timeout) do
|
|
36
30
|
while (ch = Prompt.reline.readline(msg))
|
|
37
|
-
ch
|
|
31
|
+
ch.chomp!
|
|
38
32
|
case (ch.empty? ? accept : ch)
|
|
39
33
|
when agree
|
|
40
34
|
return true
|
|
@@ -54,9 +48,9 @@ module Squared
|
|
|
54
48
|
false
|
|
55
49
|
end
|
|
56
50
|
|
|
57
|
-
def choice(msg, list = nil, min: 1, max:
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
def choice(msg, list = nil, min: 1, max: nil, multiple: false, index: false, grep: nil, border: nil, force: true,
|
|
52
|
+
attempts: 3, timeout: 0, pipe: 1, scroll: true, empty: nil, page: 25)
|
|
53
|
+
std = pipe == 2 ? $stderr : $stdout
|
|
60
54
|
multiple = Array(multiple) if multiple.is_a?(::Numeric)
|
|
61
55
|
if list
|
|
62
56
|
grep &&= Array(grep).map { |val| Regexp.new(val) }
|
|
@@ -64,33 +58,70 @@ module Squared
|
|
|
64
58
|
next if grep&.none? { |pat| pat.match?(val) }
|
|
65
59
|
|
|
66
60
|
out << val.to_s.chomp
|
|
67
|
-
puts '%2d. %s' % [out.size, val]
|
|
68
61
|
end
|
|
69
|
-
max = items.size
|
|
62
|
+
max = max ? [max, items.size].min : items.size
|
|
70
63
|
if max == 0
|
|
71
64
|
raise ArgumentError, 'empty selection list' unless empty
|
|
72
65
|
|
|
73
66
|
puts empty
|
|
74
67
|
exit 1
|
|
75
68
|
end
|
|
69
|
+
tmpl = "%#{[items.size.to_s.size, 2].max}d. %s"
|
|
70
|
+
items = items.map.with_index { |item, i| [item, tmpl % [i.succ, item]] }
|
|
76
71
|
min = grep ? 1 : [min, max].min
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
require 'io/console'
|
|
73
|
+
if min > 1 || max < items.size
|
|
74
|
+
items = items[min.pred...max]
|
|
75
|
+
min = 1
|
|
76
|
+
end
|
|
77
|
+
page = page ? [page, max].min : max
|
|
78
|
+
cur = 0
|
|
79
|
+
line = 0
|
|
80
|
+
last = (max / page.to_f).ceil
|
|
81
|
+
pre = msg
|
|
82
|
+
scroll = true if border
|
|
83
|
+
clear = -> { std.print "\r\e[K" }
|
|
84
|
+
write = lambda do |s, buf = true|
|
|
85
|
+
line += [s.lines.size, 1].max if buf
|
|
86
|
+
clear.call unless scroll && !border
|
|
87
|
+
std.puts s
|
|
88
|
+
end
|
|
89
|
+
render = lambda do |index, init = false|
|
|
90
|
+
fr = index * page
|
|
91
|
+
to = [fr + page, max].min
|
|
92
|
+
unless init
|
|
93
|
+
std.cursor_up((scroll ? 0 : page) + line.succ)
|
|
94
|
+
clear.call
|
|
95
|
+
end
|
|
96
|
+
line = 0
|
|
97
|
+
items[fr...to].each { |item| write.call(item.last, false) }
|
|
79
98
|
if border == true
|
|
80
|
-
|
|
99
|
+
write.call(print_footer)
|
|
81
100
|
elsif border
|
|
82
|
-
|
|
101
|
+
write.call(print_footer(border: border))
|
|
102
|
+
end
|
|
103
|
+
fr = scroll ? 1 : fr.succ
|
|
104
|
+
suf = "|,#{multiple.is_a?(::Array) ? "{#{multiple.join(',')}}" : '*'}" if multiple
|
|
105
|
+
msg = "#{pre + (force ? ':' : '?')} [#{fr}-#{to}#{"/#{max}" if scroll && to < max}#{suf}] "
|
|
106
|
+
if cur == last.pred
|
|
107
|
+
cur = -1
|
|
108
|
+
last = 0 if scroll || (attempts -= 1) == 0
|
|
109
|
+
end
|
|
110
|
+
if init && last > 1 && !scroll
|
|
111
|
+
write.call('', false)
|
|
112
|
+
std.cursor_up(1)
|
|
83
113
|
end
|
|
84
|
-
msg = "#{msg + (force ? ':' : '?')} [#{min}-#{max}#{if (n = multiple)
|
|
85
|
-
"|,#{n.is_a?(::Array) ? "{#{n.join(',')}}" : '*'}"
|
|
86
|
-
end}] "
|
|
87
114
|
end
|
|
115
|
+
render.call(0, true)
|
|
116
|
+
else
|
|
117
|
+
max ||= 1
|
|
118
|
+
last = 0
|
|
88
119
|
end
|
|
89
120
|
between = ->(s) { s.match?(/^\d+$/) && s.to_i.between?(min, max <= min ? Float::INFINITY : max) }
|
|
90
121
|
Timeout.timeout(timeout) do
|
|
91
122
|
while (ch = Prompt.reline.readline(msg))
|
|
92
123
|
ch.strip!
|
|
93
|
-
|
|
124
|
+
if !ch.empty?
|
|
94
125
|
if multiple
|
|
95
126
|
k = if ch == '*'
|
|
96
127
|
(min..max).to_a
|
|
@@ -112,12 +143,15 @@ module Squared
|
|
|
112
143
|
k.uniq!
|
|
113
144
|
k.sort!
|
|
114
145
|
unless multiple.is_a?(::Array) && !multiple.include?(k.size)
|
|
115
|
-
return index || !items ? k : k.map { |i| items[i.pred] }
|
|
146
|
+
return index || !items ? k : k.map { |i| items[i.pred].first }
|
|
116
147
|
end
|
|
117
148
|
end
|
|
118
149
|
elsif between.call(ch)
|
|
119
|
-
return index || !items ? ch.to_i : items[ch.to_i.pred]
|
|
150
|
+
return index || !items ? ch.to_i : items[ch.to_i.pred].first
|
|
120
151
|
end
|
|
152
|
+
elsif last > 0
|
|
153
|
+
render.call(cur += 1)
|
|
154
|
+
next
|
|
121
155
|
end
|
|
122
156
|
attempts -= 1
|
|
123
157
|
next if attempts > 0
|
|
@@ -126,7 +160,7 @@ module Squared
|
|
|
126
160
|
break
|
|
127
161
|
end
|
|
128
162
|
rescue Interrupt
|
|
129
|
-
puts
|
|
163
|
+
std.puts
|
|
130
164
|
exit 0
|
|
131
165
|
else
|
|
132
166
|
[] if multiple
|
data/lib/squared/common/shell.rb
CHANGED
|
@@ -167,7 +167,9 @@ module Squared
|
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
def line_width(lines)
|
|
170
|
-
|
|
170
|
+
require 'io/console/size'
|
|
171
|
+
cols = IO.default_console_size.last
|
|
172
|
+
[lines.empty? ? cols : [lines.max_by(&:size).size, cols].max, Rake.application.terminal_width].min
|
|
171
173
|
end
|
|
172
174
|
|
|
173
175
|
def fill_option(val, **kwargs)
|
|
@@ -28,15 +28,8 @@ module Squared
|
|
|
28
28
|
module_function
|
|
29
29
|
|
|
30
30
|
def shell(*args, name: :system, **kwargs)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
elsif RUBY_VERSION < '2.6'
|
|
34
|
-
ex = kwargs.delete(:exception)
|
|
35
|
-
end
|
|
36
|
-
ret = Kernel.send(name, *args, **kwargs)
|
|
37
|
-
raise $?.to_s if ex && !ret
|
|
38
|
-
|
|
39
|
-
ret
|
|
31
|
+
kwargs.delete(:exception) unless name == :system
|
|
32
|
+
Kernel.send(name, *args, **kwargs)
|
|
40
33
|
end
|
|
41
34
|
|
|
42
35
|
def shell_t(*args, timeout: 0, **kwargs)
|
data/lib/squared/config.rb
CHANGED
|
@@ -65,7 +65,7 @@ module Squared
|
|
|
65
65
|
command = File.basename(@main)
|
|
66
66
|
command = ARG[:VIEW] if command == @name
|
|
67
67
|
end
|
|
68
|
-
ext = @ext[1
|
|
68
|
+
ext = @ext[1..].downcase
|
|
69
69
|
if (data = @@mime_obj[ext])
|
|
70
70
|
add(data[1].first, command: command, opts: opts, ext: data[1])
|
|
71
71
|
else
|
|
@@ -98,7 +98,7 @@ module Squared
|
|
|
98
98
|
namespace task_name(name) do |ns|
|
|
99
99
|
@mime.each do |type, items|
|
|
100
100
|
items.each do |command, file, opts|
|
|
101
|
-
next if Rake::Task.task_defined?(
|
|
101
|
+
next if Rake::Task.task_defined?(task_join(ns.scope.path, command, type))
|
|
102
102
|
|
|
103
103
|
namespace command do
|
|
104
104
|
unless (data = @@mime_obj[type])
|
|
@@ -288,7 +288,7 @@ module Squared
|
|
|
288
288
|
if project
|
|
289
289
|
project.workspace.task_name(val)
|
|
290
290
|
else
|
|
291
|
-
@prefix ?
|
|
291
|
+
@prefix ? task_join(@prefix, val) : val.to_s
|
|
292
292
|
end
|
|
293
293
|
end
|
|
294
294
|
|
data/lib/squared/version.rb
CHANGED
|
@@ -163,6 +163,9 @@ module Squared
|
|
|
163
163
|
end
|
|
164
164
|
@pass.items.concat(kwargs[:pass].map { |val| val.is_a?(Regexp) ? val : val.to_s }) if kwargs[:pass]
|
|
165
165
|
@series = Application.register(self, @base.to_a, exclude: kwargs.fetch(:exclude, []))
|
|
166
|
+
if (n = ARG[:APP][:series_ref_min])
|
|
167
|
+
@series.ref_min = n
|
|
168
|
+
end
|
|
166
169
|
self.closed = 'begin'
|
|
167
170
|
pb = @stage.key?('project:begin')
|
|
168
171
|
pe = @stage.key?('project:end')
|
|
@@ -341,7 +344,7 @@ module Squared
|
|
|
341
344
|
case val
|
|
342
345
|
when Symbol
|
|
343
346
|
found = true
|
|
344
|
-
banner_include?(val)
|
|
347
|
+
banner_include?(val, ref: ref)
|
|
345
348
|
when String
|
|
346
349
|
true
|
|
347
350
|
else
|
|
@@ -353,7 +356,7 @@ module Squared
|
|
|
353
356
|
elsif meth.size == 1
|
|
354
357
|
meth = meth.first
|
|
355
358
|
end
|
|
356
|
-
elsif !banner_include?(meth = meth.to_sym)
|
|
359
|
+
elsif !banner_include?(meth = meth.to_sym, ref: ref)
|
|
357
360
|
next
|
|
358
361
|
end
|
|
359
362
|
data.order << meth
|
|
@@ -409,7 +412,11 @@ module Squared
|
|
|
409
412
|
end || @kind[name]&.last
|
|
410
413
|
if proj
|
|
411
414
|
@base << proj
|
|
412
|
-
|
|
415
|
+
args = Array(proj.bannerargs)
|
|
416
|
+
unless args.empty?
|
|
417
|
+
@banner.store[proj.ref] = args
|
|
418
|
+
@banner.items.concat(args)
|
|
419
|
+
end
|
|
413
420
|
else
|
|
414
421
|
proj = Application.impl_project
|
|
415
422
|
end
|
|
@@ -580,7 +587,7 @@ module Squared
|
|
|
580
587
|
def task_namespace(val, first: false)
|
|
581
588
|
return unless (ret = val.to_s.split(':')).size > 1
|
|
582
589
|
|
|
583
|
-
first ? ret.first : task_join(*ret[
|
|
590
|
+
first ? ret.first : task_join(*ret[..-2])
|
|
584
591
|
end
|
|
585
592
|
|
|
586
593
|
def task_resolve(obj, key)
|
|
@@ -950,7 +957,7 @@ module Squared
|
|
|
950
957
|
key = task_name(task_join(name, target))
|
|
951
958
|
sync = true
|
|
952
959
|
exception = exception?
|
|
953
|
-
if store && (kwargs = store[
|
|
960
|
+
if store && (kwargs = store[task_join(target, name)])
|
|
954
961
|
sync = kwargs[:sync] if kwargs.key?(:sync)
|
|
955
962
|
exception = kwargs[:exception] if kwargs.key?(:exception)
|
|
956
963
|
end
|
|
@@ -971,9 +978,11 @@ module Squared
|
|
|
971
978
|
end
|
|
972
979
|
end
|
|
973
980
|
when Array
|
|
974
|
-
cmd =
|
|
975
|
-
|
|
976
|
-
|
|
981
|
+
cmd = items.filter_map do |proj|
|
|
982
|
+
next unless task_defined?(out = task_join(proj.name, args.first))
|
|
983
|
+
|
|
984
|
+
out
|
|
985
|
+
end
|
|
977
986
|
next if cmd.empty?
|
|
978
987
|
|
|
979
988
|
args = args.drop(1)
|
|
@@ -1014,7 +1023,7 @@ module Squared
|
|
|
1014
1023
|
@events[label][name][task] = on
|
|
1015
1024
|
end
|
|
1016
1025
|
data[label][name][task] = val
|
|
1017
|
-
(data.store[label] ||= {})[
|
|
1026
|
+
(data.store[label] ||= {})[task_join(name, task)] = store if store
|
|
1018
1027
|
end
|
|
1019
1028
|
self
|
|
1020
1029
|
end
|
|
@@ -1028,7 +1037,7 @@ module Squared
|
|
|
1028
1037
|
Array(group).each do |val|
|
|
1029
1038
|
val = val.to_s
|
|
1030
1039
|
if val.start_with?('-')
|
|
1031
|
-
target[:exclude] << val[1
|
|
1040
|
+
target[:exclude] << val[1..]
|
|
1032
1041
|
else
|
|
1033
1042
|
target[:group][val] = data
|
|
1034
1043
|
end
|
|
@@ -1037,7 +1046,7 @@ module Squared
|
|
|
1037
1046
|
Array(ref).each do |val|
|
|
1038
1047
|
val = val.to_s
|
|
1039
1048
|
if val.start_with?('-')
|
|
1040
|
-
target[:exclude] << val[1
|
|
1049
|
+
target[:exclude] << val[1..].to_sym
|
|
1041
1050
|
else
|
|
1042
1051
|
target[:ref][val.to_sym] = data
|
|
1043
1052
|
end
|
|
@@ -1111,8 +1120,10 @@ module Squared
|
|
|
1111
1120
|
exception != false && exception != Logger::INFO
|
|
1112
1121
|
end
|
|
1113
1122
|
|
|
1114
|
-
def banner_include?(val)
|
|
1115
|
-
Application.attr_banner.include?(val)
|
|
1123
|
+
def banner_include?(val, ref: nil)
|
|
1124
|
+
return true if Application.attr_banner.include?(val)
|
|
1125
|
+
|
|
1126
|
+
ref ? Array(ref).any? { |proj| @banner.store[proj]&.include?(val) } : @banner.items.include?(val)
|
|
1116
1127
|
end
|
|
1117
1128
|
|
|
1118
1129
|
def scriptobj
|