2015-09-22のメモです。
主に関ジン研(関東ジンギス研究会)からのリンクのためと、食べ歩きの際に前回いつ行ったかを自分で検索するために記述を残しています。稀に雑多なことを書いたりもします。
以前、『風』Ver.2 の辞書をsms.txtにするRubyスクリプトの仮定の間違いらしきところを修正することで7ページ目以降も『風』の仮想鍵盤と一致したことを書いたのだが、時間がとれたしどうせならオブジェクト指向っぽく書き直してみようと考えた。オリジナルのRubyスクリプトのあるWEBページに「Rubyを使っているにもかかわらず、見事なまでに手続き指向なスクリプトですね。:D」と書いてあるのがずっと引っかかっていたもので。
オブジェクト指向っぽくということで、以下のようにイテレータを使うように書き直した。
あと細かいところだが、辞書ファイル回りの例外発生処理を追加し、current_kanji_tableを Arrayから Hashに変更している。Arrayから Hashへの変更は、デフォルト値の設定によって値の条件分岐を無くすのが目的。
書き直した結果は以下。仮定の間違いらしきところの修正に対応するコメントには「(重要)」と付けている。本当は作者の Cakeさんに事前に公開の許可をもらおうと思っていたのだけど、オリジナルのスクリプトのあるページから辿って見つかった DTI のメールアドレスは User Unknown だし他の連絡先は見つからないし、ということでいきなり公開してみる。
#!/usr/local/bin/ruby -Ku # -*- mode: ruby; coding: utf-8 -*- # coding: utf-8 # 風 for Win の辞書から sms.txt 形式データに変換する Ruby スクリプトの # 修正ついでにオブジェクト指向っぽく書き直し # cf. http://home.j00.itscom.net/cake-smd/wiki/KazeIme.html (original) READ_DIC_HEADER_SIZE = 0x298 # Wind2.reaのヘッダサイズ、0x280ではない(重要) READ_DIC_ENTRY_SIZE = 12 # Wind2.reaのエントリサイズ KANJI_DIC_HEADER_SIZE = 0x50 # Wind2.dicのヘッダサイズ # Wind2.dicのエントリサイズは固定長でない(重要) KEY_CODE_TABLE = [ 40, 38, 32, 34, 36, 35, 33, 31, 37, 39, 22, 16, 6, 10, 14, 13, 9, 5, 15, 21, 18, 12, 2, 4, 8, 7, 3, 1, 11, 17, 30, 28, 20, 24, 26, 25, 23, 19, 27, 29 ] def error_conditional( error_message, cond ) raise error_message if cond end if __FILE__ == $0 then error_conditional( # Wind2.reaのデータサイズチェック 'Invalid file size of Wind2.rea', ( File.size( 'Wind2.rea' ) - READ_DIC_HEADER_SIZE # ヘッダ除くデータサイズ ).modulo( READ_DIC_ENTRY_SIZE ).nonzero? ) # 割り切れなければ例外発生 # sms.txt表示のためのメインルーチン File.binread( 'Wind2.rea', nil, READ_DIC_HEADER_SIZE # ヘッダ除く全データ ).scan( /.{#{READ_DIC_ENTRY_SIZE}}/omn # Wind2.reaエントリに分解 ).each do |wind2rea_entry| # 読み仮名 8バイト、配列辞書のオフセット 2バイト、データ長 2バイト(重要) yomi, pos, len = wind2rea_entry.unpack( 'A8vv' ) # yomiデータを読み込んで、 # 「0バイト以上連続した\xFFと\xFF以外のデータ1バイト」(重要)と # 「2バイトデータ(Shift_JIS)」 # のペア(Wind2.dicエントリ)に分解 dic_entry_list = # yomiに対応する Wind2.dicエントリのリスト File.binread( 'Wind2.dic', len, KANJI_DIC_HEADER_SIZE + pos # yomiデータ ).scan( /(\xFF*[^\xFF])(..)/mn ) # Wind2.dicエントリに分解 error_conditional( # yomiに対応する dic_entry_listの正当性チェック sprintf( 'Invalid entries of %p from pos %d (0x%X) in Wind2.dic', yomi, pos, pos ), len > dic_entry_list.join( '' ).size ) # 読み飛ばしがあれば例外発生 # yomiの漢字テーブルの作成 current_kanji_table = Hash[ # ペアのリストから Hashを生成 dic_entry_list.map do |key_code_str, kanji_char| # key_codeと kanji_charのペアに変換 [ key_code_str.unpack( 'C*' ).inject( :+ ), # key_codeを復元 kanji_char ] end ] current_kanji_table.default = ' ' # Hashだとこれができる # yomiのページの表示 key_code_max = current_kanji_table.keys.max base_max = ( key_code_max.to_f / 40.0 ).ceil printf( "#YOMI:%s\n%s", yomi, # Shift_JISのまま表示 base_max.times.map do |base| KEY_CODE_TABLE.map do |key_code| current_kanji_table[ 40 * base + key_code ] end.each_slice( 10 ).map do |kanji_line| # 4分割 kanji_line.join( '' ) + "\n" end.join( '' ) + "#\n" end.join( '' ) ) STDERR.printf( # 進捗表示 "yomi: %s, pos: %d (0x%X), size: %d, # of Kanji: %d, max key_code: %d\n", yomi, pos, pos, len, current_kanji_table.size, key_code_max ) end end
スクリプトの文字コードをUTF-8から変更する場合は、先頭行のオプション「-Ku」(古めのRuby用)、2〜3行目の文字コード記述「coding: utf-8」(それぞれEmacs用、Ruby用)を変更する。
コメントを入れるだけのために改行しなくてもいいところで改行しているところがあるのだか、ちょっとうるさ過ぎたか。
最近のツッコミ: