squared 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 117c669053bf0539d41840f655c1f7cb9a87af7d90366ded3c19803949184cdc
4
- data.tar.gz: 84266b0dd2bc5736eb05b5799692fd4fbed756e8a096343dc85f670e9257ae07
3
+ metadata.gz: 1795e8352e8278c8f4e26ced26ac936ce906ee8e626a9cf2ff2bf6a86412f09c
4
+ data.tar.gz: '08b8e2538b6316ffb141c15e560187222cbb18e0a37f5c74af6ed5fda87e6dc3'
5
5
  SHA512:
6
- metadata.gz: 862884efb840359442202f1670ba4b8ff032397a3e6e6d5720289f844f63ec3119045bfb60b1f2c41673472d32861228587e7a33ab0fbf87d2c7df5e5fa37cde
7
- data.tar.gz: f775903d05491cbe92d80e9db391afa970c866fa4ae885666ffe4e95282d102df5b9faab6f20b17d9368243ff73c6552ff3c56ecf11423d6f68eaeaf4f242288
6
+ metadata.gz: a8d6bd537e66b744edd760ead7441aad45961bdc746e9ca81f577e8183893cd6209203f2ba507b5ab608bbf3ebe7a15aeb23aa84005a76bf10d0f3b3704c403d
7
+ data.tar.gz: 9a29c720ce14050bc604c9b561c376f55437865610827075dd6a2a961ce82b22c1f4b3fd303884186f9c59b1a330ed73ce14ad16169724c3578d8d4e01388bfe
data/README.ruby.md CHANGED
@@ -33,7 +33,7 @@ require "squared"
33
33
 
34
34
  Repo::Workspace
35
35
  .new("squared") # REPO_HOME
36
- .repo("https://github.com/anpham6/squared-repo", "nightly") # Optional
36
+ .repo("https://github.com/anpham6/squared-repo", "nightly", run: 'build') # Optional
37
37
  .run("rake install", ref: :ruby)
38
38
  .clean("rake clean", group: "default") # depend test doc
39
39
  .clean(["build/"], group: "app")
@@ -27,13 +27,13 @@ module Squared
27
27
  private_constant :AIX_TERM, :TEXT_STYLE
28
28
 
29
29
  def enable_aixterm
30
- unless (colors = get!(:colors)).frozen?
30
+ unless (colors = __get__(:colors)).frozen?
31
31
  colors.merge!(AIX_TERM)
32
32
  end
33
33
  block_given? ? yield(self) : self
34
34
  end
35
35
 
36
- def emphasize(val, title: nil, cols: nil, sub: nil)
36
+ def emphasize(val, title: nil, cols: nil, sub: nil, pipe: nil)
37
37
  n = 0
38
38
  if title
39
39
  title = title.to_s
@@ -64,8 +64,12 @@ module Squared
64
64
  out << bord
65
65
  if block_given?
66
66
  yield out
67
+ elsif pipe.respond_to?(:puts)
68
+ pipe.puts out
69
+ elsif err
70
+ defined?(__warn__) == 'method' ? __warn__(out) : warn(out)
67
71
  else
68
- err ? Warning.warn(out) : puts(out)
72
+ puts out
69
73
  end
70
74
  end
71
75
 
@@ -100,7 +104,7 @@ module Squared
100
104
  end
101
105
  else
102
106
  t = type.to_sym
103
- if (c = get!(:colors)[t])
107
+ if (c = __get__(:colors)[t])
104
108
  if index == -1
105
109
  s = wrap.(s, [c])
106
110
  else
@@ -138,7 +142,7 @@ module Squared
138
142
 
139
143
  def check_style(*args, empty: true)
140
144
  ret = []
141
- colors = get!(:colors)
145
+ colors = __get__(:colors)
142
146
  as_a(args, flat: true).each do |val|
143
147
  if !val.is_a?(Numeric)
144
148
  val = val.to_sym
@@ -153,6 +157,17 @@ module Squared
153
157
  !empty && ret.empty? ? nil : ret
154
158
  end
155
159
 
160
+ def apply_style(data, key, *args, empty: true)
161
+ return unless !data.is_a?(Symbol) || (data = __get__(:theme)[data])
162
+
163
+ set = ->(k, v) { data[k.to_sym] = check_style(v, empty: empty) }
164
+ if key.is_a?(Hash)
165
+ key.each { |k, v| set.(k, v || args.flatten) }
166
+ else
167
+ set.(key, args.flatten)
168
+ end
169
+ end
170
+
156
171
  def log_title(level, color: true)
157
172
  level = if level.is_a?(::Numeric)
158
173
  case level
@@ -172,7 +187,8 @@ module Squared
172
187
  else
173
188
  level.to_s.downcase.to_sym
174
189
  end
175
- val = get!(:logger)[level] || get!(:logger)[level = :unknown]
190
+ theme = __get__(:theme)[:logger]
191
+ val = theme[level] || theme[level = :unknown]
176
192
  level = +level.to_s.upcase
177
193
  case level
178
194
  when 'WARN', 'ERROR', 'FATAL'
@@ -5,8 +5,6 @@ require 'pathname'
5
5
  module Squared
6
6
  module Common
7
7
  module System
8
- include Common
9
-
10
8
  def shell(*cmd, **kwargs)
11
9
  if /^2\.[0-5]\./.match?(RUBY_VERSION)
12
10
  exception = kwargs.delete(:exception)
@@ -20,7 +18,7 @@ module Squared
20
18
  end
21
19
 
22
20
  def copy_d(src, dest, glob: ['**/*'], create: false, verbose: true)
23
- raise message(src, dest, hint: 'not found') if !create && !dest.exist?
21
+ raise "#{dest} (not found)" if !create && !dest.exist?
24
22
 
25
23
  subdir = []
26
24
  files = 0
@@ -40,7 +38,7 @@ module Squared
40
38
  files += 1
41
39
  end
42
40
  end
43
- puts message(dest.realpath, subdir.size.to_s, files.to_s) if verbose
41
+ puts [dest.realpath, subdir.size.to_s, files.to_s].join(' => ') if verbose
44
42
  end
45
43
 
46
44
  def copy_f(src, dest, overwrite: true, verbose: false)
@@ -16,7 +16,7 @@ module Squared
16
16
  rescue StandardError => e
17
17
  raise if exception
18
18
 
19
- warn e
19
+ defined?(__warn__) == 'method' ? __warn__(e) : warn(e)
20
20
  end
21
21
 
22
22
  def invoked?(name)
@@ -26,22 +26,36 @@ module Squared
26
26
  cyan!: '46',
27
27
  white!: '47'
28
28
  },
29
- logger: {
30
- unknown: %i[cyan],
31
- fatal: %i[white bold red!],
32
- error: %i[red bold],
33
- warn: %i[yellow bold],
34
- info: %i[blue],
35
- debug: %i[green]
36
- }.freeze
29
+ theme: {
30
+ workspace: {},
31
+ project: {},
32
+ viewer: {
33
+ banner: %i[blue bold],
34
+ key: %i[bold],
35
+ value: %i[green],
36
+ string: %i[yellow],
37
+ hash: %i[green black!],
38
+ array: %i[blue black!],
39
+ number: %i[magenta],
40
+ undefined: %i[red italic]
41
+ },
42
+ logger: {
43
+ unknown: %i[cyan],
44
+ fatal: %i[white bold red!],
45
+ error: %i[red bold],
46
+ warn: %i[yellow bold],
47
+ info: %i[blue],
48
+ debug: %i[green]
49
+ }
50
+ }
37
51
  }.compare_by_identity
38
52
  private_constant :VAR
39
53
 
40
- def get!(key)
54
+ def __get__(key)
41
55
  VAR[key.is_a?(::String) ? key.to_sym : key]
42
56
  end
43
57
 
44
- def set!(key, val)
58
+ def __set__(key, val)
45
59
  return if VAR.frozen?
46
60
 
47
61
  VAR[key.is_a?(::String) ? key.to_sym : key] = val
@@ -49,6 +63,7 @@ module Squared
49
63
 
50
64
  def finalize!
51
65
  VAR.each_value(&:freeze)
66
+ VAR[:theme].each_value(&:freeze)
52
67
  VAR.freeze
53
68
  end
54
69
 
@@ -1,70 +1,78 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  module Squared
4
6
  module Config
5
7
  class Viewer
6
- include Common::Format
8
+ include Common
9
+ include Format
7
10
  include Task
8
11
  include ::Rake::DSL
9
12
 
10
13
  class << self
11
- attr_reader :styles
12
-
13
- def style(name, *args)
14
- styles[name.to_sym]&.clear&.concat(args)
15
- end
16
-
17
14
  def to_s
18
15
  /[^:]+$/.match(super.to_s)[0]
19
16
  end
20
17
  end
21
18
 
22
- @styles = {
23
- banner: %i[blue],
24
- key: %i[bold],
25
- value: %i[green],
26
- string: %i[yellow],
27
- hash: %i[green black!],
28
- array: %i[blue black!],
29
- number: %i[magenta],
30
- undefined: %i[red italic]
31
- }.freeze
19
+ attr_reader :name, :main, :project, :theme
32
20
 
33
- attr_reader :main, :project, :name
34
-
35
- def initialize(main = 'package', project: nil, name: nil)
21
+ def initialize(main, name = nil, project: nil, dump: nil, opts: {}, auto: true, common: true)
36
22
  if project
37
- @project = get!(:project)[project.to_sym]
23
+ main = @project.base_path(main).to_s if (@project = __get__(:project)[project.to_sym])
38
24
  @required = true
39
25
  end
40
- @name = (name || @project&.name)&.to_s
41
- unless @name
42
- msg, hint = project ? [project, 'not found'] : %w[name missing]
43
- warn log_message(:warn, msg, subject: self.class, hint: hint, color: !pipe?)
44
- @required = true
26
+ @name = name&.to_s || @project&.name
27
+ @ext = File.extname(main)
28
+ @dump = dump
29
+ @mime = {}
30
+ @theme = common ? __get__(:theme)[:viewer] : {}
31
+ if exist?
32
+ @main = main.chomp(@ext)
33
+ @name = @main unless @name || @required
34
+ if auto
35
+ case @ext
36
+ when '.json', '.js'
37
+ add('json', command: File.basename(@main), opts: opts)
38
+ when '.yaml', '.yml'
39
+ add('yaml', command: File.basename(@main), opts: opts)
40
+ end
41
+ end
42
+ else
43
+ @main = main
45
44
  end
46
- @main = main
47
- @include = {}
45
+ return unless warning? && ((missing = exist? && !File.exist?(main)) || !@name)
46
+
47
+ msg, hint = if missing
48
+ ['path not found', realpath]
49
+ else
50
+ @required = true
51
+ project ? [project, 'not found'] : %w[name missing]
52
+ end
53
+ warn log_message(:warn, msg, subject: self.class, hint: hint, color: !pipe?)
48
54
  end
49
55
 
50
56
  def build
51
57
  return unless enabled?
52
58
 
59
+ params = ->(args) { exist? ? [realpath, [args.keys] + args.extras] : [args.keys, args.extras] }
60
+
53
61
  namespace name do
54
- namespace :view do
55
- if @include['json'] && !::Rake::Task.task_defined?("#{name}:view:json")
56
- desc format_desc('json')
62
+ view = @command && @command != name ? @command : 'view'
63
+ namespace view do
64
+ if @mime['json'] && (exist? || !::Rake::Task.task_defined?("#{name}:#{view}:json"))
65
+ desc format_desc(view, %w[json])
57
66
  task :json, [:keys] do |_, args|
58
- require 'json'
59
- read_keys JSON, 'json', args.keys, args.extras
67
+ read_keys(JSON, 'json', *params.(args))
60
68
  end
61
69
  end
62
70
 
63
- if @include['yaml'] && !::Rake::Task.task_defined?("#{name}:view:yaml")
64
- desc format_desc('yaml', 'yml')
71
+ if @mime['yaml'] && (exist? || !::Rake::Task.task_defined?("#{name}:#{view}:yaml"))
72
+ desc format_desc(view, %w[yaml yml])
65
73
  task :yaml, [:keys] do |_, args|
66
74
  require 'yaml'
67
- read_keys YAML, 'yaml', args.keys, args.extras, 'yml', 'yaml'
75
+ read_keys(YAML, 'yaml', *params.(args), ext: %w[yml yaml])
68
76
  end
69
77
  end
70
78
  end
@@ -73,20 +81,23 @@ module Squared
73
81
  yield self if block_given?
74
82
  end
75
83
 
76
- def add(type, gem: nil, parse: nil, ext: [], opts: {}, command: nil, file: nil)
84
+ def add(type, gem: nil, parse: nil, ext: nil, opts: {}, command: 'view', file: nil, exist: nil)
85
+ return self if @mime.frozen?
86
+
77
87
  type = type.to_s
78
88
  if parse && enabled?
79
89
  require(gem || type)
80
90
  obj = eval(parse)
81
- ext = as_a(ext)
91
+ ext << type if (ext = as_a(ext)).empty?
92
+ file = realpath if file.nil? && exist?
82
93
  namespace name do
83
- desc format_desc(ext.first || type, command: command)
84
- namespace(command || :view) do
94
+ desc format_desc(command, ext, exist: exist)
95
+ namespace command do
85
96
  task type, [:keys] do |_, args|
86
97
  if file
87
- read_keys obj, type, file.to_s, collect_args(args, :keys), *ext
98
+ read_keys(obj, type, file.to_s, collect_args(args, :keys), ext: ext)
88
99
  else
89
- read_keys obj, type, args.keys, args.extras, *ext
100
+ read_keys(obj, type, args.keys, args.extras, ext: ext)
90
101
  end
91
102
  end
92
103
  end
@@ -95,16 +106,19 @@ module Squared
95
106
  rescue LoadError, NameError
96
107
  self
97
108
  else
98
- @include[type] = opts
109
+ @mime[type] = opts
110
+ if exist?
111
+ @command = command
112
+ @mime.freeze
113
+ end
99
114
  self
100
115
  end
101
116
 
102
117
  def also(path, type = nil, name: nil, gem: nil, parse: nil, opts: {})
103
- return self unless (file = base_path(path)).exist?
118
+ return self if @mime.frozen? || !(file = base_path(path)).exist?
104
119
 
105
- ext = chop_extname(file).downcase
106
- name ||= file.basename.to_s.chomp(".#{ext}")
107
- type = (type || ext).to_s
120
+ ext = mime_type(file)
121
+ type = type&.to_s || ext
108
122
  if !parse
109
123
  case type
110
124
  when 'json'
@@ -114,49 +128,59 @@ module Squared
114
128
  parse = 'YAML'
115
129
  end
116
130
  end
117
- add(type, gem: gem, parse: parse, ext: ext, opts: opts, command: name, file: file)
131
+ name ||= file.basename.to_s.chomp(File.extname(file))
132
+ add(type, gem: gem, parse: parse, ext: ext, opts: opts, command: name, file: file, exist: true)
133
+ end
134
+
135
+ def style(name, *args)
136
+ apply_style(theme, name, *args)
137
+ self
138
+ end
139
+
140
+ def extensions
141
+ exist? ? [@ext.sub('.', '')] : @mime.keys
118
142
  end
119
143
 
120
144
  def to_s
121
- @include.keys.map { |ext| "#{main}.#{ext}" }.join(',')
145
+ realpath if exist?
146
+
147
+ @mime.keys.map { |ext| "#{main}.#{ext}" }.join(',')
122
148
  end
123
149
 
124
150
  def inspect
125
- "#<#{self.class}: #{name} => #{main} {#{@include.keys.join(', ')}}>"
151
+ "#<#{self.class}: #{name} => #{exist? ? realpath : "#{main} {#{extensions.join(', ')}}"}>"
126
152
  end
127
153
 
128
154
  def enabled?
129
- !@required || !!project&.enabled?
155
+ return File.exist?(realpath) if exist?
156
+
157
+ !@required || (!project.nil? && project.enabled?)
130
158
  end
131
159
 
132
160
  protected
133
161
 
134
- def read_keys(reader, type, file, keys, *ext)
135
- path = base_path(file)
136
- fmt = chop_extname(file)
137
- ext << type if ext.empty?
138
- if path.exist? && path.basename.to_s.include?('.')
139
- raise ArgumentError, message(file, fmt, hint: 'invalid') unless ext.include?(fmt)
162
+ def read_keys(reader, type, file, keys, ext: [type])
163
+ if (mime = mime_type(file)) && base_path(file).exist?
164
+ raise ArgumentError, message(file, mime, hint: 'invalid') unless ext.include?(mime)
140
165
  else
141
- if ext.include?(fmt)
166
+ if ext.include?(mime)
142
167
  alt = file
143
168
  file = nil
144
- ext[0] = fmt
169
+ ext[0] = mime
145
170
  else
146
171
  keys.unshift(file)
147
- alt = "#{main}.{#{ext.join(',')}}"
148
- alt = project.base_path(alt) if project
172
+ alt = base_path("#{main}.{#{ext.join(',')}}")
149
173
  file = Dir[alt].first
150
174
  end
151
- if !file
175
+ unless file
152
176
  raise ArgumentError, message(reader.name, "#{File.basename(alt, '.*')}.#{ext.first}", hint: 'not found')
153
177
  end
154
178
  end
155
179
  project&.info "#{Viewer}(#{type}) => #{file} {#{keys.join(', ')}}"
156
180
  doc = if reader.respond_to?(:load_file)
157
- reader.load_file(file, **@include[type])
181
+ reader.load_file(file, **@mime[type])
158
182
  else
159
- reader.parse(File.read(file), **@include[type])
183
+ reader.parse(File.read(file), **@mime[type])
160
184
  end
161
185
  lines = print_keys(type, doc, keys, file: file)
162
186
  return unless lines
@@ -168,15 +192,16 @@ module Squared
168
192
  sub = if pipe?
169
193
  nil
170
194
  else
195
+ styles = theme
171
196
  [
172
- { pat: /^([^:]+|(?<! ):(?! ))+$/, styles: Viewer.styles[:banner] },
173
- { pat: /^(.*?)(<[^>]+>)(.+)$/m, styles: Viewer.styles[:undefined], index: 2 },
174
- { pat: /^(.+)( : (?!undefined).+)$/m, styles: Viewer.styles[:key] },
175
- { pat: /^(.+ : )(-?[\d.]+)(\s*)$/m, styles: Viewer.styles[:number], index: 2 },
176
- { pat: /^(.+ : ")(.+)("\s*)$/m, styles: Viewer.styles[:string], index: 2 },
177
- { pat: /^(.+ : \{)(.+)(\}\s*)$/m, styles: Viewer.styles[:hash], index: 2 },
178
- { pat: /^(.+ : \[)(.+)(\]\s*)$/m, styles: Viewer.styles[:array], index: 2 },
179
- { pat: /^(.+ : (?!undefined))([^"\[{].*)$/m, styles: Viewer.styles[:value], index: 2 }
197
+ { pat: /^((?:[^:]|(?<! ):(?! ))+)$/, styles: styles[:banner] },
198
+ { pat: /^(.*?)(<[^>]+>)(.+)$/m, styles: styles[:undefined], index: 2 },
199
+ { pat: /^(.+)( : (?!undefined).+)$/m, styles: styles[:key] },
200
+ { pat: /^(.+ : )(-?[\d.]+)(\s*)$/m, styles: styles[:number], index: 2 },
201
+ { pat: /^(.+ : ")(.+)("\s*)$/m, styles: styles[:string], index: 2 },
202
+ { pat: /^(.+ : \{)(.+)(\}\s*)$/m, styles: styles[:hash], index: 2 },
203
+ { pat: /^(.+ : \[)(.+)(\]\s*)$/m, styles: styles[:array], index: 2 },
204
+ { pat: /^(.+ : (?!undefined))([^"\[{].*)$/m, styles: styles[:value], index: 2 }
180
205
  ]
181
206
  end
182
207
  emphasize(lines, title: title, sub: sub)
@@ -185,7 +210,7 @@ module Squared
185
210
  def print_keys(type, data, keys, file: nil)
186
211
  out = []
187
212
  pad = 0
188
- symbolize = @include[type][:symbolize_names]
213
+ symbolize = @mime[type][:symbolize_names]
189
214
  keys.each do |key|
190
215
  begin
191
216
  items = key.split('.')
@@ -210,20 +235,16 @@ module Squared
210
235
  $2 ? ".#{s}" : "#{s}."
211
236
  end
212
237
  end
213
- out << [key, 'undefined']
238
+ out << [key, pipe? ? JSON.dump(nil) : 'undefined']
214
239
  else
215
- out << [key, val.inspect]
240
+ out << [key, @dump == 'json' || pipe? ? JSON.dump(val) : val.inspect]
216
241
  end
217
- pad = key.size if key.size > pad
242
+ pad = [pad, key.size].max
218
243
  end
219
244
  if pipe?
220
- out = out.map do |item|
221
- val = item.last
222
- val.start_with?('"') && val.end_with?('"') ? val[1..-2] : val
223
- end
224
- puts out.join("\n")
245
+ puts out.map(&:last).join("\n")
225
246
  else
226
- out.map { |item| "#{item.first.ljust(pad)} : #{item.last}" }
247
+ out.map { |item| "#{item[0].ljust(pad)} : #{item[1]}" }
227
248
  end
228
249
  end
229
250
 
@@ -231,12 +252,28 @@ module Squared
231
252
  project ? project.base_path(file) : Pathname.new(file).realdirpath
232
253
  end
233
254
 
234
- def format_desc(type, alt = nil, command: nil)
235
- message(name, command || 'view', "#{type}[#{command.nil? ? "file?=#{main}.#{alt || type}," : ''}keys*]")
255
+ def mime_type(file)
256
+ case (ret = File.extname(file).sub('.', '').downcase)
257
+ when 'yml'
258
+ 'yaml'
259
+ when 'js'
260
+ 'json'
261
+ else
262
+ ret.empty? ? nil : ret
263
+ end
264
+ end
265
+
266
+ def format_desc(command, ext, exist: exist?)
267
+ message(name, command, "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys*]")
236
268
  end
237
269
 
238
- def chop_extname(file)
239
- File.extname(file).sub('.', '')
270
+ def realpath
271
+ file = main + @ext
272
+ Pathname.new(file).realdirpath.to_s rescue file
273
+ end
274
+
275
+ def exist?
276
+ !@ext.empty? && (!@required || !project.nil?)
240
277
  end
241
278
 
242
279
  def pipe?
@@ -245,6 +282,10 @@ module Squared
245
282
  val = ENV['PIPE_OUT']
246
283
  !val.nil? && !val.empty? && val != '0'
247
284
  end
285
+
286
+ def warning?
287
+ project ? project.warning : true
288
+ end
248
289
  end
249
290
  end
250
291
  end
@@ -7,7 +7,8 @@ module Squared
7
7
  module Repo
8
8
  module Project
9
9
  class Base
10
- include Common::System
10
+ include Common
11
+ include System
11
12
  include Shell
12
13
  include Task
13
14
  include ::Rake::DSL
@@ -17,11 +18,17 @@ module Squared
17
18
  include Common::Task
18
19
  include ::Rake::DSL
19
20
 
21
+ def populate(*); end
22
+
20
23
  def tasks
21
24
  [].freeze
22
25
  end
23
26
 
24
- def populate(*); end
27
+ def as_path(val)
28
+ return val if val.is_a?(::Pathname)
29
+
30
+ val.is_a?(::String) ? Pathname.new(val) : nil
31
+ end
25
32
 
26
33
  def to_s
27
34
  /[^:]+$/.match(super.to_s)[0]
@@ -35,25 +42,33 @@ module Squared
35
42
  @@print_order = 0
36
43
  @@tasks = {}
37
44
 
38
- attr_reader :name, :project, :workspace, :group, :path, :logger
45
+ alias __warn__ warn
46
+
47
+ attr_reader :name, :project, :workspace, :group, :path, :logger, :theme
48
+ attr_accessor :warning
39
49
 
40
50
  protected :logger
41
51
 
42
52
  def_delegators :logger, :log, :<<, :debug, :info, :warn, :error, :fatal, :unknown
43
53
 
44
- def initialize(name, project, workspace, **kwargs)
54
+ def initialize(name, path, workspace, *, group: nil, log: nil, common: true, **kwargs)
45
55
  @name = name.to_s
46
- @path = workspace.root_path(project.to_s)
56
+ @path = workspace.root_path(path.to_s)
47
57
  @project = @path.basename.to_s
48
58
  @workspace = workspace
49
- @group = kwargs[:group]&.to_s
59
+ @group = group&.to_s
50
60
  @depend = kwargs[:depend]
51
61
  @doc = kwargs[:doc]
52
62
  @test = kwargs[:test]
53
63
  @output = [kwargs[:run], nil]
54
64
  @copy = kwargs[:copy]
55
65
  @clean = kwargs[:clean]
56
- log = kwargs[:log]
66
+ @theme = if common
67
+ workspace.theme
68
+ else
69
+ __get__(:theme)[:project][to_sym] ||= {}
70
+ end
71
+ @warning = workspace.warning
57
72
  log = { file: log } unless log.is_a?(::Hash)
58
73
  if (logfile = env('LOG_FILE')).nil? && (auto = env('LOG_AUTO'))
59
74
  logfile = case auto
@@ -72,7 +87,7 @@ module Squared
72
87
  logfile.realdirpath
73
88
  rescue StandardError => e
74
89
  logfile = nil
75
- Warning.warn e
90
+ __warn__ e if @warning
76
91
  end
77
92
  end
78
93
  @logger = Logger.new(logfile, progname: @name, level: env('LOG_LEVEL') || log[:level] || Logger::INFO)
@@ -162,6 +177,10 @@ module Squared
162
177
  run(@depend, exception: workspace.exception) if @depend
163
178
  end
164
179
 
180
+ def copy(*)
181
+ run_s @copy
182
+ end
183
+
165
184
  def doc
166
185
  build @doc if @doc
167
186
  end
@@ -170,10 +189,6 @@ module Squared
170
189
  build @test if @test
171
190
  end
172
191
 
173
- def copy(*)
174
- run_s @copy
175
- end
176
-
177
192
  def clean
178
193
  return unless @clean
179
194
 
@@ -194,7 +209,7 @@ module Squared
194
209
  begin
195
210
  File.delete(file) if File.file?(file)
196
211
  rescue StandardError => e
197
- warn e
212
+ error e
198
213
  end
199
214
  end
200
215
  end
@@ -202,10 +217,6 @@ module Squared
202
217
  end
203
218
  end
204
219
 
205
- def styles
206
- workspace.styles
207
- end
208
-
209
220
  def base_path(*args)
210
221
  path.join(*args)
211
222
  end
@@ -349,7 +360,7 @@ module Squared
349
360
 
350
361
  if verbose?
351
362
  pad = 0
352
- if (args = styles[:banner])
363
+ if (args = theme[:banner])
353
364
  if args.any? { |s| s.to_s.end_with?('!') }
354
365
  pad = 1
355
366
  elsif args.size <= 1
@@ -4,7 +4,7 @@ module Squared
4
4
  module Repo
5
5
  module Project
6
6
  class Git < Base
7
- include Common::Format
7
+ include Format
8
8
 
9
9
  REF = :git
10
10
  private_constant :REF
@@ -35,7 +35,7 @@ module Squared
35
35
  end
36
36
 
37
37
  def is_a?(val)
38
- if val.is_a?(::Pathname) || (val.is_a?(::String) && (val = Pathname.new(val)))
38
+ if (val = as_path(val))
39
39
  val.join('.git').directory?
40
40
  else
41
41
  super
@@ -516,7 +516,7 @@ module Squared
516
516
  return unless verbose?
517
517
 
518
518
  if size > 0
519
- args = styles[:banner]&.reject { |s| s.to_s.end_with?('!') } || []
519
+ args = theme[:banner]&.reject { |s| s.to_s.end_with?('!') } || []
520
520
  args << :bold if args.size <= 1
521
521
  puts print_footer "#{sub_style(size, *args)} #{size == 1 ? type.sub(/s$/, '') : type}"
522
522
  else
@@ -19,7 +19,7 @@ module Squared
19
19
  end
20
20
 
21
21
  def is_a?(val)
22
- if val.is_a?(::Pathname) || (val.is_a?(::String) && (val = Pathname.new(val)))
22
+ if (val = as_path(val))
23
23
  val.join('package.json').exist?
24
24
  else
25
25
  super
@@ -33,7 +33,7 @@ module Squared
33
33
  run: nil
34
34
  }.freeze
35
35
 
36
- def initialize(name, project, workspace, **kwargs)
36
+ def initialize(name, path, workspace, *, **kwargs)
37
37
  super
38
38
  initialize_script(REF)
39
39
  if (opts = env('BUILD', strict: true))
@@ -71,7 +71,7 @@ module Squared
71
71
  when :install
72
72
  desc format_desc(action, flag)
73
73
  task flag do
74
- install flag
74
+ depend(flag, override: true)
75
75
  end
76
76
  when :outdated
77
77
  desc format_desc(action, flag, %w[prune dry-run], req: 'opts?')
@@ -134,10 +134,10 @@ module Squared
134
134
  end
135
135
  end
136
136
 
137
- def depend(flag = nil)
138
- if @depend
137
+ def depend(flag = nil, override: false)
138
+ if @depend && !override
139
139
  super
140
- else
140
+ elsif outdated?
141
141
  frozen = flag == :frozen
142
142
  force = flag == :force
143
143
  dedupe = flag == :dedupe
@@ -206,8 +206,7 @@ module Squared
206
206
  info cmd
207
207
  data = `#{cmd} --json --loglevel=error`
208
208
  Dir.chdir(pwd)
209
- doc = File.read(package)
210
- json = JSON.parse(doc)
209
+ json = JSON.parse(doc = package.read)
211
210
  pat = /^(\d+)(\.)(\d+)(\.)(\d+)$/
212
211
  dep1 = json['dependencies'] || {}
213
212
  dep2 = json['devDependencies'] || {}
@@ -451,11 +450,11 @@ module Squared
451
450
  elsif pnpm?
452
451
  if silent
453
452
  cmd << '--reporter=silent'
454
- else
455
- case level
456
- when 'debug', 'info', 'warn', 'error'
457
- cmd << "--loglevel=#{level}"
458
- end
453
+ level ||= 'error'
454
+ end
455
+ case level
456
+ when 'debug', 'info', 'warn', 'error'
457
+ cmd << "--loglevel=#{level}"
459
458
  end
460
459
  elsif silent
461
460
  cmd << '--loglevel=silent'
@@ -21,7 +21,7 @@ module Squared
21
21
  end
22
22
 
23
23
  def is_a?(val)
24
- if val.is_a?(::Pathname) || (val.is_a?(::String) && (val = Pathname.new(val)))
24
+ if (val = as_path(val))
25
25
  REQUIREMENTS.any? { |file| val.join(file).exist? }
26
26
  else
27
27
  super
@@ -29,7 +29,7 @@ module Squared
29
29
  end
30
30
  end
31
31
 
32
- def initialize(name, project, workspace, **kwargs)
32
+ def initialize(name, path, workspace, *, **kwargs)
33
33
  super
34
34
  initialize_build(REF, **kwargs)
35
35
  end
@@ -59,7 +59,7 @@ module Squared
59
59
  desc options.()
60
60
  end
61
61
  task flag do |_, args|
62
- install(flag, opts: collect_args(args, :opts))
62
+ depend(flag, opts: collect_args(args, :opts), override: true)
63
63
  end
64
64
  end
65
65
  end
@@ -68,8 +68,8 @@ module Squared
68
68
  end
69
69
  end
70
70
 
71
- def depend(flag = nil, opts: [])
72
- if @depend
71
+ def depend(flag = nil, opts: [], override: false)
72
+ if @depend && !override
73
73
  super
74
74
  elsif outdated?
75
75
  case install_type
@@ -97,7 +97,7 @@ module Squared
97
97
 
98
98
  def outdated(*); end
99
99
 
100
- def install_type
100
+ def install_type(*)
101
101
  return @requirements if @requirements
102
102
 
103
103
  ret = REQUIREMENTS.index { |file| base_path(file).exist? }
@@ -7,7 +7,7 @@ module Squared
7
7
  REF = :ruby
8
8
  GEMFILE = %w[Gemfile Gemfile.lock gem.deps.rb Isolate].freeze
9
9
  OPT_INSTALL = %w[no-cache force quiet verbose].freeze
10
- OPT_UPDATE = %w[redownload local strict conservative quiet verbose].freeze
10
+ OPT_UPDATE = %w[redownload local strict conservative group=s quiet verbose].freeze
11
11
  private_constant :REF, :GEMFILE, :OPT_INSTALL, :OPT_UPDATE
12
12
 
13
13
  class << self
@@ -18,7 +18,7 @@ module Squared
18
18
  end
19
19
 
20
20
  def is_a?(val)
21
- if val.is_a?(::Pathname) || (val.is_a?(::String) && (val = Pathname.new(val)))
21
+ if (val = as_path(val))
22
22
  [*GEMFILE, *::Rake::Application::DEFAULT_RAKEFILES, 'README.rdoc'].any? { |file| val.join(file).exist? }
23
23
  else
24
24
  super
@@ -33,7 +33,7 @@ module Squared
33
33
  rake: nil
34
34
  }.freeze
35
35
 
36
- def initialize(name, project, workspace, **kwargs)
36
+ def initialize(name, path, workspace, *, **kwargs)
37
37
  super
38
38
  initialize_build(REF, **kwargs)
39
39
  @version = env('BUILD', suffix: 'VERSION', strict: true) || kwargs.delete(:version)
@@ -51,7 +51,7 @@ module Squared
51
51
  break
52
52
  end
53
53
  rescue StandardError => e
54
- warn e
54
+ error e
55
55
  end
56
56
  end
57
57
 
@@ -80,12 +80,12 @@ module Squared
80
80
  when :'with-g', :'without-g'
81
81
  desc format_desc(action, flag, 'group+')
82
82
  task flag, [:group] do |_, args|
83
- install(flag, group: collect_args(args, :group))
83
+ depend(flag, group: collect_args(args, :group), override: true)
84
84
  end
85
85
  else
86
86
  desc format_desc(action, flag, OPT_INSTALL)
87
87
  task flag, [:opts] do |_, args|
88
- install(flag, opts: collect_args(args, :opts))
88
+ depend(flag, opts: collect_args(args, :opts), override: true)
89
89
  end
90
90
  end
91
91
  when :update
@@ -106,10 +106,10 @@ module Squared
106
106
  end
107
107
  end
108
108
 
109
- def depend(flag = nil, opts: [], group: [])
110
- if @depend
109
+ def depend(flag = nil, opts: [], group: [], override: false)
110
+ if @depend && !override
111
111
  super
112
- else
112
+ elsif outdated?
113
113
  case flag
114
114
  when :redownload, :local, :'prefer-local'
115
115
  cmd = bundle_session 'install'
@@ -213,11 +213,11 @@ module Squared
213
213
  end
214
214
  return false unless @autodetect
215
215
 
216
- error = ->(hint) { raise ArgumentError, message('failed to parse', hint: hint) }
216
+ quit = ->(hint) { raise ArgumentError, message('failed to parse', hint: hint) }
217
217
  begin
218
218
  out = `gem -C #{shell_quote(path)} list --local -d #{project}`
219
219
  data = /#{Regexp.escape(project)} \(([^)]+)\)/.match(out)
220
- error.('version') unless data
220
+ quit.('version') unless data
221
221
  ver = data[1].split(/\s*,\s*/)
222
222
  if @version
223
223
  ver.unshift(@version)
@@ -231,10 +231,10 @@ module Squared
231
231
  @version = v
232
232
  break
233
233
  end
234
- error.('path') unless data
234
+ quit.('path') unless data
235
235
  @gemdir = Pathname.new(data[1].strip).join(gempath.())
236
236
  rescue StandardError => e
237
- warn e
237
+ error e
238
238
  @version = nil
239
239
  @gemdir = nil
240
240
  @autodetect = false
@@ -248,7 +248,9 @@ module Squared
248
248
  end
249
249
 
250
250
  def outdated?
251
- GEMFILE.any? { |file| base_path(file).exist? }
251
+ return @outdated unless @outdated.nil?
252
+
253
+ @outdated = GEMFILE.any? { |file| base_path(file).exist? }
252
254
  end
253
255
 
254
256
  def dev?
@@ -261,7 +263,13 @@ module Squared
261
263
  if (val = env('BUNDLE_JOBS')).to_i > 0
262
264
  @session << "-j#{val}"
263
265
  end
264
- list.each { |flag| @session << "--#{flag}" if opts.include?(flag) }
266
+ list.each do |flag|
267
+ if opts.include?(flag)
268
+ @session << "--#{flag}"
269
+ elsif /^g(?:roup)?=(.+)$/.match(flag)
270
+ @session << "--group=#{$1}"
271
+ end
272
+ end
265
273
  end
266
274
 
267
275
  def gem_session(*cmd)
@@ -3,7 +3,8 @@
3
3
  module Squared
4
4
  module Repo
5
5
  class Workspace
6
- include Common::Format
6
+ include Common
7
+ include Format
7
8
  include System
8
9
  include Task
9
10
  include ::Rake::DSL
@@ -51,10 +52,10 @@ module Squared
51
52
 
52
53
  @project_kind = []
53
54
 
54
- attr_reader :main, :root, :home, :series
55
- attr_accessor :manifest, :manifest_url, :exception, :styles, :pipe, :verbose
55
+ attr_reader :main, :root, :home, :series, :theme
56
+ attr_accessor :manifest, :manifest_url, :exception, :pipe, :verbose, :warning
56
57
 
57
- def initialize(main)
58
+ def initialize(main, *, common: true, **)
58
59
  @main = main.to_s
59
60
  @home = if (val = env('REPO_HOME'))
60
61
  home = Pathname.new(val)
@@ -90,7 +91,7 @@ module Squared
90
91
  end
91
92
  @root ||= @home.parent
92
93
  @series = TASK_NAME.dup
93
- @styles = {}
94
+ @theme = common ? __get__(:theme)[:workspace] : {}
94
95
  @project = {}
95
96
  @script = {
96
97
  group: {},
@@ -102,9 +103,12 @@ module Squared
102
103
  @exception = !env('PIPE_FAIL', ignore: '0').nil?
103
104
  @pipe = !env('PIPE_OUT', ignore: '0').nil?
104
105
  @verbose = !@pipe
106
+ @warning = !empty?(@root, init: false)
105
107
  end
106
108
 
107
109
  def build(**kwargs)
110
+ return unless enabled?
111
+
108
112
  default = kwargs[:default]
109
113
  parallel = env('REPO_SYNC', ignore: '0') ? [] : (kwargs[:parallel] || []).map!(&:to_sym)
110
114
 
@@ -140,9 +144,9 @@ module Squared
140
144
  end
141
145
  series.merge!(parent) if incl.uniq.size > 1
142
146
  series.merge!(group)
143
- series[:refresh].clear if series[:refresh].all? { |target| target.to_s.end_with?(':build') }
147
+ series[:refresh].clear if series[:refresh].all? { |target| target.end_with?(':build') }
144
148
 
145
- if manifest_url && (empty?(root) || @override)
149
+ if repo?
146
150
  branch = env('REPO_MANIFEST') || read_manifest
147
151
  target = branch || manifest
148
152
  stage = nil
@@ -250,27 +254,35 @@ module Squared
250
254
  yield self if block_given?
251
255
  end
252
256
 
253
- def repo(url, manifest = 'latest')
257
+ def repo(url, manifest = 'latest', run: nil, dev: nil, prod: nil)
254
258
  @manifest_url = url
255
259
  @manifest = manifest
256
- self
260
+ script = case (val = env('REPO_BUILD'))
261
+ when 'verbose'
262
+ run ? "#{run}:verbose" : nil
263
+ when 'silent'
264
+ @verbose = false
265
+ @warning = false
266
+ run
267
+ else
268
+ val || run
269
+ end
270
+ case env('REPO_WARN')
271
+ when '0'
272
+ @warning = false
273
+ when '1'
274
+ @warning = true
275
+ end
276
+ script ? run(script, dev: bool_match(env('REPO_DEV'), dev), prod: bool_match(env('REPO_DEV'), prod)) : self
257
277
  end
258
278
 
259
279
  def run(script, group: nil, ref: nil, **kwargs)
260
280
  if group || ref
261
281
  script_command :run, script, group, ref
262
282
  else
263
- @script[:build] = case (val = env('REPO_BUILD'))
264
- when 'verbose'
265
- "#{script}:verbose"
266
- when 'silent'
267
- @verbose = false
268
- script
269
- else
270
- val || script
271
- end
272
- @script[:dev] = bool_match(env('REPO_DEV'), kwargs[:dev])
273
- @script[:prod] = bool_match(env('REPO_PROD'), kwargs[:prod])
283
+ @script[:build] = script
284
+ @script[:dev] = kwargs[:dev]
285
+ @script[:prod] = kwargs[:prod]
274
286
  self
275
287
  end
276
288
  end
@@ -291,17 +303,17 @@ module Squared
291
303
  script_command :test, script, group, ref
292
304
  end
293
305
 
294
- def add(name, dir = nil, **kwargs)
295
- path = (dir || name).to_s
306
+ def add(name, path = nil, **kwargs)
307
+ path = root_path((path || name).to_s)
296
308
  ref = kwargs[:ref]
297
309
  project = if !ref.is_a?(::Class)
298
- Workspace.find(path: root_path(path), ref: ref)
310
+ Workspace.find(path: path, ref: ref)
299
311
  elsif ref < Project::Base
300
312
  ref
301
313
  end
302
314
  instance = (project || Project::Base).new(name, path, self, **kwargs)
303
315
  @project[n = name.to_sym] = instance
304
- get!(:project)[n] = instance
316
+ __get__(:project)[n] = instance unless kwargs[:private]
305
317
  self
306
318
  end
307
319
 
@@ -315,13 +327,19 @@ module Squared
315
327
  self
316
328
  end
317
329
 
318
- def style(name, *args)
319
- set = ->(k, v) { styles[k.to_sym] = check_style(v, empty: false) }
320
- if name.is_a?(Hash)
321
- name.each { |k, v| set.(k, v || args.flatten) }
322
- else
323
- set.(name, args.flatten)
330
+ def style(name, *args, target: nil, empty: false)
331
+ data = nil
332
+ if target
333
+ as_a(target).each_with_index do |val, i|
334
+ if i == 0
335
+ break unless (data = __get__(:theme)[val.to_sym])
336
+ else
337
+ data = data[val.to_sym] ||= {}
338
+ end
339
+ end
340
+ return unless data
324
341
  end
342
+ apply_style(data || theme, name, *args, empty: empty)
325
343
  self
326
344
  end
327
345
 
@@ -340,12 +358,12 @@ module Squared
340
358
  ret.empty? || as_a(ignore).any? { |val| ret == val.to_s } ? nil : ret
341
359
  end
342
360
 
343
- def read_manifest
361
+ def read_manifest(*)
344
362
  require 'rexml/document'
345
363
  file = root_path('.repo/manifest.xml')
346
364
  return unless file.exist?
347
365
 
348
- doc = REXML::Document.new(File.read(file))
366
+ doc = REXML::Document.new(file.read)
349
367
  doc.elements['manifest/include'].attributes['name']&.sub('.xml', '')
350
368
  end
351
369
 
@@ -382,13 +400,12 @@ module Squared
382
400
  "#<#{self.class}: #{main} => #{self}>"
383
401
  end
384
402
 
385
- def empty?(dir)
386
- return true if dir.empty? || dir.join('.repo').directory?
387
- return true if dir.children.size == 1 && dir.join(dir.children.first).to_s == __FILE__
403
+ def enabled?
404
+ repo? || @project.any? { |_, proj| proj.enabled? }
405
+ end
388
406
 
389
- dir == root && !env('REPO_ROOT').nil? && root.children.none? do |path|
390
- path.directory? && !path.basename.to_s.start_with?('.') && path.to_s != home.to_s
391
- end
407
+ def repo?
408
+ !manifest_url.nil? && (empty?(root) || @override)
392
409
  end
393
410
 
394
411
  def multitask?
@@ -399,6 +416,15 @@ module Squared
399
416
  end
400
417
  end
401
418
 
419
+ def empty?(dir, init: true)
420
+ return true if dir.empty? || (init && dir.join('.repo').directory?)
421
+ return true if dir.children.size == 1 && dir.join(dir.children.first).to_s == __FILE__
422
+
423
+ dir == root && !env('REPO_ROOT').nil? && root.children.none? do |path|
424
+ path.directory? && !path.basename.to_s.start_with?('.') && path.to_s != home.to_s
425
+ end
426
+ end
427
+
402
428
  def task_defined?(obj, key)
403
429
  obj.is_a?(TASK_BASE[key])
404
430
  end
data/lib/squared/repo.rb CHANGED
@@ -9,7 +9,7 @@ module Squared
9
9
  project id
10
10
  else
11
11
  (id = Pathname.new(id).realdirpath.to_s) rescue nil if id.is_a?(::String)
12
- get!(:project).find { |_, val| val.path.to_s == id.to_s }
12
+ __get__(:project).find { |_, val| val.path.to_s == id.to_s }
13
13
  end
14
14
  end
15
15
  ret.size == 1 ? ret.first : ret
@@ -19,7 +19,7 @@ module Squared
19
19
  ret = project(name)
20
20
  return ret if ret&.path&.directory?
21
21
 
22
- raise NoMethodError, message('project is not initialized', name)
22
+ raise NoMethodError, "project is not initialized (#{name})"
23
23
  end
24
24
 
25
25
  def project?(name)
@@ -29,7 +29,7 @@ module Squared
29
29
  private
30
30
 
31
31
  def project(name)
32
- get!(:project)[name.to_sym]
32
+ __get__(:project)[name.to_sym]
33
33
  end
34
34
  end
35
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.0.2'
4
+ VERSION = '0.0.4'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-01 00:00:00.000000000 Z
11
+ date: 2024-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake