moji 1.5

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.
Files changed (4) hide show
  1. data/README.txt +1 -0
  2. data/lib/flag_set_maker.rb +121 -0
  3. data/lib/moji.rb +597 -0
  4. metadata +72 -0
@@ -0,0 +1 @@
1
+ See http://gimite.net/gimite/rubymess/moji.html
@@ -0,0 +1,121 @@
1
+ require "forwardable"
2
+
3
+
4
+ module FlagSetMaker
5
+
6
+
7
+ class FlagSet
8
+
9
+ def initialize(mod, names, zero= nil)
10
+ @module= mod
11
+ @flag_names= names.to_a()
12
+ @zero_name= zero
13
+ for i in 0...@flag_names.size
14
+ mod.const_set(@flag_names[i], Flags.new(1 << i, self))
15
+ end
16
+ mod.const_set(@zero_name, Flags.new(0, self)) if @zero_name
17
+ end
18
+
19
+ def to_s(v)
20
+ names= []
21
+ @flag_names.each_with_index(){ |name, i| names.push(name) if v[i]==1 }
22
+ if names.empty?()
23
+ return (@zero_name.to_s() || "0")
24
+ elsif names.size==1
25
+ return names[0].to_s()
26
+ else
27
+ return "("+names.join("|")+")"
28
+ end
29
+ end
30
+
31
+ def inspect(v= nil)
32
+ return v ? format("%p::%s", @module, to_s(v)) : super()
33
+ end
34
+
35
+ def validate(v)
36
+ return v&((1 << @flag_names.size)-1)
37
+ end
38
+
39
+ end
40
+
41
+
42
+ class Flags
43
+
44
+ extend(Forwardable)
45
+
46
+ def initialize(v, fs)
47
+ @value= fs.validate(v)
48
+ @flag_set= fs
49
+ end
50
+
51
+ def to_i()
52
+ return @value
53
+ end
54
+
55
+ def to_s()
56
+ return @flag_set.to_s(@value)
57
+ end
58
+
59
+ def inspect()
60
+ return @flag_set.inspect(@value)
61
+ end
62
+
63
+ def ==(rhs)
64
+ return rhs.is_a?(Flags) && @flag_set==rhs.flag_set && @value==rhs.to_i()
65
+ end
66
+
67
+ alias :eql? :==
68
+
69
+ def_delegators(:to_i, :hash)
70
+
71
+ def &(rhs)
72
+ return new_flag(@value&rhs.to_i())
73
+ end
74
+
75
+ def |(rhs)
76
+ return new_flag(@value|rhs.to_i())
77
+ end
78
+
79
+ def ~()
80
+ return new_flag(~@value)
81
+ end
82
+
83
+ def include?(flags)
84
+ return (@value&flags.to_i())==flags.to_i()
85
+ end
86
+
87
+ def empty?()
88
+ return @value!=0
89
+ end
90
+
91
+ protected
92
+
93
+ attr_reader(:flag_set)
94
+
95
+ private
96
+
97
+ def new_flag(v)
98
+ return Flags.new(v, @flag_set)
99
+ end
100
+
101
+ end
102
+
103
+
104
+ def make_flag_set(*args)
105
+ FlagSet.new(self, *args)
106
+ end
107
+
108
+ end
109
+
110
+
111
+ if __FILE__==$0
112
+
113
+ class Hoge
114
+
115
+ extend(FlagSetMaker)
116
+
117
+ make_flag_set([:FOO, :BAR, :HOGE], :NONE)
118
+
119
+ end
120
+
121
+ end
@@ -0,0 +1,597 @@
1
+ # coding: utf-8
2
+
3
+ #このファイルの文字コードはUTF-8です。
4
+ #このファイルをUnicode非対応のエディタで編集してはいけません(〜が文字化ける)。
5
+
6
+ =begin
7
+
8
+ =Moji モジュール
9
+
10
+ 日本語の文字種判定、文字種変換(半角→全角、ひらがな→カタカナなど)を行います。
11
+
12
+ ==ダウンロード / インストール:
13
+
14
+ ((<URL:http://gimite.ddo.jp/pukiwiki/index.php?Ruby%BE%AE%CA%AA%BD%B8>))
15
+ からダウンロードし、解凍してできた moji ディレクトリの中で以下のコマンドを実行してください。
16
+
17
+ # ruby setup.rb
18
+
19
+ または、 moji/lib の中の moji.rb と flag_set_maker.rb を lib/ruby/site_ruby/1.8 などにコピーしてください。
20
+
21
+ ==使い方:
22
+
23
+ Ruby 1.8: (({$KCODE})) を指定してから (({require "moji"})) してください。
24
+ Moji モジュールの関数に渡す文字列の文字コードは (({$KCODE})) と一致させてください。
25
+
26
+ Ruby 1.9: どの文字コードの文字列を渡しても大丈夫ですが、 String#encoding が正しく設定されている
27
+ 必要があります。正規表現を返す関数( Moji.kata など)は Encoding.default_internal
28
+ (設定されてない場合はUTF-8)用の正規表現を返します。その他のエンコーディング用の正規表現は
29
+ Moji.kata(Encoding::SJIS) などで取得できます。
30
+
31
+ $KCODE= "UTF8" # Ruby 1.9では不要
32
+ require "moji"
33
+
34
+ #文字種判定。
35
+ p Moji.type("漢") # => Moji::ZEN_KANJI
36
+ p Moji.type?("A", Moji::ZEN) # => true
37
+
38
+ #文字種変換。
39
+ p Moji.zen_to_han("Ruby") # => "Ruby"
40
+ p Moji.upcase("Ruby") # => "RUBY"
41
+ p Moji.kata_to_hira("ルビー") # => "るびー"
42
+
43
+ #文字種による正規表現。
44
+ p /#{Moji.kata}+#{Moji.hira}+/ =~ "ぼくドラえもん" # => 6
45
+ p Regexp.last_match.to_s # => "ドラえもん"
46
+
47
+ ==定数:
48
+
49
+ 以下の定数は、文字種の一番細かい分類です。
50
+ (({Moji.type})) が返すのは、以下の定数のうちの1つです。
51
+
52
+ --- HAN_CONTROL
53
+ 制御文字。
54
+ --- HAN_ASYMBOL
55
+ ASCIIに含まれる半角記号。
56
+ --- HAN_JSYMBOL
57
+ JISに含まれるがASCIIには含まれない半角記号。
58
+ --- HAN_NUMBER
59
+ 半角数字。
60
+ --- HAN_UPPER
61
+ 半角アルファベット大文字。
62
+ --- HAN_LOWER
63
+ 半角アルファベット小文字。
64
+ --- HAN_KATA
65
+ 半角カタカナ。
66
+ --- ZEN_ASYMBOL
67
+ JISの全角記号のうち、ASCIIに対応する半角記号があるもの。
68
+ --- ZEN_JSYMBOL
69
+ JISの全角記号のうち、ASCIIに対応する半角記号がないもの。
70
+ --- ZEN_NUMBER
71
+ 全角数字。
72
+ --- ZEN_UPPER
73
+ 全角アルファベット大文字。
74
+ --- ZEN_LOWER
75
+ 全角アルファベット小文字。
76
+ --- ZEN_HIRA
77
+ ひらがな。
78
+ --- ZEN_KATA
79
+ 全角カタカナ。
80
+ --- ZEN_GREEK
81
+ ギリシャ文字。
82
+ --- ZEN_CYRILLIC
83
+ キリル文字。
84
+ --- ZEN_LINE
85
+ 罫線のかけら。
86
+ --- ZEN_KANJI
87
+ 漢字。
88
+
89
+ 以下の定数は、上の文字種の組み合わせと別名です。
90
+
91
+ --- HAN_SYMBOL
92
+ JISに含まれる半角記号。(({HAN_ASYMBOL | HAN_JSYMBOL}))
93
+ --- HAN_ALPHA
94
+ 半角アルファベット。(({HAN_UPPER | HAN_LOWER}))
95
+ --- HAN_ALNUM
96
+ 半角英数字。(({HAN_ALPHA | HAN_NUMBER}))
97
+ --- HAN
98
+ 全ての半角文字。(({HAN_CONTROL | HAN_SYMBOL | HAN_ALNUM | HAN_KATA}))
99
+ --- ZEN_SYMBOL
100
+ JISに含まれる全角記号。(({ZEN_ASYMBOL | ZEN_JSYMBOL}))
101
+ --- ZEN_ALPHA
102
+ 全角アルファベット。(({ZEN_UPPER | ZEN_LOWER}))
103
+ --- ZEN_ALNUM
104
+ 全角英数字。(({ZEN_ALPHA | ZEN_NUMBER}))
105
+ --- ZEN_KANA
106
+ 全角かな/カナ。(({ZEN_KATA | ZEN_HIRA}))
107
+ --- ZEN
108
+ JISに含まれる全ての全角文字。(({ZEN_SYMBOL | ZEN_ALNUM | ZEN_KANA | ZEN_GREEK | ZEN_CYRILLIC | ZEN_LINE | ZEN_KANJI}))
109
+ --- ASYMBOL
110
+ ASCIIに含まれる半角記号とその全角版。(({HAN_ASYMBOL | ZEN_ASYMBOL}))
111
+ --- JSYMBOL
112
+ JISに含まれるが (({ASYMBOL})) には含まれない全角/半角記号。(({HAN_JSYMBOL | ZEN_JSYMBOL}))
113
+ --- SYMBOL
114
+ JISに含まれる全ての全角/半角記号。(({HAN_SYMBOL | ZEN_SYMBOL}))
115
+ --- NUMBER
116
+ 全角/半角数字。(({HAN_NUMBER | ZEN_NUMBER}))
117
+ --- UPPER
118
+ 全角/半角アルファベット大文字。(({HAN_UPPER | ZEN_UPPER}))
119
+ --- LOWER
120
+ 全角/半角アルファベット小文字。(({HAN_LOWER | ZEN_LOWER}))
121
+ --- ALPHA
122
+ 全角/半角アルファベット。(({HAN_ALPHA | ZEN_ALPHA}))
123
+ --- ALNUM
124
+ 全角/半角英数字。(({HAN_ALNUM | ZEN_ALNUM}))
125
+ --- HIRA
126
+ (({ZEN_HIRA})) の別名。
127
+ --- KATA
128
+ 全角/半角カタカナ。(({HAN_KATA | ZEN_KATA}))
129
+ --- KANA
130
+ 全角/半角 かな/カナ。(({KATA | ZEN_HIRA}))
131
+ --- GREEK
132
+ (({ZEN_GREEK})) の別名。
133
+ --- CYRILLIC
134
+ (({ZEN_CYRILLIC})) の別名。
135
+ --- LINE
136
+ (({ZEN_LINE})) の別名。
137
+ --- KANJI
138
+ (({ZEN_KANJI})) の別名。
139
+ --- ALL
140
+ 上記全ての文字。
141
+
142
+ ==モジュール関数:
143
+
144
+ --- Moji.type(ch)
145
+
146
+ 文字 ((|ch|)) の文字種を返します。
147
+
148
+ 「一番細かい分類」の((<定数|定数:>))のうち1つを返します。
149
+
150
+ 上の分類に当てはまらない文字(Unicodeのハングルなど)に対しては (({nil})) を返します。
151
+ また、UnicodeのB面以降の文字に対しても (({nil})) を返します。
152
+
153
+ 文字が割り当てられていない文字コードに対する結果は不定です( (({nil})) を返す事もあります)。
154
+
155
+ p Moji.type("漢") # => Moji::ZEN_KANJI
156
+
157
+ --- Moji.type?(ch, type)
158
+
159
+ 文字 ((|ch|)) が文字種 ((|type|)) に含まれれば、 (({true})) を返します。
160
+
161
+ ((|type|)) には全ての((<定数|定数:>))と、それらを (({|}))
162
+ で結んだものを使えます。
163
+
164
+ p Moji.type?("A", Moji::ZEN) # => true
165
+
166
+ --- Moji.regexp(type[, encoding])
167
+
168
+ 文字種 ((|type|)) の1文字を表す正規表現を返します。
169
+
170
+ ((|type|)) には全ての((<定数|定数:>))と、それらを (({|}))
171
+ で結んだものを使えます。
172
+
173
+ Ruby 1.9では ((|encoding|)) に Encoding オブジェクトを渡すと、指定のエンコーディング用の
174
+ 正規表現を返します。
175
+ 省略すると Encoding.default_internal (指定されてない場合は Encoding::UTF_8 )とみなします。
176
+
177
+ p Moji.regexp(Moji::HIRA) # => /[ぁ-ん]/
178
+
179
+ --- Moji.zen_to_han(str[, type])
180
+
181
+ 文字列 ((|str|)) の全角を半角に変換して返します。
182
+
183
+ ((|type|)) には、変換対象とする文字種を((<定数|定数:>))で指定します。
184
+ デフォルトは (({ALL})) (全て)です。
185
+
186
+ p Moji.zen_to_han("Ruby!?") # => "Ruby!?"
187
+ p Moji.zen_to_han("Ruby!?", Moji::ALPHA) # => "Ruby!?"
188
+
189
+ --- Moji.han_to_zen(str[, type])
190
+
191
+ 文字列 ((|str|)) の半角を全角に変換して返します。
192
+
193
+ ((|type|)) には、変換対象とする文字種を((<定数|定数:>))で指定します。
194
+ デフォルトは (({ALL})) (全て)です。
195
+
196
+ p Moji.han_to_zen("Ruby!?") # => "Ruby!?"
197
+ p Moji.han_to_zen("Ruby!?", Moji::SYMBOL) # => "Ruby!?"
198
+
199
+ --- Moji.normalize_zen_han(str)
200
+
201
+ 文字列 ((|str|)) の大文字、小文字を一般的なものに統一します。
202
+
203
+ 具体的には、ASCIIに含まれる記号と英数字( (({ALNUM|ASYMBOL}))
204
+ )を半角に、それ以外の記号とカタカナ( (({JSYMBOL|HAN_KATA})) )を全角に変換します。
205
+
206
+ --- Moji.upcase(str[, type])
207
+
208
+ 文字列 ((|str|)) の小文字を大文字に変換して返します。
209
+
210
+ ((|type|)) には、変換対象とする文字種を((<定数|定数:>))で指定します。
211
+ デフォルトは (({LOWER})) (全角/半角のアルファベット)です。
212
+ ギリシャ文字、キリル文字には対応していません。
213
+
214
+ p Moji.upcase("Ruby") # => "RUBY"
215
+
216
+ --- Moji.downcase(str[, type])
217
+
218
+ 文字列 ((|str|)) の小文字を大文字に変換して返します。
219
+
220
+ ((|type|)) には、変換対象とする文字種を((<定数|定数:>))で指定します。
221
+ デフォルトは (({UPPER})) (全角/半角のアルファベット)です。
222
+ ギリシャ文字、キリル文字には対応していません。
223
+
224
+ p Moji.downcase("Ruby") # => "ruby"
225
+
226
+ --- Moji.kata_to_hira(str)
227
+
228
+ 文字列 ((|str|)) の全角カタカナをひらがなに変換して返します。
229
+
230
+ 半角カタカナは直接変換できません。 (({han_to_zen})) で全角にしてから変換してください。
231
+
232
+ p Moji.kata_to_hira("ルビー") # => "るびー"
233
+
234
+ --- Moji.hira_to_kata(str)
235
+
236
+ 文字列 ((|str|)) のひらがなを全角カタカナに変換して返します。
237
+
238
+ p Moji.hira_to_kata("るびー") # => "ルビー"
239
+
240
+ --- Moji.han_control([encoding])
241
+ --- Moji.han_asymbol([encoding])
242
+ --- ...
243
+ --- Moji.kana([encoding])
244
+ --- ...
245
+
246
+ ((<定数|定数:>))それぞれに対応するメソッドが有り、
247
+ それぞれの文字種の1文字を表す正規表現を返します。
248
+
249
+ 例えば、 (({Moji.kana})) は (({Moji.regexp(Moji::KANA)})) と同じです。
250
+
251
+ Ruby 1.9では ((|encoding|)) に Encoding オブジェクトを渡すと、指定のエンコーディング用の
252
+ 正規表現を返します。
253
+ 省略すると Encoding.default_internal (指定されてない場合は Encoding::UTF_8 )とみなします。
254
+
255
+ 以下の例のように、文字クラスっぽく使えます。
256
+ p /#{Moji.kata}+#{Moji.hira}+/ =~ "ぼくドラえもん" # => 6
257
+ p Regexp.last_match.to_s # => "ドラえもん"
258
+
259
+ ==動作環境:
260
+
261
+ たぶんRuby 1.8以降。
262
+
263
+ Linux Ruby 1.8.7, 1.9.2にて動作確認しました。
264
+
265
+ ==作者:
266
+
267
+ Gimite 市川 (連絡先: ((<URL:http://gimite.ddo.jp/bbs/tnote.cgi>)) )
268
+
269
+ ==ライセンス:
270
+
271
+ Public Domainです。煮るなり焼くなりご自由に。
272
+
273
+ ==更新履歴:
274
+
275
+ 2010/9/19 Ver.1.5
276
+ *Ruby 1.9に対応。
277
+
278
+ 2008/8/30 Ver.1.4
279
+ *Moji.type("\n")がnilを返すバグを修正。(thanks to 橋爪さん)
280
+
281
+ 2006/7/23 Ver.1.3
282
+ *半角中黒(・)の字種判別、全角中黒との相互変換ができていなかったのを修正。(thanks to xyzzyさん)
283
+
284
+ 2006/10/5 Ver.1.2
285
+ *EUC 以外の文字コードにも対応し、ライブラリ名を Moji に変更。
286
+ *han_to_zen, zen_to_han の対象文字種のデフォルトを全て( (({ALL})) )に。
287
+ *normalize_zen_han 追加。
288
+
289
+ 2005/1/3 Ver.1.1
290
+ *(({$KCODE})) が指定されていないとEUCUtil.typeが正常動作しない問題を修正。
291
+ *定数に (({ASYMBOL})) と (({JSYMBOL})) を追加。
292
+
293
+ 2004/11/16 Ver.1.0
294
+ *EUCUtil 公開。
295
+
296
+ =end
297
+
298
+
299
+ if RUBY_VERSION < "1.9.0" && $KCODE=="NONE"
300
+ warn("Warning: Set $KCODE before requiring 'moji' (UTF8 assumed)")
301
+ $KCODE= "u"
302
+ end
303
+
304
+ require "enumerator"
305
+ require "flag_set_maker"
306
+ if RUBY_VERSION < "1.9.0"
307
+ require "nkf"
308
+ require "jcode"
309
+ end
310
+
311
+ nkf_kcode= RUBY_VERSION >= "1.9.0" ? nil : {"SJIS" => "s", "EUC" => "e"}[$KCODE]
312
+
313
+ script= <<'EOS'
314
+
315
+
316
+ module Moji
317
+
318
+ extend(FlagSetMaker)
319
+
320
+ module Detail
321
+
322
+ HAN_ASYMBOL_LIST= ' !"#$%&\'()*+,-./:;<=>?@[\]^_`{|}~'
323
+ ZEN_ASYMBOL_LIST= ' !”#$%&’()*+,-./:;<=>?@[¥]^_‘{|} ̄'
324
+ HAN_JSYMBOL1_LIST= '。「」、ー゙゚・'
325
+ ZEN_JSYMBOL1_LIST= '。「」、ー゛゜・'
326
+ ZEN_JSYMBOL_LIST= '、。・゛゜´`¨ヽヾゝゞ〃仝々〆〇ー―‐\~〜∥…‥“〔〕〈〉《》「」『』【】'+
327
+ '±×÷≠≦≧∞∴♂♀°′″℃¢£§☆★○●◎◇◇◆□■△▲▽▼※〒→←↑↓〓'
328
+ HAN_KATA_LIST= 'ハヒフヘホウカキクケコサシスセソタチツテトアイエオナニヌネノマミムメモヤユヨラリルレロワヲンァィゥェォャュョッ'.split(//)
329
+ HAN_VSYMBOLS= ['', '゙', '゚']
330
+ ZEN_KATA_LISTS= [
331
+ 'ハヒフヘホウカキクケコサシスセソタチツテトアイエオ'+
332
+ 'ナニヌネノマミムメモヤユヨラリルレロワヲンァィゥェォャュョッ',
333
+ 'バビブベボヴガギグゲゴザジズゼゾダヂヅデド',
334
+ 'パピプペポ',
335
+ ].map(){ |s| s.split(//) }
336
+
337
+ if RUBY_VERSION >= "1.9.0"
338
+
339
+ def self.convert_encoding(str, &block)
340
+ orig_enc = str.encoding
341
+ if orig_enc == Encoding::UTF_8
342
+ # 無駄なコピーを避けるためにencodeを呼ばない。
343
+ return yield(str)
344
+ else
345
+ result = yield(str.encode(Encoding::UTF_8))
346
+ return result.is_a?(String) ? result.encode(orig_enc) : result
347
+ end
348
+ end
349
+
350
+ else
351
+
352
+ def self.convert_encoding(str, &block)
353
+ return yield(str)
354
+ end
355
+
356
+ end
357
+
358
+ end
359
+
360
+ def self.uni_range(*args)
361
+ if RUBY_VERSION >= "1.9.0"
362
+ str= args.each_slice(2).map(){ |f, e| '\u%04x-\u%04x' % [f, e] }.join("")
363
+ return /[#{str}]/
364
+ elsif $KCODE=="UTF8"
365
+ str= args.map(){ |n| NKF.nkf("-wW160x", [n].pack("n")) }.
366
+ enum_slice(2).map(){ |f, e| "#{f}-#{e}" }.to_s()
367
+ return /[#{str}]/u
368
+ else
369
+ return nil
370
+ end
371
+ end
372
+
373
+ make_flag_set([
374
+ :HAN_CONTROL, :HAN_ASYMBOL, :HAN_JSYMBOL, :HAN_NUMBER, :HAN_UPPER, :HAN_LOWER, :HAN_KATA,
375
+ :ZEN_ASYMBOL, :ZEN_JSYMBOL, :ZEN_NUMBER, :ZEN_UPPER, :ZEN_LOWER, :ZEN_HIRA, :ZEN_KATA,
376
+ :ZEN_GREEK, :ZEN_CYRILLIC, :ZEN_LINE, :ZEN_KANJI,
377
+ ])
378
+
379
+ HAN_SYMBOL= HAN_ASYMBOL | HAN_JSYMBOL
380
+ HAN_ALPHA= HAN_UPPER | HAN_LOWER
381
+ HAN_ALNUM= HAN_ALPHA | HAN_NUMBER
382
+ HAN= HAN_CONTROL | HAN_SYMBOL | HAN_ALNUM | HAN_KATA
383
+ ZEN_SYMBOL= ZEN_ASYMBOL | ZEN_JSYMBOL
384
+ ZEN_ALPHA= ZEN_UPPER | ZEN_LOWER
385
+ ZEN_ALNUM= ZEN_ALPHA | ZEN_NUMBER
386
+ ZEN_KANA= ZEN_KATA | ZEN_HIRA
387
+ ZEN= ZEN_SYMBOL | ZEN_ALNUM | ZEN_KANA | ZEN_GREEK | ZEN_CYRILLIC | ZEN_LINE | ZEN_KANJI
388
+ ASYMBOL= HAN_ASYMBOL | ZEN_ASYMBOL
389
+ JSYMBOL= HAN_JSYMBOL | ZEN_JSYMBOL
390
+ SYMBOL= HAN_SYMBOL | ZEN_SYMBOL
391
+ NUMBER= HAN_NUMBER | ZEN_NUMBER
392
+ UPPER= HAN_UPPER | ZEN_UPPER
393
+ LOWER= HAN_LOWER | ZEN_LOWER
394
+ ALPHA= HAN_ALPHA | ZEN_ALPHA
395
+ ALNUM= HAN_ALNUM | ZEN_ALNUM
396
+ HIRA= ZEN_HIRA
397
+ KATA= HAN_KATA | ZEN_KATA
398
+ KANA= KATA | ZEN_HIRA
399
+ GREEK= ZEN_GREEK
400
+ CYRILLIC= ZEN_CYRILLIC
401
+ LINE= ZEN_LINE
402
+ KANJI= ZEN_KANJI
403
+ ALL= HAN | ZEN
404
+
405
+ CHAR_REGEXPS= {
406
+ HAN_CONTROL => /[\x00-\x1f\x7f]/,
407
+ HAN_ASYMBOL =>
408
+ Regexp.new("["+Detail::HAN_ASYMBOL_LIST.gsub(/[\[\]\-\^\\]/){ "\\"+$& }+"]"),
409
+ HAN_JSYMBOL => Regexp.new("["+Detail::HAN_JSYMBOL1_LIST+"]"),
410
+ HAN_NUMBER => /[0-9]/,
411
+ HAN_UPPER => /[A-Z]/,
412
+ HAN_LOWER => /[a-z]/,
413
+ HAN_KATA => /[ヲ-ッア-ン]/,
414
+ ZEN_ASYMBOL => Regexp.new("["+Detail::ZEN_ASYMBOL_LIST+"]"),
415
+ ZEN_JSYMBOL => Regexp.new("["+Detail::ZEN_JSYMBOL_LIST+"]"),
416
+ ZEN_NUMBER => /[0-9]/,
417
+ ZEN_UPPER => /[A-Z]/,
418
+ ZEN_LOWER => /[a-z]/,
419
+ ZEN_HIRA => /[ぁ-ん]/,
420
+ ZEN_KATA => /[ァ-ヶ]/,
421
+ ZEN_GREEK => /[Α-Ωα-ω]/,
422
+ ZEN_CYRILLIC => /[А-Яа-я]/,
423
+ ZEN_LINE => uni_range(0x2570, 0x25ff) || /[─-╂]/,
424
+ ZEN_KANJI => uni_range(0x3400, 0x4dbf, 0x4e00, 0x9fff, 0xf900, 0xfaff) || /[亜-瑤]/,
425
+ }
426
+
427
+ def type(ch)
428
+ Detail.convert_encoding(ch) do |ch|
429
+ ch= ch.slice(/\A./m)
430
+ result = nil
431
+ for tp, reg in CHAR_REGEXPS
432
+ if ch=~reg
433
+ result= tp
434
+ break
435
+ end
436
+ end
437
+ result
438
+ end
439
+ end
440
+
441
+ def type?(ch, tp)
442
+ Detail.convert_encoding(ch) do |ch|
443
+ tp.include?(type(ch))
444
+ end
445
+ end
446
+
447
+ def regexp(tp, encoding= nil)
448
+
449
+ regs= []
450
+ for tp2, reg in CHAR_REGEXPS
451
+ regs.push(reg) if tp.include?(tp2)
452
+ end
453
+ reg= regs.size==1 ? regs[0] : Regexp.new(regs.join("|"))
454
+
455
+ if RUBY_VERSION >= "1.9.0" && !encoding
456
+ encoding= Encoding.default_internal || Encoding::UTF_8
457
+ end
458
+ if encoding && encoding != Encoding::UTF_8
459
+ return Regexp.new(reg.to_s().encode(encoding))
460
+ else
461
+ return reg
462
+ end
463
+
464
+ end
465
+
466
+ def zen_to_han(str, tp= ALL)
467
+ Detail.convert_encoding(str) do |str|
468
+ if tp.include?(ZEN_KATA)
469
+ reg= Regexp.new("["+Detail::ZEN_KATA_LISTS.to_s()+"]")
470
+ str= str.gsub(reg) do
471
+ for i in 0...3
472
+ pos= Detail::ZEN_KATA_LISTS[i].index($&)
473
+ break Detail::HAN_KATA_LIST[pos]+Detail::HAN_VSYMBOLS[i] if pos
474
+ end
475
+ end
476
+ end
477
+ str= str.tr("a-z", "a-z") if tp.include?(ZEN_LOWER)
478
+ str= str.tr("A-Z", "A-Z") if tp.include?(ZEN_UPPER)
479
+ str= str.tr("0-9", "0-9") if tp.include?(ZEN_NUMBER)
480
+ str= str.tr(Detail::ZEN_ASYMBOL_LIST,
481
+ Detail::HAN_ASYMBOL_LIST.gsub(/[\-\^\\]/){ "\\"+$& }) if tp.include?(ZEN_ASYMBOL)
482
+ str= str.tr(Detail::ZEN_JSYMBOL1_LIST,
483
+ Detail::HAN_JSYMBOL1_LIST) if tp.include?(ZEN_JSYMBOL)
484
+ str
485
+ end
486
+ end
487
+
488
+ def han_to_zen(str, tp= ALL)
489
+ Detail.convert_encoding(str) do |str|
490
+ #[半]濁音記号がJSYMBOLに含まれるので、KATAの変換をJSYMBOLより前にやる必要あり。
491
+ if tp.include?(HAN_KATA)
492
+ str= str.gsub(/(#{han_kata})([゙゚]?)/) do
493
+ i= {""=>0, "゙"=>1, "゚"=>2}[$2]
494
+ pos= Detail::HAN_KATA_LIST.index($1)
495
+ s= Detail::ZEN_KATA_LISTS[i][pos]
496
+ (!s || s=="") ? Detail::ZEN_KATA_LISTS[0][pos]+$2 : s
497
+ end
498
+ end
499
+ str= str.tr("a-z", "a-z") if tp.include?(HAN_LOWER)
500
+ str= str.tr("A-Z", "A-Z") if tp.include?(HAN_UPPER)
501
+ str= str.tr("0-9", "0-9") if tp.include?(HAN_NUMBER)
502
+ str= str.tr(Detail::HAN_ASYMBOL_LIST.gsub(/[\-\^\\]/){ "\\"+$& },
503
+ Detail::ZEN_ASYMBOL_LIST) if tp.include?(HAN_ASYMBOL)
504
+ str= str.tr(Detail::HAN_JSYMBOL1_LIST,
505
+ Detail::ZEN_JSYMBOL1_LIST) if tp.include?(HAN_JSYMBOL)
506
+ str
507
+ end
508
+ end
509
+
510
+ def normalize_zen_han(str)
511
+ Detail.convert_encoding(str) do |str|
512
+ zen_to_han(han_to_zen(str, HAN_JSYMBOL|HAN_KATA), ZEN_ALNUM|ZEN_ASYMBOL)
513
+ end
514
+ end
515
+
516
+ def upcase(str, tp= LOWER)
517
+ Detail.convert_encoding(str) do |str|
518
+ str= str.tr("a-z", "A-Z") if tp.include?(HAN_LOWER)
519
+ str= str.tr("a-z", "A-Z") if tp.include?(ZEN_LOWER)
520
+ str
521
+ end
522
+ end
523
+
524
+ def downcase(str, tp= UPPER)
525
+ Detail.convert_encoding(str) do |str|
526
+ str= str.tr("A-Z", "a-z") if tp.include?(HAN_UPPER)
527
+ str= str.tr("A-Z", "a-z") if tp.include?(ZEN_UPPER)
528
+ str
529
+ end
530
+ end
531
+
532
+ def kata_to_hira(str)
533
+ Detail.convert_encoding(str) do |str|
534
+ str.tr("ァ-ン", "ぁ-ん")
535
+ end
536
+ end
537
+
538
+ def hira_to_kata(str)
539
+ Detail.convert_encoding(str) do |str|
540
+ str.tr("ぁ-ん", "ァ-ン")
541
+ end
542
+ end
543
+
544
+ module_function(
545
+ :type, :type?, :regexp, :zen_to_han, :han_to_zen, :normalize_zen_han, :upcase, :downcase,
546
+ :kata_to_hira, :hira_to_kata
547
+ )
548
+
549
+ def self.define_regexp_method(name, tp)
550
+ define_method(name) do |*args|
551
+ regexp(tp, *args)
552
+ end
553
+ module_function(name)
554
+ end
555
+
556
+ #han_control, han_asymbol, …などのモジュール関数を定義。
557
+ for cons in constants
558
+ val= const_get(cons)
559
+ define_regexp_method(cons.downcase(), val) if val.is_a?(FlagSetMaker::Flags)
560
+ end
561
+
562
+ def self.test()
563
+ orig_str= "ドラえもん(Doraemon)は、日本で1番有名な漫画だ。"
564
+ for encoding in RUBY_VERSION >= "1.9.0" ? [Encoding::UTF_8, Encoding::SJIS] : [nil]
565
+ str= encoding ? orig_str.encode(encoding) : orig_str
566
+ str.each_char() do |ch|
567
+ ch= ch.encode(Encoding::UTF_8) if encoding
568
+ printf("%2s %s\n", ch, Moji.type(ch))
569
+ end
570
+ str= Moji.zen_to_han(str, Moji::ALL)
571
+ if encoding
572
+ puts(str.encode(Encoding::UTF_8))
573
+ puts(str.encoding)
574
+ else
575
+ puts(str)
576
+ end
577
+ str= Moji.han_to_zen(str, Moji::ALL)
578
+ if encoding
579
+ puts(str.encode(Encoding::UTF_8))
580
+ puts(str.encoding)
581
+ else
582
+ puts(str)
583
+ end
584
+ end
585
+ end
586
+
587
+ end
588
+
589
+ EOS
590
+
591
+ script= NKF.nkf("-#{nkf_kcode}Wx", script) if nkf_kcode
592
+ #UTF-8の場合、nkfしてはいけない(~が〜になるので)。
593
+ eval(script, TOPLEVEL_BINDING)
594
+
595
+ if __FILE__==$0
596
+ Moji.test()
597
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moji
3
+ version: !ruby/object:Gem::Version
4
+ hash: 5
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 5
9
+ version: "1.5"
10
+ platform: ruby
11
+ authors:
12
+ - Hiroshi Ichikawa
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-20 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Character type classification/conversion for Japanese
22
+ email: gimite+moji@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - README.txt
31
+ - lib/moji.rb
32
+ - lib/flag_set_maker.rb
33
+ has_rdoc: true
34
+ homepage: http://gimite.net/gimite/rubymess/moji.html
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --quiet
40
+ - --title
41
+ - moji Reference
42
+ - --main
43
+ - lib/moji.rb
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 3
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.7
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Character type classification/conversion for Japanese
71
+ test_files: []
72
+