autorequire 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,337 @@
1
+ URLS
2
+
3
+ http://codeforpeople.com/lib/ruby/autorequire/
4
+ http://rubyforge.org/frs/?group_id=1024
5
+
6
+ ABOUT
7
+
8
+ autorequire is sleeker, more aerodynamic, greasier version of autoload.
9
+
10
+ like autoload it's primary usage is to speed up the load time of large
11
+ libraries which, themselves, do many requires.
12
+
13
+ INSTALL
14
+
15
+ gem install autorequire
16
+
17
+ VERSION
18
+
19
+ 0.0.0
20
+
21
+ HISTORY
22
+
23
+ 0.0.0 :
24
+
25
+ initial release
26
+
27
+ AUTHOR
28
+
29
+ ara [dot] t [dot] howard [at] noaa [dot] gov
30
+
31
+ SAMPLES
32
+
33
+ <========< emsg.rb >========>
34
+
35
+ ~ > cat emsg.rb
36
+ #
37
+ # rescues err and prints msg - support method for samples/*
38
+ #
39
+ def emsg
40
+ yield
41
+ rescue Exception => e
42
+ puts "#{ e } (#{ e.class })!"
43
+ end
44
+
45
+ <========< libgen.rb >========>
46
+
47
+ ~ > cat libgen.rb
48
+ #
49
+ # generates a temporaray ruby lib - support method for samples/*
50
+ #
51
+ require 'fileutils'
52
+ def libgen path, libdir = './.lib/'
53
+ f, fu = File, FileUtils
54
+ dirname, basename = f.split path
55
+ dirname = f.join libdir, dirname
56
+ fu.mkdir_p dirname
57
+ path = f.join dirname, basename
58
+ open(path,'w'){|fd| fd << yield}
59
+ at_exit{ Dir.glob(f.join(libdir, '*')){|e| fu.rm_rf e} }
60
+ path
61
+ end
62
+
63
+
64
+ <========< sample/a.rb >========>
65
+
66
+ ~ > cat sample/a.rb
67
+
68
+ #
69
+ # simple use is much like autoload
70
+ #
71
+ emsg{ p Queue }
72
+
73
+ autorequire 'Queue', 'thread'
74
+
75
+ emsg{ p Queue }
76
+
77
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/a.rb
78
+
79
+ Queue (NameError)!
80
+ Queue
81
+
82
+
83
+ <========< sample/b.rb >========>
84
+
85
+ ~ > cat sample/b.rb
86
+
87
+ #
88
+ # but we can also specify nested classes. note the alternative hash syntax.
89
+ # a list of const => lib pairs may also be given.
90
+ #
91
+ emsg{ p CGI::Session }
92
+
93
+ autorequire 'CGI::Session' => 'cgi/session'
94
+
95
+ emsg{ p CGI::Session }
96
+
97
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/b.rb
98
+
99
+ CGI (NameError)!
100
+ CGI::Session
101
+
102
+
103
+ <========< sample/c.rb >========>
104
+
105
+ ~ > cat sample/c.rb
106
+
107
+ #
108
+ # like autoload, calling autorequire on a class defines the lib to be loaded
109
+ # when the const_missing hook for __that__ class is called
110
+ #
111
+ class C
112
+ lib = libgen('a.rb'){ 'class C::A; end' }
113
+
114
+ emsg{ p A }
115
+
116
+ autorequire 'A' => lib
117
+
118
+ emsg{ p A }
119
+ end
120
+
121
+ emsg{ p A}
122
+ emsg{ p C::A}
123
+
124
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/c.rb
125
+
126
+ A (NameError)!
127
+ C::A
128
+ A (NameError)!
129
+ C::A
130
+
131
+
132
+ <========< sample/d.rb >========>
133
+
134
+ ~ > cat sample/d.rb
135
+
136
+ #
137
+ # however, we can scope the constant to the top-level, even from within
138
+ # another class
139
+ #
140
+ emsg{ p A }
141
+
142
+ class C
143
+ lib = libgen('a.rb'){ 'class ::A; end' }
144
+ autorequire '::A' => lib
145
+ emsg{ p A }
146
+ emsg{ p ::A }
147
+ end
148
+
149
+ emsg{ p A }
150
+
151
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/d.rb
152
+
153
+ A (NameError)!
154
+ A (NameError)!
155
+ A
156
+ A
157
+
158
+
159
+ <========< sample/e.rb >========>
160
+
161
+ ~ > cat sample/e.rb
162
+
163
+ #
164
+ # this is a nice way to setup bulk autoloads in a large library
165
+ #
166
+ emsg{ p Net::Ftp }
167
+ emsg{ p CGI::Session }
168
+
169
+ module M
170
+ autorequire '::Net::FTP' => 'net/ftp', '::CGI::Session' => 'cgi/session'
171
+ end
172
+
173
+ emsg{ p Net::FTP }
174
+ emsg{ p CGI::Session }
175
+
176
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/e.rb
177
+
178
+ Net (NameError)!
179
+ CGI (NameError)!
180
+ Net::FTP
181
+ CGI::Session
182
+
183
+
184
+ <========< sample/f.rb >========>
185
+
186
+ ~ > cat sample/f.rb
187
+
188
+ #
189
+ # you may have notice autorequire works for nested constants. it does this be
190
+ # dynamically setting up proxy modules to resolve a name. once the names have
191
+ # actually been resolved the proxy is dropped.
192
+ #
193
+ emsg{ p Net }
194
+ emsg{ p CGI }
195
+
196
+ autorequire '::Net::FTP' => 'net/ftp', '::CGI::Session' => 'cgi/session'
197
+
198
+ emsg{ p Net }
199
+ emsg{ p CGI }
200
+
201
+ emsg{ p Net::FTP }
202
+ emsg{ p CGI::Session }
203
+
204
+ emsg{ p Net }
205
+ emsg{ p CGI }
206
+
207
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/f.rb
208
+
209
+ Net (NameError)!
210
+ CGI (NameError)!
211
+ "ConstProxy(Net)"
212
+ "ConstProxy(CGI)"
213
+ Net::FTP
214
+ CGI::Session
215
+ Net
216
+ CGI
217
+
218
+
219
+ <========< sample/g.rb >========>
220
+
221
+ ~ > cat sample/g.rb
222
+
223
+ #
224
+ # this actually works for arbitrarily deep const nestings
225
+ #
226
+ lib =
227
+ libgen('a/b/c/d.rb'){
228
+ '
229
+ module A
230
+ module B
231
+ module C
232
+ class D
233
+ end
234
+ end
235
+ end
236
+ end
237
+ '
238
+ }
239
+
240
+ autorequire 'A::B::C::D' => lib
241
+
242
+ p A
243
+ p A::B
244
+ p A::B::C
245
+ p A::B::C::D
246
+ p A::B::C
247
+ p A::B
248
+ p A
249
+
250
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/g.rb
251
+
252
+ "ConstProxy(A)"
253
+ "ConstProxy(B)"
254
+ "ConstProxy(C)"
255
+ A::B::C::D
256
+ A::B::C
257
+ A::B
258
+ A
259
+
260
+
261
+ <========< sample/h.rb >========>
262
+
263
+ ~ > cat sample/h.rb
264
+
265
+ #
266
+ # if you don't specify which lib to load it's name is guessed using a rather
267
+ # naive approach.
268
+ #
269
+ emsg{ p PStore }
270
+ emsg{ p CGI::Session }
271
+ emsg{ p FileUtils }
272
+
273
+ autorequire 'PStore' # requires 'pstore'
274
+ autorequire 'CGI::Session' # requires 'cgi/session'
275
+ autorequire '::FileUtils' # requires 'fileutils'
276
+
277
+ emsg{ p PStore }
278
+ emsg{ p CGI::Session }
279
+ emsg{ p FileUtils }
280
+
281
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/h.rb
282
+
283
+ PStore (NameError)!
284
+ CGI (NameError)!
285
+ FileUtils
286
+ PStore
287
+ CGI::Session
288
+ FileUtils
289
+
290
+
291
+ <========< sample/i.rb >========>
292
+
293
+ ~ > cat sample/i.rb
294
+
295
+ #
296
+ # if you're feeling risque you can set Autorequire.everything = true to use
297
+ # this default loading for __any__ const missing.
298
+ #
299
+ Autorequire.everything = 42
300
+
301
+ emsg{ p PStore }
302
+ emsg{ p CGI::Session }
303
+ emsg{ p FileUtils }
304
+
305
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/i.rb
306
+
307
+ PStore
308
+ CGI::Session
309
+ FileUtils
310
+
311
+
312
+ <========< sample/j.rb >========>
313
+
314
+ ~ > cat sample/j.rb
315
+
316
+ #
317
+ # you do, at least, get a meaningful error if the const to lib translation
318
+ # fails
319
+ #
320
+ autorequire 'FuBar' => 'does-not-exist.rb'
321
+
322
+ emsg{ p FuBar }
323
+
324
+ ~ > ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb sample/j.rb
325
+
326
+ resolving <FuBar> by loading <does-not-exist.rb> failed (Autorequire::NameError)!
327
+
328
+
329
+ CAVEATS
330
+
331
+ this library is experimental. nonetheless it's relatively straight forward
332
+ and i have no plans to change it's interface - though i may add to it in
333
+ future release.
334
+
335
+ LICENSE
336
+
337
+ same as ruby's
@@ -0,0 +1,73 @@
1
+ URLS
2
+
3
+ http://codeforpeople.com/lib/ruby/autorequire/
4
+ http://rubyforge.org/frs/?group_id=1024
5
+
6
+ ABOUT
7
+
8
+ autorequire is sleeker, more aerodynamic, greasier version of autoload.
9
+
10
+ like autoload it's primary usage is to speed up the load time of large
11
+ libraries which, themselves, do many requires.
12
+
13
+ INSTALL
14
+
15
+ gem install autorequire
16
+
17
+ VERSION
18
+
19
+ 0.0.0
20
+
21
+ HISTORY
22
+
23
+ 0.0.0 :
24
+
25
+ initial release
26
+
27
+ AUTHOR
28
+
29
+ ara [dot] t [dot] howard [at] noaa [dot] gov
30
+
31
+ SAMPLES
32
+
33
+ <========< emsg.rb >========>
34
+
35
+ ~ > cat emsg.rb
36
+ #
37
+ # rescues err and prints msg - support method for samples/*
38
+ #
39
+ def emsg
40
+ yield
41
+ rescue Exception => e
42
+ puts "#{ e } (#{ e.class })!"
43
+ end
44
+
45
+ <========< libgen.rb >========>
46
+
47
+ ~ > cat libgen.rb
48
+ #
49
+ # generates a temporaray ruby lib - support method for samples/*
50
+ #
51
+ require 'fileutils'
52
+ def libgen path, libdir = './.lib/'
53
+ f, fu = File, FileUtils
54
+ dirname, basename = f.split path
55
+ dirname = f.join libdir, dirname
56
+ fu.mkdir_p dirname
57
+ path = f.join dirname, basename
58
+ open(path,'w'){|fd| fd << yield}
59
+ at_exit{ Dir.glob(f.join(libdir, '*')){|e| fu.rm_rf e} }
60
+ path
61
+ end
62
+
63
+ @samples
64
+
65
+ CAVEATS
66
+
67
+ this library is experimental. nonetheless it's relatively straight forward
68
+ and i have no plans to change it's interface - though i may add to it in
69
+ future release.
70
+
71
+ LICENSE
72
+
73
+ same as ruby's
File without changes
data/emsg.rb ADDED
@@ -0,0 +1,5 @@
1
+ def emsg
2
+ yield
3
+ rescue Exception => e
4
+ puts "#{ $! } (#{ $!.class })!"
5
+ end
@@ -0,0 +1,23 @@
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
+ spec.name = lib
7
+ spec.version = version
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.summary = lib
10
+
11
+ # spec.files = Dir[ File::join("{lib,bin}", "*") ]
12
+ # spec.require_path = "lib"
13
+
14
+ spec.files = Dir::glob "**/**"
15
+ spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
16
+
17
+ spec.has_rdoc = File::exist? "doc"
18
+ spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
19
+
20
+ spec.author = "Ara T. Howard"
21
+ spec.email = "ara.t.howard@noaa.gov"
22
+ spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
23
+ end
@@ -0,0 +1,32 @@
1
+ $VERBOSE=nil
2
+ def indent s, n = 2
3
+ ws = ' ' * n
4
+ s.gsub %r/^/, ws
5
+ end
6
+
7
+ template = IO::read 'README.tmpl'
8
+
9
+ samples = ''
10
+ prompt = '~ > '
11
+
12
+ libs = Dir['lib/*'].map{|lib| " -r #{ lib } "}.join
13
+
14
+ Dir['sample/*'].sort.each do |sample|
15
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
16
+
17
+ cmd = "cat #{ sample }"
18
+ samples << indent(prompt + cmd, 2) << "\n\n"
19
+ samples << indent(`#{ cmd }`, 4) << "\n"
20
+
21
+ cmd = "ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb #{ sample }"
22
+ samples << indent(prompt + cmd, 2) << "\n\n"
23
+
24
+ #cmd = "ruby -r ./emsg.rb -I ./lib #{ libs } #{ sample }"
25
+ cmd = "ruby -r ./emsg.rb -r ./libgen.rb -r ./lib/autorequire.rb #{ sample }"
26
+ samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
27
+ end
28
+
29
+ #samples.gsub! %r/^/, ' '
30
+
31
+ readme = template.gsub %r/^[\ ]*@samples\s*$/, samples
32
+ print readme
@@ -0,0 +1,201 @@
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 f =~ %r/\.lnk/
40
+ path.push f
41
+ dir |= [File.dirname(f)]
42
+ end
43
+ for f in dir
44
+ next if f == "."
45
+ next if f == "CVS"
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ for f in path
49
+ next if (/\~$/ =~ f)
50
+ next if (/^\./ =~ File.basename(f))
51
+ unless bin
52
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
+ else
54
+ from = File.join(srcdir, f)
55
+ to = File.join(destdir, f)
56
+ shebangify(from) do |sf|
57
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
58
+ $deferr.printf "chmod %04o %s\n", mode, to
59
+ File::install(sf, to, mode, false)
60
+ end
61
+ end
62
+ end
63
+ #}}}
64
+ end
65
+ def shebangify f
66
+ #{{{
67
+ open(f) do |fd|
68
+ buf = fd.read 42
69
+ if buf =~ %r/^\s*#\s*!.*ruby/o
70
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
+ begin
72
+ fd.rewind
73
+ ftmp.puts "#!#{ $ruby }"
74
+ while((buf = fd.read(8192)))
75
+ ftmp.write buf
76
+ end
77
+ ftmp.close
78
+ yield ftmp.path
79
+ ensure
80
+ ftmp.close!
81
+ end
82
+ else
83
+ yield f
84
+ end
85
+ end
86
+ #}}}
87
+ end
88
+ def ARGV.switch
89
+ #{{{
90
+ return nil if self.empty?
91
+ arg = self.shift
92
+ return nil if arg == '--'
93
+ if arg =~ /^-(.)(.*)/
94
+ return arg if $1 == '-'
95
+ raise 'unknown switch "-"' if $2.index('-')
96
+ self.unshift "-#{$2}" if $2.size > 0
97
+ "-#{$1}"
98
+ else
99
+ self.unshift arg
100
+ nil
101
+ end
102
+ #}}}
103
+ end
104
+ def ARGV.req_arg
105
+ #{{{
106
+ self.shift || raise('missing argument')
107
+ #}}}
108
+ end
109
+ def linkify d, linked = []
110
+ #--{{{
111
+ if test ?d, d
112
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
+ versioned.each do |v|
114
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
+ lnk = nil
116
+ begin
117
+ if test ?l, dst
118
+ lnk = "#{ dst }.lnk"
119
+ puts "#{ dst } -> #{ lnk }"
120
+ File::rename dst, lnk
121
+ end
122
+ unless test ?e, dst
123
+ puts "#{ src } -> #{ dst }"
124
+ File::copy src, dst
125
+ linked << dst
126
+ end
127
+ ensure
128
+ if lnk
129
+ at_exit do
130
+ puts "#{ lnk } -> #{ dst }"
131
+ File::rename lnk, dst
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ linked
138
+ #--}}}
139
+ end
140
+
141
+
142
+ #
143
+ # main program
144
+ #
145
+
146
+ libdir = $site_libdir
147
+ bindir = $bindir
148
+ no_linkify = false
149
+ linked = nil
150
+ help = false
151
+
152
+ usage = <<-usage
153
+ #{ File::basename $0 }
154
+ -d, --destdir <destdir>
155
+ -l, --libdir <libdir>
156
+ -b, --bindir <bindir>
157
+ -r, --ruby <ruby>
158
+ -n, --no_linkify
159
+ -h, --help
160
+ usage
161
+
162
+ begin
163
+ while switch = ARGV.switch
164
+ case switch
165
+ when '-d', '--destdir'
166
+ libdir = ARGV.req_arg
167
+ when '-l', '--libdir'
168
+ libdir = ARGV.req_arg
169
+ when '-b', '--bindir'
170
+ bindir = ARGV.req_arg
171
+ when '-r', '--ruby'
172
+ $ruby = ARGV.req_arg
173
+ when '-n', '--no_linkify'
174
+ no_linkify = true
175
+ when '-h', '--help'
176
+ help = true
177
+ else
178
+ raise "unknown switch #{switch.dump}"
179
+ end
180
+ end
181
+ rescue
182
+ STDERR.puts $!.to_s
183
+ STDERR.puts usage
184
+ exit 1
185
+ end
186
+
187
+ if help
188
+ STDOUT.puts usage
189
+ exit
190
+ end
191
+
192
+ unless no_linkify
193
+ linked = linkify('lib') + linkify('bin')
194
+ end
195
+
196
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
197
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
198
+
199
+ if linked
200
+ linked.each{|path| File::rm_f path}
201
+ end
@@ -0,0 +1,152 @@
1
+ module Autorequire
2
+ class NameError < ::NameError; end
3
+ class LoadError < ::LoadError; end
4
+ class << self
5
+ attr_accessor "everything"
6
+ alias_method "everything?", "everything"
7
+ end
8
+ end
9
+
10
+ class Module
11
+ alias_method "const_missing!", "const_missing"
12
+ def const_missing c
13
+ c = c.to_s
14
+
15
+ if autorequire.has_key? c
16
+ value = autorequire[c]
17
+ if ConstProxy?(value)
18
+ return value
19
+ else
20
+ value.flatten.each do |lib|
21
+ begin
22
+ require lib
23
+ rescue LoadError
24
+ #raise NameError, "resolving <#{ c }> by loading <#{ lib }> failed"
25
+ raise Autorequire::NameError, "resolving <#{ c }> by loading <#{ lib }> failed"
26
+ end
27
+ end
28
+ end
29
+ elsif Autorequire.everything?
30
+ lib4 = lambda{|k| k.to_s.sub(%r/^::/,'').downcase.gsub(%r/::/, File::SEPARATOR)}
31
+ lib = Object == self ? lib4[c] : lib4["#{ name }::#{ c }"]
32
+ begin
33
+ require lib
34
+ rescue LoadError
35
+ raise Autorequire::NameError, "resolving <#{ c }> by loading <#{ lib }> failed"
36
+ end
37
+ else
38
+ #const_missing! c
39
+ raise NameError, c
40
+ end
41
+
42
+ #begin
43
+ if ConstProxy?(self)
44
+ raise NameError, c unless to_const.const_defined? c
45
+ to_const.const_get c
46
+ else
47
+ raise NameError, c unless const_defined? c
48
+ const_get c
49
+ end
50
+ #rescue NameError => ne
51
+ ##const_missing! c
52
+ #raise NameError, c
53
+ #end
54
+ end
55
+ def autorequire c = nil, *libs
56
+ if c
57
+ lib4 = lambda{|k| k.to_s.sub(%r/^::/,'').downcase.gsub(%r/::/, File::SEPARATOR)}
58
+ h = Hash === c ? c : {c => libs}
59
+ h.each do |c,libs|
60
+ libs << lib4[c] if libs.empty?
61
+ m = self
62
+ if c =~ %r/::/
63
+ if c =~ %r/^::/
64
+ c = c.gsub %r/^::/, ''
65
+ ::Object.autorequire(c, *libs)
66
+ next
67
+ end
68
+ list = c.split %r/::/
69
+ c = list.pop
70
+ while((name = list.shift))
71
+ cp = ConstProxy(name,m)
72
+ m.autorequire[name] = cp
73
+ m = cp
74
+ end
75
+ end
76
+ m.autorequire[c.to_s] = [libs].flatten
77
+ end
78
+ self
79
+ else
80
+ @autorequire ||= {}
81
+ end
82
+ end
83
+ def Autorequire(*a, &b) autorequire(*a, &b) end
84
+ end
85
+
86
+ module ConstProxy
87
+ def self.new name, parent
88
+ name = name.to_s
89
+ Module.new do
90
+ include ConstProxy
91
+ singleton_class = class << self; self; end
92
+ singleton_class.module_eval do
93
+ define_method('name'){ name }
94
+ define_method('parent'){ parent }
95
+ define_method('to_s'){ "ConstProxy(#{ name })" }
96
+ define_method('inspect'){ "\"#{ to_s }\"" }
97
+ define_method('to_const'){
98
+ if ConstProxy?(parent)
99
+ parent.to_const.const_get name # recurse
100
+ else
101
+ parent.const_get name
102
+ end
103
+ }
104
+ end
105
+ end
106
+ end
107
+ module ::Kernel
108
+ def ConstProxy(*a, &b) ConstProxy.new(*a, &b) end
109
+ def ConstProxy?(other) other.is_a?(Module) and other.ancestors.include?(ConstProxy) end
110
+ end
111
+ end
112
+
113
+ class Object
114
+ def autorequire(*a, &b) self.class.autorequire(*a, &b) end
115
+ def Autorequire(*a, &b) self.class.autorequire(*a, &b) end
116
+ end
117
+
118
+
119
+
120
+ if $0 == __FILE__
121
+ autorequire 'Net::FTP' => %w( net/ftp net/http )
122
+ p Net
123
+ p Net::FTP
124
+ p Net
125
+
126
+
127
+ autorequire 'A::B::C::D' => 'a/b/c/d'
128
+ p A
129
+ p A::B
130
+ p A::B::C
131
+ p A::B::C::D
132
+ p A::B::C
133
+ p A::B
134
+ p A
135
+
136
+ autorequire 'Net::FTP'
137
+ p Net
138
+ p Net::FTP
139
+ p Net
140
+
141
+ autorequire 'CGI::Session'
142
+ p CGI
143
+ p CGI::Session
144
+ p CGI
145
+
146
+ autorequire 'PStore'
147
+ p PStore
148
+
149
+ Autorequire.everything = true
150
+ p CGI::Session
151
+ p CGI
152
+ end
@@ -0,0 +1,12 @@
1
+ require 'fileutils'
2
+
3
+ def libgen path, libdir = './.lib/'
4
+ f, fu = File, FileUtils
5
+ dirname, basename = f.split path
6
+ dirname = f.join libdir, dirname
7
+ fu.mkdir_p dirname
8
+ path = f.join dirname, basename
9
+ open(path,'w'){|fd| fd << yield}
10
+ at_exit{ Dir.glob(f.join(libdir, '*')){|e| fu.rm_rf e} }
11
+ path
12
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # simple use is much like autoload
3
+ #
4
+ emsg{ p Queue }
5
+
6
+ autorequire 'Queue', 'thread'
7
+
8
+ emsg{ p Queue }
@@ -0,0 +1,9 @@
1
+ #
2
+ # but we can also specify nested classes. note the alternative hash syntax.
3
+ # a list of const => lib pairs may also be given.
4
+ #
5
+ emsg{ p CGI::Session }
6
+
7
+ autorequire 'CGI::Session' => 'cgi/session'
8
+
9
+ emsg{ p CGI::Session }
@@ -0,0 +1,16 @@
1
+ #
2
+ # like autoload, calling autorequire on a class defines the lib to be loaded
3
+ # when the const_missing hook for __that__ class is called
4
+ #
5
+ class C
6
+ lib = libgen('a.rb'){ 'class C::A; end' }
7
+
8
+ emsg{ p A }
9
+
10
+ autorequire 'A' => lib
11
+
12
+ emsg{ p A }
13
+ end
14
+
15
+ emsg{ p A}
16
+ emsg{ p C::A}
@@ -0,0 +1,14 @@
1
+ #
2
+ # however, we can scope the constant to the top-level, even from within
3
+ # another class
4
+ #
5
+ emsg{ p A }
6
+
7
+ class C
8
+ lib = libgen('a.rb'){ 'class ::A; end' }
9
+ autorequire '::A' => lib
10
+ emsg{ p A }
11
+ emsg{ p ::A }
12
+ end
13
+
14
+ emsg{ p A }
@@ -0,0 +1,12 @@
1
+ #
2
+ # this is a nice way to setup bulk autoloads in a large library
3
+ #
4
+ emsg{ p Net::Ftp }
5
+ emsg{ p CGI::Session }
6
+
7
+ module M
8
+ autorequire '::Net::FTP' => 'net/ftp', '::CGI::Session' => 'cgi/session'
9
+ end
10
+
11
+ emsg{ p Net::FTP }
12
+ emsg{ p CGI::Session }
@@ -0,0 +1,18 @@
1
+ #
2
+ # you may have notice autorequire works for nested constants. it does this be
3
+ # dynamically setting up proxy modules to resolve a name. once the names have
4
+ # actually been resolved the proxy is dropped.
5
+ #
6
+ emsg{ p Net }
7
+ emsg{ p CGI }
8
+
9
+ autorequire '::Net::FTP' => 'net/ftp', '::CGI::Session' => 'cgi/session'
10
+
11
+ emsg{ p Net }
12
+ emsg{ p CGI }
13
+
14
+ emsg{ p Net::FTP }
15
+ emsg{ p CGI::Session }
16
+
17
+ emsg{ p Net }
18
+ emsg{ p CGI }
@@ -0,0 +1,26 @@
1
+ #
2
+ # this actually works for arbitrarily deep const nestings
3
+ #
4
+ lib =
5
+ libgen('a/b/c/d.rb'){
6
+ '
7
+ module A
8
+ module B
9
+ module C
10
+ class D
11
+ end
12
+ end
13
+ end
14
+ end
15
+ '
16
+ }
17
+
18
+ autorequire 'A::B::C::D' => lib
19
+
20
+ p A
21
+ p A::B
22
+ p A::B::C
23
+ p A::B::C::D
24
+ p A::B::C
25
+ p A::B
26
+ p A
@@ -0,0 +1,15 @@
1
+ #
2
+ # if you don't specify which lib to load it's name is guessed using a rather
3
+ # naive approach.
4
+ #
5
+ emsg{ p PStore }
6
+ emsg{ p CGI::Session }
7
+ emsg{ p FileUtils }
8
+
9
+ autorequire 'PStore' # requires 'pstore'
10
+ autorequire 'CGI::Session' # requires 'cgi/session'
11
+ autorequire '::FileUtils' # requires 'fileutils'
12
+
13
+ emsg{ p PStore }
14
+ emsg{ p CGI::Session }
15
+ emsg{ p FileUtils }
@@ -0,0 +1,9 @@
1
+ #
2
+ # if you're feeling risque you can set Autorequire.everything = true to use
3
+ # this default loading for __any__ const missing.
4
+ #
5
+ Autorequire.everything = 42
6
+
7
+ emsg{ p PStore }
8
+ emsg{ p CGI::Session }
9
+ emsg{ p FileUtils }
@@ -0,0 +1,7 @@
1
+ #
2
+ # you do, at least, get a meaningful error if the const to lib translation
3
+ # fails
4
+ #
5
+ autorequire 'FuBar' => 'does-not-exist.rb'
6
+
7
+ emsg{ p FuBar }
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: autorequire
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.0
7
+ date: 2006-04-11 00:00:00.000000 -06:00
8
+ summary: autorequire
9
+ require_paths:
10
+ - lib
11
+ email: ara.t.howard@noaa.gov
12
+ homepage: http://codeforpeople.com/lib/ruby/autorequire/
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Ara T. Howard
31
+ files:
32
+ - lib
33
+ - install.rb
34
+ - gemspec.rb
35
+ - autorequire-0.0.0.gem
36
+ - README.tmpl
37
+ - gen_readme.rb
38
+ - sample
39
+ - README
40
+ - emsg.rb
41
+ - libgen.rb
42
+ - lib/autorequire.rb
43
+ - sample/a.rb
44
+ - sample/f.rb
45
+ - sample/b.rb
46
+ - sample/e.rb
47
+ - sample/c.rb
48
+ - sample/d.rb
49
+ - sample/i.rb
50
+ - sample/j.rb
51
+ - sample/h.rb
52
+ - sample/g.rb
53
+ test_files: []
54
+ rdoc_options: []
55
+ extra_rdoc_files: []
56
+ executables: []
57
+ extensions: []
58
+ requirements: []
59
+ dependencies: []