bgem 0.0.12 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bgem +1 -1
  3. data/lib/bgem.rb +271 -58
  4. metadata +15 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1d1c08e11ff9c3de03b3930c47c20205e61cd0364db2eb246afafa596c36b815
4
- data.tar.gz: 73103ebeb0f449b11a079601a61c02c91285706c95db4d36191abe03bed568c0
3
+ metadata.gz: 9298c8361ba7b012178c101f0fd572726305ce892a35ae0dedc35ad5f4c3d0ab
4
+ data.tar.gz: 2b471ee714a1e266f93010a4f665b1755a2bf43123d7bb105c219d06676b72e6
5
5
  SHA512:
6
- metadata.gz: 2bcfe3b46efc42ee2b035459c629647d07ecc51bb88a5280e84a0cac234fcce6e0333b1d7093aa89ea40471183698772a195712007db02c45678f423db2108e8
7
- data.tar.gz: ddb3eef3954990c53eda84f50d60b4d22cf0ffcc63b86dab5f4240af39aa74e3c6804baa1d08f43e28e914dfb4047d063bf24e33d95c7d40e93494dadd1122ec
6
+ metadata.gz: 957d72e96fbd1bc35811beb79799e811527366029ed88c5ad62a07df638ad6ea43f65d707cba78e2726c41bfd6bfb0ac9006c0db8e621573b0be8bb257402bc9
7
+ data.tar.gz: bd60ed05e9714ba87cfde9aea6bc80d6f86a4f153dddab96f4271dd1dfc8cc71613512142e2e77f00533704ec358527452a096742e9286855a72ed9b7a69200d
data/bin/bgem CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'bgem'
4
- Bgem.run
4
+ Bgem::CLI.run
data/lib/bgem.rb CHANGED
@@ -1,4 +1,17 @@
1
1
  module Bgem
2
+ module CLI
3
+ def self.run
4
+ case ARGV[0]
5
+ when '-v', '--version'
6
+ puts VERSION
7
+ else
8
+ Bgem.run
9
+ end
10
+ end
11
+ end
12
+
13
+ VERSION = '0.1.0'
14
+
2
15
  require 'pathname'
3
16
  require 'string/indent'
4
17
 
@@ -9,101 +22,305 @@ module Bgem
9
22
  class << self
10
23
  def run config_file = CONFIG_FILE
11
24
  config = Config.new config_file
12
- target = TargetFile.new config.output, config.scope
13
- target.write SourceFile.new(config.entry).to_s
14
- target
25
+ write = Write.new config
26
+ write[Output.new(config.entry).to_s]
27
+ write
15
28
  end
16
29
  end
17
30
 
18
31
  class Config
32
+ attr_accessor :entry, :output, :scope
19
33
  def initialize config_file
20
34
  @entry, @output, @scope = SOURCE_FILE, 'output.rb', nil
21
- DSL.new self, config_file
22
- end
35
+ DSL.new self, (IO.read config_file)
23
36
 
24
- attr_accessor :entry, :output, :scope
37
+ @dir = Pathname File.dirname config_file
38
+ define_macros
39
+ end
25
40
 
41
+ def define_macros
42
+ Output::Ext.file_extensions.map do |type|
43
+ dir = @dir + type.to_s
44
+ MacroDir.new(type, dir) if dir.directory?
45
+ end.compact.each do |macro_dir|
46
+ macro_dir.define_macros
47
+ end
48
+ end
49
+
26
50
  class DSL
27
- def initialize config, file
51
+ def initialize config, code
28
52
  @config = config
29
- instance_eval IO.read file
53
+ instance_eval code
30
54
  end
31
-
55
+
32
56
  def entry file
33
57
  @config.entry = file
34
58
  end
35
-
59
+
36
60
  def output file
37
61
  @config.output = file
38
62
  end
39
-
63
+
40
64
  def inside *headers
41
65
  @config.scope = headers
42
66
  end
43
67
  end
68
+
69
+ class MacroDir
70
+ def initialize type, dir
71
+ @type, @dir = type, dir
72
+ @constant = Output::Exts.const_get @type.upcase
73
+ end
74
+
75
+ def define_macros
76
+ files = @dir.glob '*.rb'
77
+
78
+ files.each do |file|
79
+ n = file.basename.to_s.split('.').first
80
+ constant = @constant; k = Class.new { include constant }
81
+ to_s = "define_method :to_s do\n#{file.read}\nend"
82
+ k.instance_eval to_s
83
+ constant.const_set n.capitalize, k
84
+ end
85
+ end
86
+ end
44
87
  end
45
88
 
46
- class SourceFile
47
- def initialize file = SOURCE_FILE, indent: 0
48
- @file, @indent = (Pathname file), indent
49
- @source = @file.read
50
- head, @type, _rb = @file.basename.to_s.split '.'
51
- @constant, _colon, @ancestor = head.partition ':'
52
- end
53
-
54
- def to_s
55
- "#{head}#{source}end".indent @indent
56
- end
89
+ class Output
90
+ class Ext
91
+ module StandardHooks
92
+ module DSL
93
+ def hook hook_name, default: false
94
+ define_method hook_name do
95
+ directory = @dir + "#{hook_name}.#{@name}"
96
+
97
+ if default
98
+ default_directory = @dir + @name
99
+ directory = default_directory unless directory.directory?
100
+ end
101
+
102
+ concatenate sorted_files_in directory
103
+ end
104
+ end
105
+ end
106
+
107
+ module Helpers
108
+ def concatenate files
109
+ files.map do |file|
110
+ Output.new(file, indent: INDENT).to_s
111
+ end.join "\n\n"
112
+ end
113
+
114
+ def sorted_files_in directory
115
+ patterns = Ext.file_extensions.map do |ext|
116
+ directory.join "*.#{ext}"
117
+ end
118
+
119
+ files = Dir[*patterns]
120
+ order_file = directory.join 'order'
121
+
122
+ if order_file.exist?
123
+ sort_with_order_file order_file, files
124
+ else
125
+ files.sort
126
+ end
127
+ end
128
+
129
+ def sort_with_order_file order_file, files
130
+ order = order_file.readlines.map &:chomp
131
+
132
+ files_ordered_to_be_first = order.inject([]) do |array, name|
133
+ files_starting_with_name = files.select do |file|
134
+ basename = File.basename file
135
+ basename.start_with? "#{name}."
136
+ end
137
+ array += files_starting_with_name
138
+ end
139
+
140
+ other_files = files - files_ordered_to_be_first
141
+ files_ordered_to_be_first += other_files.sort
142
+ end
143
+ end
144
+
145
+ extend DSL
146
+ include Helpers
147
+
148
+ hook :post, default: true
149
+ hook :pre
150
+ end
57
151
 
58
- private
59
- def head
60
- if @ancestor.empty?
61
- "#{@type} #{@constant}\n"
152
+ def self.file_extensions
153
+ Exts.constants.map &:downcase
154
+ end
155
+
156
+ def self.new file_extension:, type:, name:, dir:, code:
157
+ parent_constant = Exts.const_get file_extension.upcase
158
+
159
+ type ||= if parent_constant.respond_to? :default
160
+ parent_constant.default
161
+ else
162
+ 'default'
163
+ end
164
+ constant_name = type.capitalize
165
+
166
+ if parent_constant.const_defined? constant_name
167
+ child_constant = parent_constant.const_get constant_name
62
168
  else
63
- "#{@type} #{@constant} < #{@ancestor}\n"
169
+ fail "Don't know what to do with '#{type}'. #{parent_constant}::#{constant_name} is not defined."
64
170
  end
171
+
172
+ child_constant.new file_extension: file_extension, type: type, name: name, dir: dir, code: code
65
173
  end
66
174
 
67
- def source
68
- source = @source.indent INDENT
69
- source.prepend "#{pre}\n\n" unless pre.empty?
70
- source.prepend "#{before}\n\n" unless before.empty?
71
- source.concat "\n#{after}\n" unless after.empty?
72
- source
175
+ module Common
176
+ def initialize **kwargs
177
+ @file_extension = kwargs[:file_extension]
178
+ @type = kwargs[:type]
179
+ @name = kwargs[:name]
180
+ @dir = kwargs[:dir]
181
+ @code = kwargs[:code]
182
+
183
+ setup
184
+ end
185
+
186
+ attr_reader :file_extension, :type, :name, :dir, :code
187
+
188
+ def ext
189
+ file_extension
190
+ end
191
+
192
+ def setup
193
+ end
73
194
  end
195
+ end
196
+
197
+ module Exts
74
198
 
75
- def self.define_appendix name
76
- define_method name do
77
- pattern = @file.dirname.join "#{__method__}.#{@constant}/*.rb"
78
- concatenate pattern
199
+ module ERB
200
+ include Ext::Common
201
+
202
+ class Default
203
+ include ERB
204
+
205
+ def to_s
206
+ <<~S
207
+ module #{@name}
208
+ class Context
209
+ def env
210
+ binding
211
+ end
212
+ end
213
+
214
+ def self.[] params
215
+ env = Context.new.env
216
+ params.each do |name, value|
217
+ env.local_variable_set name, value
218
+ end
219
+
220
+ template = <<~TEMPLATE
221
+ #{@code}TEMPLATE
222
+
223
+ require 'erb'
224
+ renderer = ERB.new template
225
+ renderer.result env
226
+ end
227
+ end
228
+ S
229
+ end
79
230
  end
80
231
  end
81
232
 
82
- [:pre, :before].each { |name| define_appendix name }
83
-
84
- def after
85
- patterns = ["#{@constant}/*.rb", "after.#{@constant}/*.rb"].map do |pattern|
86
- @file.dirname.join pattern
233
+ module RB
234
+ include Ext::Common
235
+ include Ext::StandardHooks
236
+
237
+ def self.default
238
+ 'module'
239
+ end
240
+
241
+ attr_reader :head
242
+
243
+ def to_s
244
+ "#{head}#{body}end"
245
+ end
246
+
247
+ def body
248
+ wrap code
249
+ end
250
+
251
+ def wrap code
252
+ code = @code.indent INDENT
253
+ code.prepend "#{pre}\n\n" unless pre.empty?
254
+ code.concat "\n#{post}\n" unless post.empty?
255
+ code
256
+ end
257
+
258
+ class Class
259
+ include RB
260
+
261
+ def setup
262
+ @name, _colon, @parent = @name.partition ':'
263
+ end
264
+
265
+ def head
266
+ if subclass?
267
+ "class #{@name} < #{@parent}\n"
268
+ else
269
+ "class #{@name}\n"
270
+ end
271
+ end
272
+
273
+ def subclass?
274
+ not @parent.empty?
275
+ end
87
276
  end
277
+
278
+ class Module
279
+ include RB
280
+
281
+ def head
282
+ "module #{@name}\n"
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ def initialize file = SOURCE_FILE, indent: 0
289
+ file, @indent = (Pathname file), indent
290
+
291
+ parts = file.basename.to_s.split '.'
88
292
 
89
- concatenate *patterns
293
+ case parts.size
294
+ when 3
295
+ name, type, file_extension = parts
296
+ when 2
297
+ name, file_extension = parts
298
+ else
299
+ fail "#{file} has more than two dots in its name."
90
300
  end
91
301
 
92
- def concatenate *patterns
93
- Dir[*patterns].sort.map do |file|
94
- self.class.new(file, indent: INDENT).to_s
95
- end.join "\n\n"
302
+ if Exts.const_defined? file_extension.upcase
303
+ @output = Ext.new file_extension: file_extension, type: type, name: name, dir: file.dirname, code: file.read
304
+ else
305
+ fail "Don't know what to do with #{file}. Bgem::Output::Exts::#{file_extension.upcase} is not defined."
96
306
  end
307
+ end
308
+
309
+ def to_s
310
+ @output.to_s.indent @indent
311
+ end
97
312
  end
98
313
 
99
- class TargetFile
100
- def initialize path = 'output.rb', scope
101
- @path = Pathname path
102
- @scope = scope
314
+ class Write
315
+ def initialize config
316
+ @file = Pathname config.output
317
+ @scope = config.scope
103
318
  end
104
319
 
105
- def write string
106
- @path.dirname.mkpath
320
+ attr_reader :file
321
+
322
+ def [] string
323
+ file.dirname.mkpath
107
324
 
108
325
  if @scope
109
326
  @scope.each do |header|
@@ -111,11 +328,7 @@ module Bgem
111
328
  end
112
329
  end
113
330
 
114
- @path.write "#{string}\n"
115
- end
116
-
117
- def file
118
- @path
331
+ file.write "#{string}\n"
119
332
  end
120
333
  end
121
334
  end
metadata CHANGED
@@ -1,31 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bgem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - Anatoly Chernow
8
- autorequire:
7
+ - Anatoly Chernov
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-25 00:00:00.000000000 Z
11
+ date: 2023-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: string-indent
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.0.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.0.1
27
- description:
28
- email:
27
+ description:
28
+ email:
29
29
  executables:
30
30
  - bgem
31
31
  extensions: []
@@ -33,10 +33,11 @@ extra_rdoc_files: []
33
33
  files:
34
34
  - bin/bgem
35
35
  - lib/bgem.rb
36
- homepage:
37
- licenses: []
36
+ homepage: https://github.com/ch1c0t/bgem
37
+ licenses:
38
+ - ISC
38
39
  metadata: {}
39
- post_install_message:
40
+ post_install_message:
40
41
  rdoc_options: []
41
42
  require_paths:
42
43
  - lib
@@ -51,9 +52,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
52
  - !ruby/object:Gem::Version
52
53
  version: '0'
53
54
  requirements: []
54
- rubyforge_project:
55
- rubygems_version: 2.7.6
56
- signing_key:
55
+ rubygems_version: 3.4.20
56
+ signing_key:
57
57
  specification_version: 4
58
- summary: Build gems without too much hassle.
58
+ summary: To make Ruby gems from macros.
59
59
  test_files: []