ruby/lib/jcode.rb

168 строки
3.1 KiB
Ruby

# jcode.rb - ruby code to handle japanese (EUC/SJIS) string
$vsave, $VERBOSE = $VERBOSE, FALSE
class String
printf STDERR, "feel free for some warnings:\n" if $VERBOSE
def jlength
self.split(//).length
end
alias original_succ succ
private :original_succ
def mbchar?
case $KCODE[0]
when ?s, ?S
self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n
when ?e, ?E
self =~ /[\xa1-\xfe][\xa1-\xfe]/n
else
false
end
end
def succ
if self[-2] and self[-2, 2].mbchar?
s = self.dup
s[-1] += 1
s[-1] += 1 unless s[-2, 2].mbchar?
return s
else
original_succ
end
end
def upto(to)
return if self > to
curr = self
tail = self[-2..-1]
if tail.length == 2 and tail =~ /^.$/ then
if self[0..-2] == to[0..-2]
first = self[-2].chr
for c in self[-1] .. to[-1]
if (first+c.chr).mbchar?
yield self[0..-2]+c.chr
end
end
end
else
loop do
yield curr
return if curr == to
curr = curr.succ
return if curr.length > to.length
end
end
return nil
end
private
def _expand_ch str
a = []
str.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r|
if $3
a.push $3
elsif $1.length != $2.length
next
elsif $1.length == 1
$1[0].upto($2[0]) { |c| a.push c.chr }
else
$1.upto($2) { |c| a.push c }
end
end
a
end
def expand_ch_hash from, to
h = {}
afrom = _expand_ch(from)
ato = _expand_ch(to)
afrom.each_with_index do |x,i| h[x] = ato[i] || ato[-1] end
h
end
def bsquote(str)
str.gsub(/\\/, '\\\\\\\\')
end
HashCache = {}
TrPatternCache = {}
DeletePatternCache = {}
SqueezePatternCache = {}
public
def tr!(from, to)
return self.delete!(from) if to.length == 0
pattern = TrPatternCache[from] ||= /[#{bsquote(from)}]/
if from[0] == ?^
last = /.$/.match(to)[0]
self.gsub!(pattern, last)
else
h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
self.gsub!(pattern) do |c| h[c] end
end
end
def tr(from, to)
(str = self.dup).tr!(from, to) or str
end
def delete!(del)
self.gsub!(DeletePatternCache[del] ||= /[#{bsquote(del)}]+/, '')
end
def delete(del)
(str = self.dup).delete!(del) or str
end
def squeeze!(del=nil)
pattern =
if del
SqueezePatternCache[del] ||= /([#{bsquote(del)}])\1+/
else
/(.|\n)\1+/
end
self.gsub!(pattern, '\1')
end
def squeeze(del=nil)
(str = self.dup).squeeze!(del) or str
end
def tr_s!(from, to)
return self.delete!(from) if to.length == 0
pattern = SqueezePatternCache[from] ||= /([#{bsquote(from)}])\1+"/
if from[0] == ?^
last = /.$/.match(to)[0]
self.gsub!(pattern, last)
else
h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
self.gsub!(pattern) do h[$1] end
end
end
def tr_s(from, to)
(str = self.dup).tr_s!(from,to) or str
end
def chop!
self.gsub!(/(?:.|\r?\n)\z/, '')
end
def chop
(str = self.dup).chop! or str
end
def jcount(str)
self.delete("^#{str}").jlength
end
end
$VERBOSE = $vsave