autorequire 0.0.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.
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: []