| Hisashi Morita ( @ 2006-10-03 22:26:00 |
[xyzzy][Lisp][LaTeX] latex-insert-index
latex-insert-index
------------------
LaTeXでの索引設定がつらくなったので、xyzzy用にでっちあげた。動く。
Usage
-----
Todo
----
* プロンプトで必要に応じてsortkeyの候補が提示されるとうれしい(ASCIIな 語句では不要なことが多いので、[↑]や[TAB]で提示されるとか)。
* 日本語の場合は、読みをsortkeyとして自動的に提示したい(現状ではカタカナを ひらがなにするだけで、漢字はそのまま)。
* 読みはカタカナとひらがなから選べるように。
* Emacsでも動くように。とりあえず\sjを\cjにする必要あり。
* メニューの編集-変換-*にあるコマンドの実体はどこに?
雑感
----
* テキストは、新規に書くよりも編集することのほうが多い。だからマークアップ言語編集 用のモードは、既存のテキストを後からマークアップしやすいように設計してあるとうれ しい(良い例:psgml)。
疑問
----
xyzzyでバッファを使わずにプロセスの出力を受ける方法が分からない。
プロセスを起動する方法は、
* make-processで作ったプロセスにprocess-send-string で入力を書き込む
* make-temp-file-nameで作ったファイル名を引数にcall-pro cessで外部プロセスを呼ぶ
あたりが目的のものらしいということが分かった。xyzzy付属のfilter.lが 参考になる。
でも、バッファを使わずにプロセスの出力を受ける方法が分からない。filter-r egionとかは結果をinsert-fileでバッファに挿入してる。
ちょっとしたテキストを外部プロセスで処理した結果を、無駄なバッファを作ったり消し たりせずに、stringとして受け取りたいだけなんだけど。
エディタ組み込みのシステムだから、バッファを介してやり取りするのが原則ということ なんだろうか。
make-process-input-streamとかmake-process-o utput-streamとかいう関数があって、それでプロセスをストリーム化できた らいいのになあ。見落としてる?
----------------
2006-10-10 追記
佐野さんのコメントを受けて、とりあえずプロセスのほうだけ改善。MeCabを使える ようになって、かなり快適。文字変換のほうの改善はこれから。
----
直交性の話は、ちょっと文脈と無関係に持ち出してしまったけど、Emacsやxyzz yのようなLispを使ったエディタに対して、ずっと次のような疑問を持っていたため。
例えばこういうふうなインタフェースになってると、テキスト編集の処理を書くのが楽そ うな気がする。
* 文字列を受け取って文字列を返すような編集関数を定義
* 高階関数を使って、編集関数をバッファやリージョンに適用(擬似コードだと(repl ace region (apply 'editing-function region))のような感じ)
文字列の操作と対象への適用が直交しているので、ユーザは適用対象がバッファかどうか など考えずに編集関数だけ書けばいい。そして編集関数はどんな文字列データに適用して もいいので、独立していて使い回しがきく。
(プロセスの処理の場合も同様で、最終的に出力をバッファに挿入するかどうかなんて考 えずに、入力する文字列と出力される文字列のことだけ考えたい)
でも、そうはなっていない。Emacsでもxyzzyでも、正規表現でバッファをなめ る関数を使って、マッチ情報を後で取り出して何かしたりとかいうのが定石みたい。
たぶん実行効率のせいなんだろうなと思うけど、普段はあれこれ気持ちいいのに、バッフ ァの操作になると途端に自由度が下がって気持ち良さが減るので、残念。
(余談だけど、UnixのCLIシェル環境で、標準入出力を使ってくれるコマンドはパ イプの途中に自由に挟み込めるので気持ちがいい。反対に、入出力にファイルしか受け付 けないコマンドは使っていてつらい。データをどこに流すかはシェルで制御するから、自 由にさせてよという感じ。それと少し似ているかも)
(Haskellで書かれたEmacsライクなエディタがあったけど、あれはどうなっ てるんだろう)
latex-insert-index
------------------
LaTeXでの索引設定がつらくなったので、xyzzy用にでっちあげた。動く。
Usage
-----
M-x latex-index-insert ENTER リージョンを索引項目にする
C-u M-x latex-index-insert ENTER 最近killした文字列を索引項目にする
M-x kata-to-hira-region ENTER リージョン内のカタカナをひらがなに(おまけ)
(defun latex-insert-index (begin end pre &optional sortkey)
"Insert \\index using region text (or killed text if with prefix arg)
as index term. If term is non-ASCII and sortkey is ommited, term is
copied as sortkey."
(interactive "r\nP\nsSort Key:")
(let ((term (if pre (caar *kill-ring*) (buffer-substring begin end))))
(insert (concat
"\\index{"
(if (or (equal sortkey nil) (equal sortkey ""))
(if (string-match "\\sj" term) (concat (kata-to-hira-string term) "@") "")
(concat sortkey "@"))
term
"}" )
)))
(defun kata-to-hira (chr)
"Convert katakana character to hiragana character if possible."
(let* ((kata (mapcar 'character
(split-string (concat
"ァ ア ィ イ ゥ ウ ェ エ ォ オ "
"カ ガ キ ギ ク グ ケ ゲ コ ゴ "
"サ ザ シ ジ ス ズ セ ゼ ソ ゾ "
"タ ダ チ ヂ ッ ツ ヅ テ デ ト ド "
"ナ ニ ヌ ネ ノ "
"ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ "
"マ ミ ム メ モ "
"ャ ヤ ュ ユ ョ ヨ "
"ラ リ ル レ ロ ゎ ワ ゐ ゑ ヲ ン") " ")))
(hira (mapcar 'character
(split-string (concat
"ぁ あ ぃ い ぅ う ぇ え ぉ お "
"か が き ぎ く ぐ け げ こ ご "
"さ ざ し じ す ず せ ぜ そ ぞ "
"た だ ち ぢ っ つ づ て で と ど "
"な に ぬ ね の "
"は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ "
"ま み む め も "
"ゃ や ゅ ゆ ょ よ "
"ら り る れ ろ ゎ わ ゐ ゑ を ん") " ")))
(dic (mapcar (lambda (x y) (list* x y)) kata hira))
(counterpart (cdr (assoc chr dic :test 'equal))))
(if counterpart counterpart chr)))
(defun kata-to-hira-string (str)
"Return a string converting katakana to hiragana."
(map 'string 'kata-to-hira str))
(defun kata-to-hira-region (begin end)
"Convert katakana in region to hiragana."
(interactive "r")
(let ((src (buffer-substring begin end)))
(progn
(delete-region begin end)
(insert (kata-to-hira-string src)))))
Todo
----
* プロンプトで必要に応じてsortkeyの候補が提示されるとうれしい(ASCIIな
* 日本語の場合は、読みをsortkeyとして自動的に提示したい(現状ではカタカナを
* 読みはカタカナとひらがなから選べるように。
* Emacsでも動くように。とりあえず\sjを\cjにする必要あり。
* メニューの編集-変換-*にあるコマンドの実体はどこに?
雑感
----
* テキストは、新規に書くよりも編集することのほうが多い。だからマークアップ言語編集
疑問
----
xyzzyでバッファを使わずにプロセスの出力を受ける方法が分からない。
プロセスを起動する方法は、
* make-processで作ったプロセスにprocess-send-string
* make-temp-file-nameで作ったファイル名を引数にcall-pro
あたりが目的のものらしいということが分かった。xyzzy付属のfilter.lが
でも、バッファを使わずにプロセスの出力を受ける方法が分からない。filter-r
ちょっとしたテキストを外部プロセスで処理した結果を、無駄なバッファを作ったり消し
エディタ組み込みのシステムだから、バッファを介してやり取りするのが原則ということ
make-process-input-streamとかmake-process-o
----------------
2006-10-10 追記
佐野さんのコメントを受けて、とりあえずプロセスのほうだけ改善。MeCabを使える
----
直交性の話は、ちょっと文脈と無関係に持ち出してしまったけど、Emacsやxyzz
例えばこういうふうなインタフェースになってると、テキスト編集の処理を書くのが楽そ
* 文字列を受け取って文字列を返すような編集関数を定義
* 高階関数を使って、編集関数をバッファやリージョンに適用(擬似コードだと(repl
文字列の操作と対象への適用が直交しているので、ユーザは適用対象がバッファかどうか
(プロセスの処理の場合も同様で、最終的に出力をバッファに挿入するかどうかなんて考
でも、そうはなっていない。Emacsでもxyzzyでも、正規表現でバッファをなめ
たぶん実行効率のせいなんだろうなと思うけど、普段はあれこれ気持ちいいのに、バッフ
(余談だけど、UnixのCLIシェル環境で、標準入出力を使ってくれるコマンドはパ
(Haskellで書かれたEmacsライクなエディタがあったけど、あれはどうなっ
;; 2006-10 utility for LaTeX work
(defun latex-insert-index-ja (begin end pre &optional key)
"Insert \\index{key@term} using region text (or last killed text if
with prefix arg) as index term. If the term is Japanese and the key is
ommited, term's reading is copied as key."
(interactive "r\nP\nsKey:")
(let ((term (if pre (caar *kill-ring*) (buffer-substring begin end))))
(insert (concat
"\\index{"
(if (or (equal key nil) (equal key ""))
(if (string-match "\\sj" term)
(concat (mecab-reading-hiragana term) "@")
"")
(concat key "@"))
term
"}" )
)))
(defun kata-to-hira (chr)
"Convert katakana character to hiragana character if possible."
(let* ((kata (mapcar 'character
(split-string (concat
"ァ ア ィ イ ゥ ウ ェ エ ォ オ "
"カ ガ キ ギ ク グ ケ ゲ コ ゴ "
"サ ザ シ ジ ス ズ セ ゼ ソ ゾ "
"タ ダ チ ヂ ッ ツ ヅ テ デ ト ド "
"ナ ニ ヌ ネ ノ "
"ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ "
"マ ミ ム メ モ "
"ャ ヤ ュ ユ ョ ヨ "
"ラ リ ル レ ロ ゎ ワ ゐ ゑ ヲ ン") " ")))
(hira (mapcar 'character
(split-string (concat
"ぁ あ ぃ い ぅ う ぇ え ぉ お "
"か が き ぎ く ぐ け げ こ ご "
"さ ざ し じ す ず せ ぜ そ ぞ "
"た だ ち ぢ っ つ づ て で と ど "
"な に ぬ ね の "
"は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ "
"ま み む め も "
"ゃ や ゅ ゆ ょ よ "
"ら り る れ ろ ゎ わ ゐ ゑ を ん") " ")))
(dic (mapcar (lambda (x y) (list* x y)) kata hira))
(counterpart (cdr (assoc chr dic :test 'equal))))
(if counterpart counterpart chr)))
(defun kata-to-hira-string (str)
"Return a string converting katakana to hiragana."
(map 'string 'kata-to-hira str))
(defun kata-to-hira-region (begin end)
"Convert katakana in region to hiragana."
(interactive "r")
(let ((src (buffer-substring begin end)))
(progn
(delete-region begin end)
(insert (kata-to-hira-string src)))))
;; thanks to snmsts
(defun run-command (cmd &optional input)
"Run CMD as sub-process with INPUT for stdin. Return stdout as string."
(let ((buf (create-new-buffer "tmp"))
proc)
(save-window-excursion
(with-set-buffer
(setup-temp-buffer buf)
(set-buffer buf)
(setq proc (make-process cmd))
(if input (process-send-string proc (concat input (string #\C-z)))
nil)
(while (eql :run (process-status proc))
(do-events))
(prog1
(string-right-trim "\r\n" (buffer-substring (point-min) (point-max)))
(delete-buffer buf))))))
(defun mecab-reading-katakana (str)
"Acquire reading of Japanese text in katakana using MeCab morphological analyzer."
(run-command "C:/Program Files/MeCab/bin/mecab.exe -Oyomi" str))
(defun mecab-reading-hiragana (str)
"Acquire reading of Japanese text in hiragana using MeCab morphological analyzer."
(kata-to-hira-string (mecab-reading-katakana str)))