5 # This module defines the IRC casemap class and the most common casemaps
7 # Author:: Giuseppe Bilotta (giuseppe.bilotta@gmail.com)
13 # Due to its Scandinavian origins, IRC has strange case mappings, which
14 # consider the characters <tt>{}|^</tt> as the uppercase
15 # equivalents of # <tt>[]\~</tt>.
17 # This is however not the same on all IRC servers: some use standard ASCII
18 # casemapping, other do not consider <tt>^</tt> as the uppercase of
24 # Create a new casemap with name _name_, uppercase characters _upper_ and
25 # lowercase characters _lower_
27 def initialize(name, upper, lower)
29 raise "Casemap #{name.inspect} already exists!" if @@casemaps.has_key?(@key)
37 # Returns the Casemap with the given name
40 @@casemaps[name.to_sym][:casemap]
43 # Retrieve the 'uppercase characters' of this Casemap
46 @@casemaps[@key][:upper]
49 # Retrieve the 'lowercase characters' of this Casemap
52 @@casemaps[@key][:lower]
55 # Return a Casemap based on the receiver
61 # A Casemap is represented by its lower/upper mappings
64 self.__to_s__[0..-2] + " #{upper.inspect} ~(#{self})~ #{lower.inspect}>"
67 # As a String we return our name
73 # Two Casemaps are equal if they have the same upper and lower ranges
76 other = arg.to_irc_casemap
77 return self.upper == other.upper && self.lower == other.lower
80 # Give a warning if _arg_ and self are not the same Casemap
83 other = arg.to_irc_casemap
87 warn "Casemap mismatch (#{self.inspect} != #{other.inspect})"
96 class RfcCasemap < Casemap
100 super('rfc1459', "\x41-\x5e", "\x61-\x7e")
106 # The strict-rfc1459 Casemap
108 class StrictRfcCasemap < Casemap
112 super('strict-rfc1459', "\x41-\x5d", "\x61-\x7d")
116 StrictRfcCasemap.instance
120 class AsciiCasemap < Casemap
124 super('ascii', "\x41-\x5a", "\x61-\x7a")
128 AsciiCasemap.instance
131 # This module is included by all classes that are either bound to a server
132 # or should have a casemap.
134 module ServerOrCasemap
138 # This method initializes the instance variables @server and @casemap
139 # according to the values of the hash keys :server and :casemap in _opts_
141 def init_server_or_casemap(opts={})
142 @server = opts.fetch(:server, nil)
143 raise TypeError, "#{@server} is not a valid Irc::Server" if @server and not @server.kind_of?(Server)
145 @casemap = opts.fetch(:casemap, nil)
148 @server.casemap.must_be(@casemap)
152 @casemap = (@casemap || 'rfc1459').to_irc_casemap
156 # This is an auxiliary method: it returns true if the receiver fits the
157 # server and casemap specified in _opts_, false otherwise.
159 def fits_with_server_and_casemap?(opts={})
160 srv = opts.fetch(:server, nil)
161 cmap = opts.fetch(:casemap, nil)
162 cmap = cmap.to_irc_casemap unless cmap.nil?
165 return true if cmap.nil? or cmap == casemap
167 return true if srv == @server and (cmap.nil? or cmap == casemap)
172 # Returns the casemap of the receiver, by looking at the bound
173 # @server (if possible) or at the @casemap otherwise
176 return @server.casemap if defined?(@server) and @server
180 # Returns a hash with the current @server and @casemap as values of
181 # :server and :casemap
183 def server_and_casemap
185 h[:server] = @server if defined?(@server) and @server
186 h[:casemap] = @casemap if defined?(@casemap) and @casemap
190 # We allow up/downcasing with a different casemap
192 def irc_downcase(cmap=casemap)
193 self.to_s.irc_downcase(cmap)
196 # Up/downcasing something that includes this module returns its
197 # Up/downcased to_s form
203 # We allow up/downcasing with a different casemap
205 def irc_upcase(cmap=casemap)
206 self.to_s.irc_upcase(cmap)
209 # Up/downcasing something that includes this module returns its
210 # Up/downcased to_s form
221 # We extend the String class with some Irc::Casemap methods
225 # This method returns the Irc::Casemap whose name is the receiver
228 Irc::Casemap.get(self) rescue raise TypeError, "Unkown Irc::Casemap #{self.inspect}"
231 # This method returns a string which is the downcased version of the
232 # receiver, according to the given _casemap_
235 def irc_downcase(casemap='rfc1459')
236 cmap = casemap.to_irc_casemap
237 self.tr(cmap.upper, cmap.lower)
240 # This is the same as the above, except that the string is altered in place
242 # See also the discussion about irc_downcase
244 def irc_downcase!(casemap='rfc1459')
245 cmap = casemap.to_irc_casemap
246 self.tr!(cmap.upper, cmap.lower)
249 # Upcasing functions are provided too
251 # See also the discussion about irc_downcase
253 def irc_upcase(casemap='rfc1459')
254 cmap = casemap.to_irc_casemap
255 self.tr(cmap.lower, cmap.upper)
260 # See also the discussion about irc_downcase
262 def irc_upcase!(casemap='rfc1459')
263 cmap = casemap.to_irc_casemap
264 self.tr!(cmap.lower, cmap.upper)