squared 0.1.5 → 0.2.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.
@@ -20,44 +20,80 @@ module Squared
20
20
  end
21
21
  end
22
22
 
23
- def copy_d(src, dest, glob: ['**/*'], pass: nil, create: false, verbose: true)
24
- src = ::Pathname.new(src)
25
- dest = ::Pathname.new(dest)
23
+ def copy_dir(src, dest, glob = ['**/*'], create: false, link: nil, force: false, pass: nil, verbose: true)
24
+ src = Pathname.new(src)
25
+ dest = Pathname.new(dest)
26
26
  raise "#{dest} (not found)" if !create && !dest.parent.exist?
27
27
 
28
- subdir = []
29
- files = 0
28
+ subdir = {}
30
29
  dest.mkpath if create
31
30
  if pass
32
31
  exclude = []
33
- (pass.is_a?(::Array) ? pass : [pass]).each { |val| exclude += ::Dir.glob(src.join(val)) }
32
+ pass = [pass] unless pass.is_a?(::Array)
33
+ pass.each { |val| exclude += Dir.glob(src.join(val)) }
34
34
  end
35
35
  (glob.is_a?(::Array) ? glob : [glob]).each do |val|
36
- ::Dir.glob(src.join(val)) do |path|
37
- next if exclude&.include?(path) || (path = ::Pathname.new(path)).directory?
36
+ Dir.glob(src.join(val)) do |path|
37
+ next if exclude&.include?(path) || (path = Pathname.new(path)).directory?
38
38
 
39
- target = dest.join(path.relative_path_from(src))
40
- dir = target.dirname
41
- unless subdir.include?(dir.to_s)
39
+ dir = dest.join(path.relative_path_from(src)).dirname
40
+ if (data = subdir[dir.to_s])
41
+ data << path
42
+ else
42
43
  dir.mkpath
43
- subdir << dir.to_s
44
+ subdir[dir.to_s] = [path]
44
45
  end
45
- copy_f path, target
46
- files += 1
47
46
  end
48
47
  end
49
- puts [dest.realpath, subdir.size.to_s, files.to_s].join(' => ') if verbose
48
+ count = 0
49
+ soft = 0
50
+ subdir.each do |dir, files|
51
+ if link
52
+ items = files.dup
53
+ files.clear
54
+ items.each do |file|
55
+ if file.exist?
56
+ if file.symlink?
57
+ next unless force
58
+ else
59
+ files << file
60
+ next
61
+ end
62
+ end
63
+ if link == 'hard'
64
+ FileUtils.ln(file, dir, force: force, verbose: false)
65
+ else
66
+ FileUtils.ln_s(file, dir, force: force, verbose: false)
67
+ end
68
+ soft += 1
69
+ end
70
+ end
71
+ next if files.empty?
72
+
73
+ out = FileUtils.cp(files, dir, verbose: false)
74
+ count += out.size
75
+ end
76
+ puts [dest.realpath, subdir.size, soft > 0 ? "#{count}+#{soft}" : count].join(' => ') if verbose
50
77
  end
51
78
 
52
- def copy_f(src, dest, overwrite: true, verbose: false)
53
- unless overwrite
54
- if (path = ::Pathname.new(dest)).directory?
55
- src = (src.is_a?(::Array) ? src : [src]).reject { |val| path.join(::File.basename(val)).exist? }
79
+ def copy_guard(src, dest, link: nil, force: false, verbose: true)
80
+ unless force
81
+ if (path = Pathname.new(dest)).directory?
82
+ src = [src] unless src.is_a?(::Array)
83
+ src = src.reject { |val| path.join(File.basename(val)).exist? }
84
+ return if src.empty?
56
85
  elsif path.exist?
57
86
  return
58
87
  end
59
88
  end
60
- ::FileUtils.cp(src, dest, verbose: verbose)
89
+ case link
90
+ when 'hard', 1
91
+ FileUtils.ln(src, dest, force: force, verbose: verbose)
92
+ when true, 'soft', 0
93
+ FileUtils.ln_s(src, dest, force: force, verbose: verbose)
94
+ else
95
+ FileUtils.cp(src, dest, verbose: verbose)
96
+ end
61
97
  end
62
98
  end
63
99
  end
@@ -9,7 +9,7 @@ module Squared
9
9
  module_function
10
10
 
11
11
  def task_invoke(*cmd, args: [], exception: true, warning: true)
12
- cmd.each { |name| ::Rake::Task[name].invoke(*args) }
12
+ cmd.each { |name| Rake::Task[name].invoke(*args) }
13
13
  rescue StandardError => e
14
14
  raise if exception
15
15
 
@@ -28,10 +28,10 @@ module Squared
28
28
  end
29
29
 
30
30
  def task_invoked?(*args)
31
- ::Rake::Task.tasks.any? do |obj|
31
+ Rake::Task.tasks.any? do |obj|
32
32
  next unless obj.already_invoked
33
33
 
34
- args.any? { |val| val.is_a?(::Regexp) ? val.match?(obj.name) : val == obj.name }
34
+ args.any? { |val| val.is_a?(::Regexp) ? obj.name =~ val : val == obj.name }
35
35
  end
36
36
  end
37
37
 
@@ -64,7 +64,7 @@ module Squared
64
64
  def env_pipe(key, default = 1, suffix: nil, root: nil)
65
65
  if default.is_a?(::String)
66
66
  begin
67
- default = (root ? root.join(default) : ::Pathname.new(default)).realdirpath
67
+ default = (root ? root.join(default) : Pathname.new(default)).realdirpath
68
68
  rescue StandardError => e
69
69
  default = 1
70
70
  warn e
@@ -91,7 +91,7 @@ module Squared
91
91
  when '1'
92
92
  true
93
93
  else
94
- ::Regexp.new(ret, options, timeout: timeout)
94
+ Regexp.new(ret, options, timeout: timeout)
95
95
  end
96
96
  end
97
97
  end
@@ -11,41 +11,77 @@ module Squared
11
11
  include Utils
12
12
  include Rake::DSL
13
13
 
14
- def self.to_s
15
- super.match(/[^:]+\z/)[0]
14
+ class << self
15
+ def parse(gem, namespace, ext = [pkg])
16
+ require gem
17
+ obj = eval(namespace)
18
+ ext = [ext] unless ext.is_a?(Array)
19
+ ext.each { |val| @@mime_obj[val] = [obj, ext] }
20
+ rescue LoadError, NameError => e
21
+ warn e
22
+ nil
23
+ else
24
+ @@mime_obj[ext.first]
25
+ end
26
+
27
+ def link(project, main = project.dependfile.basename, name = nil, **kwargs, &blk)
28
+ return unless project.enabled?
29
+
30
+ ret = Viewer.new(main, name, project: project, **kwargs)
31
+ ret.instance_eval(&blk) if block_given?
32
+ ret
33
+ end
34
+
35
+ def to_s
36
+ super.match(/[^:]+\z/)[0]
37
+ end
16
38
  end
17
39
 
40
+ @@mime_obj = {}
41
+ @@task_desc = Rake::TaskManager.record_task_metadata
42
+
18
43
  attr_reader :main, :name, :project, :theme
19
44
  attr_accessor :pipe
20
45
 
21
- def initialize(main, name = nil, project: nil, prefix: nil, dump: nil, opts: {}, auto: true,
46
+ def initialize(main, name = nil, project: nil, prefix: nil, command: nil, dump: nil, opts: {}, auto: true,
22
47
  common: ARG[:COMMON], pipe: ARG[:PIPE], **)
23
- if project
24
- main = @project.basepath(main).to_s if (@project = __get__(:project)[project.to_s])
48
+ if project && (project.respond_to?(:workspace) || (project = __get__(:project)[project.to_s]))
49
+ main = project.basepath(main).to_s
50
+ @project = project
25
51
  @required = true
26
52
  end
27
- @name = name&.to_s || @project&.name
28
- @prefix = prefix
29
- @ext = File.extname(main).downcase
53
+ @name = name || @project&.name
54
+ @prefix = prefix unless @project
55
+ @ext = File.extname(main)
30
56
  @dump = dump
31
57
  @mime = {}
32
58
  @theme = common ? __get__(:theme)[:viewer] : {}
33
59
  @pipe = env_pipe(pipe, @project ? @project.pipe : 1)
34
- if exist?
60
+ if target?
35
61
  @main = main.chomp(@ext)
36
62
  @name = @main unless @name || @required
37
63
  if auto
38
- case @ext
39
- when '.json', '.js'
40
- add('json', command: File.basename(@main), opts: opts)
41
- when '.yaml', '.yml'
42
- add('yaml', command: File.basename(@main), opts: opts)
64
+ unless command
65
+ command = File.basename(@main)
66
+ command = ARG[:VIEW] if command == @name
67
+ end
68
+ ext = @ext[1..-1].downcase
69
+ if (data = @@mime_obj[ext])
70
+ add(data[1].first, command: command, opts: opts, ext: data[1])
71
+ else
72
+ case ext
73
+ when 'json', 'js'
74
+ add('json', command: command, opts: opts)
75
+ when 'yaml', 'yml'
76
+ add('yaml', command: command, opts: opts)
77
+ end
43
78
  end
44
79
  end
45
80
  else
46
81
  @main = main
82
+ @command = command || ARG[:VIEW]
47
83
  end
48
- return unless warning? && ((missing = exist? && !File.exist?(main)) || !@name)
84
+ return unless warning? && ((missing = target? && !File.exist?(main)) || !@name)
49
85
 
50
86
  msg, hint = if missing
51
87
  ['path not found', realpath]
@@ -60,21 +96,24 @@ module Squared
60
96
  return unless enabled?
61
97
 
62
98
  namespace(ns = task_name(name)) do
63
- view = @command && @command != name ? @command : 'view'
64
- params = ->(args) { exist? ? [realpath, [args.keys] + args.extras] : [args.keys, args.extras] }
65
- namespace view do
66
- if @mime['json'] && (exist? || !Rake::Task.task_defined?("#{ns}:#{view}:json"))
67
- desc format_desc(view, 'json')
68
- task 'json', [:keys] do |_, args|
69
- read_keys(JSON, 'json', *params.(args))
70
- end
71
- end
99
+ @mime.each do |type, items|
100
+ items.each do |command, file, opts|
101
+ next if Rake::Task.task_defined?("#{ns}:#{command}:#{type}")
102
+
103
+ namespace command do
104
+ unless (data = @@mime_obj[type])
105
+ ext = [type]
106
+ ext << 'yml' if type == 'yaml'
107
+ next unless (data = Viewer.parse(type, type.upcase, ext))
108
+ end
109
+ obj, ext = data
110
+ target = file || target? ? file || realpath : nil
72
111
 
73
- if @mime['yaml'] && (exist? || !Rake::Task.task_defined?("#{ns}:#{view}:yaml"))
74
- desc format_desc(view, 'yaml', 'yml')
75
- task 'yaml', [:keys] do |_, args|
76
- require 'yaml'
77
- read_keys(YAML, 'yaml', *params.(args), ext: ['yml', 'yaml'])
112
+ task_desc(command, *ext, target: target)
113
+ task type, [:keys] do |_, args|
114
+ params = target ? [target, args.to_a] : [args.keys, args.extras]
115
+ read_keys(obj, ext.first, *params, ext: ext, opts: opts)
116
+ end
78
117
  end
79
118
  end
80
119
  end
@@ -82,57 +121,52 @@ module Squared
82
121
  yield self if block_given?
83
122
  end
84
123
 
85
- def add(type, gem: nil, parse: nil, ext: nil, opts: {}, command: 'view', file: nil, exist: nil)
124
+ def add(type, ext: nil, opts: {}, command: ARG[:VIEW], gem: nil, namespace: nil, file: nil)
86
125
  return self if @mime.frozen?
87
126
 
88
- type = type.to_s
89
- if parse && enabled?
90
- require(gem || type)
91
- obj = eval(parse)
92
- ext << type if (ext = as_a(ext)).empty?
93
- file = realpath if !file && exist?
94
-
95
- namespace task_name(name) do
96
- namespace command do
97
- desc format_desc(command, *ext, exist: exist)
98
- task type, [:keys] do |_, args|
99
- if file
100
- read_keys(obj, type, file.to_s, args.to_a, ext: ext)
101
- else
102
- read_keys(obj, type, args.keys, args.extras, ext: ext)
103
- end
127
+ if enabled?
128
+ if namespace
129
+ require(gem || type)
130
+ obj = eval(namespace)
131
+ else
132
+ as_a(ext).each do |val|
133
+ next unless (data = @@mime_obj[val])
134
+
135
+ obj = data.first
136
+ break
137
+ end
138
+ end
139
+ if obj
140
+ ext << type if (ext = as_a(ext)).empty?
141
+ if !file && target?
142
+ ext.each do |val|
143
+ next unless (out = basepath("#{main}.#{val}")).exist?
144
+
145
+ file = out
146
+ break
104
147
  end
105
148
  end
106
149
  end
107
150
  end
108
151
  rescue LoadError, NameError => e
109
- project&.log&.warn e
152
+ log&.warn e
110
153
  self
111
154
  else
112
- @mime[type] = opts
113
- if exist?
114
- @command = command
155
+ (@mime[type] ||= []) << [command || @command, file, opts]
156
+ if target?
157
+ @mime[type].freeze
115
158
  @mime.freeze
116
159
  end
117
160
  self
118
161
  end
119
162
 
120
- def also(path, type = nil, name: nil, gem: nil, parse: nil, opts: {})
163
+ def also(path, type = nil, name: nil, **kwargs)
121
164
  return self if @mime.frozen? || !(file = basepath(path)).exist?
122
165
 
123
166
  ext = mimetype(file)
124
- type = type&.to_s || ext
125
- unless parse
126
- case type
127
- when 'json'
128
- parse = 'JSON'
129
- when 'yaml', 'yml'
130
- type = 'yaml'
131
- parse = 'YAML'
132
- end
133
- end
167
+ type ||= ext
134
168
  name ||= file.basename.to_s.chomp(File.extname(file))
135
- add(type, gem: gem, parse: parse, ext: ext, opts: opts, command: name, file: file, exist: true)
169
+ add(type, ext: ext, command: name, file: file, **kwargs)
136
170
  end
137
171
 
138
172
  def style(name, *args)
@@ -141,23 +175,23 @@ module Squared
141
175
  end
142
176
 
143
177
  def enabled?
144
- return File.exist?(realpath) if exist?
178
+ return File.exist?(realpath) if target?
145
179
 
146
180
  !@required || !!project&.enabled?
147
181
  end
148
182
 
149
183
  def extensions
150
- exist? ? [@ext.sub('.', '')] : @mime.keys
184
+ target? ? [@ext.sub('.', '').downcase] : @mime.keys
151
185
  end
152
186
 
153
187
  def to_s
154
- realpath if exist?
188
+ realpath if target?
155
189
 
156
190
  @mime.keys.map { |ext| "#{main}.#{ext}" }.join(',')
157
191
  end
158
192
 
159
193
  def inspect
160
- "#<#{self.class}: #{name} => #{exist? ? realpath : "#{main} {#{extensions.join(', ')}}"}>"
194
+ "#<#{self.class}: #{name} => #{target? ? realpath : "#{main} {#{extensions.join(', ')}}"}>"
161
195
  end
162
196
 
163
197
  private
@@ -166,7 +200,11 @@ module Squared
166
200
  puts_oe(*args, pipe: pipe)
167
201
  end
168
202
 
169
- def read_keys(reader, type, file, keys, ext: [type])
203
+ def log
204
+ project&.log
205
+ end
206
+
207
+ def read_keys(reader, type, file, keys, ext: [type], opts: {})
170
208
  if file && (mime = mimetype(file)) && basepath(file).exist?
171
209
  raise_error(file, mime, hint: 'invalid') unless ext.include?(mime)
172
210
  else
@@ -187,14 +225,15 @@ module Squared
187
225
  raise_error(reader.name, "#{File.basename(alt, '.*')}.#{ext.first}", **args)
188
226
  end
189
227
  end
190
- project&.log&.info "#{Viewer}(#{type}) => #{file} {#{keys.join(', ')}}"
228
+ log&.info "#{Viewer}(#{type}) => #{file} {#{keys.join(', ')}}"
229
+ return puts File.read(file) if keys.last == '*'
230
+
191
231
  doc = if reader.respond_to?(:load_file)
192
- reader.load_file(file, **@mime[type])
232
+ reader.load_file(file, **opts)
193
233
  else
194
- reader.parse(File.read(file), **@mime[type])
234
+ reader.parse(File.read(file), **opts)
195
235
  end
196
- lines = print_keys(type, doc, keys, file: file)
197
- return unless lines
236
+ return unless (lines = print_keys(type, doc, keys, file: file, opts: opts))
198
237
 
199
238
  title = Pathname.new(file)
200
239
  .realpath
@@ -213,13 +252,13 @@ module Squared
213
252
  { pat: /\A(.+ : (?!undefined))([^"\[{].*)\z/m, styles: theme[:value],
214
253
  index: 2 }
215
254
  ]
216
- end)
255
+ end, border: theme[:border])
217
256
  end
218
257
 
219
- def print_keys(type, data, keys, file: nil)
258
+ def print_keys(type, data, keys, file: nil, opts: {})
220
259
  out = []
221
260
  pad = 0
222
- symbolize = @mime[type][:symbolize_names]
261
+ symbolize = opts[:symbolize_names]
223
262
  keys.each do |key|
224
263
  begin
225
264
  items = key.split('.')
@@ -234,7 +273,7 @@ module Squared
234
273
  end
235
274
  end
236
275
  rescue StandardError
237
- project&.log&.warn "#{Viewer}(#{type}) => #{file && "#{file} "}{#{key}: undefined}"
276
+ log&.warn "#{Viewer}(#{type}) => #{file && "#{file} "}{#{key}: undefined}"
238
277
  val = Regexp.escape($!.message)
239
278
  key = key.sub(/(#{val})\.|\.(#{val})|(#{val})/) do
240
279
  s = "<#{$3 || $2 || $1}>"
@@ -258,17 +297,26 @@ module Squared
258
297
  end
259
298
 
260
299
  def task_name(val)
261
- @prefix ? "#{@prefix}:#{val}" : val.to_s
300
+ if project
301
+ project.workspace.task_name(val)
302
+ else
303
+ @prefix ? "#{@prefix}:#{val}" : val.to_s
304
+ end
262
305
  end
263
306
 
264
- def format_desc(command, *ext, exist: exist?)
265
- return unless Rake::TaskManager.record_task_metadata
307
+ def task_desc(command, *ext, target: nil)
308
+ return unless @@task_desc
266
309
 
267
- val = "#{ext.first}[#{exist ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys+]"
268
- message(@prefix, *name.split(':'), command, val, empty: true)
310
+ val = "#{ext.first}[#{target ? '' : "file?=#{File.basename(main)}.#{ext.last},"}keys+]"
311
+ args = *name.split(':').push(command, val)
312
+ if project
313
+ project.workspace.task_desc(*args)
314
+ else
315
+ desc message(@prefix, *args, empty: true)
316
+ end
269
317
  end
270
318
 
271
- def exist?
319
+ def target?
272
320
  !@ext.empty? && (!@required || !project.nil?)
273
321
  end
274
322
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.1.5'
4
+ VERSION = '0.2.0'
5
5
  end