rbot 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/AUTHORS +16 -0
  2. data/COPYING +21 -0
  3. data/ChangeLog +418 -0
  4. data/INSTALL +8 -0
  5. data/README +44 -0
  6. data/REQUIREMENTS +34 -0
  7. data/TODO +5 -0
  8. data/Usage_en.txt +129 -0
  9. data/bin/rbot +81 -0
  10. data/data/rbot/contrib/plugins/figlet.rb +20 -0
  11. data/data/rbot/contrib/plugins/ri.rb +83 -0
  12. data/data/rbot/contrib/plugins/stats.rb +232 -0
  13. data/data/rbot/contrib/plugins/vandale.rb +49 -0
  14. data/data/rbot/languages/dutch.lang +73 -0
  15. data/data/rbot/languages/english.lang +75 -0
  16. data/data/rbot/languages/french.lang +39 -0
  17. data/data/rbot/languages/german.lang +67 -0
  18. data/data/rbot/plugins/autoop.rb +68 -0
  19. data/data/rbot/plugins/autorejoin.rb +16 -0
  20. data/data/rbot/plugins/cal.rb +15 -0
  21. data/data/rbot/plugins/dice.rb +81 -0
  22. data/data/rbot/plugins/eightball.rb +19 -0
  23. data/data/rbot/plugins/excuse.rb +470 -0
  24. data/data/rbot/plugins/fish.rb +61 -0
  25. data/data/rbot/plugins/fortune.rb +22 -0
  26. data/data/rbot/plugins/freshmeat.rb +98 -0
  27. data/data/rbot/plugins/google.rb +51 -0
  28. data/data/rbot/plugins/host.rb +14 -0
  29. data/data/rbot/plugins/httpd.rb.disabled +35 -0
  30. data/data/rbot/plugins/insult.rb +258 -0
  31. data/data/rbot/plugins/karma.rb +85 -0
  32. data/data/rbot/plugins/lart.rb +181 -0
  33. data/data/rbot/plugins/math.rb +122 -0
  34. data/data/rbot/plugins/nickserv.rb +89 -0
  35. data/data/rbot/plugins/nslookup.rb +43 -0
  36. data/data/rbot/plugins/opme.rb +19 -0
  37. data/data/rbot/plugins/quakeauth.rb +51 -0
  38. data/data/rbot/plugins/quotes.rb +321 -0
  39. data/data/rbot/plugins/remind.rb +228 -0
  40. data/data/rbot/plugins/roshambo.rb +54 -0
  41. data/data/rbot/plugins/rot13.rb +10 -0
  42. data/data/rbot/plugins/roulette.rb +147 -0
  43. data/data/rbot/plugins/rss.rb.disabled +414 -0
  44. data/data/rbot/plugins/seen.rb +89 -0
  45. data/data/rbot/plugins/slashdot.rb +94 -0
  46. data/data/rbot/plugins/spell.rb +36 -0
  47. data/data/rbot/plugins/tube.rb +71 -0
  48. data/data/rbot/plugins/url.rb +88 -0
  49. data/data/rbot/plugins/weather.rb +649 -0
  50. data/data/rbot/plugins/wserver.rb +71 -0
  51. data/data/rbot/plugins/xmlrpc.rb.disabled +52 -0
  52. data/data/rbot/templates/keywords.rbot +4 -0
  53. data/data/rbot/templates/lart/larts +98 -0
  54. data/data/rbot/templates/lart/praises +5 -0
  55. data/data/rbot/templates/levels.rbot +30 -0
  56. data/data/rbot/templates/users.rbot +1 -0
  57. data/lib/rbot/auth.rb +203 -0
  58. data/lib/rbot/channel.rb +54 -0
  59. data/lib/rbot/config.rb +363 -0
  60. data/lib/rbot/dbhash.rb +112 -0
  61. data/lib/rbot/httputil.rb +141 -0
  62. data/lib/rbot/ircbot.rb +808 -0
  63. data/lib/rbot/ircsocket.rb +185 -0
  64. data/lib/rbot/keywords.rb +433 -0
  65. data/lib/rbot/language.rb +69 -0
  66. data/lib/rbot/message.rb +256 -0
  67. data/lib/rbot/messagemapper.rb +262 -0
  68. data/lib/rbot/plugins.rb +291 -0
  69. data/lib/rbot/post-install.rb +8 -0
  70. data/lib/rbot/rbotconfig.rb +36 -0
  71. data/lib/rbot/registry.rb +271 -0
  72. data/lib/rbot/rfc2812.rb +1104 -0
  73. data/lib/rbot/timer.rb +201 -0
  74. data/lib/rbot/utils.rb +83 -0
  75. data/setup.rb +1360 -0
  76. metadata +129 -0
@@ -0,0 +1,291 @@
1
+ module Irc
2
+ module Plugins
3
+ require 'rbot/messagemapper'
4
+
5
+ # base class for all rbot plugins
6
+ # certain methods will be called if they are provided, if you define one of
7
+ # the following methods, it will be called as appropriate:
8
+ #
9
+ # map(template, options)::
10
+ # map is the new, cleaner way to respond to specific message formats
11
+ # without littering your plugin code with regexps. examples:
12
+ #
13
+ # plugin.map 'karmastats', :action => 'karma_stats'
14
+ #
15
+ # # while in the plugin...
16
+ # def karma_stats(m, params)
17
+ # m.reply "..."
18
+ # end
19
+ #
20
+ # # the default action is the first component
21
+ # plugin.map 'karma'
22
+ #
23
+ # # attributes can be pulled out of the match string
24
+ # plugin.map 'karma for :key'
25
+ # plugin.map 'karma :key'
26
+ #
27
+ # # while in the plugin...
28
+ # def karma(m, params)
29
+ # item = params[:key]
30
+ # m.reply 'karma for #{item}'
31
+ # end
32
+ #
33
+ # # you can setup defaults, to make parameters optional
34
+ # plugin.map 'karma :key', :defaults => {:key => 'defaultvalue'}
35
+ #
36
+ # # the default auth check is also against the first component
37
+ # # but that can be changed
38
+ # plugin.map 'karmastats', :auth => 'karma'
39
+ #
40
+ # # maps can be restricted to public or private message:
41
+ # plugin.map 'karmastats', :private false,
42
+ # plugin.map 'karmastats', :public false,
43
+ # end
44
+ #
45
+ # To activate your maps, you simply register them
46
+ # plugin.register_maps
47
+ # This also sets the privmsg handler to use the map lookups for
48
+ # handling messages. You can still use listen(), kick() etc methods
49
+ #
50
+ # listen(UserMessage)::
51
+ # Called for all messages of any type. To
52
+ # differentiate them, use message.kind_of? It'll be
53
+ # either a PrivMessage, NoticeMessage, KickMessage,
54
+ # QuitMessage, PartMessage, JoinMessage, NickMessage,
55
+ # etc.
56
+ #
57
+ # privmsg(PrivMessage)::
58
+ # called for a PRIVMSG if the first word matches one
59
+ # the plugin register()d for. Use m.plugin to get
60
+ # that word and m.params for the rest of the message,
61
+ # if applicable.
62
+ #
63
+ # kick(KickMessage)::
64
+ # Called when a user (or the bot) is kicked from a
65
+ # channel the bot is in.
66
+ #
67
+ # join(JoinMessage)::
68
+ # Called when a user (or the bot) joins a channel
69
+ #
70
+ # part(PartMessage)::
71
+ # Called when a user (or the bot) parts a channel
72
+ #
73
+ # quit(QuitMessage)::
74
+ # Called when a user (or the bot) quits IRC
75
+ #
76
+ # nick(NickMessage)::
77
+ # Called when a user (or the bot) changes Nick
78
+ # topic(TopicMessage)::
79
+ # Called when a user (or the bot) changes a channel
80
+ # topic
81
+ #
82
+ # connect():: Called when a server is joined successfully, but
83
+ # before autojoin channels are joined (no params)
84
+ #
85
+ # save:: Called when you are required to save your plugin's
86
+ # state, if you maintain data between sessions
87
+ #
88
+ # cleanup:: called before your plugin is "unloaded", prior to a
89
+ # plugin reload or bot quit - close any open
90
+ # files/connections or flush caches here
91
+ class Plugin
92
+ attr_reader :bot # the associated bot
93
+ # initialise your plugin. Always call super if you override this method,
94
+ # as important variables are set up for you
95
+ def initialize
96
+ @bot = Plugins.bot
97
+ @names = Array.new
98
+ @handler = MessageMapper.new(self)
99
+ @registry = BotRegistryAccessor.new(@bot, self.class.to_s.gsub(/^.*::/, ""))
100
+ end
101
+
102
+ def map(*args)
103
+ @handler.map(*args)
104
+ # register this map
105
+ name = @handler.last.items[0]
106
+ self.register name
107
+ unless self.respond_to?('privmsg')
108
+ def self.privmsg(m)
109
+ @handler.handle(m)
110
+ end
111
+ end
112
+ end
113
+
114
+ # return an identifier for this plugin, defaults to a list of the message
115
+ # prefixes handled (used for error messages etc)
116
+ def name
117
+ @names.join("|")
118
+ end
119
+
120
+ # return a help string for your module. for complex modules, you may wish
121
+ # to break your help into topics, and return a list of available topics if
122
+ # +topic+ is nil. +plugin+ is passed containing the matching prefix for
123
+ # this message - if your plugin handles multiple prefixes, make sure your
124
+ # return the correct help for the prefix requested
125
+ def help(plugin, topic)
126
+ "no help"
127
+ end
128
+
129
+ # register the plugin as a handler for messages prefixed +name+
130
+ # this can be called multiple times for a plugin to handle multiple
131
+ # message prefixes
132
+ def register(name)
133
+ return if Plugins.plugins.has_key?(name)
134
+ Plugins.plugins[name] = self
135
+ @names << name
136
+ end
137
+
138
+ # default usage method provided as a utility for simple plugins. The
139
+ # MessageMapper uses 'usage' as its default fallback method.
140
+ def usage(m, params = {})
141
+ m.reply "incorrect usage, ask for help using '#{@bot.nick}: help #{m.plugin}'"
142
+ end
143
+
144
+ end
145
+
146
+ # class to manage multiple plugins and delegate messages to them for
147
+ # handling
148
+ class Plugins
149
+ # hash of registered message prefixes and associated plugins
150
+ @@plugins = Hash.new
151
+ # associated IrcBot class
152
+ @@bot = nil
153
+
154
+ # bot:: associated IrcBot class
155
+ # dirlist:: array of directories to scan (in order) for plugins
156
+ #
157
+ # create a new plugin handler, scanning for plugins in +dirlist+
158
+ def initialize(bot, dirlist)
159
+ @@bot = bot
160
+ @dirs = dirlist
161
+ scan
162
+ end
163
+
164
+ # access to associated bot
165
+ def Plugins.bot
166
+ @@bot
167
+ end
168
+
169
+ # access to list of plugins
170
+ def Plugins.plugins
171
+ @@plugins
172
+ end
173
+
174
+ # load plugins from pre-assigned list of directories
175
+ def scan
176
+ dirs = Array.new
177
+ dirs << Config::datadir + "/plugins"
178
+ dirs += @dirs
179
+ dirs.each {|dir|
180
+ if(FileTest.directory?(dir))
181
+ d = Dir.new(dir)
182
+ d.sort.each {|file|
183
+ next if(file =~ /^\./)
184
+ next unless(file =~ /\.rb$/)
185
+ tmpfilename = "#{dir}/#{file}"
186
+
187
+ # create a new, anonymous module to "house" the plugin
188
+ # the idea here is to prevent namespace pollution. perhaps there
189
+ # is another way?
190
+ plugin_module = Module.new
191
+
192
+ begin
193
+ plugin_string = IO.readlines(tmpfilename).join("")
194
+ debug "loading plugin #{tmpfilename}"
195
+ plugin_module.module_eval(plugin_string)
196
+ rescue TimeoutError, StandardError, NameError, LoadError, SyntaxError => err
197
+ puts "warning: plugin #{tmpfilename} load failed: " + err
198
+ puts err.backtrace.join("\n")
199
+ end
200
+ }
201
+ end
202
+ }
203
+ end
204
+
205
+ # call the save method for each active plugin
206
+ def save
207
+ delegate 'save'
208
+ end
209
+
210
+ # call the cleanup method for each active plugin
211
+ def cleanup
212
+ delegate 'cleanup'
213
+ end
214
+
215
+ # drop all plugins and rescan plugins on disk
216
+ # calls save and cleanup for each plugin before dropping them
217
+ def rescan
218
+ save
219
+ cleanup
220
+ @@plugins = Hash.new
221
+ scan
222
+ end
223
+
224
+ # return list of help topics (plugin names)
225
+ def helptopics
226
+ if(@@plugins.length > 0)
227
+ # return " [plugins: " + @@plugins.keys.sort.join(", ") + "]"
228
+ return " [#{length} plugins: " + @@plugins.values.uniq.collect{|p| p.name}.sort.join(", ") + "]"
229
+ else
230
+ return " [no plugins active]"
231
+ end
232
+ end
233
+
234
+ def length
235
+ @@plugins.values.uniq.length
236
+ end
237
+
238
+ # return help for +topic+ (call associated plugin's help method)
239
+ def help(topic="")
240
+ if(topic =~ /^(\S+)\s*(.*)$/)
241
+ key = $1
242
+ params = $2
243
+ if(@@plugins.has_key?(key))
244
+ begin
245
+ return @@plugins[key].help(key, params)
246
+ rescue TimeoutError, StandardError, NameError, SyntaxError => err
247
+ puts "plugin #{@@plugins[key].name} help() failed: " + err
248
+ puts err.backtrace.join("\n")
249
+ end
250
+ else
251
+ return false
252
+ end
253
+ end
254
+ end
255
+
256
+ # see if each plugin handles +method+, and if so, call it, passing
257
+ # +message+ as a parameter
258
+ def delegate(method, *args)
259
+ @@plugins.values.uniq.each {|p|
260
+ if(p.respond_to? method)
261
+ begin
262
+ p.send method, *args
263
+ rescue TimeoutError, StandardError, NameError, SyntaxError => err
264
+ puts "plugin #{p.name} #{method}() failed: " + err
265
+ puts err.backtrace.join("\n")
266
+ end
267
+ end
268
+ }
269
+ end
270
+
271
+ # see if we have a plugin that wants to handle this message, if so, pass
272
+ # it to the plugin and return true, otherwise false
273
+ def privmsg(m)
274
+ return unless(m.plugin)
275
+ if (@@plugins.has_key?(m.plugin) &&
276
+ @@plugins[m.plugin].respond_to?("privmsg") &&
277
+ @@bot.auth.allow?(m.plugin, m.source, m.replyto))
278
+ begin
279
+ @@plugins[m.plugin].privmsg(m)
280
+ rescue TimeoutError, StandardError, NameError, SyntaxError => err
281
+ puts "plugin #{@@plugins[m.plugin].name} privmsg() failed: " + err
282
+ puts err.backtrace.join("\n")
283
+ end
284
+ return true
285
+ end
286
+ return false
287
+ end
288
+ end
289
+
290
+ end
291
+ end
@@ -0,0 +1,8 @@
1
+ # write out our datadir so we can reference it at runtime
2
+ File.open("#{config('rbdir')}/rbot/pkgconfig.rb", "w") {|f|
3
+ f.puts "module Irc"
4
+ f.puts " module PKGConfig"
5
+ f.puts " DATADIR = '#{config('datadir')}/rbot'"
6
+ f.puts " end"
7
+ f.puts "end"
8
+ }
@@ -0,0 +1,36 @@
1
+ module Irc
2
+ module Config
3
+ @@datadir = nil
4
+ # setup pkg-based configuration - i.e. where were we installed to, where
5
+ # are our data files, etc.
6
+ begin
7
+ debug "trying to load rubygems"
8
+ require 'rubygems'
9
+ debug "loaded rubygems, looking for rbot-#$version"
10
+ gemname, gem = Gem.source_index.find{|name, spec| spec.name == 'rbot' && spec.version.version == $version}
11
+ debug "got gem #{gem}"
12
+ if gem && path = gem.full_gem_path
13
+ debug "installed via rubygems to #{path}"
14
+ @@datadir = "#{path}/data/rbot"
15
+ else
16
+ debug "not installed via rubygems"
17
+ end
18
+ rescue LoadError
19
+ debug "no rubygems installed"
20
+ end
21
+
22
+ if @@datadir.nil?
23
+ begin
24
+ require 'rbot/pkgconfig'
25
+ @@datadir = PKGConfig::DATADIR
26
+ rescue LoadError
27
+ puts "fatal - no way to determine data dir"
28
+ exit 2
29
+ end
30
+ end
31
+
32
+ def Config.datadir
33
+ @@datadir
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,271 @@
1
+ require 'rbot/dbhash'
2
+
3
+ module Irc
4
+
5
+ # this is the backend of the RegistryAccessor class, which ties it to a
6
+ # DBHash object called plugin_registry(.db). All methods are delegated to
7
+ # the DBHash.
8
+ class BotRegistry
9
+ def initialize(bot)
10
+ @bot = bot
11
+ upgrade_data
12
+ @db = DBTree.new @bot, "plugin_registry"
13
+ end
14
+
15
+ # delegation hack
16
+ def method_missing(method, *args, &block)
17
+ @db.send(method, *args, &block)
18
+ end
19
+
20
+ # check for older versions of rbot with data formats that require updating
21
+ # NB this function is called _early_ in init(), pretty much all you have to
22
+ # work with is @bot.botclass.
23
+ def upgrade_data
24
+ if File.exist?("#{@bot.botclass}/registry.db")
25
+ puts "upgrading old-style (rbot 0.9.5 or earlier) plugin registry to new format"
26
+ old = BDB::Hash.open "#{@bot.botclass}/registry.db", nil,
27
+ "r+", 0600, "set_pagesize" => 1024,
28
+ "set_cachesize" => [0, 32 * 1024, 0]
29
+ new = BDB::CIBtree.open "#{@bot.botclass}/plugin_registry.db", nil,
30
+ BDB::CREATE | BDB::EXCL | BDB::TRUNCATE,
31
+ 0600, "set_pagesize" => 1024,
32
+ "set_cachesize" => [0, 32 * 1024, 0]
33
+ old.each {|k,v|
34
+ new[k] = v
35
+ }
36
+ old.close
37
+ new.close
38
+ File.delete("#{@bot.botclass}/registry.db")
39
+ end
40
+ end
41
+ end
42
+
43
+ # This class provides persistent storage for plugins via a hash interface.
44
+ # The default mode is an object store, so you can store ruby objects and
45
+ # reference them with hash keys. This is because the default store/restore
46
+ # methods of the plugins' RegistryAccessor are calls to Marshal.dump and
47
+ # Marshal.restore,
48
+ # for example:
49
+ # blah = Hash.new
50
+ # blah[:foo] = "fum"
51
+ # @registry[:blah] = blah
52
+ # then, even after the bot is shut down and disconnected, on the next run you
53
+ # can access the blah object as it was, with:
54
+ # blah = @registry[:blah]
55
+ # The registry can of course be used to store simple strings, fixnums, etc as
56
+ # well, and should be useful to store or cache plugin data or dynamic plugin
57
+ # configuration.
58
+ #
59
+ # WARNING:
60
+ # in object store mode, don't make the mistake of treating it like a live
61
+ # object, e.g. (using the example above)
62
+ # @registry[:blah][:foo] = "flump"
63
+ # will NOT modify the object in the registry - remember that BotRegistry#[]
64
+ # returns a Marshal.restore'd object, the object you just modified in place
65
+ # will disappear. You would need to:
66
+ # blah = @registry[:blah]
67
+ # blah[:foo] = "flump"
68
+ # @registry[:blah] = blah
69
+
70
+ # If you don't need to store objects, and strictly want a persistant hash of
71
+ # strings, you can override the store/restore methods to suit your needs, for
72
+ # example (in your plugin):
73
+ # def initialize
74
+ # class << @registry
75
+ # def store(val)
76
+ # val
77
+ # end
78
+ # def restore(val)
79
+ # val
80
+ # end
81
+ # end
82
+ # end
83
+ # Your plugins section of the registry is private, it has its own namespace
84
+ # (derived from the plugin's class name, so change it and lose your data).
85
+ # Calls to registry.each etc, will only iterate over your namespace.
86
+ class BotRegistryAccessor
87
+ # plugins don't call this - a BotRegistryAccessor is created for them and
88
+ # is accessible via @registry.
89
+ def initialize(bot, prefix)
90
+ @bot = bot
91
+ @registry = @bot.registry
92
+ @orig_prefix = prefix
93
+ @prefix = prefix + "/"
94
+ @default = nil
95
+ # debug "initializing registry accessor with prefix #{@prefix}"
96
+ end
97
+
98
+ # use this to chop up your namespace into bits, so you can keep and
99
+ # reference separate object stores under the same registry
100
+ def sub_registry(prefix)
101
+ return BotRegistryAccessor.new(@bot, @orig_prefix + "+" + prefix)
102
+ end
103
+
104
+ # convert value to string form for storing in the registry
105
+ # defaults to Marshal.dump(val) but you can override this in your module's
106
+ # registry object to use any method you like.
107
+ # For example, if you always just handle strings use:
108
+ # def store(val)
109
+ # val
110
+ # end
111
+ def store(val)
112
+ Marshal.dump(val)
113
+ end
114
+
115
+ # restores object from string form, restore(store(val)) must return val.
116
+ # If you override store, you should override restore to reverse the
117
+ # action.
118
+ # For example, if you always just handle strings use:
119
+ # def restore(val)
120
+ # val
121
+ # end
122
+ def restore(val)
123
+ Marshal.restore(val)
124
+ end
125
+
126
+ # lookup a key in the registry
127
+ def [](key)
128
+ if @registry.has_key?(@prefix + key)
129
+ return restore(@registry[@prefix + key])
130
+ elsif @default != nil
131
+ return restore(@default)
132
+ else
133
+ return nil
134
+ end
135
+ end
136
+
137
+ # set a key in the registry
138
+ def []=(key,value)
139
+ @registry[@prefix + key] = store(value)
140
+ end
141
+
142
+ # set the default value for registry lookups, if the key sought is not
143
+ # found, the default will be returned. The default default (har) is nil.
144
+ def set_default (default)
145
+ @default = store(default)
146
+ end
147
+
148
+ # just like Hash#each
149
+ def each(&block)
150
+ @registry.each {|key,value|
151
+ if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
152
+ block.call(key, restore(value))
153
+ end
154
+ }
155
+ end
156
+
157
+ # just like Hash#each_key
158
+ def each_key(&block)
159
+ @registry.each {|key, value|
160
+ if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
161
+ block.call(key)
162
+ end
163
+ }
164
+ end
165
+
166
+ # just like Hash#each_value
167
+ def each_value(&block)
168
+ @registry.each {|key, value|
169
+ if key =~ /^#{Regexp.escape(@prefix)}/
170
+ block.call(restore(value))
171
+ end
172
+ }
173
+ end
174
+
175
+ # just like Hash#has_key?
176
+ def has_key?(key)
177
+ return @registry.has_key?(@prefix + key)
178
+ end
179
+ alias include? has_key?
180
+ alias member? has_key?
181
+
182
+ # just like Hash#has_both?
183
+ def has_both?(key, value)
184
+ return @registry.has_both?(@prefix + key, store(value))
185
+ end
186
+
187
+ # just like Hash#has_value?
188
+ def has_value?(value)
189
+ return @registry.has_value?(store(value))
190
+ end
191
+
192
+ # just like Hash#index?
193
+ def index(value)
194
+ ind = @registry.index(store(value))
195
+ if ind && ind.gsub!(/^#{Regexp.escape(@prefix)}/, "")
196
+ return ind
197
+ else
198
+ return nil
199
+ end
200
+ end
201
+
202
+ # delete a key from the registry
203
+ def delete(key)
204
+ return @registry.delete(@prefix + key)
205
+ end
206
+
207
+ # returns a list of your keys
208
+ def keys
209
+ return @registry.keys.collect {|key|
210
+ if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
211
+ key
212
+ else
213
+ nil
214
+ end
215
+ }.compact
216
+ end
217
+
218
+ # Return an array of all associations [key, value] in your namespace
219
+ def to_a
220
+ ret = Array.new
221
+ @registry.each {|key, value|
222
+ if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
223
+ ret << [key, restore(value)]
224
+ end
225
+ }
226
+ return ret
227
+ end
228
+
229
+ # Return an hash of all associations {key => value} in your namespace
230
+ def to_hash
231
+ ret = Hash.new
232
+ @registry.each {|key, value|
233
+ if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
234
+ ret[key] = restore(value)
235
+ end
236
+ }
237
+ return ret
238
+ end
239
+
240
+ # empties the registry (restricted to your namespace)
241
+ def clear
242
+ @registry.each_key {|key|
243
+ if key =~ /^#{Regexp.escape(@prefix)}/
244
+ @registry.delete(key)
245
+ end
246
+ }
247
+ end
248
+ alias truncate clear
249
+
250
+ # returns an array of the values in your namespace of the registry
251
+ def values
252
+ ret = Array.new
253
+ self.each {|k,v|
254
+ ret << restore(v)
255
+ }
256
+ return ret
257
+ end
258
+
259
+ # returns the number of keys in your registry namespace
260
+ def length
261
+ self.keys.length
262
+ end
263
+ alias size length
264
+
265
+ def flush
266
+ @registry.flush
267
+ end
268
+
269
+ end
270
+
271
+ end