2007/12/30

Common Lisp で OLE ライブラリを作りはじめる

Common Lisp の OLE ライブラリ(Ruby の Win32OLE みたいなの)がなかったので作りはじめてみました。
ここ数日せっせとハックしてます。

自宅には Windows マシンがないので OS インストールからでした。
Linux マシンの qemu/kvm に Vista をインストール。
ついで Cygwin, Meadow, SBCL, SLIME, VS2008C++Express, WIN32SDK をインストール。

そしてようやく開発開始です。
C ではコードを書かず、cffi を使って Lisp のコードだけで作成する方針でいきます。
VARIANT の union にやられながら、とりあず BOOL, BST, IDispatch だけを実装して、次のコードが動くようになりました。
IE でページを表示してタイトルを取得しています。
Excel のサンプルを作りたいところですが、Excel を持っていないので。。。とても古いバージョンがどっかにあったかなぁ。

(let ((ie (create-instance "InternetExplorer.Application")))
(property ie :visible t)
(invoke ie :navigate "http://sbcl.sourceforge.net/")
(loop while (property ie :busy)
do (sleep 0.5))
(let ((document (property ie :document)))
(format t "document title is \"~a\".~%" (property document :title)))
(sleep 3)
(invoke ie :quit))

やっぱり名前は cl-win32ole ですよね。

2007/12/29

バレエ発表会 くるみ割り人形

昨日は娘のバレエ発表会でした。
第1部、第2部とあり。なんと第2部はくるみ割り人形の全幕。
一番驚いたのは小学4年生のレベルが高いこと。なんだかとても綺麗で上手でした。去年はそんな印象はなかったのですが、これは来年、再来年とますます期待できそうです。
うちの娘も1回間違えたものの上手に踊っていました。
表情も一番いい笑顔でしたよ。

2007/12/25

[Common Lisp] iconv をアップデート ver 0.4

iconv のまたバージョンアップしました。
UTF-32 等に変換するとバッファが足りなくなるので、errno E2BIG を見るようにしました。
errno を見る方法ですが、SBCL なら sb-alien:get-errno、CMUCL なら unix:unix-errno、その他なら __errno_location を使うようにしました。
あとは CMUCL、32bit、64bit 環境で動かして見つけた不具合を修正。

2007/12/24

[本] Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp

年末年始のおともに買いました。
amazon.com のレビューで「This book has been called "The best book on programming ever written". 」なんて書かれていましたので。

[Common Lisp] iconv をアップデート

iconv をアップデートしました。バージョン 0.3 です。
変更点は次のとおりです。


  • UFFI をやめて CFFI を使うようにしました。

  • ポータブルな参照方法が見つからなかったので、errno を見るのを止めました。

  • error-p 引数を削除して、返り値の2番目で成功か否かを返すようにしました。

  • from-code と to-code は symbol でも動くようにしました。


ほんとたいしたことのないライブラリなので trivial-iconv とかいう名前にしておけばよかったなぁ。
それはともかく、英語は難しいです。

2007/12/23

[Common Lisp] LTK の味見

Common Lisp の Tk バインディングである LTK をちょっと味見してみました。
CLIM にくらべるとずっと手軽な感じです。
Debian の UTF-8 な環境ですが、日本語の入出力も普通にできました。
最近なんだか Web ばかりですが、GUI のプログラミングも楽しいですね♪

#|
http://www.peter-herth.de/ltk/
(require :asdf-install)
(asdf-install:install :ltk)
|#

(eval-when (:compile-toplevel :load-toplevel :execute)
(require :ltk))

(in-package :ltk)

;;デモ
;;(ltktest)
;;(ltk-eyes)

(defun main ()
(setf *debug-tk* nil)
(with-ltk ()
(let ((btn (make-instance
'button
:text "やあ、LTK♪"
:command (lambda ()
(do-msg "それでは。" "ハローワールド!")
(setf *exit-mainloop* t))))
(txt (make-instance 'text)))
(pack btn)
(pack txt))))

(main)

2007/12/21

再 CLIM(McCLIM) で Hello World! まで

McCLIM の Wiki(McCliki)にある "A Guided Tour of the Common Lisp Interface Manager" を読んでいます。それにのっていた Hello World ですが、"Hello World!" を真ん中に表示するための次のコードがとても気に入りました。
(floor w 2) (floor h 2) :align-x :center :align-y :center
今日はただそれだけです。

(eval-when (:compile-toplevel :load-toplevel :execute)
  (require :mcclim))

(in-package :clim-user)

(define-application-frame hello-world ()
  ((greeting :initform "Hello World!"
  :accessor greeting))
  (:pane (make-pane 'hello-world-pane)))

(defclass hello-world-pane (clim-stream-pane)
  ())

(defmethod handle-repaint ((pane hello-world-pane) region)
  (let ((w (bounding-rectangle-width pane))
  (h (bounding-rectangle-height pane)))
  (draw-rectangle* pane 0 0 w h
  :filled t
  :ink (pane-background pane))
  (draw-text* pane
  (greeting *application-frame*)
  (floor w 2) (floor h 2) :align-x :center :align-y :center)))

(defun run ()
  (run-frame-top-level
  (make-application-frame 'hello-world :width 300 :height 200)))

;;(run)

2007/12/17

Common Lisp で Brainf*ck コンパイラ

どう書く?org の「BFコンパイラー」をやってみました。
Common Lisp での回答はすでに出ていますが、今回はマクロキャラクタを使ってやってみます。
お題は「BFで書かれたソースを、同じ言語に変換するコンパイラー」ですが、マクロキャラクタでリードテーブル(*readtable*)を拡張し言語(Common Lisp)自体が Brainf*ck のソースそのままをロード(load)、コンパイル(compile-file)できるようにします(といっても、セットしたマクロキャラクタにしたがいリーダーが自動的に CL に変換してくれているのですが)。。
SBCL のコンパイラはネイティブコードにコンパイルしてくれるので、Brainf*ck のソースもネイティブコードにコンパイルしている、と言えるのかもしれません;)

(defparameter *memory* nil  "メモリ")

(defparameter *ptr* 0 "ポインタ")

(defun init-bf-env ()
"実行環境の初期化を行います。"
(setf *memory*
(make-array 1 :initial-element 0 :adjustable t :fill-pointer 1)
*ptr* 0))

(define-symbol-macro *-*ptr* (aref *memory* *ptr*))

(defun make-bf-readtable ()
(let ((*readtable* (copy-readtable nil)))
(loop for (char . fun) in
`((#\/ . ,#'(lambda (stream char)
(declare (ignore char))
(do () ((char= (read-char stream nil #\Newline t)
#\Newline)))
(values)))
(#\> . ,#'(lambda (stream char)
(declare (ignore stream char))
`(when (<= (length *memory*) (incf *ptr*))
(vector-push-extend 0 *memory*))))
(#\< . ,#'(lambda (stream char)
(declare (ignore stream char))
`(decf *ptr*)))
(#\+ . ,#'(lambda (stream char)
(declare (ignore stream char))
`(incf *-*ptr*)))
(#\- . ,#'(lambda (stream char)
(declare (ignore stream char))
`(decf *-*ptr*)))
(#\. . ,#'(lambda (stream char)
(declare (ignore stream char))
`(write-char (code-char *-*ptr*))))
(#\, . ,#'(lambda (stream char)
(declare (ignore stream char))
`(setf *-*ptr* (char-code (read-char)))))
(#\[ . ,#'(lambda (stream char)
(declare (ignore char))
`(loop until (zerop *-*ptr*)
do (progn ,@(read-delimited-list #\] stream t))))))
do (set-macro-character char fun))
(set-macro-character #\] (get-macro-character #\)) nil)
*readtable*))

;; テスト。*readtable* を設定して load する。
(let ((*readtable* (make-bf-readtable)))
(init-bf-env) ;実行時には *memory* と *ptr* の初期化が必要
(load #p"hello-world.bf"))

;; もちろんコンパイルもできます。
(let ((*readtable* (make-bf-readtable)))
(compile-file #p"hello-world.bf"))

;; コンパイルしたものを実行。速いです!!
(progn (init-bf-env) ;実行時には *memory* と *ptr* の初期化が必要
(load "hello-world.fasl"))

実行前に (init-bf-env) が必要なのがちょっとわずらわしいですね。
dispatching macro character を使えばそのへんを含めた上で、Common Lisp のソースに Brainf*ck のソースを埋め込む、といったこともできるでしょう。

2007/12/16

Common Lisp で Twitter API をたたいてみる

いまさらながら Twitter を再開しています。
そこで Common Lisp で Twitter API をたたいてみたいと思います。

REST なので Drakma で http-request すればできちゃいます。フォーマットは JSON を指定して、CL-JSON でデコードします。
デコードまでしてしまえば alist のリストが手に入るので、後は煮るなり焼くなり好きなように。なのですが、せっかくの Common Lisp なので無駄に with-selector なんていうマクロを書いて遊んでいます。

次のページを参考にさせていただきました。ありがとうございます。
観測気球さんのTwitter API 仕様書 (勝手に日本語訳シリーズ)
Twitter Development Talk API Documentation

(eval-when (:compile-toplevel :load-toplevel :execute)
(require :drakma)
(require :cl-json))

;; 文字コードは UTF-8 で
(setf drakma:*drakma-default-external-format* :utf-8)

;; ボディを文字列で取得するために、テキストとして判定される Content-Type を追加
(pushnew '("application" . "json") drakma:*text-content-types* :test #'equal)

(defparameter *basic-authorization*
(with-open-file (in (merge-pathnames #p".twitter.lisp" (user-homedir-pathname)))
(read in))
"Basic 認証のパラメータを取得する。~/.twitter.lisp の中身は (\"username\" \"password\")")

(defun public-timeline ()
"public_timeline を取得する。"
(json:decode-json-from-string
(drakma:http-request "http://twitter.com/statuses/public_timeline.json"
:basic-authorization *basic-authorization*)))

(defmacro select (accessor data)
"各フィールドへ assoc でアクセスするマクロ。"
`(reduce #'(lambda (acc key)
`(cdr (assoc ,key ,acc)))
,accessor
:initial-value ,data))

(defmacro with-selector (fields from &body body)
"レスポンスボディの各フィールドへのアクセスマクロ。
(loop for each in (public-timeline)
do (with-selector ((user :user :screen_name)
(text :text))
each
(format t \"~15a ~a~%\" user text)))"

(let ((data (gensym)))
`(let ((,data ,from))
(let ,(mapcar #'(lambda (x)
(list (car x) (select (cdr x) data)))
fields)
,@body))))

;; public_timeline を取ってきてスクリーンネームとテキストを表示する。
(loop for each in (public-timeline)
do (with-selector ((user :user :screen_name)
(text :text))
each
(format t "~15a ~a~%" user text)))

2007/12/12

Common Lisp のシンボルの美しさについて

Common Lisp のシンボル(Symbol)は次の属性を持っています。


  • 名前: symbol-name

  • ホームパッケージ: symbol-package

  • プロパティリスト: symbol-plist

  • 値: symbol-value

  • 関数: symbol-function


(defvar sym 'あたい)

(defun sym ()
'関数)

(setf (get 'sym 'キー1) '値1)

(macrolet ((p (&body body)
`(progn ,@(mapcar #'(lambda (arg)
`(format t "~30a ; => ~a~%" ',arg ,arg))
body))))
(p sym
(sym)
(get 'sym 'キー1)
(symbol-name 'sym)
(symbol-package 'sym)
(symbol-plist 'sym)
(symbol-value 'sym)
(symbol-function 'sym)))

シンボル sym は変数であり関数でありプロパティリストであり、自分の名前とパッケージを知っています。
Common Lisp のシンボルはこのようにきちんとした構造を持った一つのオブジェクトなのです。
そして、Lisp ではこのようなシンボルを変数のように使います。
他の言語の変数は、それ自体では実態がなく、他の何かの参照のようなものです。
しかし Lisp の変数は、シンボルというオブジェクトです。
これは Lisp の美しさの一つだと思います。
他の言語の変数が何か特殊でいびつなもののように思えます。
I love Common Lisp.

FON La Fonera

ずっと FON の La Fonera が安定稼動してくれませんでした。ブチブチ接続が切れてしまうのです。

調べてみました。
FoN まとめ Wiki
「La Foneraでインターネット接続は出来るのですが、2~3分おきに再起動が必要になります」
「10MBイーサネット、半二重設定で使用されている場合に発生する」
とあるのを見ました。これが原因でしょうか?

さっそく、Amazon で PLANEX 5ポート10M/100Mスタンディングスイッチングハブ FX-05ST を購入し、それ経由で La Fonera を繋いでみることにしました。
これで La Fonera は100M接続になるので改善するはずです。

安定稼動しました。
うん、よかった。

2007/12/04

[Common Lisp] マクロを定義するマクロ(Anaphora より)

Anaphora はアナホォリックマクロを集めたライブラリです。
その中でマクロを定義するマクロが使われています。
if や and ごとに直接アナフォリックマクロを定義するのではなく、アナフォリックマクロを定義するマクロ anaphoric を定義した上で、それを利用して if や and のアナフォリックマクロ(aif, aand, etc.)を定義しています。
Lisp ならではの素敵なコードです。

On Lisp でもアナフォリックマクロとマクロを定義するマクロが解説されています。

Anaphora の anaphora.lisp より抜粋です。

(defmacro anaphoric (op test &body body)
`(let ((it ,test))
(,op it ,@body)))

(defmacro aif (test then &optional else)
`(anaphoric if ,test ,then ,else))

(defmacro aand (first &rest rest)
`(anaphoric and ,first ,@rest))

(aif (car '("Hello" "World"))
(format nil "~a World!" it))
;; ==> "Hello World!"

(aand (cdr '(1 2 3)) (cdr it) (cdr it))
;; ==> 3

2007/12/02

[Common Lisp][UCW][Elephant] UCW で作った TODO リストアプリケーションに永続化機能を追加する

以前 CUW で作成した TODO リストアプリケーション は todo オブジェクトをメモリ上に持っているだけでした。
今回は Elephant を使って todo オブジェクトを永続化してみます。
Elephant は Common Lisp のオブジェクトデータベースです。
バックエンドとして Berkeley DB、CL-SQL 経由の PostgreSQL or SQLite3 が使用可能です。Postmodern も使えるようになっているかもしれません。

elephant:open-store でデータストアをオープンします。
バックエンドで Berkeley DB を使う場合は、あらかじめディレクトリを作成しておく必要があります(ensure-directories-exist を使えばいいと思います)。

永続化するクラスは elephant:defpclass で作成します。
クラスオプションの :index に t を指定するとインスタンスは自動的に永続化されます。

elephant:defpclass で作成したクラスはユニークな識別子となる oid スロットを持ちます。

永続化したクラスの全インスタンスを取得するには elephant:get-instances-by-class を使います。

データストアからインスタンスを削除するには elephant:drop-instances を使います。

以下、ソースです。メモリ上にリストで保持していたときよりも少しシンプルになりました。

;; ucw がロードされていなければロードする。
(eval-when (:load-toplevel :compile-toplevel :execute)
(require :elephant) ; Elephant
(unless (find-package :ucw)
;; UCW の start.lisp をロードする。パスは環境にあわせて修正してください。
(load (merge-pathnames "letter/lisp/ucw/ucw-boxset/start.lisp"
(user-homedir-pathname)))))

(in-package :it.bese.ucw-user)

;; Elephant のストアをオープンする。バックエンドは Berkeley DB を使います。
(elephant:open-store `(:BDB ,(ensure-directories-exist #p"/tmp/todo/")))

(defvar *todo-list-application*
(make-instance 'cookie-session-application
:url-prefix "/todo/" ; / で終ること
:charset :utf-8 ; 文字コードを UTF-8 に設定
:debug-on-error t) ; エラー時にはデバッガを起動
"アプリケーションの作成。")

;; アプリケーションをサーバに登録する。
(register-application *default-server* *todo-list-application*)

;; エントリポイントの作成。http://localhost:8080/todo/index.ucw
(defentry-point "index.ucw" (:application *todo-list-application*)
()
(call 'top-window))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; モデル
(elephant:defpclass todo ()
((content :initarg :content :accessor content)
(done :initform nil :accessor done))
(:index t) ; 自動的に永続化されます。
(:documentation "TODO クラス"))

(defmethod print-object ((todo todo) stream)
"debug のために"
(print-unreadable-object (todo stream :type t :identity t)
(format stream "~a: ~a" (elephant::oid todo) (content todo))))

(defun delete-todo (todo)
"TODO を削除します。"
(elephant:drop-instances (list todo)))

(defun get-all-todo ()
(elephant:get-instances-by-class 'todo))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ビュー
(defcomponent top-window (simple-window-component)
((body :initarg :body
:accessor body
:component todo-list-view))
(:default-initargs :title "TODO リスト")
(:documentation "トップウィンドウ。
body に一覧や編集のコンポーネントをセットして画面表示を行う。"
))

(defmethod render ((top top-window))
(<:h1 "TODO リスト")
;; body の表示
(render (body top)))

(defcomponent todo-list-view ()
()
(:documentation "TODO の一覧コンポーネント"))

(defmethod render ((self todo-list-view))
"TODO の一覧を表示する。"
(<ucw:a :action (call 'todo-create-view) "新規作成")
(<:table
:border 1
(<:tr (<:th "完了") (<:th "TODO") (<:th "削除"))
(loop for each in (get-all-todo)
do (let* ((todo each))
(<:tr
(<:td (<:as-html
(if (done todo)
"済"
(<ucw:a
:action (done-todo-action self todo)
"完了する"))))
(<:td (<:as-html (content todo)))
(<:td (<ucw:a :action (delete-todo-action self todo)
"削除する")))))))

(defaction done-todo-action ((self todo-list-view) todo)
"TODO を完了する。"
(setf (done todo) t))

(defaction delete-todo-action ((self todo-list-view) id)
"TODO を1件削除する。"
(delete-todo id))

(defcomponent todo-create-view ()
((content
:accessor content
:initform (make-instance 'string-field)))
(:documentation "TODO を新規作成するためのコンポーネント"))

(defmethod render ((self todo-create-view))
"TODO 新規作成画面"
(<ucw:form
:action (create-todo self)
"TODO" (render (content self))
(<:submit :value "新規作成"))
(<ucw:a :action (ok self) "キャンセル"))

(defaction create-todo ((self todo-create-view))
"画面からの入力により TODO を新規作成する。"
(make-instance 'todo :content (value (content self)))
(ok self))

CLIM(McCLIM) で Hello World! まで

McCLIM とは CLIM(Common Lisp Interface Manager) のオープンソースの実装です。
CLIM はユーザインターフェイスを構築するためのポータブルの機能階層提供する Lisp をベースとしたプログラミングインターフェースです。
具体的にはウィンドウ、グラフィック、ストリーム指向の入出力などの機能を提供します。

では、Hello World! です。

(eval-when (:compile-toplevel :load-toplevel :execute)
(require :clx)
(require :mcclim))

(in-package :clim-user)

(define-application-frame hello-frame ()
()
(:pane (make-pane 'application-pane :display-function #'display-hello ))
(:geometry :width 400 :height 200))

(defmethod display-hello ((hello-frame hello-frame) stream)
(format stream "Hello World!"))

(run-frame-top-level (make-application-frame 'hello-frame))

define-application-frame でトップレベルのウィンドウを定義します。
ウィンドウ内の部品はペイン(pane)と呼ばれ、application-pane を作り、表示関数に format を使って "Hello World!" を表示するメソッドを指定しています。
CLIM では入出力がストリームベースとなっているため、format のような普通の入出力関数をこのようなところで使うことができるようです。

次のようにしてデモを起動することができます。
(eval-when (:compile-toplevel :load-toplevel :execute)
(require :clx)
(require :mcclim)
(require :clim-examples))
(clim-demo::demodemo)

2007/11/25

祖父が他界しました。

94歳でした。
立派な人でした。

2007/11/24

Common Lisp で XML をいじる

Closure XML Parser http://common-lisp.net/project/cxml/ を使って XML をいじってみます。


準備


CVS で最新バージョンを取得します。


cvs -d :pserver:anonymous:anonymous@common-lisp.net:/project/cxml/cvsroot co cxml
cvs -d :pserver:anonymous:anonymous@common-lisp.net:/project/cxml/cvsroot co closure-common

いつもの手順で asdf:*central-registry* に登録します。


Quick Start


まずは require です。


(require :cxml)

お試し用の XML ファイルを作成します。


(with-open-file (out "/tmp/try.xml" :direction :output
:element-type '(unsigned-byte 8)
:if-exists :supersede)
(cxml:with-xml-output
(cxml:make-octet-stream-sink out :indentation 2 :canonical nil)
(cxml:with-element "try"
(cxml:attribute "title" "XML")
(cxml:with-element "para"
(cxml:text "試してみよう。")))))

DOM でいじってみます。


(let* ((builder (cxml-dom:make-dom-builder)) ;DOM ビルダーを作る
(dom (cxml:parse-file "/tmp/try.xml" builder)) ;パースする
(try-element (dom:document-element dom))) ;エレメントを取得
(format t "DOM オブジェクト: ~a~%" dom)
(format t "try タグ(~a)のタグ名: ~a, title属性の値: ~a~%"
try-element
(dom:tag-name try-element) ;タグ名を取得
(dom:get-attribute try-element "title"))) ;属性値を取得

リストでいじってみます。


リストから XML ファイルを出力します。


(with-open-file (out "/tmp/try.xml" :direction :output
:element-type '(unsigned-byte 8)
:if-exists :supersede)
(cxml-xmls:map-node (cxml:make-octet-stream-sink out)
'("try" (("title" "XML")) ("para" nil "リストから出力。"))
:include-namespace-uri nil))

XML から リストを取得します。


(cxml:parse-file "/tmp/try.xml" (cxml-xmls:make-xmls-builder))
;; => ("try" (("title" "XML")) ("para" NIL "リストから出力。"))

給与 話し合いの結果

今月の給与は以前のものに戻っていました。
管理監督者ではなく残業代も支給されるということです。

いまの会社はタイムカードについては管理監督者になったとしてもうたなくてはならないし、毎日の始業・就業時間を記入した勤務表も提出しなければならない、ということでした。
いろいろなっとくいかないような気もしますが、もとの給与体系に戻ったのでよしとしましょう。

2007/11/18

DocBook のメモ

ちょっと DocBook を調べたのでメモしておきます。

参考図書
DocBook: The Definitive Guide
DocBook XSL: The Complete Guide

セットアップ
必要なパッケージ

最低限必要なパッケージはたぶん次のものす。

docbook
docbook-xml
sgml-base
opensp
emacs
psgml

環境変数の設定

文字コードに UTF-8 を使用するので、次のように環境変数をセットしました。

Example 1. 環境変数の設定
export SP_BCTF=utf-8

検証

C-c C-v で onsgmls を使って入力した文章を検証することができます。

Example 2. 検証コマンド
onsgmls -wxml -e -g -s -u /usr/share/sgml/declaration/xml.dcl memo.xml


xmllint というのもあります。

Example 3. xmmlint
xmllint --valid --noout memo.xml

変換

DocBook は xsltproc コマンド等によってスタイルシートに基づいて HTML 等に変化されます。
HTML への変換

DocBook を HTML に変換してみます。
1ファイルの HTML への変換

1ファイルの HTML への変換には html/docbook.xls スタイルシートを使います。

Example 4. 1ファイルの HTML への変換
xsltproc -o dst.html /usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl src.xml


src.xml を -o オプションで指定した dst.html に変換します。
複数ファイルの HTML への変換

複数の HTML に分割して変換するには html/chunk.xsl スタイルシートを使います。出力ファイルは指定しません。デフォルトで index.html がトップページとして出力されます。

Example 5. 複数ファイルの HTML への変換
xsltproc /usr/share/xml/docbook/stylesheet/nwalsh/html/chunk.xsl src.xml


root.filename パラメータでトップページのファイル名を index.html 以外にすることができます。

トップページ以外のファイル名も DocBook 中で明示的に指定したり、id 属性をファイル名にしたり、自動で生成してくれたりします。
その他いろいろ

実にいろいろなことができるみたい。CSS スタイルシートやアイコン。HTML の インデント。エンコーディング指定。などなど。おもしろい。
PDF への変換

PDF への変換でどうしても日本語フォントが表示できないと悩んでいたら、問題は PDF ビューアの方にありました。xpdf, evince ともだめで、Adobe Reader では表示されました。どうやら埋め込みの TrueType フォントを表示できるかどうかとうい問題だったようです。(日本語フォントの設定は Makefile と userconfig.xml を参照)

そうすると、次の問題は埋め込み TrueType フォントではなく Ryumin-Light の Type1 フォントを使う方法ですね。

それにしても、仕上がりはどうしようもなくきたない。いろいろ設定が必要なのかもしれない。日本語の組版に対応していないのかな。Couldn't find hyphenation pattern en というエラーメッセージも出てるし。うぅむ。

Makefile

SRC=memo

XLS=/usr/share/xml/docbook/stylesheet/nwalsh

FOP=fop
#FOP=/home/ancient/tmp/fop-0.94/fop

#JLIB=/usr/share/java

SAZANAMI_GOTHIC=/usr/share/fonts/truetype/sazanami/sazanami-gothic.ttf
SAZANAMI_MINCHO=/usr/share/fonts/truetype/sazanami/sazanami-mincho.ttf

html:
xsltproc -o $(SRC).html $(XLS)/html/docbook.xsl $(SRC).xml
opera $(SRC).html

chunk:
xsltproc $(XLS)/html/chunk.xsl $(SRC).xml
opera index.html

fo:
xsltproc -o $(SRC).fo \
--stringparam body.font.family Mincho \
--stringparam title.font.family Gothic \
$(XLS)/fo/docbook.xsl $(SRC).xml
$(FOP) -c userconfig.xml -fo $(SRC).fo -pdf $(SRC).pdf
acroread $(SRC).pdf

# --stringparam body.start.indent 0pc \

font:
fop-ttfreader $(SAZANAMI_GOTHIC) fonts/sazanami-gothic.xml
fop-ttfreader $(SAZANAMI_MINCHO) fonts/sazanami-mincho.xml

word:
xsltproc -o $(SRC)-word.xml --stringparam wordml.template template.xml $(XLS)/roundtrip/docbook.xsl $(SRC).xml
openoffice $(SRC)-word.xml

clean:
rm -f *.html *~

userconfig.xml
<fop version="1.0">
<renderers>
<renderer mime="application/pdf">
<fonts>
<font metrics-url="file:///home/ancient/letter/docbook/memo/fonts/sazanami-gothic.xml"
kerning="yes"
embed-url="file:///usr/share/fonts/truetype/sazanami/sazanami-gothic.ttf">
<font-triplet name="Gothic" style="normal" weight="normal"/>
<font-triplet name="Gothic" style="normal" weight="bold"/>
<font-triplet name="Gothic" style="italic" weight="normal"/>
<font-triplet name="Gothic" style="italic" weight="bold"/>
</font>
<font metrics-url="file:///home/ancient/letter/docbook/memo/fonts/sazanami-mincho.xml"
kerning="yes"
embed-url="file:///usr/share/fonts/truetype/sazanami/sazanami-mincho.ttf">
<font-triplet name="Mincho" style="normal" weight="normal"/>
<font-triplet name="Mincho" style="normal" weight="bold"/>
<font-triplet name="Mincho" style="italic" weight="normal"/>
<font-triplet name="Mincho" style="italic" weight="bold"/>
</font>
</fonts>
</renderer>
</renderers>
</fop>

memo.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>
<title>DocBook のメモ</title>

<sect1>
<title>セットアップ</title>

<sect2>
<title>必要なパッケージ</title>
<para>最低限必要なパッケージはたぶん次のものす。</para>
<itemizedlist>
<listitem>
<para>docbook</para>
</listitem>
<listitem>
<para>docbook-xml</para>
</listitem>
<listitem>
<para>sgml-base</para>
</listitem>
<listitem>
<para>opensp</para>
</listitem>
<listitem>
<para>emacs</para>
</listitem>
<listitem>
<para>psgml</para>
</listitem>
</itemizedlist>
</sect2>

<sect2>
<title>環境変数の設定</title>
<para>文字コードに UTF-8 を使用するので、次のように環境変数をセットしました。</para>
<example>
<title>環境変数の設定</title>
<programlisting>export SP_BCTF=utf-8</programlisting>
</example>
</sect2>

</sect1>

<sect1>
<title>検証</title>
<para>C-c C-v で onsgmls を使って入力した文章を検証することができます。</para>
<example>
<title>検証コマンド</title>
<programlisting>onsgmls -wxml -e -g -s -u /usr/share/sgml/declaration/xml.dcl memo.xml</programlisting>
</example>
<para>xmllint というのもあります。</para>
<example>
<title>xmmlint</title>
<programlisting>xmllint --valid --noout memo.xml</programlisting>
</example>
</sect1>

<sect1>
<title>変換</title>

<para>DocBook は xsltproc コマンド等によってスタイルシートに基づいて HTML 等に変化されます。</para>

<sect2>
<title>HTML への変換</title>
<para>DocBook を HTML に変換してみます。</para>


<sect3>
<title>1ファイルの HTML への変換</title>
<para>1ファイルの HTML への変換には html/docbook.xls スタイルシートを使います。</para>
<example>
<title>1ファイルの HTML への変換</title>
<programlisting>xsltproc -o dst.html /usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl src.xml</programlisting>
</example>
<para>src.xml を -o オプションで指定した dst.html に変換します。</para>
</sect3>

<sect3>
<title>複数ファイルの HTML への変換</title>
<para>複数の HTML に分割して変換するには html/chunk.xsl スタイルシートを使います。出力ファイルは指定しません。デフォルトで index.html がトップページとして出力されます。</para>
<example>
<title>複数ファイルの HTML への変換</title>
<programlisting>xsltproc /usr/share/xml/docbook/stylesheet/nwalsh/html/chunk.xsl src.xml</programlisting>
</example>
<para>root.filename パラメータでトップページのファイル名を index.html 以外にすることができます。</para>
<para>トップページ以外のファイル名も DocBook 中で明示的に指定したり、id 属性をファイル名にしたり、自動で生成してくれたりします。</para>
</sect3>

<sect3>
<title>その他いろいろ</title>
<para>実にいろいろなことができるみたい。CSS スタイルシートやアイコン。HTML の インデント。エンコーディング指定。などなど。おもしろい。</para>
</sect3>

</sect2>


<sect2>
<title>PDF への変換</title>

<para>PDF への変換でどうしても日本語フォントが表示できないと悩んでいたら、問題は PDF ビューアの方にありました。xpdf, evince ともだめで、Adobe Reader では表示されました。どうやら埋め込みの TrueType フォントを表示できるかどうかとうい問題だったようです。</para>

<para>そうすると、次の問題は埋め込み TrueType フォントではなく Ryumin-Light の Type1 フォントを使う方法ですね。</para>

<para>それにしても、仕上がりはどうしようもなくきたない。いろいろ設定が必要なのかもしれない。日本語の組版に対応していないのかな。Couldn't find hyphenation pattern en というエラーメッセージも出てるし。うぅむ。</para>
</sect2>
</sect1>
</article>

2007/11/17

クエックブックを Muse で書くようにする

いままで HTML で書いていたクエックブックを Muse で書くようにしました。
<contents> で Table Of Contents を自動的に作ってくれるとこと、<src lang="lisp"> で自動的の強調表示してくれるところが気にいっています。
src タグでの強調表示は Emacs のメジャーモードを lang 属性に指定することによって、Htmlize 機能を使って強調表示してくれます。なので、Emacs のメジャーモードのある言語なら全て強調表示ができます。
それに、Muse のファイル自体読みやすく書きやすい。
ただ処理速度が遅いのがちょっと気になりました。Erlang の方を HTML に変換するには少々時間が必要です。

DocBook もどうかなぁと思っていじってみましたが、S式好きにはどうも XML は耐えられないようです。

2007/11/13

[Common Lisp] たまには何か書かないと

ここのところ全然 Lisp をさわってなかったので、何でもいいから書きたくなりました。
それで書いたのが次のコード。
series を使って、/tmp/a 内容を /tmp/b に行番号付きで出力するだけです。
scan-file, collect-file では external-format や if-exists の指定ができないため、scan-stream, collect-stream を使っています。

(eval-when (:compile-toplevel :load-toplevel :execute)
(require :series))

(with-open-file (in "/tmp/a")
(with-open-file (out "/tmp/b" :direction :output :if-exists :supersede)
(let ((no (series:generator (series:scan-range :from 1))))
(series:collect-stream
out (series:scan-stream in #'read-line)
#'(lambda (line stream)
(format stream "~a ~a~%" (series:next-in no) line))))))

scan-file, collect-file を使うとこんな感じです。
(let ((no (series:generator (series:scan-range :from 1))))
(series:collect-file
"/tmp/c" (series:scan-file "/tmp/a" #'read-line)
#'(lambda (line stream)
(format stream "~a ~a~%" (series:next-in no) line))))

やっぱり Common Lisp は楽しい♪

2007/11/11

~/.uim

私が Debian 環境で使っている日本語入力 uim のローマ字入力のカスタマイズです。
下記のような ~/.uim を作成してカスタマイズしています。
変数 ja-rk-rule で設定しますが、最初に (require "japanese.scm") が必要です。
Dvorak 配列を使用しているので、ACTJLOD配列 を基にした配列になっています。

;;;-*- scheme -*-

(require "japanese.scm")

;; Japanese EUC
(set! ja-rk-rule
'(
((("-"). ())("ー" "ー" "ー"))
(((","). ())("、" "、" "、"))
((("."). ())("。" "。" "。"))
((("!"). ())("!" "!" "!"))
((("\""). ())("”" "”" "\""))
;;((("#"). ())("#" "#" "#"))
;;((("$"). ())("$" "$" "$"))
;;((("%"). ())("%" "%" "%"))
;;((("&"). ())("&" "&" "&"))
;;((("'"). ())("’" "’" "'"))
((("("). ())("(" "(" "("))
(((")"). ())(")" ")" ")"))
;;((("~"). ())("〜" "〜" "~"))
;;((("="). ())("=" "=" "="))
;;((("^"). ())("^" "^" "^"))
;;((("\\"). ())("\" "\" "\\"))
;;((("|"). ())("|" "|" "|"))
;;((("`"). ())("‘" "‘" "`"))
;;((("@"). ())("@" "@" "@"))
;;((("{"). ())("{" "{" "{"))
((("["). ())("「" "「" "「"))
;;((("+"). ())("+" "+" "+"))
;;(((";"). ())(";" ";" ";"))
;;((("*"). ())("*" "*" "*"))
;;(((":"). ())(":" ":" ":"))
;;((("}"). ())("}" "}" "}"))
((("]"). ())("」" "」" "」"))
;;((("<"). ())("<" "<" "<"))
;;(((">"). ())(">" ">" ">"))
((("?"). ())("?" "?" "?"))
;;((("/"). ())("/" "/" "/"))
;;((("_"). ())("_" "_" "_"))
((("yen"). ())("¥" "¥" "¥")) ;; XXX

((("1"). ())("1" "1" "1"))
((("2"). ())("2" "2" "2"))
((("3"). ())("3" "3" "3"))
((("4"). ())("4" "4" "4"))
((("5"). ())("5" "5" "5"))
((("6"). ())("6" "6" "6"))
((("7"). ())("7" "7" "7"))
((("8"). ())("8" "8" "8"))
((("9"). ())("9" "9" "9"))
((("0"). ())("0" "0" "0"))

((("a"). ())("あ" "ア" "ア"))
((("i"). ())("い" "イ" "イ"))
((("u"). ())("う" "ウ" "ウ"))
((("e"). ())("え" "エ" "エ"))
((("o"). ())("お" "オ" "オ"))

((("x" "a"). ())("ぁ" "ァ" "ァ"))
((("x" "i"). ())("ぃ" "ィ" "ィ"))
((("x" "y" "i"). ())("ぃ" "ィ" "ィ"))
((("x" "u"). ())("ぅ" "ゥ" "ゥ"))
((("x" "e"). ())("ぇ" "ェ" "ェ"))
((("x" "y" "e"). ())("ぇ" "ェ" "ェ"))
((("x" "o"). ())("ぉ" "ォ" "ォ"))

((("c" "c"). ("c"))("っ" "ッ" "ッ"))

((("c" "a"). ())("か" "カ" "カ"))
((("c" "i"). ())("き" "キ" "キ"))
((("c" "u"). ())("く" "ク" "ク"))
((("c" "e"). ())("け" "ケ" "ケ"))
((("c" "o"). ())("こ" "コ" "コ"))
((("c" "'"). ())(("か" "カ" "カ") ("い" "イ" "イ")))
((("c" "("). ())(("こ" "コ" "コ") ("う" "ウ" "ウ")))
((("c" ")"). ())(("け" "ケ" "ケ") ("い" "イ" "イ")))
((("c" "p"). ())(("く" "ク" "ク") ("う" "ウ" "ウ")))
((("c" "y"). ())(("き" "キ" "キ") ("い" "イ" "イ")))
((("c" ";"). ())(("か" "カ" "カ") ("ん" "ン" "ン")))
((("c" "q"). ())(("こ" "コ" "コ") ("ん" "ン" "ン")))
((("c" "j"). ())(("け" "ケ" "ケ") ("ん" "ン" "ン")))
((("c" "k"). ())(("く" "ク" "ク") ("ん" "ン" "ン")))
((("c" "x"). ())(("き" "キ" "キ") ("ん" "ン" "ン")))
((("c" "h" "a"). ())(("き" "キ" "キ") ("ゃ" "ャ" "ャ")))
((("c" "h" "i"). ())(("き" "キ" "キ") ("ぃ" "ィ" "ィ")))
((("c" "h" "u"). ())(("き" "キ" "キ") ("ゅ" "ュ" "ュ")))
((("c" "h" "e"). ())(("き" "キ" "キ") ("ぇ" "ェ" "ェ")))
((("c" "h" "o"). ())(("き" "キ" "キ") ("ょ" "ョ" "ョ")))
((("c" "h" "'"). ())(("き" "キ" "キ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("c" "h" "y"). ())(("き" "キ" "キ") ("ぃ" "ィ" "ィ") ("う" "ウ" "ウ")))
((("c" "h" "p"). ())(("き" "キ" "キ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("c" "h" ")"). ())(("き" "キ" "キ") ("ぇ" "ェ" "ェ") ("う" "ウ" "ウ")))
((("c" "h" "("). ())(("き" "キ" "キ") ("ょ" "ョ" "ョ") ("い" "イ" "イ")))
((("c" "h" ";"). ())(("き" "キ" "キ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("c" "h" "x"). ())(("き" "キ" "キ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("c" "h" "k"). ())(("き" "キ" "キ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("c" "h" "j"). ())(("き" "キ" "キ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("c" "h" "q"). ())(("き" "キ" "キ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("g" "g"). ("g"))("っ" "ッ" "ッ"))

((("g" "a"). ())("が" "ガ" "ガ"))
((("g" "i"). ())("ぎ" "ギ" "ギ"))
((("g" "u"). ())("ぐ" "グ" "グ"))
((("g" "e"). ())("げ" "ゲ" "ゲ"))
((("g" "o"). ())("ご" "ゴ" "ゴ"))
((("g" "'"). ())(("が" "ガ" "ガ") ("い" "イ" "イ")))
((("g" "y"). ())(("ぐ" "グ" "グ") ("い" "イ" "イ")))
((("g" "p"). ())(("ぐ" "グ" "グ") ("う" "ウ" "ウ")))
((("g" ")"). ())(("げ" "ゲ" "ゲ") ("い" "イ" "イ")))
((("g" "("). ())(("ご" "ゴ" "ゴ") ("う" "ウ" "ウ")))
((("g" ";"). ())(("が" "ガ" "ガ") ("ん" "ン" "ン")))
((("g" "x"). ())(("ぎ" "ギ" "ギ") ("ん" "ン" "ン")))
((("g" "k"). ())(("ぐ" "グ" "グ") ("ん" "ン" "ン")))
((("g" "j"). ())(("げ" "ゲ" "ゲ") ("ん" "ン" "ン")))
((("g" "q"). ())(("ご" "ゴ" "ゴ") ("ん" "ン" "ン")))
((("g" "n" "a"). ())(("ぎ" "ギ" "ギ") ("ゃ" "ャ" "ャ")))
((("g" "n" "i"). ())(("ぎ" "ギ" "ギ") ("ぃ" "ィ" "ィ")))
((("g" "n" "u"). ())(("ぎ" "ギ" "ギ") ("ゅ" "ュ" "ュ")))
((("g" "n" "e"). ())(("ぎ" "ギ" "ギ") ("ぇ" "ェ" "ェ")))
((("g" "n" "o"). ())(("ぎ" "ギ" "ギ") ("ょ" "ョ" "ョ")))
((("g" "n" "'"). ())(("ぎ" "ギ" "ギ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("g" "n" "y"). ())(("ぎ" "ギ" "ギ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("g" "n" "p"). ())(("ぎ" "ギ" "ギ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("g" "n" ")"). ())(("ぎ" "ギ" "ギ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("g" "n" "("). ())(("ぎ" "ギ" "ギ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("g" "n" ";"). ())(("ぎ" "ギ" "ギ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("g" "n" "x"). ())(("ぎ" "ギ" "ギ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("g" "n" "k"). ())(("ぎ" "ギ" "ギ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("g" "n" "j"). ())(("ぎ" "ギ" "ギ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("g" "n" "q"). ())(("ぎ" "ギ" "ギ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("s" "s"). ("s"))("っ" "ッ" "ッ"))

((("s" "a"). ())("さ" "サ" "サ"))
((("s" "i"). ())("し" "シ" "シ"))
((("s" "u"). ())("す" "ス" "ス"))
((("s" "e"). ())("せ" "セ" "セ"))
((("s" "o"). ())("そ" "ソ" "ソ"))
((("s" "'"). ())(("さ" "サ" "サ") ("い" "イ" "イ")))
((("s" "y"). ())(("す" "ス" "ス") ("い" "イ" "イ")))
((("s" "p"). ())(("す" "ス" "ス") ("う" "ウ" "ウ")))
((("s" ")"). ())(("せ" "セ" "セ") ("い" "イ" "イ")))
((("s" "("). ())(("そ" "ソ" "ソ") ("う" "ウ" "ウ")))
((("s" ";"). ())(("さ" "サ" "サ") ("ん" "ン" "ン")))
((("s" "x"). ())(("し" "シ" "シ") ("ん" "ン" "ン")))
((("s" "k"). ())(("す" "ス" "ス") ("ん" "ン" "ン")))
((("s" "j"). ())(("せ" "セ" "セ") ("ん" "ン" "ン")))
((("s" "q"). ())(("そ" "ソ" "ソ") ("ん" "ン" "ン")))

((("s" "h" "a"). ())(("し" "シ" "シ") ("ゃ" "ャ" "ャ")))
((("s" "h" "i"). ())(("し" "シ" "シ") ("ぃ" "ィ" "ィ")))
((("s" "h" "u"). ())(("し" "シ" "シ") ("ゅ" "ュ" "ュ")))
((("s" "h" "e"). ())(("し" "シ" "シ") ("ぇ" "ェ" "ェ")))
((("s" "h" "o"). ())(("し" "シ" "シ") ("ょ" "ョ" "ョ")))
((("s" "h" "'"). ())(("し" "シ" "シ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("s" "h" "y"). ())(("し" "シ" "シ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("s" "h" "p"). ())(("し" "シ" "シ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("s" "h" ")"). ())(("し" "シ" "シ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("s" "h" "("). ())(("し" "シ" "シ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("s" "h" ";"). ())(("し" "シ" "シ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("s" "h" "x"). ())(("し" "シ" "シ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("s" "h" "k"). ())(("し" "シ" "シ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("s" "h" "j"). ())(("し" "シ" "シ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("s" "h" "q"). ())(("し" "シ" "シ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("z" "z"). ("z"))("っ" "ッ" "ッ"))

((("z" "a"). ())("ざ" "ザ" "ザ"))
((("z" "i"). ())("じ" "ジ" "ジ"))
((("z" "u"). ())("ず" "ズ" "ズ"))
((("z" "e"). ())("ぜ" "ゼ" "ゼ"))
((("z" "o"). ())("ぞ" "ゾ" "ゾ"))
((("z" "'"). ())(("ざ" "ザ" "ザ") ("い" "イ" "イ")))
((("z" "y"). ())(("ず" "ズ" "ズ") ("い" "イ" "イ")))
((("z" "p"). ())(("ず" "ズ" "ズ") ("う" "ウ" "ウ")))
((("z" ")"). ())(("ぜ" "ゼ" "ゼ") ("い" "イ" "イ")))
((("z" "("). ())(("ぞ" "ゾ" "ゾ") ("う" "ウ" "ウ")))
((("z" ";"). ())(("ざ" "ザ" "ザ") ("ん" "ン" "ン")))
((("z" "x"). ())(("じ" "ジ" "ジ") ("ん" "ン" "ン")))
((("z" "k"). ())(("ず" "ズ" "ズ") ("ん" "ン" "ン")))
((("z" "j"). ())(("ぜ" "ゼ" "ゼ") ("ん" "ン" "ン")))
((("z" "q"). ())(("ぞ" "ゾ" "ゾ") ("ん" "ン" "ン")))
((("z" "h" "a"). ())(("じ" "ジ" "ジ") ("ゃ" "ャ" "ャ")))
((("z" "h" "i"). ())(("じ" "ジ" "ジ") ("ぃ" "ィ" "ィ")))
((("z" "h" "u"). ())(("じ" "ジ" "ジ") ("ゅ" "ュ" "ュ")))
((("z" "h" "e"). ())(("じ" "ジ" "ジ") ("ぇ" "ェ" "ェ")))
((("z" "h" "o"). ())(("じ" "ジ" "ジ") ("ょ" "ョ" "ョ")))
((("z" "h" "'"). ())(("じ" "ジ" "ジ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("z" "h" "y"). ())(("じ" "ジ" "ジ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("z" "h" "p"). ())(("じ" "ジ" "ジ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("z" "h" ")"). ())(("じ" "ジ" "ジ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("z" "h" "("). ())(("じ" "ジ" "ジ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("z" "h" ";"). ())(("じ" "ジ" "ジ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("z" "h" "x"). ())(("じ" "ジ" "ジ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("z" "h" "k"). ())(("じ" "ジ" "ジ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("z" "h" "j"). ())(("じ" "ジ" "ジ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("z" "h" "q"). ())(("じ" "ジ" "ジ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("t" "t"). ("t"))("っ" "ッ" "ッ"))

((("t" "a"). ())("た" "タ" "タ"))
((("t" "i"). ())("ち" "チ" "チ"))
((("t" "u"). ())("つ" "ツ" "ツ"))
((("t" "e"). ())("て" "テ" "テ"))
((("t" "o"). ())("と" "ト" "ト"))
((("t" "'"). ())(("た" "タ" "タ") ("い" "イ" "イ")))
((("t" "y"). ())(("つ" "ツ" "ツ") ("い" "イ" "イ")))
((("t" "p"). ())(("つ" "ツ" "ツ") ("う" "ウ" "ウ")))
((("t" ")"). ())(("て" "テ" "テ") ("い" "イ" "イ")))
((("t" "("). ())(("と" "ト" "ト") ("う" "ウ" "ウ")))
((("t" ";"). ())(("た" "タ" "タ") ("ん" "ン" "ン")))
((("t" "x"). ())(("ち" "チ" "チ") ("ん" "ン" "ン")))
((("t" "k"). ())(("つ" "ツ" "ツ") ("ん" "ン" "ン")))
((("t" "j"). ())(("て" "テ" "テ") ("ん" "ン" "ン")))
((("t" "q"). ())(("と" "ト" "ト") ("ん" "ン" "ン")))

((("t" "h" "a"). ())(("ち" "チ" "チ") ("ゃ" "ャ" "ャ")))
((("t" "h" "i"). ())(("ち" "チ" "チ") ("ぃ" "ィ" "ィ")))
((("t" "h" "u"). ())(("ち" "チ" "チ") ("ゅ" "ュ" "ュ")))
((("t" "h" "e"). ())(("ち" "チ" "チ") ("ぇ" "ェ" "ェ")))
((("t" "h" "o"). ())(("ち" "チ" "チ") ("ょ" "ョ" "ョ")))
((("t" "h" "'"). ())(("ち" "チ" "チ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("t" "h" "y"). ())(("ち" "チ" "チ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("t" "h" "p"). ())(("ち" "チ" "チ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("t" "h" ")"). ())(("ち" "チ" "チ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("t" "h" "("). ())(("ち" "チ" "チ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("t" "h" ";"). ())(("ち" "チ" "チ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("t" "h" "x"). ())(("ち" "チ" "チ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("t" "h" "k"). ())(("ち" "チ" "チ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("t" "h" "j"). ())(("ち" "チ" "チ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("t" "h" "q"). ())(("ち" "チ" "チ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("t" "s" "a"). ())(("つ" "ツ" "ツ") ("ぁ" "ァ" "ァ")))
((("t" "s" "i"). ())(("つ" "ツ" "ツ") ("ぃ" "ィ" "ィ")))
((("t" "s" "u"). ())("つ" "ツ" "ツ"))
((("t" "s" "e"). ())(("つ" "ツ" "ツ") ("ぇ" "ェ" "ェ")))
((("t" "s" "o"). ())(("つ" "ツ" "ツ") ("ぉ" "ォ" "ォ")))

((("x" "t" "u"). ())("っ" "ッ" "ッ"))
((("x" "t" "s" "u"). ())("っ" "ッ" "ッ"))

((("d" "a"). ())("だ" "ダ" "ダ"))
((("d" "i"). ())("ぢ" "ヂ" "ヂ"))
((("d" "u"). ())("づ" "ヅ" "ヅ"))
((("d" "e"). ())("で" "デ" "デ"))
((("d" "o"). ())("ど" "ド" "ド"))
((("d" "'"). ())(("だ" "ダ" "ダ") ("い" "イ" "イ")))
((("d" "y"). ())(("づ" "ヅ" "ヅ") ("い" "イ" "イ")))
((("d" "p"). ())(("づ" "ヅ" "ヅ") ("う" "ウ" "ウ")))
((("d" ")"). ())(("で" "デ" "デ") ("い" "イ" "イ")))
((("d" "("). ())(("ど" "ド" "ド") ("う" "ウ" "ウ")))
((("d" ";"). ())(("だ" "ダ" "ダ") ("ん" "ン" "ン")))
((("d" "x"). ())(("ぢ" "ヂ" "ヂ") ("ん" "ン" "ン")))
((("d" "k"). ())(("づ" "ヅ" "ヅ") ("ん" "ン" "ン")))
((("d" "j"). ())(("で" "デ" "デ") ("ん" "ン" "ン")))
((("d" "q"). ())(("ど" "ド" "ド") ("ん" "ン" "ン")))

((("d" "h" "a"). ())(("ぢ" "ヂ" "ヂ") ("ゃ" "ャ" "ャ")))
((("d" "h" "i"). ())(("ぢ" "ヂ" "ヂ") ("ぃ" "ィ" "ィ")))
((("d" "h" "u"). ())(("ぢ" "ヂ" "ヂ") ("ゅ" "ュ" "ュ")))
((("d" "h" "e"). ())(("ぢ" "ヂ" "ヂ") ("ぇ" "ェ" "ェ")))
((("d" "h" "o"). ())(("ぢ" "ヂ" "ヂ") ("ょ" "ョ" "ョ")))
((("d" "h" "'"). ())(("ぢ" "ヂ" "ヂ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("d" "h" "y"). ())(("ぢ" "ヂ" "ヂ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("d" "h" "p"). ())(("ぢ" "ヂ" "ヂ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("d" "h" ")"). ())(("ぢ" "ヂ" "ヂ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("d" "h" "("). ())(("ぢ" "ヂ" "ヂ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("d" "h" ";"). ())(("ぢ" "ヂ" "ヂ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("d" "h" "x"). ())(("ぢ" "ヂ" "ヂ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("d" "h" "k"). ())(("ぢ" "ヂ" "ヂ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("d" "h" "j"). ())(("ぢ" "ヂ" "ヂ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("d" "h" "q"). ())(("ぢ" "ヂ" "ヂ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("n" "n"). ())("ん" "ン" "ン"))
((("n"). ())("ん" "ン" "ン"))

((("n" "a"). ())("な" "ナ" "ナ"))
((("n" "i"). ())("に" "ニ" "ニ"))
((("n" "u"). ())("ぬ" "ヌ" "ヌ"))
((("n" "e"). ())("ね" "ネ" "ネ"))
((("n" "o"). ())("の" "ノ" "ノ"))
((("n" "'"). ())(("な" "ナ" "ナ") ("い" "イ" "イ")))
((("n" "y"). ())(("ぬ" "ヌ" "ヌ") ("い" "イ" "イ")))
((("n" "p"). ())(("ぬ" "ヌ" "ヌ") ("う" "ウ" "ウ")))
((("n" ")"). ())(("ね" "ネ" "ネ") ("い" "イ" "イ")))
((("n" "("). ())(("の" "ノ" "ノ") ("う" "ウ" "ウ")))
((("n" ";"). ())(("な" "ナ" "ナ") ("ん" "ン" "ン")))
((("n" "x"). ())(("に" "ニ" "ニ") ("ん" "ン" "ン")))
((("n" "k"). ())(("ぬ" "ヌ" "ヌ") ("ん" "ン" "ン")))
((("n" "j"). ())(("ね" "ネ" "ネ") ("ん" "ン" "ン")))
((("n" "q"). ())(("の" "ノ" "ノ") ("ん" "ン" "ン")))

((("n" "h" "a"). ())(("に" "ニ" "ニ") ("ゃ" "ャ" "ャ")))
((("n" "h" "i"). ())(("に" "ニ" "ニ") ("ぃ" "ィ" "ィ")))
((("n" "h" "u"). ())(("に" "ニ" "ニ") ("ゅ" "ュ" "ュ")))
((("n" "h" "e"). ())(("に" "ニ" "ニ") ("ぇ" "ェ" "ェ")))
((("n" "h" "o"). ())(("に" "ニ" "ニ") ("ょ" "ョ" "ョ")))
((("n" "h" "'"). ())(("に" "ニ" "ニ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("n" "h" "y"). ())(("に" "ニ" "ニ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("n" "h" "p"). ())(("に" "ニ" "ニ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("n" "h" ")"). ())(("に" "ニ" "ニ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("n" "h" "("). ())(("に" "ニ" "ニ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("n" "h" ";"). ())(("に" "ニ" "ニ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("n" "h" "x"). ())(("に" "ニ" "ニ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("n" "h" "k"). ())(("に" "ニ" "ニ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("n" "h" "j"). ())(("に" "ニ" "ニ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("n" "h" "q"). ())(("に" "ニ" "ニ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("h" "h"). ("h"))("っ" "ッ" "ッ"))

((("h" "a"). ())("は" "ハ" "ハ"))
((("h" "i"). ())("ひ" "ヒ" "ヒ"))
((("h" "u"). ())("ふ" "フ" "フ"))
((("h" "e"). ())("へ" "ヘ" "ヘ"))
((("h" "o"). ())("ほ" "ホ" "ホ"))
((("h" "'"). ())(("は" "ハ" "ハ") ("い" "イ" "イ")))
((("h" "y"). ())(("ふ" "フ" "フ") ("い" "イ" "イ")))
((("h" "p"). ())(("ふ" "フ" "フ") ("う" "ウ" "ウ")))
((("h" ")"). ())(("へ" "ヘ" "ヘ") ("い" "イ" "イ")))
((("h" "("). ())(("ほ" "ホ" "ホ") ("う" "ウ" "ウ")))
((("h" ";"). ())(("は" "ハ" "ハ") ("ん" "ン" "ン")))
((("h" "x"). ())(("ひ" "ヒ" "ヒ") ("ん" "ン" "ン")))
((("h" "k"). ())(("ふ" "フ" "フ") ("ん" "ン" "ン")))
((("h" "j"). ())(("へ" "ヘ" "ヘ") ("ん" "ン" "ン")))
((("h" "q"). ())(("ほ" "ホ" "ホ") ("ん" "ン" "ン")))

((("h" "n" "a"). ())(("ひ" "ヒ" "ヒ") ("ゃ" "ャ" "ャ")))
((("h" "n" "i"). ())(("ひ" "ヒ" "ヒ") ("ぃ" "ィ" "ィ")))
((("h" "n" "u"). ())(("ひ" "ヒ" "ヒ") ("ゅ" "ュ" "ュ")))
((("h" "n" "e"). ())(("ひ" "ヒ" "ヒ") ("ぇ" "ェ" "ェ")))
((("h" "n" "o"). ())(("ひ" "ヒ" "ヒ") ("ょ" "ョ" "ョ")))
((("h" "n" "'"). ())(("ひ" "ヒ" "ヒ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("h" "n" "y"). ())(("ひ" "ヒ" "ヒ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("h" "n" "p"). ())(("ひ" "ヒ" "ヒ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("h" "n" ")"). ())(("ひ" "ヒ" "ヒ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("h" "n" "("). ())(("ひ" "ヒ" "ヒ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("h" "n" ";"). ())(("ひ" "ヒ" "ヒ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("h" "n" "x"). ())(("ひ" "ヒ" "ヒ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("h" "n" "k"). ())(("ひ" "ヒ" "ヒ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("h" "n" "j"). ())(("ひ" "ヒ" "ヒ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("h" "n" "q"). ())(("ひ" "ヒ" "ヒ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("b" "b"). ("b"))("っ" "ッ" "ッ"))

((("b" "a"). ())("ば" "バ" "バ"))
((("b" "i"). ())("び" "ビ" "ビ"))
((("b" "u"). ())("ぶ" "ブ" "ブ"))
((("b" "e"). ())("べ" "ベ" "ベ"))
((("b" "o"). ())("ぼ" "ボ" "ボ"))
((("b" "'"). ())(("ば" "バ" "バ") ("い" "イ" "イ")))
((("b" "y"). ())(("ぶ" "ブ" "ブ") ("い" "イ" "イ")))
((("b" "p"). ())(("ぶ" "ブ" "ブ") ("う" "ウ" "ウ")))
((("b" ")"). ())(("べ" "ベ" "ベ") ("い" "イ" "イ")))
((("b" "("). ())(("ぼ" "ボ" "ボ") ("う" "ウ" "ウ")))
((("b" ";"). ())(("ば" "バ" "バ") ("ん" "ン" "ン")))
((("b" "x"). ())(("び" "ビ" "ビ") ("ん" "ン" "ン")))
((("b" "k"). ())(("ぶ" "ブ" "ブ") ("ん" "ン" "ン")))
((("b" "j"). ())(("べ" "ベ" "ベ") ("ん" "ン" "ン")))
((("b" "q"). ())(("ぼ" "ボ" "ボ") ("ん" "ン" "ン")))

((("b" "n" "a"). ())(("び" "ビ" "ビ") ("ゃ" "ャ" "ャ")))
((("b" "n" "i"). ())(("び" "ビ" "ビ") ("ぃ" "ィ" "ィ")))
((("b" "n" "u"). ())(("び" "ビ" "ビ") ("ゅ" "ュ" "ュ")))
((("b" "n" "e"). ())(("び" "ビ" "ビ") ("ぇ" "ェ" "ェ")))
((("b" "n" "o"). ())(("び" "ビ" "ビ") ("ょ" "ョ" "ョ")))
((("b" "n" "'"). ())(("び" "ビ" "ビ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("b" "n" "y"). ())(("び" "ビ" "ビ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("b" "n" "p"). ())(("び" "ビ" "ビ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("b" "n" ")"). ())(("び" "ビ" "ビ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("b" "n" "("). ())(("び" "ビ" "ビ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("b" "n" ";"). ())(("び" "ビ" "ビ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("b" "n" "x"). ())(("び" "ビ" "ビ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("b" "n" "k"). ())(("び" "ビ" "ビ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("b" "n" "j"). ())(("び" "ビ" "ビ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("b" "n" "q"). ())(("び" "ビ" "ビ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("f" "f"). ("f"))("っ" "ッ" "ッ"))

((("f" "a"). ())("ぱ" "パ" "パ"))
((("f" "i"). ())("ぴ" "ピ" "ピ"))
((("f" "u"). ())("ぷ" "プ" "プ"))
((("f" "e"). ())("ぺ" "ペ" "ペ"))
((("f" "o"). ())("ぽ" "ポ" "ポ"))
((("f" "'"). ())(("ぱ" "パ" "パ") ("い" "イ" "イ")))
((("f" "y"). ())(("ぷ" "プ" "プ") ("い" "イ" "イ")))
((("f" "p"). ())(("ぷ" "プ" "プ") ("う" "ウ" "ウ")))
((("f" ")"). ())(("ぺ" "ペ" "ペ") ("い" "イ" "イ")))
((("f" "("). ())(("ぽ" "ポ" "ポ") ("う" "ウ" "ウ")))
((("f" ";"). ())(("ぱ" "パ" "パ") ("ん" "ン" "ン")))
((("f" "x"). ())(("ぴ" "ピ" "ピ") ("ん" "ン" "ン")))
((("f" "k"). ())(("ぷ" "プ" "プ") ("ん" "ン" "ン")))
((("f" "j"). ())(("ぺ" "ペ" "ペ") ("ん" "ン" "ン")))
((("f" "q"). ())(("ぽ" "ポ" "ポ") ("ん" "ン" "ン")))

((("f" "n" "a"). ())(("ぴ" "ピ" "ピ") ("ゃ" "ャ" "ャ")))
((("f" "n" "i"). ())(("ぴ" "ピ" "ピ") ("ぃ" "ィ" "ィ")))
((("f" "n" "u"). ())(("ぴ" "ピ" "ピ") ("ゅ" "ュ" "ュ")))
((("f" "n" "e"). ())(("ぴ" "ピ" "ピ") ("ぇ" "ェ" "ェ")))
((("f" "n" "o"). ())(("ぴ" "ピ" "ピ") ("ょ" "ョ" "ョ")))
((("f" "n" "'"). ())(("ぴ" "ピ" "ピ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("f" "n" "y"). ())(("ぴ" "ピ" "ピ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("f" "n" "p"). ())(("ぴ" "ピ" "ピ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("f" "n" ")"). ())(("ぴ" "ピ" "ピ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("f" "n" "("). ())(("ぴ" "ピ" "ピ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("f" "n" ";"). ())(("ぴ" "ピ" "ピ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("f" "n" "x"). ())(("ぴ" "ピ" "ピ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("f" "n" "k"). ())(("ぴ" "ピ" "ピ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("f" "n" "j"). ())(("ぴ" "ピ" "ピ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("f" "n" "q"). ())(("ぴ" "ピ" "ピ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("m" "m"). ("m"))("っ" "ッ" "ッ"))

((("m" "b"). ("b"))("ん" "ン" "ン"))
((("m" "p"). ("p"))("ん" "ン" "ン"))

((("m" "a"). ())("ま" "マ" "マ"))
((("m" "i"). ())("み" "ミ" "ミ"))
((("m" "u"). ())("む" "ム" "ム"))
((("m" "e"). ())("め" "メ" "メ"))
((("m" "o"). ())("も" "モ" "モ"))
((("m" "'"). ())(("ま" "マ" "マ") ("い" "イ" "イ")))
((("m" "y"). ())(("む" "ム" "ム") ("い" "イ" "イ")))
((("m" "p"). ())(("む" "ム" "ム") ("う" "ウ" "ウ")))
((("m" ")"). ())(("め" "メ" "メ") ("い" "イ" "イ")))
((("m" "("). ())(("も" "モ" "モ") ("う" "ウ" "ウ")))
((("m" ";"). ())(("ま" "マ" "マ") ("ん" "ン" "ン")))
((("m" "x"). ())(("み" "ミ" "ミ") ("ん" "ン" "ン")))
((("m" "k"). ())(("む" "ム" "ム") ("ん" "ン" "ン")))
((("m" "j"). ())(("め" "メ" "メ") ("ん" "ン" "ン")))
((("m" "q"). ())(("も" "モ" "モ") ("ん" "ン" "ン")))

((("m" "n" "a"). ())(("み" "ミ" "ミ") ("ゃ" "ャ" "ャ")))
((("m" "n" "i"). ())(("み" "ミ" "ミ") ("ぃ" "ィ" "ィ")))
((("m" "n" "u"). ())(("み" "ミ" "ミ") ("ゅ" "ュ" "ュ")))
((("m" "n" "e"). ())(("み" "ミ" "ミ") ("ぇ" "ェ" "ェ")))
((("m" "n" "o"). ())(("み" "ミ" "ミ") ("ょ" "ョ" "ョ")))
((("m" "n" "'"). ())(("み" "ミ" "ミ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("m" "n" "y"). ())(("み" "ミ" "ミ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("m" "n" "p"). ())(("み" "ミ" "ミ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("m" "n" ")"). ())(("み" "ミ" "ミ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("m" "n" "("). ())(("み" "ミ" "ミ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("m" "n" ";"). ())(("み" "ミ" "ミ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("m" "n" "x"). ())(("み" "ミ" "ミ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("m" "n" "k"). ())(("み" "ミ" "ミ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("m" "n" "j"). ())(("み" "ミ" "ミ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("m" "n" "q"). ())(("み" "ミ" "ミ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("v" "v"). ("v"))("っ" "ッ" "ッ"))

((("v" "a"). ())("や" "ヤ" "ヤ"))
((("v" "u"). ())("ゆ" "ユ" "ユ"))
((("v" "e"). ())(("い" "イ" "イ") ("ぇ" "ェ" "ェ")))
((("v" "o"). ())("よ" "ヨ" "ヨ"))
((("v" "'"). ())(("や" "ヤ" "ヤ") ("い" "イ" "イ")))
((("v" "p"). ())(("い" "イ" "イ") ("い" "イ" "イ")))
((("v" ")"). ())(("い" "イ" "イ") ("う" "ウ" "ウ")))
((("v" "("). ())(("よ" "ヨ" "ヨ") ("う" "ウ" "ウ")))
((("v" ";"). ())(("や" "ヤ" "ヤ") ("ん" "ン" "ン")))
((("v" "k"). ())(("ゆ" "ユ" "ユ") ("ん" "ン" "ン")))
((("v" "j"). ())(("い" "イ" "イ") ("ん" "ン" "ン")))
((("v" "q"). ())(("よ" "ヨ" "ヨ") ("ん" "ン" "ン")))

((("v" "h" "a"). ())(("う゛" "ヴ" "ヴ") ("ぁ" "ァ" "ァ")))
((("v" "h" "i"). ())(("う゛" "ヴ" "ヴ") ("ぃ" "ィ" "ィ")))
((("v" "h" "u"). ())("う゛" "ヴ" "ヴ"))
((("v" "h" "e"). ())(("う゛" "ヴ" "ヴ") ("ぇ" "ェ" "ェ")))
((("v" "h" "o"). ())(("う゛" "ヴ" "ヴ") ("ぉ" "ォ" "ォ")))

((("v" "n" "a"). ())(("う゛" "ヴ" "ヴ") ("ゃ" "ャ" "ャ")))
((("v" "n" "u"). ())(("う゛" "ヴ" "ヴ") ("ゅ" "ュ" "ュ")))
((("v" "n" "o"). ())(("う゛" "ヴ" "ヴ") ("ょ" "ョ" "ョ")))

((("x" "c" "a"). ())("ヵ" "ヵ" "カ"))
((("x" "k" "a"). ())("ヵ" "ヵ" "カ"))
((("x" "k" "e"). ())("ヶ" "ヶ" "ケ"))

((("x" "y" "a"). ())("ゃ" "ャ" "ャ"))
((("x" "y" "u"). ())("ゅ" "ュ" "ュ"))
((("x" "y" "o"). ())("ょ" "ョ" "ョ"))

((("r" "r"). ("r"))("っ" "ッ" "ッ"))

((("r" "a"). ())("ら" "ラ" "ラ"))
((("r" "i"). ())("り" "リ" "リ"))
((("r" "u"). ())("る" "ル" "ル"))
((("r" "e"). ())("れ" "レ" "レ"))
((("r" "o"). ())("ろ" "ロ" "ロ"))
((("r" "'"). ())(("ら" "ラ" "ラ") ("い" "イ" "イ")))
((("r" "y"). ())(("る" "ル" "ル") ("い" "イ" "イ")))
((("r" "p"). ())(("る" "ル" "ル") ("う" "ウ" "ウ")))
((("r" ")"). ())(("れ" "レ" "レ") ("い" "イ" "イ")))
((("r" "("). ())(("ろ" "ロ" "ロ") ("う" "ウ" "ウ")))
((("r" ";"). ())(("ら" "ラ" "ラ") ("ん" "ン" "ン")))
((("r" "x"). ())(("り" "リ" "リ") ("ん" "ン" "ン")))
((("r" "k"). ())(("る" "ル" "ル") ("ん" "ン" "ン")))
((("r" "j"). ())(("れ" "レ" "レ") ("ん" "ン" "ン")))
((("r" "q"). ())(("ろ" "ロ" "ロ") ("ん" "ン" "ン")))

((("r" "h" "a"). ())(("り" "リ" "リ") ("ゃ" "ャ" "ャ")))
((("r" "h" "i"). ())(("り" "リ" "リ") ("ぃ" "ィ" "ィ")))
((("r" "h" "u"). ())(("り" "リ" "リ") ("ゅ" "ュ" "ュ")))
((("r" "h" "e"). ())(("り" "リ" "リ") ("ぇ" "ェ" "ェ")))
((("r" "h" "o"). ())(("り" "リ" "リ") ("ょ" "ョ" "ョ")))
((("r" "h" "'"). ())(("り" "リ" "リ") ("ゃ" "ャ" "ャ") ("い" "イ" "イ")))
((("r" "h" "y"). ())(("り" "リ" "リ") ("ゅ" "ュ" "ュ") ("い" "イ" "イ")))
((("r" "h" "p"). ())(("り" "リ" "リ") ("ゅ" "ュ" "ュ") ("う" "ウ" "ウ")))
((("r" "h" ")"). ())(("り" "リ" "リ") ("ぇ" "ェ" "ェ") ("い" "イ" "イ")))
((("r" "h" "("). ())(("り" "リ" "リ") ("ょ" "ョ" "ョ") ("う" "ウ" "ウ")))
((("r" "h" ";"). ())(("り" "リ" "リ") ("ゃ" "ャ" "ャ") ("ん" "ン" "ン")))
((("r" "h" "x"). ())(("り" "リ" "リ") ("ぃ" "ィ" "ィ") ("ん" "ン" "ン")))
((("r" "h" "k"). ())(("り" "リ" "リ") ("ゅ" "ュ" "ュ") ("ん" "ン" "ン")))
((("r" "h" "j"). ())(("り" "リ" "リ") ("ぇ" "ェ" "ェ") ("ん" "ン" "ン")))
((("r" "h" "q"). ())(("り" "リ" "リ") ("ょ" "ョ" "ョ") ("ん" "ン" "ン")))

((("w" "w"). ("w"))("っ" "ッ" "ッ"))

((("w" "a"). ())("わ" "ワ" "ワ"))
((("w" "'"). ())(("わ" "ワ" "ワ") ("い" "イ" "イ")))
((("w" ";"). ())(("わ" "ワ" "ワ") ("ん" "ン" "ン")))
((("w" "i"). ())(("う" "ウ" "ウ") ("ぃ" "ィ" "ィ")))
((("w" "u"). ())("う" "ウ" "ウ"))
((("w" "e"). ())(("う" "ウ" "ウ") ("ぇ" "ェ" "ェ")))
((("w" "o"). ())("を" "ヲ" "ヲ"))
((("w" "h" "a"). ())(("う" "ウ" "ウ") ("ぁ" "ァ" "ァ")))
((("w" "h" "i"). ())(("う" "ウ" "ウ") ("ぃ" "ィ" "ィ")))
((("w" "h" "u"). ())("う" "ウ" "ウ"))
((("w" "h" "e"). ())(("う" "ウ" "ウ") ("ぇ" "ェ" "ェ")))
((("w" "h" "o"). ())(("う" "ウ" "ウ") ("ぉ" "ォ" "ォ")))

((("d" "r"). ())(("で" "デ" "デ") ("あ" "ア" "ア") ("る" "ル" "ル")))
((("d" "s"). ())(("で" "デ" "デ") ("す" "ス" "ス")))
((("m" "n"). ())(("も" "モ" "モ") ("の" "ノ" "ノ")))
((("m" "s"). ())(("ま" "マ" "マ") ("す" "ス" "ス")))
((("c" "r"). ())(("か" "カ" "カ") ("ら" "ラ" "ラ")))
((("n" "d"). ())(("の" "ノ" "ノ") ("で" "デ" "デ")))
((("s" "r"). ())(("す" "ス" "ス") ("る" "ル" "ル")))
((("s" "t"). ())(("し" "シ" "シ") ("た" "タ" "タ")))
((("t" "m"). ())(("た" "タ" "タ") ("め" "メ" "メ")))

((("z" "-"). ())("〜" "〜" ""))
((("z" "["). ())("『" "『" ""))
((("z" "]"). ())("』" "』" ""))
((("z" ","). ())("‥" "‥" ""))
((("z" "."). ())("…" "…" ""))
((("z" "/"). ())("・" "・" "・"))
))

(set! ja-wide-rule
'(("a" "a")
("b" "b")
("c" "c")
("d" "d")
("e" "e")
("f" "f")
("g" "g")
("h" "h")
("i" "i")
("j" "j")
("k" "k")
("l" "l")
("m" "m")
("n" "n")
("o" "o")
("p" "p")
("q" "q")
("r" "r")
("s" "s")
("t" "t")
("u" "u")
("v" "v")
("w" "w")
("x" "x")
("y" "y")
("z" "z")
("A" "A")
("B" "B")
("C" "C")
("D" "D")
("E" "E")
("F" "F")
("G" "G")
("H" "H")
("I" "I")
("J" "J")
("K" "K")
("L" "L")
("M" "M")
("N" "N")
("O" "O")
("P" "P")
("Q" "Q")
("R" "R")
("S" "S")
("T" "T")
("U" "U")
("V" "V")
("W" "W")
("X" "X")
("Y" "Y")
("Z" "Z")

("1" "1")
("2" "2")
("3" "3")
("4" "4")
("5" "5")
("6" "6")
("7" "7")
("8" "8")
("9" "9")
("0" "0")

("-" "−")
("," ",")
("." ".")
("!" "!")
("\"" "”")
("#" "#")
("$" "$")
("%" "%")
("&" "&")
("'" "’")
("(" "(")
(")" ")")
("~" "〜")
("=" "=")
("^" "^")
("\\" "\")
("yen" "¥")
("|" "|")
("`" "‘")
("@" "@")
("{" "{")
("[" "[")
("+" "+")
(";" ";")
("*" "*")
(":" ":")
("}" "}")
("]" "]")
("<" "<")
(">" ">")
("?" "?")
("/" "/")
("_" "_")
(" " " ")
))