bgem 0.0.12 → 0.1.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.
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: []