OSDN Git Service

Initial commit.
[mave/mave.git] / mave_base.rb
1 require 'kconv'
2
3 #===============================================================================
4 #
5 #       Integer
6 #
7 class Integer
8
9         #-----------------------------------------------------------
10         #
11         #       数値を人間に読みやすい表現形式で返す
12         #
13         def to_h(dot = false)
14                 unless((full = self.to_s).length > 3)
15                         full
16                 else
17                         case full.length % 3
18                                 when 1 then top = full[0, 1] + (dot ? '.' + full[1, 1] : '')
19                                 when 2 then top = full[0, 2]
20                                 when 0 then top = full[0, 3]
21                         end
22                         top + '....KKKMMMGGGTTTPPP'[full.length].chr
23                 end
24         end
25 end
26
27 #===============================================================================
28 #
29 #       String
30 #
31 class String
32
33         #-----------------------------------------------------------
34         #
35         #       キャラクタセットの定義
36         #
37         #               http://www.iana.org/assignments/character-sets
38         #
39         @@charsets = {
40                 'ISO-2022-JP'   => Kconv::JIS,
41                 'SHIFT_JIS'             => Kconv::SJIS,
42                 'EUC-JP'                => Kconv::EUC,
43                 'UTF-8'                 => Kconv::UTF8,
44         }
45
46         def self.charset(charset)
47                 @@charsets[charset]
48         end
49
50         #-----------------------------------------------------------
51         #
52         #       メッセージヘッダのデコーダ
53         #
54         #               http://tools.ietf.org/html/rfc2047
55         #
56         @@decoders = {}
57
58         def self.bind_decoder(code)
59                 @@decoders[code.upcase] = Proc.new
60         end
61
62         def decode_mh                                                                                           # decode message header
63                 gsub(/=\?([^?]+)\?(B|Q)\?([^?]+)\?=/i) {
64                         $3.decode_ec($2).decode_cs('UTF-8', $1)                         #### now fixed utf-8
65                 }
66         end
67
68         def decode_ec(code)                                                                                     # decode encodings
69                 (it = @@decoders[code.upcase]) ? it.call(self) : self
70         end
71
72         def decode_cs(out_code, in_code)                                                        # decode character sets
73                 (it = @@decoders[in_code.upcase]) ? it.call(self, out_code) : self
74         end
75
76         #-----------------------------------------------------------
77         #
78         #       文字列を指定の長さに切り詰める
79         #
80         @@snippers = {}
81         @@each_snippers = {}
82         @@current_snip_charset = 'UTF-8'
83
84         def self.bind_snipper(charset)
85                 @@snippers[charset] = Proc.new
86         end
87
88         def self.bind_each_snipper(charset)
89                 @@each_snippers[charset] = Proc.new
90         end
91
92         def self.set_snip_charset(charset)
93                 @@current_snip_charset = charset
94         end
95
96         def snip(n)
97                 @@snippers[@@current_snip_charset].call(self, n)
98         end
99
100         def each_snip(n, max = 9999)
101                 @@each_snippers[@@current_snip_charset].call(self, n, max, Proc.new)
102         end
103
104         #-----------------------------------------------------------
105         #
106         #       端末の UTF-8 対応の不備を補う
107         #
108         #               http://ja.wikipedia.org/wiki/UTF-8
109         #
110         def enspc
111                 self.gsub(/[\xC0-\xE2][\x80-\xBF]+/) {|c|                               #### いーかげん
112                         c + '_'
113                 }
114         end
115 end
116
117 #===============================================================================
118 #
119 #       多言語対応クラス
120 #
121 #               http://www.gnu.org/software/gettext/gettext.html
122 #
123 class Intl
124
125         @@domains = {}
126         @@domains[@@current_domain = 'default'] = {}
127
128         def self.bind_text_domain(domain, dirname = '')
129                 load "#{dirname}#{domain}.pmo"
130                 @@domains[domain] = @@catalog
131         end
132
133         def self.set_text_domain(domain)
134                 @@current_domain = domain
135         end
136
137         def self.get_text(msgid)
138                 @@domains[@@current_domain][msgid] or msgid
139         end
140 end
141
142 #===============================================================================
143 #
144 #       多言語対応
145 #
146 def _(msgid)
147         Intl.get_text(msgid)
148 end
149
150 #===============================================================================
151 #
152 #       その他
153 #
154 def yap(arg = 'done.')
155         @yap = 0 unless(@yap)
156         print "#{@yap += 1}: #{arg.inspect}\n"
157 end
158
159 def debug(log = 'log.', obj = self)
160         @debug = File.new('debug.log', 'a') and @debug.write('-' * 76 + "\n") unless(@debug)
161         @debug.write(obj.to_s + ': ' + log.to_s + "\n")
162 end
163
164 #===============================================================================
165 #
166 #       各種デコーダを登録
167 #
168 String.bind_decoder('7BIT') {|str|                                                              # 7bit decoder
169         str
170 }
171 String.bind_decoder('8BIT') {|str|                                                              # 8bit decoder
172         str
173 }
174 String.bind_decoder('BINARY') {|str|                                                    # binary decoder?
175         '-- binary --'
176 }
177 String.bind_decoder('BASE64') {|str|                                                    # Base64 decoder
178         str.unpack('m')[0]
179 }
180 String.bind_decoder('QUOTED-PRINTABLE') {|str|                                  # Quoted Printable decoder
181         str.unpack('M')[0]
182 }
183 String.bind_decoder('B') {|str|                                                                 # Base64 decoder
184         str.unpack('m')[0]
185 }
186 String.bind_decoder('Q') {|str|                                                                 # Quoted Printable decoder
187         str.unpack('M')[0]
188 }
189 String.bind_decoder('US-ASCII') {|str, out_code|                                # us-ascii(auto) decoder
190         str.kconv(String.charset(out_code))
191 }
192 String.bind_decoder('ISO-2022-JP') {|str, out_code|                             # iso-2022-jp decoder
193         str.kconv(String.charset(out_code), Kconv::JIS)
194 }
195 String.bind_decoder('SHIFT_JIS') {|str, out_code|                               # shift_jis decoder
196         str.kconv(String.charset(out_code), Kconv::SJIS)
197 }
198 String.bind_decoder('EUC-JP') {|str, out_code|                                  # euc-jp decoder
199         str.kconv(String.charset(out_code), Kconv::EUC)
200 }
201 String.bind_decoder('UTF-8') {|str, out_code|                                   # utf-8 decoder
202         str.kconv(String.charset(out_code), Kconv::UTF8)
203 }
204 #       http://tools.ietf.org/html/rfc2152
205 String.bind_decoder('UTF-7') {|str, out_code|                                   # utf-7 decoder
206         str.gsub(%r|\+([A-Za-z0-9+/]+)-?|) {|p|
207                 ($1 + '==').unpack('m')[0].kconv(Kconv::UTF8, Kconv::UTF16)
208         }.gsub(/\+-/, '+').kconv(String.charset(out_code), Kconv::UTF8)
209 }
210
211 #### String.wsize                                                                                               # 表示幅を得る
212
213 #### String.center                                                                                              # センタリングする
214
215 String.bind_snipper('UTF-8') {|str, n|                                                  # 指定の長さに切り詰める
216         ws = str[0, n * 2].gsub(/[\xC0-\xFD][\x80-\xBF]+/, "\xFF\xFF")[0, n]
217         wc = ws.count("\xFF")
218         str.slice(0, n + wc / 2 - wc % 2).enspc + ' ' * (n - ws.length + wc % 2)
219 }
220
221 String.bind_each_snipper('UTF-8') {|str, n, max, proc|                  # 指定の長さに切り詰め、順に行を渡す
222         p = 0; while(p <= str.length)                                                           # '<': 改行文字のみの行は省略
223                 break if((max -= 1) < 0)
224                 ws = str[p, n * 2].gsub(/[\xC0-\xFD][\x80-\xBF]+/, "\xFF\xFF")[0, n]
225                 wc = ws.count("\xFF")
226                 proc.call(str.slice(p, nn = n + wc / 2 - wc % 2).enspc + ' ' * (n - ws.length + wc % 2))
227                 p += nn
228         end
229 }
230
231 #### TAB 対応
232
233 __END__
234