squared 0.0.1 → 0.0.3

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.
@@ -9,82 +9,94 @@ module Squared
9
9
  include ::Rake::DSL
10
10
 
11
11
  class << self
12
- include Common::Format
13
-
14
- attr_reader :styles
15
-
16
- def style(name, *args)
17
- args = check_style(args)
18
- styles[name.to_sym]&.clear&.concat(args)
12
+ def to_s
13
+ /[^:]+$/.match(super.to_s)[0]
19
14
  end
20
15
  end
21
16
 
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
17
+ attr_reader :name, :main, :project, :theme
32
18
 
33
- attr_reader :main, :project, :name
34
-
35
- def initialize(main = 'package', project: nil, name: nil)
19
+ def initialize(main, name = nil, project: nil, opts: {}, auto: true, common: true)
36
20
  if project
37
- @project = get(:project)[project.to_sym]
21
+ main = @project.base_path(main).to_s if (@project = __get__(:project)[project.to_sym])
38
22
  @required = true
39
23
  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: 'Config::Viewer', hint: hint, color: !pipe?)
44
- @required = true
24
+ @name = name&.to_s || @project&.name
25
+ @ext = File.extname(main)
26
+ @mime = {}
27
+ @theme = common ? __get__(:theme)[:viewer] : {}
28
+ if exist?
29
+ @main = main.chomp(@ext)
30
+ @name = @main unless @name || @required
31
+ if auto
32
+ case @ext
33
+ when '.json', '.js'
34
+ add('json', command: File.basename(@main), opts: opts)
35
+ when '.yaml', '.yml'
36
+ add('yaml', command: File.basename(@main), opts: opts)
37
+ end
38
+ end
39
+ else
40
+ @main = main
45
41
  end
46
- @main = main
47
- @include = {}
42
+ return unless warning? && ((missing = exist? && !File.exist?(main)) || !@name)
43
+
44
+ msg, hint = if missing
45
+ ['path not found', realpath]
46
+ else
47
+ @required = true
48
+ project ? [project, 'not found'] : %w[name missing]
49
+ end
50
+ warn log_message(:warn, msg, subject: self.class, hint: hint, color: !pipe?)
48
51
  end
49
52
 
50
53
  def build
51
54
  return unless enabled?
52
55
 
53
- namespace @name do
54
- namespace :view do
55
- if @include['json'] && !::Rake::Task.task_defined?("#{@name}:view:json")
56
- desc format_desc('json')
56
+ params = ->(args) { exist? ? [realpath, [args.keys] + args.extras] : [args.keys, args.extras] }
57
+
58
+ namespace name do
59
+ view = @command && @command != name ? @command : 'view'
60
+ namespace view do
61
+ if @mime['json'] && (exist? || !::Rake::Task.task_defined?("#{name}:#{view}:json"))
62
+ desc format_desc(view, %w[json])
57
63
  task :json, [:keys] do |_, args|
58
64
  require 'json'
59
- read_keys JSON, 'json', args.keys, args.extras
65
+ read_keys(JSON, 'json', *params.(args))
60
66
  end
61
67
  end
62
68
 
63
- if @include['yaml'] && !::Rake::Task.task_defined?("#{@name}:view:yaml")
64
- desc format_desc('yaml', 'yml')
69
+ if @mime['yaml'] && (exist? || !::Rake::Task.task_defined?("#{name}:#{view}:yaml"))
70
+ desc format_desc(view, %w[yaml yml])
65
71
  task :yaml, [:keys] do |_, args|
66
72
  require 'yaml'
67
- read_keys YAML, 'yaml', args.keys, args.extras, 'yml', 'yaml'
73
+ read_keys(YAML, 'yaml', *params.(args), ext: %w[yml yaml])
68
74
  end
69
75
  end
70
76
  end
71
77
  end
78
+
79
+ yield self if block_given?
72
80
  end
73
81
 
74
- def add(type, gem: nil, parse: nil, ext: [], opts: {}, command: nil, file: nil)
82
+ def add(type, gem: nil, parse: nil, ext: [], opts: {}, command: 'view', file: nil)
83
+ return self if @mime.frozen?
84
+
75
85
  type = type.to_s
76
86
  if parse && enabled?
77
87
  require(gem || type)
78
88
  obj = eval(parse)
79
89
  ext = as_a(ext)
80
- namespace @name do
81
- desc format_desc(ext.first || type, command: command)
82
- namespace(command || :view) do
90
+ ext << type if ext.empty?
91
+ file = realpath if file.nil? && exist?
92
+ namespace name do
93
+ desc format_desc(command, ext)
94
+ namespace command do
83
95
  task type, [:keys] do |_, args|
84
96
  if file
85
- read_keys obj, type, file.to_s, collect_args(args, :keys), *ext
97
+ read_keys(obj, type, file.to_s, collect_args(args, :keys), ext: ext)
86
98
  else
87
- read_keys obj, type, args.keys, args.extras, *ext
99
+ read_keys(obj, type, args.keys, args.extras, ext: ext)
88
100
  end
89
101
  end
90
102
  end
@@ -93,16 +105,19 @@ module Squared
93
105
  rescue LoadError, NameError
94
106
  self
95
107
  else
96
- @include[type] = opts
108
+ @mime[type] = opts
109
+ if exist?
110
+ @command = command
111
+ @mime.freeze
112
+ end
97
113
  self
98
114
  end
99
115
 
100
116
  def also(path, type = nil, name: nil, gem: nil, parse: nil, opts: {})
101
- return self unless (file = base_path(path)).exist?
117
+ return self if @mime.frozen? || !(file = base_path(path)).exist?
102
118
 
103
- ext = chop_extname(file).downcase
104
- name ||= file.basename.to_s.chomp(".#{ext}")
105
- type = (type || ext).to_s
119
+ ext = mime_type(file)
120
+ type = type&.to_s || ext
106
121
  if !parse
107
122
  case type
108
123
  when 'json'
@@ -112,42 +127,61 @@ module Squared
112
127
  parse = 'YAML'
113
128
  end
114
129
  end
130
+ name ||= file.basename.to_s.chomp(File.extname(file))
115
131
  add(type, gem: gem, parse: parse, ext: ext, opts: opts, command: name, file: file)
116
132
  end
117
133
 
134
+ def style(name, *args)
135
+ apply_style(theme, name, *args)
136
+ self
137
+ end
138
+
139
+ def extensions
140
+ exist? ? [@ext.sub('.', '')] : @mime.keys
141
+ end
142
+
143
+ def to_s
144
+ realpath if exist?
145
+
146
+ @mime.keys.map { |ext| "#{main}.#{ext}" }.join(',')
147
+ end
148
+
149
+ def inspect
150
+ "#<#{self.class}: #{name} => #{exist? ? realpath : "#{main} {#{extensions.join(', ')}}"}>"
151
+ end
152
+
118
153
  def enabled?
119
- !@required || !!@project&.enabled?
154
+ return File.exist?(realpath) if exist?
155
+
156
+ !@required || (!project.nil? && project.enabled?)
120
157
  end
121
158
 
122
159
  protected
123
160
 
124
- def read_keys(reader, type, file, keys, *ext)
125
- path = base_path(file)
126
- fmt = chop_extname(file)
127
- ext << type if ext.empty?
128
- if path.exist? && path.basename.to_s.include?('.')
129
- raise ArgumentError, message(file, fmt, hint: 'invalid') unless ext.include?(fmt)
161
+ def read_keys(reader, type, file, keys, ext: [type])
162
+ if (mime = mime_type(file)) && base_path(file).exist?
163
+ raise ArgumentError, message(file, mime, hint: 'invalid') unless ext.include?(mime)
130
164
  else
131
- if ext.include?(fmt)
165
+ if ext.include?(mime)
132
166
  alt = file
133
167
  file = nil
134
- ext[0] = fmt
168
+ ext[0] = mime
135
169
  else
136
170
  keys.unshift(file)
137
- alt = "#{@main}.{#{ext.join(',')}}"
138
- alt = @project.base_path(alt) if @project
171
+ alt = base_path("#{main}.{#{ext.join(',')}}")
139
172
  file = Dir[alt].first
140
173
  end
141
- if !file
174
+ unless file
142
175
  raise ArgumentError, message(reader.name, "#{File.basename(alt, '.*')}.#{ext.first}", hint: 'not found')
143
176
  end
144
177
  end
178
+ project&.info "#{Viewer}(#{type}) => #{file} {#{keys.join(', ')}}"
145
179
  doc = if reader.respond_to?(:load_file)
146
- reader.load_file(file, **@include[type])
180
+ reader.load_file(file, **@mime[type])
147
181
  else
148
- reader.parse(File.read(file), **@include[type])
182
+ reader.parse(File.read(file), **@mime[type])
149
183
  end
150
- lines = print_keys(type, doc, keys)
184
+ lines = print_keys(type, doc, keys, file: file)
151
185
  return unless lines
152
186
 
153
187
  title = Pathname.new(file)
@@ -157,24 +191,25 @@ module Squared
157
191
  sub = if pipe?
158
192
  nil
159
193
  else
194
+ styles = theme
160
195
  [
161
- { pat: /^([^:]+|(?<! ):(?! ))+$/, styles: Viewer.styles[:banner] },
162
- { pat: /^(.*?)(<[^>]+>)(.+)$/m, styles: Viewer.styles[:undefined], index: 2 },
163
- { pat: /^(.+)( : (?!undefined))(.+)$/m, styles: Viewer.styles[:key] },
164
- { pat: /^(.+)( : )(-?[\d.]+)(\s*)$/m, styles: Viewer.styles[:number], index: 3 },
165
- { pat: /^(.+)( : ")(.+)("\s*)$/m, styles: Viewer.styles[:string], index: 3 },
166
- { pat: /^(.+)( : \{)(.+)(\}\s*)$/m, styles: Viewer.styles[:hash], index: 3 },
167
- { pat: /^(.+)( : \[)(.+)(\]\s*)$/m, styles: Viewer.styles[:array], index: 3 },
168
- { pat: /^(.+)( : (?!undefined))([^"\[{].*)$/m, styles: Viewer.styles[:value], index: 3 }
196
+ { pat: /^((?:[^:]|(?<! ):(?! ))+)$/, styles: styles[:banner] },
197
+ { pat: /^(.*?)(<[^>]+>)(.+)$/m, styles: styles[:undefined], index: 2 },
198
+ { pat: /^(.+)( : (?!undefined).+)$/m, styles: styles[:key] },
199
+ { pat: /^(.+ : )(-?[\d.]+)(\s*)$/m, styles: styles[:number], index: 2 },
200
+ { pat: /^(.+ : ")(.+)("\s*)$/m, styles: styles[:string], index: 2 },
201
+ { pat: /^(.+ : \{)(.+)(\}\s*)$/m, styles: styles[:hash], index: 2 },
202
+ { pat: /^(.+ : \[)(.+)(\]\s*)$/m, styles: styles[:array], index: 2 },
203
+ { pat: /^(.+ : (?!undefined))([^"\[{].*)$/m, styles: styles[:value], index: 2 }
169
204
  ]
170
205
  end
171
206
  emphasize(lines, title: title, sub: sub)
172
207
  end
173
208
 
174
- def print_keys(type, data, keys)
209
+ def print_keys(type, data, keys, file: nil)
175
210
  out = []
176
211
  pad = 0
177
- symbolize = @include[type][:symbolize_names]
212
+ symbolize = @mime[type][:symbolize_names]
178
213
  keys.each do |key|
179
214
  begin
180
215
  items = key.split('.')
@@ -189,6 +224,7 @@ module Squared
189
224
  end
190
225
  end
191
226
  rescue StandardError
227
+ project&.warn "#{Viewer}(#{type}) => #{file ? "#{file} " : ''}{#{key}: undefined}"
192
228
  val = Regexp.escape($!.message)
193
229
  key = key.sub(/(#{val})\.|\.(#{val})|(#{val})/) do
194
230
  s = "<#{$3 || $2 || $1}>"
@@ -198,41 +234,59 @@ module Squared
198
234
  $2 ? ".#{s}" : "#{s}."
199
235
  end
200
236
  end
201
- out << [key, 'undefined']
237
+ out << [key, pipe? ? nil : 'undefined']
202
238
  else
203
- out << [key, val.inspect]
239
+ out << [key, pipe? ? val : val.inspect]
204
240
  end
205
241
  pad = key.size if key.size > pad
206
242
  end
207
243
  if pipe?
208
- out = out.map do |item|
209
- val = item.last
210
- val.start_with?('"') && val.end_with?('"') ? val[1..-2] : val
211
- end
244
+ require 'json'
245
+ out = out.map { |item| JSON.dump(item[1]) }
212
246
  puts out.join("\n")
213
247
  else
214
- out.map { |item| "#{item.first.ljust(pad)} : #{item.last}" }
248
+ out.map { |item| "#{item[0].ljust(pad)} : #{item[1]}" }
215
249
  end
216
250
  end
217
251
 
218
252
  def base_path(file)
219
- @project ? @project.base_path(file) : Pathname.new(file).realdirpath
253
+ project ? project.base_path(file) : Pathname.new(file).realdirpath
220
254
  end
221
255
 
222
- def format_desc(type, alt = nil, command: nil)
223
- message(@name, command || 'view', "#{type}[#{command.nil? ? "file?=#{@main}.#{alt || type}," : ''}keys*]")
256
+ def mime_type(file)
257
+ case (ret = File.extname(file).sub('.', '').downcase)
258
+ when 'yml'
259
+ 'yaml'
260
+ when 'js'
261
+ 'json'
262
+ else
263
+ ret.empty? ? nil : ret
264
+ end
265
+ end
266
+
267
+ def format_desc(command, ext)
268
+ message(name, command, "#{ext.first}[#{exist? ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys*]")
224
269
  end
225
270
 
226
- def chop_extname(file)
227
- File.extname(file).sub('.', '')
271
+ def realpath
272
+ file = main + @ext
273
+ Pathname.new(file).realdirpath.to_s rescue file
274
+ end
275
+
276
+ def exist?
277
+ !@ext.empty? && (!@required || !project.nil?)
228
278
  end
229
279
 
230
280
  def pipe?
231
- return @project.workspace.pipe? if @project
281
+ return project.workspace.pipe if project
232
282
 
233
283
  val = ENV['PIPE_OUT']
234
284
  !val.nil? && !val.empty? && val != '0'
235
285
  end
286
+
287
+ def warning?
288
+ project ? project.warning : true
289
+ end
236
290
  end
237
291
  end
238
292
  end