moshで濁音が分解されちゃったのを結合し直す方法

(地味にmoshrecipe初の実用的トピックな気がする)
see http://d.hatena.ne.jp/nishiohirokazu/20110721/1311215412
Macは他所のOSと違って、NFD形式でUnicode文字列を扱うシーンが多い。特にファイル名にNFDを使うので、Macからファイルを持ってきたときに

  • ゆひ? のように、濁音や半濁音がはてなマークになる
  • ゆび の び を消そうとしてバックスペースを押しても ゆひ になる。

のような不思議現象が観察される。
よって、"濁音が分解されちゃった"というのは、文字列がNFD形式になっているということで、これをNFC形式に変換してやるといい。

(define from "\x30b7;\x3099;\x30e3;\x30cf;\x309a;\x30f3;") ;; NFDな"ジャパン"
(define to "\x30b8;\x30e3;\x30d1;\x30f3;") ;; NFCな"ジャパン"

(string=? from to) ;; => #f
(string=? (string-normalize-nfc from) to) ;; => #t

moshR6RSなので、string-normalize-nfcやstring-normalize-nfdが普通に使える。string=?手続きは、見た目が同じ文字列であっても、構成する文字が異なるときは別の文字列とみなす。
(ちなみにこれらのUnicode手続きはR6RS Schemeでは標準に含まれているのでR6RSSchemeならどこでも使える。R7RSではオプションになる見込み。)

Cygwinでは/dev/clipboardデバイスクリップボードの内容になっているので、クリップボードの内容で動作するスクリプトが気軽に書ける。

(import (rnrs) (yuni util files))

(define str (car (file->string-list "/dev/clipboard")))
(put-bytevector (open-file-output-port "/dev/clipboard" (file-options no-fail))
                (string->utf8 (string-normalize-nfd str)))

このスクリプトCygwin上のnmoshで実行すると、クリップボード中のNFC文字列がNFD文字列に変換される。"ジャパン"をクリップボードにコピーしたあと、このスクリプトを走らせて、メモ帳にペーストしてみると、ちゃんと6回backspaceしないと消えないジャパンになる。
他のOSでは地味に難しくて、クリップボードを操作するにはコマンドを呼び出す必要がある(MacOSならpbcopy、Xならxclip等)。