configuration 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.
- data/README +210 -0
- data/config/a.rb +5 -0
- data/config/b.rb +19 -0
- data/config/c.rb +8 -0
- data/config/d.rb +5 -0
- data/gemspec.rb +35 -0
- data/gen_readme.rb +37 -0
- data/install.rb +214 -0
- data/lib/configuration.rb +165 -0
- data/samples/a.rb +11 -0
- data/samples/b.rb +11 -0
- data/samples/c.rb +11 -0
- data/samples/d.rb +14 -0
- metadata +68 -0
data/README
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
NAME
|
2
|
+
configuration.rb
|
3
|
+
|
4
|
+
SYNOPSIS
|
5
|
+
pure ruby scoped configuration files
|
6
|
+
|
7
|
+
DESCRIPTION
|
8
|
+
configuration.rb provides a mechanism for configuring ruby programs with
|
9
|
+
ruby configuration files. a configuration.rb file, for example
|
10
|
+
'config/app.rb', can be written simply as
|
11
|
+
|
12
|
+
Configuration.for('app'){
|
13
|
+
key 'value'
|
14
|
+
foo 'bar'
|
15
|
+
port 42
|
16
|
+
}
|
17
|
+
|
18
|
+
and loaded via the normal ruby require/load mechanism
|
19
|
+
|
20
|
+
Kernel.load 'config/app.rb'
|
21
|
+
|
22
|
+
or with a slightly augmented loading mechnanism which simply searches an
|
23
|
+
extra set of paths in *addition* to the standard ones
|
24
|
+
|
25
|
+
Configuration.path = %w( config configuration )
|
26
|
+
|
27
|
+
Configuration.load 'app'
|
28
|
+
|
29
|
+
configurations are completely open
|
30
|
+
|
31
|
+
Configuration.for('app'){
|
32
|
+
object_id 'very open'
|
33
|
+
}
|
34
|
+
|
35
|
+
support arbitrarily nested values
|
36
|
+
|
37
|
+
Configuration.for('app'){
|
38
|
+
a { b { c { d 42 } } }
|
39
|
+
}
|
40
|
+
|
41
|
+
c = Configuration.for 'app'
|
42
|
+
|
43
|
+
p c.a.b.c.d #=> 42
|
44
|
+
|
45
|
+
allow POLS scoped lookup of vars
|
46
|
+
|
47
|
+
Configuration.for('config'){
|
48
|
+
outer 'bar'
|
49
|
+
|
50
|
+
inner {
|
51
|
+
value 42
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
c = Configuration.for 'config'
|
56
|
+
|
57
|
+
p c.outer #=> 'bar'
|
58
|
+
p c.inner.value #=> 42
|
59
|
+
p c.inner.outer #=> 'bar'
|
60
|
+
|
61
|
+
|
62
|
+
and not a whole lot else - configuration.rb is s very small library
|
63
|
+
consisting of one file and < 150 loc
|
64
|
+
|
65
|
+
SAMPLES
|
66
|
+
|
67
|
+
<========< samples/a.rb >========>
|
68
|
+
|
69
|
+
~ > cat samples/a.rb
|
70
|
+
|
71
|
+
#
|
72
|
+
# basic usage is quite, simple, load the config and use it's values. the
|
73
|
+
# config syntax is fairly obvious, i think, but note that it *is* ruby and any
|
74
|
+
# ruby can be included. also note that each config is named, allowing
|
75
|
+
# multiple configs to be places in one file
|
76
|
+
#
|
77
|
+
require 'configuration'
|
78
|
+
|
79
|
+
c = Configuration.load 'a'
|
80
|
+
|
81
|
+
p c.a + c.b - c.c
|
82
|
+
|
83
|
+
~ > cat config/a.rb
|
84
|
+
|
85
|
+
Configuration.for('a'){
|
86
|
+
a 40
|
87
|
+
b 4
|
88
|
+
c 2
|
89
|
+
}
|
90
|
+
|
91
|
+
~ > ruby samples/a.rb
|
92
|
+
|
93
|
+
42
|
94
|
+
|
95
|
+
|
96
|
+
<========< samples/b.rb >========>
|
97
|
+
|
98
|
+
~ > cat samples/b.rb
|
99
|
+
|
100
|
+
#
|
101
|
+
# configuration.rb supports a very natural nesting syntax. note how values
|
102
|
+
# are scoped in a POLS fashion
|
103
|
+
#
|
104
|
+
require 'configuration'
|
105
|
+
|
106
|
+
c = Configuration.for 'b'
|
107
|
+
|
108
|
+
p c.www.url
|
109
|
+
p c.db.url
|
110
|
+
p c.mail.url
|
111
|
+
|
112
|
+
~ > cat config/b.rb
|
113
|
+
|
114
|
+
Configuration.for('b'){
|
115
|
+
host "codeforpeople.com"
|
116
|
+
|
117
|
+
www {
|
118
|
+
port 80
|
119
|
+
url "http://#{ host }:#{ port }"
|
120
|
+
}
|
121
|
+
|
122
|
+
db {
|
123
|
+
port 5342
|
124
|
+
url "db://#{ host }:#{ port }"
|
125
|
+
}
|
126
|
+
|
127
|
+
mail {
|
128
|
+
host "gmail.com"
|
129
|
+
port 25
|
130
|
+
url "mail://#{ host }:#{ port }"
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
~ > ruby samples/b.rb
|
135
|
+
|
136
|
+
"http://codeforpeople.com:80"
|
137
|
+
"db://codeforpeople.com:5342"
|
138
|
+
"mail://gmail.com:25"
|
139
|
+
|
140
|
+
|
141
|
+
<========< samples/c.rb >========>
|
142
|
+
|
143
|
+
~ > cat samples/c.rb
|
144
|
+
|
145
|
+
#
|
146
|
+
# configuration.rb let's you keep code very dry.
|
147
|
+
#
|
148
|
+
|
149
|
+
require 'configuration'
|
150
|
+
|
151
|
+
Configuration.load 'c'
|
152
|
+
|
153
|
+
p Configuration.for('development').db
|
154
|
+
p Configuration.for('production').db
|
155
|
+
p Configuration.for('testing').db
|
156
|
+
|
157
|
+
~ > cat config/c.rb
|
158
|
+
|
159
|
+
%w( development production testing ).each do |environment|
|
160
|
+
|
161
|
+
Configuration.for(environment){
|
162
|
+
adapter "sqlite3"
|
163
|
+
db "db/#{ environment }"
|
164
|
+
}
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
~ > ruby samples/c.rb
|
169
|
+
|
170
|
+
"db/development"
|
171
|
+
"db/production"
|
172
|
+
"db/testing"
|
173
|
+
|
174
|
+
|
175
|
+
<========< samples/d.rb >========>
|
176
|
+
|
177
|
+
~ > cat samples/d.rb
|
178
|
+
|
179
|
+
#
|
180
|
+
# configuration.rb makes use of an external blank slate dsl, this means that
|
181
|
+
# you Configuration objects do, in fact, have all built-in ruby methods such
|
182
|
+
# as #inspect, etc, *unless* you configure over the top of them. the effect
|
183
|
+
# is a configuration object that behaves like a nice ruby object, but which
|
184
|
+
# allows *any* key to be configured
|
185
|
+
#
|
186
|
+
require 'configuration'
|
187
|
+
|
188
|
+
c = Configuration.for 'd'
|
189
|
+
|
190
|
+
p c.object_id
|
191
|
+
p c.inspect
|
192
|
+
p c.p
|
193
|
+
|
194
|
+
~ > cat config/d.rb
|
195
|
+
|
196
|
+
Configuration.for('d'){
|
197
|
+
object_id 42
|
198
|
+
inspect 'forty-two'
|
199
|
+
p 42.0
|
200
|
+
}
|
201
|
+
|
202
|
+
~ > ruby samples/d.rb
|
203
|
+
|
204
|
+
42
|
205
|
+
"forty-two"
|
206
|
+
42.0
|
207
|
+
|
208
|
+
|
209
|
+
AUTHOR
|
210
|
+
ara.t.howard@gmail.com
|
data/config/b.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Configuration.for('b'){
|
2
|
+
host "codeforpeople.com"
|
3
|
+
|
4
|
+
www {
|
5
|
+
port 80
|
6
|
+
url "http://#{ host }:#{ port }"
|
7
|
+
}
|
8
|
+
|
9
|
+
db {
|
10
|
+
port 5342
|
11
|
+
url "db://#{ host }:#{ port }"
|
12
|
+
}
|
13
|
+
|
14
|
+
mail {
|
15
|
+
host "gmail.com"
|
16
|
+
port 25
|
17
|
+
url "mail://#{ host }:#{ port }"
|
18
|
+
}
|
19
|
+
}
|
data/config/c.rb
ADDED
data/config/d.rb
ADDED
data/gemspec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
Gem::Specification::new do |spec|
|
6
|
+
$VERBOSE = nil
|
7
|
+
|
8
|
+
shiteless = lambda do |list|
|
9
|
+
list.delete_if do |file|
|
10
|
+
file =~ %r/\.svn/ or
|
11
|
+
file =~ %r/\.tmp/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
spec.name = lib
|
16
|
+
spec.version = version
|
17
|
+
spec.platform = Gem::Platform::RUBY
|
18
|
+
spec.summary = lib
|
19
|
+
|
20
|
+
spec.files = shiteless[Dir::glob("**/**")]
|
21
|
+
spec.executables = shiteless[Dir::glob("bin/*")].map{|exe| File::basename exe}
|
22
|
+
|
23
|
+
spec.require_path = "lib"
|
24
|
+
spec.autorequire = lib
|
25
|
+
|
26
|
+
spec.has_rdoc = File::exist? "doc"
|
27
|
+
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
28
|
+
#spec.add_dependency 'lib', '>= version'
|
29
|
+
|
30
|
+
spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
|
31
|
+
|
32
|
+
spec.author = "Ara T. Howard"
|
33
|
+
spec.email = "ara.t.howard@gmail.com"
|
34
|
+
spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
|
35
|
+
end
|
data/gen_readme.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
$VERBOSE=nil
|
4
|
+
|
5
|
+
def indent s, n = 2
|
6
|
+
ws = ' ' * n
|
7
|
+
s.gsub %r/^/, ws
|
8
|
+
end
|
9
|
+
|
10
|
+
template = IO::read 'README.tmpl'
|
11
|
+
|
12
|
+
samples = ''
|
13
|
+
prompt = '~ > '
|
14
|
+
|
15
|
+
Dir['sample*/*'].sort.each do |sample|
|
16
|
+
config = sample.gsub(%r/samples?/, 'config')
|
17
|
+
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
18
|
+
|
19
|
+
cmd = "cat #{ sample }"
|
20
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
21
|
+
samples << indent(`#{ cmd }`, 4) << "\n"
|
22
|
+
|
23
|
+
cmd = "cat #{ config }"
|
24
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
25
|
+
samples << indent(`#{ cmd }`, 4) << "\n"
|
26
|
+
|
27
|
+
cmd = "ruby #{ sample }"
|
28
|
+
samples << indent(prompt + cmd, 2) << "\n\n"
|
29
|
+
|
30
|
+
cmd = "ruby -Ilib -Iconfig #{ sample }"
|
31
|
+
samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
#samples.gsub! %r/^/, ' '
|
35
|
+
|
36
|
+
readme = template.gsub %r/^\s*@samples\s*$/, samples
|
37
|
+
print readme
|
data/install.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'find'
|
4
|
+
require 'ftools'
|
5
|
+
require 'tempfile'
|
6
|
+
include Config
|
7
|
+
|
8
|
+
LIBDIR = "lib"
|
9
|
+
LIBDIR_MODE = 0644
|
10
|
+
|
11
|
+
BINDIR = "bin"
|
12
|
+
BINDIR_MODE = 0755
|
13
|
+
|
14
|
+
|
15
|
+
$srcdir = CONFIG["srcdir"]
|
16
|
+
$version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
17
|
+
$libdir = File.join(CONFIG["libdir"], "ruby", $version)
|
18
|
+
$archdir = File.join($libdir, CONFIG["arch"])
|
19
|
+
$site_libdir = $:.find {|x| x =~ /site_ruby$/}
|
20
|
+
$bindir = CONFIG["bindir"] || CONFIG['BINDIR']
|
21
|
+
$ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
|
22
|
+
$ruby_ext = CONFIG['EXEEXT'] || ''
|
23
|
+
$ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
|
24
|
+
|
25
|
+
if !$site_libdir
|
26
|
+
$site_libdir = File.join($libdir, "site_ruby")
|
27
|
+
elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
|
28
|
+
$site_libdir = File.join($site_libdir, $version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
|
32
|
+
#{{{
|
33
|
+
path = []
|
34
|
+
dir = []
|
35
|
+
Find.find(srcdir) do |f|
|
36
|
+
next unless FileTest.file?(f)
|
37
|
+
next if (f = f[srcdir.length+1..-1]) == nil
|
38
|
+
next if (/CVS$/ =~ File.dirname(f))
|
39
|
+
next if (/\.svn/ =~ File.dirname(f))
|
40
|
+
next if f =~ %r/\.lnk/
|
41
|
+
next if f =~ %r/\.svn/
|
42
|
+
next if f =~ %r/\.swp/
|
43
|
+
next if f =~ %r/\.svn/
|
44
|
+
path.push f
|
45
|
+
dir |= [File.dirname(f)]
|
46
|
+
end
|
47
|
+
for f in dir
|
48
|
+
next if f == "."
|
49
|
+
next if f == "CVS"
|
50
|
+
File::makedirs(File.join(destdir, f))
|
51
|
+
end
|
52
|
+
for f in path
|
53
|
+
next if (/\~$/ =~ f)
|
54
|
+
next if (/^\./ =~ File.basename(f))
|
55
|
+
unless bin
|
56
|
+
File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
|
57
|
+
else
|
58
|
+
from = File.join(srcdir, f)
|
59
|
+
to = File.join(destdir, f)
|
60
|
+
shebangify(from) do |sf|
|
61
|
+
$deferr.print from, " -> ", File::catname(from, to), "\n"
|
62
|
+
$deferr.printf "chmod %04o %s\n", mode, to
|
63
|
+
File::install(sf, to, mode, false)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
#}}}
|
68
|
+
end
|
69
|
+
def shebangify f
|
70
|
+
#{{{
|
71
|
+
open(f) do |fd|
|
72
|
+
buf = fd.read 42
|
73
|
+
if buf =~ %r/^\s*#\s*!.*ruby/o
|
74
|
+
ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
|
75
|
+
begin
|
76
|
+
fd.rewind
|
77
|
+
ftmp.puts "#!#{ $ruby }"
|
78
|
+
while((buf = fd.read(8192)))
|
79
|
+
ftmp.write buf
|
80
|
+
end
|
81
|
+
ftmp.close
|
82
|
+
yield ftmp.path
|
83
|
+
ensure
|
84
|
+
ftmp.close!
|
85
|
+
end
|
86
|
+
else
|
87
|
+
yield f
|
88
|
+
end
|
89
|
+
end
|
90
|
+
#}}}
|
91
|
+
end
|
92
|
+
def ARGV.switch
|
93
|
+
#{{{
|
94
|
+
return nil if self.empty?
|
95
|
+
arg = self.shift
|
96
|
+
return nil if arg == '--'
|
97
|
+
if arg =~ /^-(.)(.*)/
|
98
|
+
return arg if $1 == '-'
|
99
|
+
raise 'unknown switch "-"' if $2.index('-')
|
100
|
+
self.unshift "-#{$2}" if $2.size > 0
|
101
|
+
"-#{$1}"
|
102
|
+
else
|
103
|
+
self.unshift arg
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
#}}}
|
107
|
+
end
|
108
|
+
def ARGV.req_arg
|
109
|
+
#{{{
|
110
|
+
self.shift || raise('missing argument')
|
111
|
+
#}}}
|
112
|
+
end
|
113
|
+
def linkify d, linked = []
|
114
|
+
#--{{{
|
115
|
+
if test ?d, d
|
116
|
+
versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
|
117
|
+
versioned.each do |v|
|
118
|
+
src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
|
119
|
+
lnk = nil
|
120
|
+
begin
|
121
|
+
if test ?l, dst
|
122
|
+
lnk = "#{ dst }.lnk"
|
123
|
+
puts "#{ dst } -> #{ lnk }"
|
124
|
+
File::rename dst, lnk
|
125
|
+
end
|
126
|
+
unless test ?e, dst
|
127
|
+
puts "#{ src } -> #{ dst }"
|
128
|
+
File::copy src, dst
|
129
|
+
linked << dst
|
130
|
+
end
|
131
|
+
ensure
|
132
|
+
if lnk
|
133
|
+
at_exit do
|
134
|
+
puts "#{ lnk } -> #{ dst }"
|
135
|
+
File::rename lnk, dst
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
linked
|
142
|
+
#--}}}
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
#
|
147
|
+
# main program
|
148
|
+
#
|
149
|
+
|
150
|
+
libdir = $site_libdir
|
151
|
+
bindir = $bindir
|
152
|
+
no_linkify = false
|
153
|
+
linked = nil
|
154
|
+
help = false
|
155
|
+
|
156
|
+
usage = <<-usage
|
157
|
+
#{ File::basename $0 }
|
158
|
+
-d, --destdir <destdir>
|
159
|
+
-l, --libdir <libdir>
|
160
|
+
-b, --bindir <bindir>
|
161
|
+
-r, --ruby <ruby>
|
162
|
+
-n, --no_linkify
|
163
|
+
-s, --sudo
|
164
|
+
-h, --help
|
165
|
+
usage
|
166
|
+
|
167
|
+
begin
|
168
|
+
while switch = ARGV.switch
|
169
|
+
case switch
|
170
|
+
when '-d', '--destdir'
|
171
|
+
libdir = ARGV.req_arg
|
172
|
+
when '-l', '--libdir'
|
173
|
+
libdir = ARGV.req_arg
|
174
|
+
when '-b', '--bindir'
|
175
|
+
bindir = ARGV.req_arg
|
176
|
+
when '-r', '--ruby'
|
177
|
+
$ruby = ARGV.req_arg
|
178
|
+
when '-n', '--no_linkify'
|
179
|
+
no_linkify = true
|
180
|
+
when '-s', '--sudo'
|
181
|
+
sudo = 'sudo'
|
182
|
+
when '-h', '--help'
|
183
|
+
help = true
|
184
|
+
else
|
185
|
+
raise "unknown switch #{switch.dump}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
rescue
|
189
|
+
STDERR.puts $!.to_s
|
190
|
+
STDERR.puts usage
|
191
|
+
exit 1
|
192
|
+
end
|
193
|
+
|
194
|
+
if help
|
195
|
+
STDOUT.puts usage
|
196
|
+
exit
|
197
|
+
end
|
198
|
+
|
199
|
+
system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
|
200
|
+
|
201
|
+
unless no_linkify
|
202
|
+
linked = linkify('lib') + linkify('bin')
|
203
|
+
end
|
204
|
+
|
205
|
+
system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
|
206
|
+
|
207
|
+
install_rb(LIBDIR, libdir, LIBDIR_MODE)
|
208
|
+
install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
|
209
|
+
|
210
|
+
if linked
|
211
|
+
linked.each{|path| File::rm_f path}
|
212
|
+
end
|
213
|
+
|
214
|
+
system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
|
@@ -0,0 +1,165 @@
|
|
1
|
+
|
2
|
+
class Configuration
|
3
|
+
Version = '0.0.3'
|
4
|
+
def Configuration.version() Version end
|
5
|
+
|
6
|
+
Path = [
|
7
|
+
if defined? CONFIGURATION_PATH
|
8
|
+
CONFIGURATION_PATH
|
9
|
+
else
|
10
|
+
ENV['CONFIGURATION_PATH']
|
11
|
+
end
|
12
|
+
].compact.flatten.join(File::PATH_SEPARATOR).split(File::PATH_SEPARATOR)
|
13
|
+
|
14
|
+
Table = Hash.new
|
15
|
+
Error = Class.new StandardError
|
16
|
+
Import = Class.new Error
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def for name, options = nil, &block
|
20
|
+
name = name.to_s
|
21
|
+
if Table.has_key?(name)
|
22
|
+
if options or block
|
23
|
+
configuration = Table[name]
|
24
|
+
Table[name] = DSL.evaluate(configuration, options || {}, &block)
|
25
|
+
else
|
26
|
+
Table[name]
|
27
|
+
end
|
28
|
+
else
|
29
|
+
if options or block
|
30
|
+
Table[name] = new name, options || {}, &block
|
31
|
+
else
|
32
|
+
load name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def path *value
|
38
|
+
return self.path = value.first unless value.empty?
|
39
|
+
Path
|
40
|
+
end
|
41
|
+
|
42
|
+
def path= value
|
43
|
+
Path.clear
|
44
|
+
Path.replace [value].compact.flatten.join(File::PATH_SEPARATOR).split(File::PATH_SEPARATOR)
|
45
|
+
end
|
46
|
+
|
47
|
+
def load name
|
48
|
+
name = name.to_s
|
49
|
+
name = name + '.rb' unless name[%r/\.rb$/]
|
50
|
+
key = name.sub %r/\.rb$/, ''
|
51
|
+
load_path = $LOAD_PATH.dup
|
52
|
+
begin
|
53
|
+
$LOAD_PATH.replace(path + load_path)
|
54
|
+
::Kernel.load name
|
55
|
+
ensure
|
56
|
+
$LOAD_PATH.replace load_path
|
57
|
+
end
|
58
|
+
Table[key]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
send :extend, ClassMethods
|
62
|
+
|
63
|
+
module InstanceMethods
|
64
|
+
attr 'name'
|
65
|
+
|
66
|
+
def initialize *argv, &block
|
67
|
+
options = Hash === argv.last ? argv.pop : Hash.new
|
68
|
+
@name = argv.shift
|
69
|
+
DSL.evaluate(self, options, &block)
|
70
|
+
end
|
71
|
+
|
72
|
+
def method_missing m, *a, &b
|
73
|
+
return(Pure[@__parent].send m, *a, &b) rescue super if @__parent
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
send :include, InstanceMethods
|
78
|
+
|
79
|
+
|
80
|
+
class DSL
|
81
|
+
instance_methods.each do |m|
|
82
|
+
undef_method m unless m[%r/^__/]
|
83
|
+
end
|
84
|
+
|
85
|
+
Kernel.methods.each do |m|
|
86
|
+
next if m[%r/^__/]
|
87
|
+
module_eval <<-code
|
88
|
+
def #{ m }(*a, &b)
|
89
|
+
method_missing '#{ m }', *a, &b
|
90
|
+
end
|
91
|
+
code
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.evaluate configuration, options = {}, &block
|
95
|
+
dsl = new configuration
|
96
|
+
Pure[dsl].instance_eval &block if block
|
97
|
+
options.each{|key, value| Pure[dsl].send key, value}
|
98
|
+
Pure[dsl].instance_eval{ @__configuration }
|
99
|
+
end
|
100
|
+
|
101
|
+
def initialize configuration, &block
|
102
|
+
@__configuration = configuration
|
103
|
+
@__singleton_class =
|
104
|
+
class << @__configuration
|
105
|
+
self
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def method_missing m, *a, &b
|
110
|
+
if(a.empty? and b.nil?)
|
111
|
+
return Pure[@__configuration].send(m, *a, &b)
|
112
|
+
end
|
113
|
+
if b
|
114
|
+
raise ArgumentError unless a.empty?
|
115
|
+
parent = @__configuration
|
116
|
+
name = m.to_s
|
117
|
+
configuration =
|
118
|
+
if @__configuration.respond_to?(name) and Configuration === @__configuration.send(name)
|
119
|
+
@__configuration.send name
|
120
|
+
else
|
121
|
+
Configuration.new name
|
122
|
+
end
|
123
|
+
Pure[configuration].instance_eval{ @__parent = parent }
|
124
|
+
DSL.evaluate configuration, &b
|
125
|
+
value = configuration
|
126
|
+
end
|
127
|
+
unless a.empty?
|
128
|
+
value = a.size == 1 ? a.first : a
|
129
|
+
end
|
130
|
+
@__singleton_class.module_eval do
|
131
|
+
define_method(m){ value }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class Pure
|
137
|
+
Instance_Methods = Hash.new
|
138
|
+
|
139
|
+
::Object.instance_methods.each do |m|
|
140
|
+
Instance_Methods[m.to_s] = ::Object.instance_method m
|
141
|
+
undef_method m unless m[%r/^__/]
|
142
|
+
end
|
143
|
+
|
144
|
+
def method_missing m, *a, &b
|
145
|
+
Instance_Methods[m.to_s].bind(@object).call(*a, &b)
|
146
|
+
end
|
147
|
+
|
148
|
+
def initialize object
|
149
|
+
@object = object
|
150
|
+
end
|
151
|
+
|
152
|
+
def Pure.[] object
|
153
|
+
new object
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def Configuration(*a, &b)
|
159
|
+
if a.empty? and b.nil?
|
160
|
+
const_get :Configuration
|
161
|
+
else
|
162
|
+
Configuration.new(*a, &b)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
data/samples/a.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#
|
2
|
+
# basic usage is quite, simple, load the config and use it's values. the
|
3
|
+
# config syntax is fairly obvious, i think, but note that it *is* ruby and any
|
4
|
+
# ruby can be included. also note that each config is named, allowing
|
5
|
+
# multiple configs to be places in one file
|
6
|
+
#
|
7
|
+
require 'configuration'
|
8
|
+
|
9
|
+
c = Configuration.load 'a'
|
10
|
+
|
11
|
+
p c.a + c.b - c.c
|
data/samples/b.rb
ADDED
data/samples/c.rb
ADDED
data/samples/d.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#
|
2
|
+
# configuration.rb makes use of an external blank slate dsl, this means that
|
3
|
+
# you Configuration objects do, in fact, have all built-in ruby methods such
|
4
|
+
# as #inspect, etc, *unless* you configure over the top of them. the effect
|
5
|
+
# is a configuration object that behaves like a nice ruby object, but which
|
6
|
+
# allows *any* key to be configured
|
7
|
+
#
|
8
|
+
require 'configuration'
|
9
|
+
|
10
|
+
c = Configuration.for 'd'
|
11
|
+
|
12
|
+
p c.object_id
|
13
|
+
p c.inspect
|
14
|
+
p c.p
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: configuration
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ara T. Howard
|
8
|
+
autorequire: configuration
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-02-12 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: ara.t.howard@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- config
|
26
|
+
- config/a.rb
|
27
|
+
- config/b.rb
|
28
|
+
- config/c.rb
|
29
|
+
- config/d.rb
|
30
|
+
- gemspec.rb
|
31
|
+
- gen_readme.rb
|
32
|
+
- install.rb
|
33
|
+
- lib
|
34
|
+
- lib/configuration.rb
|
35
|
+
- README
|
36
|
+
- samples
|
37
|
+
- samples/a.rb
|
38
|
+
- samples/b.rb
|
39
|
+
- samples/c.rb
|
40
|
+
- samples/d.rb
|
41
|
+
has_rdoc: false
|
42
|
+
homepage: http://codeforpeople.com/lib/ruby/configuration/
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.0.1
|
64
|
+
signing_key:
|
65
|
+
specification_version: 2
|
66
|
+
summary: configuration
|
67
|
+
test_files: []
|
68
|
+
|