alki-dsl 0.3.4 → 0.4.0

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
  SHA1:
3
- metadata.gz: 950660806cfbd74f9c85f33cb0aa9279d5337e07
4
- data.tar.gz: 7cf697039eaad23ce522769d0e08c735e6d52d41
3
+ metadata.gz: 74a68f3b18db59488fcbe8c2037b3933f33aef5d
4
+ data.tar.gz: '070150789ebbd1bc8b2615395c3e803c0b259913'
5
5
  SHA512:
6
- metadata.gz: 3c5ab25ef97f889ca268c34718ba26eade49cdb7d2f0f00b848d2212f82d1bc25b4873a78cc5028e21e717cbc1ce9c40f45d593da618c17a95fc9e84b7461433
7
- data.tar.gz: 54e8939ddd2a280267d5ca38b21d587296eeb22d43fee1da5683dc48aa73aadea98ea5235ddc3536e4d62d94389a5e8007059520b0bf3dc558bbdd52b4c5b710
6
+ metadata.gz: 420aa794f86a9c2339e784cabd08260d304f500e4c6d6b9731e4b66c7d607153f89a6e1fb3f570a54040a475b7c16e0dbed658f237fd5bab1ee163cbc1e84742
7
+ data.tar.gz: 2a8a0cc25a0fe87a36fe278f5c3ee4768d4816650ead0354dda92e4861ff15e418e5b263ac04e78ef009db02303da87cacc6d996cf667e252dda54d5c2ec2eea
data/README.adoc ADDED
@@ -0,0 +1,277 @@
1
+ # Alki::Dsl
2
+
3
+ Alki::Dsl is a library for building DSLs. The resulting DSL buliders can be used standalone or as builders for
4
+ https://github.com/alki-project/alki-loader[Alki::Loader].
5
+
6
+ Alki::Dsl also allows composing and extending DSLs and comes with built in DSLs for building classes and
7
+ new DSLs.
8
+
9
+ ## Synopsis
10
+
11
+ ```ruby
12
+ require 'alki/dsl'
13
+
14
+ strings_dsl = Alki::Dsl.build 'alki/dsls/dsl' do
15
+ init do
16
+ @strings = []
17
+ end
18
+
19
+ dsl_method :add do |val|
20
+ @strings << val
21
+ end
22
+
23
+ finish do
24
+ ctx[:result] = @strings.join("\n")
25
+ end
26
+ end
27
+
28
+ val = strings_dsl.build do
29
+ add "hello"
30
+ add "world"
31
+ end
32
+
33
+ puts val
34
+
35
+ # output:
36
+ # hello
37
+ # world
38
+ ```
39
+
40
+ ## Installation
41
+
42
+ Add this line to your application's Gemfile:
43
+
44
+ ```ruby
45
+ gem 'alki-dsl'
46
+ ```
47
+
48
+ And then execute:
49
+
50
+ $ bundle
51
+
52
+ Or install it yourself as:
53
+
54
+ $ gem install alki-dsl
55
+
56
+ ## Usage
57
+
58
+ All DSLs created with Alki::Dsl are Class objects with `::build` methods. These build methods take an optional
59
+ hash of parameters, along with a ruby block to be evaluated. DSLs created with Alki::Dsl cannot directly
60
+ strings.
61
+
62
+ While DSLs can be created with Alki::Dsl manually, the easiest way is to use the provided "dsl" DSL. Each
63
+ DSL defines any number of "dsl methods", which are methods that will be exposed to the user of the DSL.
64
+ The DSL can also define "init" and "finish" blocks which will be run before and after the DSL is evaluated.
65
+
66
+ DSLs can "require" other DSLs, causing both of their methods to be available to the user.
67
+
68
+ DSLs are always evaluated within a new instance, so instance variables can be used to store state, however
69
+ these will not be accessible to other DSLs being evaluated at the same time (via requires).
70
+
71
+ Data is passed into and out of a DSL via the `ctx` hash. It is initially set using the hash provided to the
72
+ DSLs build method, but can be updated by code in the DSL. Unlike instance variables, all DSLs being run share
73
+ a single ctx hash, so it can be used to pass data between them.
74
+
75
+ The result of the build method will either be the full ctx hash, or just the value of `ctx[:result]` if it
76
+ exists (including if it's set to false or nil).
77
+
78
+ ```ruby
79
+ require 'alki/dsl'
80
+
81
+ strings_dsl = Alki::Dsl.build 'alki/dsls/dsl' do
82
+ init do # Init block, runs before any dsl methods are called
83
+ ctx[:strings] = [] # Store strings in ctx so other DSLs can access them
84
+ end
85
+
86
+ dsl_method :add do |val| # Simple dsl method called "add"
87
+ ctx[:strings] << val
88
+ end
89
+
90
+ finish do # Finish block, runs after any dsls methods are called
91
+ sep = ctx[:separator] || "\n" # Allow caller of dsl to set the separator
92
+ ctx[:result] = ctx[:strings].join(sep) # Set ctx[:result] so we only return this value
93
+ end
94
+ end
95
+
96
+ my_dsl = Alki::Dsl.build 'alki/dsls/dsl' do
97
+ require_dsl strings_dsl # Require other DSL. Value can also be a "load" string (see Alki::Loader section)
98
+
99
+ init do # This init block will be run *after* the strings_dsl one
100
+ @transform = nil
101
+ end
102
+
103
+ dsl_method :transform do |&blk|
104
+ @transform = blk # Don't need to share this, so just use instance variable
105
+ end
106
+
107
+ finish do # This finish block will be run *before* the strings_dsl one.
108
+ if @transform
109
+ ctx[:strings].map! &@transform
110
+ end
111
+ end
112
+ end
113
+
114
+ result = my_dsl.build(separator: ', ') do # Pass in a separator via data hash
115
+ transform(&:capitalize)
116
+
117
+ add "hello"
118
+ add "world"
119
+ end
120
+
121
+ puts result
122
+
123
+ # output: Hello, World
124
+
125
+ ```
126
+
127
+ ### Using with Alki::Loader
128
+
129
+ https://github.com/alki-project/alki-loader[Alki::Loader] is library that provides extra functionality
130
+ over base Ruby around loading source files. One of its features is to associate "builder" objects with files
131
+ or directories so that the code within them is processed by the builder object when they are loaded. More
132
+ documentation can be found at the Alki::Loader https://github.com/alki-project/alki-loader[github page].
133
+
134
+ The DSLs created by Alki::Dsl can be used as Alki::Loader builder objects, allowing DSLs to be used to define
135
+ classes and modules. In addition, because the provided "dsl" DSL creates classes, it can also be used with
136
+ Alki::Loader to allow defining your DSLs in standalone source files.
137
+
138
+ To get started, in your project create a dsls directory at something like `lib/my_project/dsls`. This will
139
+ be where we put our DSL source files.
140
+
141
+ To register it create a `lib/alki_loader.rb` file:
142
+
143
+ .lib/alki_loader.rb
144
+ ```ruby
145
+ Alki::Loader.register 'my_project/dsls', builder: 'alki/dsls/dsl'
146
+ ```
147
+
148
+ ****
149
+ *Note*: This registers the builder using a string. This is a "load" string and is used frequently in Alki
150
+ projects. When used, the string will be `require`-d and then transformed into a constant name
151
+ (so "alki/dsls/dsl" becomes Alki::Dsls::Dsl) and the resulting class will be used. In addition to less
152
+ typing, this also allows lazy loading behavior, where the file and class are only loaded if needed.
153
+
154
+ The DSL class can be passed directly instead of the load string.
155
+ ****
156
+
157
+ Now a DSL definition file can be created in `lib/my_project/dsls`. Revisiting the previous example, a "strings"
158
+ can be created.
159
+
160
+ .lib/my_project/dsls/strings.rb
161
+ ```ruby
162
+ Alki do
163
+ init do
164
+ ctx[:strings] = []
165
+ end
166
+
167
+ dsl_method :add do |val|
168
+ ctx[:strings] << val
169
+ end
170
+
171
+ finish do
172
+ sep = ctx[:separator] || "\n"
173
+ ctx[:result] = ctx[:strings].join(sep)
174
+ end
175
+ end
176
+ ```
177
+
178
+ The `Alki do ... end` block is part of Alki::Loader and is required. The rest of the DSL is the same
179
+ as before. When this file is loaded by Ruby, it will create a DSL class called MyProject::Dsls::Strings.
180
+
181
+ To use we can require the file normally (making sure to add `lib` to the load path and requiring 'alki/dsl'
182
+ first).
183
+
184
+ ```
185
+ $ irb -Ilib
186
+ > require 'alki/dsl'
187
+ > require 'my_project/dsls/strings'
188
+ > MyProject::Dsls::Strings.build do
189
+ > add "hello"
190
+ > add "world"
191
+ > end
192
+ => "hello\nworld"
193
+ >
194
+ ```
195
+
196
+ The second DSL can now be setup the same way. Note that the `require_dsl` value has been replaced with a load
197
+ string.
198
+
199
+ .lib/my_project/dsls/transformable_strings.rb
200
+ ```ruby
201
+ Alki do
202
+ require_dsl 'my_project/dsls/strings'
203
+
204
+ init do
205
+ @transform = nil
206
+ end
207
+
208
+ dsl_method :transform do |&blk|
209
+ @transform = blk
210
+ end
211
+
212
+ finish do
213
+ if @transform
214
+ ctx[:strings].map! &@transform
215
+ end
216
+ end
217
+ end
218
+ ```
219
+
220
+ So what if we want to use our DSL with Alki::Loader as well? First, Alki::Loader requires builders to
221
+ define a constant with the correct name, so we need code to do that. Alki::Dsl comes with a "class" DSL
222
+ that makes this easy. First lets create a new DSL that adapts our transformable_strings DSL into a module
223
+ builder.
224
+
225
+ .lib/my_project/dsls/strings_class.rb
226
+ ```ruby
227
+ Alki do
228
+ require_dsl 'alki/dsls/class'
229
+ require_dsl 'my_project/dsls/transformable_strings', :after # This makes it's finish runs before ours
230
+
231
+ finish do
232
+ # Helpers provided by alki/dsls/class
233
+ create_as_module # Don't need a class, just a module
234
+ value = ctx[:result]
235
+ add_class_method(:value) { value }
236
+ end
237
+ end
238
+ ```
239
+
240
+ Now we can create a new directory, register it with Alki::Loader, and add a file that uses the DSL. Note
241
+ that we can set separator in the Alki::Loader register call. Any data values set here are passed in
242
+ as `ctx` in the DSL.
243
+
244
+ .lib/alki_loader.rb
245
+ ```ruby
246
+ Alki::Loader.register 'my_project/dsls', builder: 'alki/dsls/dsl'
247
+ Alki::Loader.register 'my_project/strings', builder: 'my_project/dsls/strings_class', separator: ', '
248
+ ```
249
+
250
+ .lib/my_project/strings/hello_world.rb
251
+ ```ruby
252
+ Alki do
253
+ transform &:capitalize
254
+
255
+ add "hello"
256
+ add "world"
257
+ end
258
+ ```
259
+
260
+ ```
261
+ $ irb -Ilib
262
+ > require 'alki/dsl'
263
+ > require 'my_project/strings/hello_world'
264
+ > MyProject::Strings::HelloWorld.value
265
+ => "Hello, World"
266
+ >
267
+ ```
268
+
269
+ ## Contributing
270
+
271
+ Bug reports and pull requests are welcome on GitHub at https://github.com/alki-project/alki-dsl. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the http://contributor-covenant.org[Contributor Covenant] code of conduct.
272
+
273
+
274
+ ## License
275
+
276
+ The gem is available as open source under the terms of the http://opensource.org/licenses/MIT[MIT License].
277
+
data/alki-dsl.gemspec CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency 'alki-support', '~> 0.6'
20
+ spec.add_dependency 'alki-support', '~> 0.7'
21
+ spec.add_dependency 'alki-loader', '~> 0.1'
21
22
  spec.add_development_dependency 'minitest', '~> 5.9', '>= 5.9.1'
22
23
  end
@@ -17,11 +17,9 @@ module Alki
17
17
  end
18
18
 
19
19
  def self.build(data)
20
- class_name = data[:class_name]
21
- if !class_name && data[:name] && data[:prefix]
22
- class_name = Alki::Support.classify(
23
- data[:prefix].empty? ? data[:name] : "#{data[:prefix]}/#{data[:name]}"
24
- )
20
+ class_name = data[:constant_name]
21
+ if !class_name && data[:name]
22
+ class_name = Alki::Support.classify(data[:name])
25
23
  end
26
24
 
27
25
  klass = Alki::Support.constantize class_name, data[:parent_class] if class_name
@@ -40,7 +38,7 @@ module Alki
40
38
  raise "#{class_name} already exists as is a #{klass.class}"
41
39
  end
42
40
  super_class = if data[:super_class]
43
- Alki::Support.load_class data[:super_class]
41
+ Alki.load data[:super_class]
44
42
  else
45
43
  Object
46
44
  end
@@ -59,8 +57,8 @@ module Alki
59
57
  if data[:secondary_classes]
60
58
  data[:secondary_classes].each do |data|
61
59
  if data[:subclass]
62
- data = data.merge(parent_class: klass,class_name: data[:subclass])
63
- elsif !data[:class_name] && !data[:name]
60
+ data = data.merge(parent_class: klass,constant_name: data[:subclass])
61
+ elsif !data[:constant_name] && !data[:name]
64
62
  raise ArgumentError.new("Secondary classes must have names")
65
63
  end
66
64
  build data
data/lib/alki/dsl.rb CHANGED
@@ -1,48 +1,10 @@
1
- require 'alki/dsl/evaluator'
2
- require 'alki/dsl/registry'
1
+ require 'alki/loader'
3
2
 
4
3
  module Alki
5
4
  module Dsl
6
- @loaded = {}
7
- def self.[]=(path,value)
8
- @loaded[path] =value
9
- end
10
-
11
- def self.[](path)
12
- @loaded[path]
13
- end
14
-
15
- def self.register(*args)
16
- Alki::Dsl::Registry.register *args
17
- end
18
-
19
- def self.register_dir(*args)
20
- Alki::Dsl::Registry.register_dir *args
21
- end
22
-
23
- def self.load(path)
24
- path = File.absolute_path(path)
25
- require path
26
- self[path]
27
- end
28
-
29
5
  def self.build(name,data={},&blk)
30
- Alki::Support.load_class(name).build data, &blk
6
+ Alki.load(name).build data, &blk
31
7
  end
32
8
  end
33
9
  end
34
10
 
35
- module Kernel
36
- def Alki(builder=nil,&blk)
37
- if blk
38
- path = caller_locations(1,1)[0].absolute_path
39
- result = if builder
40
- builder.build({}, &blk)
41
- else
42
- Alki::Dsl::Registry.build path, &blk
43
- end
44
- Alki::Dsl[path] = result
45
- end
46
- ::Alki
47
- end
48
- end
@@ -20,29 +20,37 @@ module Alki
20
20
  @finishers.reverse_each(&:call)
21
21
  clear_dsl_methods mod
22
22
 
23
- @processors.each do |processor|
24
- processor.build data
23
+ if data.key? :result
24
+ data[:result]
25
+ else
26
+ data
25
27
  end
26
-
27
- data
28
28
  end
29
29
 
30
30
  def process_dsl(dsl,data)
31
31
  return unless @dsls_seen.add? dsl
32
32
  cbs = dsl.generate(data)
33
+ after_requires = []
33
34
  if cbs[:requires]
34
- cbs[:requires].each do |required_dsl|
35
- process_dsl Alki::Support.load_class(required_dsl), data
35
+ cbs[:requires].each do |(required_dsl,order)|
36
+ case order
37
+ when :before
38
+ process_dsl Alki.load(required_dsl), data
39
+ when :after
40
+ after_requires << [Alki.load(required_dsl), data]
41
+ end
36
42
  end
37
43
  end
38
44
  @inits << cbs[:init] if cbs[:init]
39
45
  @finishers << cbs[:finish] if cbs[:finish]
40
- @processors << cbs[:processors] if cbs[:processors]
41
46
  if cbs[:methods]
42
47
  cbs[:methods].each do |name, proc|
43
48
  define_dsl_method data[:module], name, &proc
44
49
  end
45
50
  end
51
+ after_requires.each do |process_args|
52
+ process_dsl *process_args
53
+ end
46
54
  end
47
55
 
48
56
  def define_dsl_method(mod,name,&blk)
@@ -64,4 +72,4 @@ module Alki
64
72
  end
65
73
  end
66
74
  end
67
- end
75
+ end
@@ -1,5 +1,5 @@
1
1
  module Alki
2
2
  module Dsl
3
- VERSION = '0.3.4'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -24,7 +24,7 @@ module Alki
24
24
  end
25
25
 
26
26
  def finish
27
- ctx[:class] = Alki::ClassBuilder.build class_builder
27
+ ctx[:result] = Alki::ClassBuilder.build class_builder
28
28
  ctx.delete :class_builder
29
29
  end
30
30
  end
data/lib/alki/dsls/dsl.rb CHANGED
@@ -10,7 +10,7 @@ module Alki
10
10
 
11
11
  def self.dsl_info
12
12
  {
13
- requires: ['alki/dsls/class'],
13
+ requires: [['alki/dsls/class',:before]],
14
14
  methods: [
15
15
  :dsl_method,
16
16
  [:init,:dsl_init],
@@ -49,9 +49,9 @@ module Alki
49
49
  @info[:finish] = :_dsl_finish
50
50
  end
51
51
 
52
- def require_dsl(dsl)
53
- dsl_class = Alki::Support.load_class(dsl)
54
- @info[:requires] << dsl_class
52
+ def require_dsl(dsl, order=:before)
53
+ dsl_class = Alki.load(dsl)
54
+ @info[:requires] << [dsl_class,order]
55
55
  if defined? dsl_class::Helpers
56
56
  add_module dsl_class::Helpers
57
57
  add_helper_module dsl_class::Helpers
@@ -13,7 +13,7 @@ describe 'dsl configuration' do
13
13
  end
14
14
 
15
15
  it 'should allow using dsls specified in same dsl config' do
16
- Kernel.load(fixture_path('example','numbers','three.rb'))
16
+ require 'alki_test/numbers/three'
17
17
  AlkiTest::Numbers::Three.new.must_equal 3
18
18
  end
19
- end
19
+ end
@@ -0,0 +1,2 @@
1
+ Alki::Loader.register '../numbers', builder: 'alki_test/dsls/number', name: 'alki_test/numbers'
2
+ Alki::Loader.register 'alki_test/dsls', builder: 'alki/dsls/dsl'
@@ -105,11 +105,11 @@ describe Alki::ClassBuilder do
105
105
  obj.instance_variable_get(:@b).must_equal 2
106
106
  end
107
107
 
108
- it 'should allow providing a class name' do
108
+ it 'should allow providing a constant name' do
109
109
  if defined?(AlkiTestClass)
110
110
  Object.send :remove_const, :AlkiTestClass
111
111
  end
112
- build(class_name: "AlkiTestClass")
112
+ build(constant_name: "AlkiTestClass")
113
113
  assert(defined?(AlkiTestClass),'Expected AlkiTestClass to be defined')
114
114
  Object.send :remove_const, :AlkiTestClass
115
115
  assert(!defined?(AlkiTestClass))
@@ -119,16 +119,7 @@ describe Alki::ClassBuilder do
119
119
  if defined?(AlkiTest::TestClass)
120
120
  Object.send :remove_const, :AlkiTest
121
121
  end
122
- build(prefix: '', name: "alki_test/test_class")
123
- assert(defined?(AlkiTest::TestClass),'Expected AlkiTest::TestClass to be defined')
124
- Object.send :remove_const, :AlkiTest
125
- end
126
-
127
- it 'should use prefix and name to create class name' do
128
- if defined?(AlkiTest::TestClass)
129
- Object.send :remove_const, :AlkiTest
130
- end
131
- build(prefix: 'alki_test', name: "test_class")
122
+ build(name: "alki_test/test_class")
132
123
  assert(defined?(AlkiTest::TestClass),'Expected AlkiTest::TestClass to be defined')
133
124
  Object.send :remove_const, :AlkiTest
134
125
  end
@@ -137,12 +128,25 @@ describe Alki::ClassBuilder do
137
128
  build(
138
129
  secondary_classes: [
139
130
  {
140
- class_name: 'AlkiTestClass'
131
+ constant_name: 'AlkiTestClass'
141
132
  }
142
133
  ]
143
134
  )
144
135
  assert(defined?(AlkiTestClass),'Expected AlkiTestClass to be defined')
145
136
  Object.send :remove_const, :AlkiTestClass
146
137
  end
138
+
139
+ it 'should allow creating subclasses' do
140
+ build(
141
+ constant_name: 'AlkiTestClass',
142
+ secondary_classes: [
143
+ {
144
+ subclass: 'Subclass'
145
+ }
146
+ ]
147
+ )
148
+ assert(defined?(AlkiTestClass::Subclass),'Expected AlkiTestClass::Subclass to be defined')
149
+ Object.send :remove_const, :AlkiTestClass
150
+ end
147
151
  end
148
152
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alki-dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Edlefsen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-20 00:00:00.000000000 Z
11
+ date: 2016-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: alki-support
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.6'
19
+ version: '0.7'
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
- version: '0.6'
26
+ version: '0.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: alki-loader
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: minitest
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,21 +67,18 @@ extra_rdoc_files: []
53
67
  files:
54
68
  - ".gitignore"
55
69
  - Gemfile
70
+ - README.adoc
56
71
  - alki-dsl.gemspec
57
72
  - lib/alki/class_builder.rb
58
73
  - lib/alki/dsl.rb
59
74
  - lib/alki/dsl/base.rb
60
- - lib/alki/dsl/builder.rb
61
75
  - lib/alki/dsl/class_helpers.rb
62
76
  - lib/alki/dsl/evaluator.rb
63
- - lib/alki/dsl/loader.rb
64
- - lib/alki/dsl/registry.rb
65
77
  - lib/alki/dsl/version.rb
66
78
  - lib/alki/dsls/class.rb
67
79
  - lib/alki/dsls/dsl.rb
68
- - lib/alki/dsls/dsl_config.rb
69
80
  - test/feature/config_test.rb
70
- - test/fixtures/example/config/dsls.rb
81
+ - test/fixtures/example/lib/alki_loader.rb
71
82
  - test/fixtures/example/lib/alki_test/dsls/number.rb
72
83
  - test/fixtures/example/lib/alki_test/dsls/value.rb
73
84
  - test/fixtures/example/numbers/three.rb
@@ -100,7 +111,7 @@ specification_version: 4
100
111
  summary: Alki dsl library
101
112
  test_files:
102
113
  - test/feature/config_test.rb
103
- - test/fixtures/example/config/dsls.rb
114
+ - test/fixtures/example/lib/alki_loader.rb
104
115
  - test/fixtures/example/lib/alki_test/dsls/number.rb
105
116
  - test/fixtures/example/lib/alki_test/dsls/value.rb
106
117
  - test/fixtures/example/numbers/three.rb
@@ -1,42 +0,0 @@
1
- require 'alki/support'
2
- require 'alki/dsl/evaluator'
3
-
4
- module Alki
5
- module Dsl
6
- class Builder
7
- def self.build(data,&blk)
8
- result = Alki::Dsl::Evaluator.evaluate _dsls,data,&blk
9
- if _processor
10
- _processor.build result
11
- else
12
- result
13
- end
14
- end
15
-
16
- private
17
-
18
- def self.dsl(name)
19
- klass = Alki::Support.load_class name
20
- unless klass
21
- raise "Unable to load class #{name.inspect}"
22
- end
23
- dsls = _dsls
24
- dsls += [klass]
25
- define_singleton_method(:_dsls) { dsls }
26
- end
27
-
28
- def self.processor(name)
29
- klass = Alki::Support.load_class name
30
- define_singleton_method(:_processor) { klass }
31
- end
32
-
33
- def self._dsls
34
- []
35
- end
36
-
37
- def self._processor
38
- nil
39
- end
40
- end
41
- end
42
- end
@@ -1,28 +0,0 @@
1
- require 'alki/support'
2
- require 'alki/dsl'
3
-
4
- module Alki
5
- module Dsl
6
- class Loader
7
- def initialize(root_dir)
8
- @root_dir = root_dir
9
- end
10
-
11
- def all_paths
12
- Dir[File.join(@root_dir,'**','*.rb')].map do |path|
13
- path.gsub(File.join(@root_dir,''),'').gsub(/\.rb$/,'')
14
- end
15
- end
16
-
17
- def load_all
18
- all_paths.inject({}) do |h,path|
19
- h.merge!(path => Alki::Dsl.load(path))
20
- end
21
- end
22
-
23
- def load(file)
24
- Alki::Dsl.load File.expand_path("#{file}.rb",@root_dir)
25
- end
26
- end
27
- end
28
- end
@@ -1,76 +0,0 @@
1
- require 'alki/dsl/loader'
2
- require 'alki/support'
3
-
4
- module Alki
5
- module Dsl
6
- module Registry
7
- @registered_paths = {}
8
- @registered_dirs = {}
9
-
10
- def self.registered_paths
11
- @registered_paths.keys
12
- end
13
-
14
- def self.registered_dirs
15
- @registered_dirs.keys
16
- end
17
-
18
- def self.register(path,builder,**data)
19
- @registered_paths[File.absolute_path(path)] = Entry.new(builder,data)
20
- end
21
-
22
- def self.register_dir(dir_path,builder,**data)
23
- @registered_dirs[File.join(File.absolute_path(dir_path),'')] = [builder,data]
24
- end
25
-
26
- def self.lookup(path, load_configs: true)
27
- path = File.absolute_path path
28
- entry = @registered_paths[path]
29
- return entry if entry
30
-
31
- @registered_dirs.each do |dir,(builder,data)|
32
- if path.start_with? dir
33
- data = {name: Alki::Support.path_name(path, dir)}.merge data
34
- return Entry.new(builder,data)
35
- end
36
- end
37
-
38
- if load_configs
39
- root = Alki::Support.find_root(path) do |dir|
40
- File.exists?(File.join(dir,'config','dsls.rb'))
41
- end
42
- if root
43
- config_file = File.join(root,'config','dsls.rb')
44
- register config_file, 'alki/dsls/dsl_config', root: root
45
- require config_file
46
- return lookup path, load_configs: false
47
- end
48
- end
49
-
50
- nil
51
- end
52
-
53
- def self.build(path,&blk)
54
- entry = lookup path
55
- if entry
56
- entry.build blk
57
- else
58
- nil
59
- end
60
- end
61
-
62
- class Entry
63
- attr_reader :data
64
-
65
- def initialize(builder,data)
66
- @builder = builder
67
- @data = data
68
- end
69
-
70
- def build(blk)
71
- Alki::Support.load_class(@builder).build @data, &blk
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,28 +0,0 @@
1
- require 'alki/dsl/base'
2
-
3
- module Alki
4
- module Dsls
5
- class DslConfig < Alki::Dsl::Base
6
- def self.dsl_info
7
- {
8
- methods: %i(register register_dir register_lib_dir)
9
- }
10
- end
11
-
12
- def register(path,*args)
13
- path = File.expand_path(path,@ctx[:root])
14
- Alki::Dsl::Registry.register path, *args
15
- end
16
-
17
- def register_dir(path,*args)
18
- path = File.expand_path(path,@ctx[:root])
19
- Alki::Dsl::Registry.register_dir path, *args
20
- end
21
-
22
- def register_lib_dir(prefix,dsl,**data)
23
- path = File.join(@ctx[:root],'lib', prefix)
24
- Alki::Dsl::Registry.register_dir path, dsl, data.merge(prefix: prefix)
25
- end
26
- end
27
- end
28
- end
@@ -1,4 +0,0 @@
1
- Alki do
2
- register_dir 'numbers', 'alki_test/dsls/number', prefix: 'alki_test/numbers'
3
- register_lib_dir 'alki_test/dsls', 'alki/dsls/dsl'
4
- end