--- egg-remix.0208.el Fri Aug 13 19:32:12 2004 +++ egg-remix.0209.el Sun Mar 6 22:41:22 2005 @@ -1,5 +1,5 @@ ;;; egg-remix.el --- Roman-Kana conversion input interface for Tamago4 -;; Copyright (C) 2000-2004 Hiroki Hayashi +;; Copyright (C) 2000-2005 Hiroki Hayashi ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as @@ -55,7 +55,22 @@ ;; nil または "mlh" たまご modeless モード (mlh モード) ;; "remix" Egg ReMix モード +;; フック +;; 内部で Tamago を require する直前に呼ぶフック(remix-egg-preinit-hook)と +;; remix-setup を実行する直前に呼ぶフック(remix-setup-hook)があります。 +;; remix-egg-preinit-hook ではローマ字かな変換ルールに対する変更など Tamago +;; の初期化に必要なパラメータ設定が、remix-setup-hook では入力キーマップなど +;; の設定ができます。 + ;; Change Log: +;; Mar 6 2005: version 0.209 +;; ・ユーザ辞書へ登録する最短文字数を、remix-sysdict-length で +;; 設定できるように変更 (Thanks to Hideyuki SHIRAI) +;; ・remix-setup-hook を追加 (Thanks to Hideyuki SHIRAI) +;; ・初期化の一部を remix-setup に移動 +;; (Thanks to Hideyuki SHIRAI) +;; ・Tamago の関数の上書きを、remix-override-egg に移動 +;; ・remix-egg-preinit-hook を追加 ;; Aug 12 2004: version 0.208 ;; ・Emacs-21.3.50 での invisible に対する動作変更への対応 ;; Jun 15 2003: version 0.207 @@ -83,15 +98,15 @@ ;; ・isearch で日本語を入力中に C-g で中断すると、以後の ;; ミニバッファへの入力ができなくなる問題に対応 ;; (C-g へ abort する関数をバインドして回避) -;; ・変換モードから C-k でフェンスモードに戻ったときに、フェンスが -;; 正しく作成されない問題を fix +;; ・変換モードから C-k でフェンスモードに戻ったときに、フェンス +;; が正しく作成されない問題を fix ;; Oct 12 2000: version 0.202 -;; ・remix-fence-open, remix-fence-continue, remix-fence-close が -;; 2文字以上のときに正常に動作しない問題に対応 +;; ・remix-fence-open, remix-fence-continue, remix-fence-close +;; が2文字以上のときに正常に動作しない問題に対応 ;; ・fence に使う文字列が remix-fence-* になっていたのを ;; its-fence-* に修正 -;; ・remix-sysdict や remix-usrdict が nil のときに正常に動作しない -;; 問題点を fix +;; ・remix-sysdict や remix-usrdict が nil のときに正常に動作し +;; ない問題点を fix ;; Sep 27 2000: version 0.201 ;; ・細かな bug を fix ;; Sep 27 2000: version 0.200 @@ -99,153 +114,151 @@ ;; Code: -(require 'egg) - -(defconst remix-version "0.208" +(defconst remix-version "0.209" "Egg ReMix のバージョン") -(defconst remix-version-date "Aug 12 2004" +(defconst remix-version-date "Feb 17 2005" "Egg ReMix の最終更新日") -(activate-input-method default-input-method) -(activate-input-method nil) +(defvar remix-egg-preinit-hook nil + "*Tamago を初期化する前に実行するフック") ;;;;==== ;;;; 機能拡張のための Tamago4 native 関数のオーバーライド ;;;; 将来的には不必要になって欲しい:-) ;;;;==== - -;;;; its-restart 呼び出しを選択できるようにする -(defun egg-decide-before-point () - (interactive) - (let* ((inhibit-read-only t) - (buffer-invisibility-spec nil) - (start (if (get-text-property (1- (point)) 'egg-start) +(defun remix-override-egg () + "Tamago の関数を上書きして拡張する" + ;;; its-restart 呼び出しを選択できるようにする + (defun egg-decide-before-point () + (interactive) + (let* ((inhibit-read-only t) + (buffer-invisibility-spec nil) + (start (if (get-text-property (1- (point)) 'egg-start) + (point) + (previous-single-property-change (point) 'egg-start))) + (end (if (get-text-property (point) 'egg-end) (point) - (previous-single-property-change (point) 'egg-start))) - (end (if (get-text-property (point) 'egg-end) - (point) - (next-single-property-change (point) 'egg-end))) - (decided (buffer-substring start (point))) - (undecided (buffer-substring (point) end)) - i len bunsetsu source context) - (delete-region - (previous-single-property-change start 'egg-start nil (point-min)) - (next-single-property-change end 'egg-end nil (point-max))) - (setq i 0 - len (length decided)) - (while (< i len) - (setq bunsetsu (nconc bunsetsu (list (egg-get-bunsetsu-info i decided))) - i (egg-next-bunsetsu-point i 1 decided len)) - (if (or (= i len) - (egg-get-bunsetsu-last (1- i) decided)) - (progn - (insert (mapconcat 'egg-get-bunsetsu-converted bunsetsu nil)) - (setq context (cons (cons (egg-bunsetsu-get-backend (car bunsetsu)) - (egg-end-conversion bunsetsu nil)) - context) - bunsetsu nil)))) - (setq len (length undecided)) - (if (= len 0) - (progn - (egg-do-auto-fill) - (run-hooks 'input-method-after-insert-chunk-hook) - context) - (setq i 0) + (next-single-property-change (point) 'egg-end))) + (decided (buffer-substring start (point))) + (undecided (buffer-substring (point) end)) + i len bunsetsu source context) + (delete-region + (previous-single-property-change start 'egg-start nil (point-min)) + (next-single-property-change end 'egg-end nil (point-max))) + (setq i 0 + len (length decided)) (while (< i len) - (setq bunsetsu (egg-get-bunsetsu-info i undecided) - source (cons (egg-get-bunsetsu-source bunsetsu) - source)) - (put-text-property 0 (length (car source)) - 'egg-lang - (egg-get-source-language bunsetsu) - (car source)) - (setq i (egg-next-bunsetsu-point i 1 undecided len))) + (setq bunsetsu (nconc bunsetsu (list (egg-get-bunsetsu-info i decided))) + i (egg-next-bunsetsu-point i 1 decided len)) + (if (or (= i len) + (egg-get-bunsetsu-last (1- i) decided)) + (progn + (insert (mapconcat 'egg-get-bunsetsu-converted bunsetsu nil)) + (setq context (cons (cons (egg-bunsetsu-get-backend (car bunsetsu)) + (egg-end-conversion bunsetsu nil)) + context) + bunsetsu nil)))) + (setq len (length undecided)) + (if (= len 0) + (progn + (egg-do-auto-fill) + (run-hooks 'input-method-after-insert-chunk-hook) + context) + (setq i 0) + (while (< i len) + (setq bunsetsu (egg-get-bunsetsu-info i undecided) + source (cons (egg-get-bunsetsu-source bunsetsu) + source)) + (put-text-property 0 (length (car source)) + 'egg-lang + (egg-get-source-language bunsetsu) + (car source)) + (setq i (egg-next-bunsetsu-point i 1 undecided len))) + (funcall (nth 3 (assoc egg-mode-preference egg-input-mode-alist)) + (apply 'concat (nreverse source)) t t context)))) + + ;;; its-restart 呼び出しを選択できるようにする + (defun egg-abort-conversion () + (interactive) + (let ((inhibit-read-only t) + (buffer-invisibility-spec nil) + source context) + (goto-char (previous-single-property-change + (if (get-text-property (1- (point)) 'egg-start) + (point) + (previous-single-property-change (point) 'egg-start)) + 'egg-start nil (point-min))) + (setq source (get-text-property (point) 'egg-source) + context (get-text-property (point) 'egg-context)) + (delete-region (point) (next-single-property-change + (next-single-property-change (point) 'egg-end) + 'egg-end nil (point-max))) (funcall (nth 3 (assoc egg-mode-preference egg-input-mode-alist)) - (apply 'concat (nreverse source)) t t context)))) - -;;; its-restart 呼び出しを選択できるようにする -(defun egg-abort-conversion () - (interactive) - (let ((inhibit-read-only t) - (buffer-invisibility-spec nil) - source context) - (goto-char (previous-single-property-change - (if (get-text-property (1- (point)) 'egg-start) - (point) - (previous-single-property-change (point) 'egg-start)) - 'egg-start nil (point-min))) - (setq source (get-text-property (point) 'egg-source) - context (get-text-property (point) 'egg-context)) - (delete-region (point) (next-single-property-change - (next-single-property-change (point) 'egg-end) - 'egg-end nil (point-max))) - (funcall (nth 3 (assoc egg-mode-preference egg-input-mode-alist)) - source nil nil context))) + source nil nil context))) ;;; egg-mode-preference を拡張し、各種のモードを追加できるようにする -;;;###autoload -(defun egg-mode (&rest arg) - "Toggle EGG mode. + (defun egg-mode (&rest arg) + "Toggle EGG mode. \\[describe-bindings] " - (interactive "P") - (if (null arg) - ;; Turn off - (unwind-protect + (interactive "P") + (if (null arg) + ;; Turn off + (unwind-protect + (progn + (funcall (nth 4 (assoc egg-mode-preference egg-input-mode-alist))) + (egg-exit-conversion)) + (setq describe-current-input-method-function nil) + (let ((modelist egg-input-mode-alist) + mode) + (while (setq mode (car modelist)) + (set (modename mode) nil) + (setq modelist (cdr modelist)))) + (remove-hook 'input-method-activate-hook 'its-set-mode-line-title t) + (force-mode-line-update)) + ;; Turn on + (if (null (string= (car arg) egg-last-method-name)) (progn - (funcall (nth 4 (assoc egg-mode-preference egg-input-mode-alist))) - (egg-exit-conversion)) - (setq describe-current-input-method-function nil) - (let ((modelist egg-input-mode-alist) - mode) - (while (setq mode (car modelist)) - (set (modename mode) nil) - (setq modelist (cdr modelist)))) - (remove-hook 'input-method-activate-hook 'its-set-mode-line-title t) - (force-mode-line-update)) - ;; Turn on - (if (null (string= (car arg) egg-last-method-name)) - (progn - (funcall (nth 1 arg)) - (setq egg-default-language its-current-language))) - (egg-set-conversion-backend (nthcdr 2 arg)) - (egg-set-conversion-backend - (list (assq its-current-language (nthcdr 2 arg))) t) - (setq egg-last-method-name (car arg) - egg-activated t) - (egg-activate-keymap) - - (let ((mode (assoc egg-mode-preference egg-input-mode-alist))) - (set (modename mode) t) - (if (nth 3 mode) - (its-define-select-keys (symbol-value (mapname mode))))) - - (setq inactivate-current-input-method-function 'egg-mode) - (setq describe-current-input-method-function 'egg-help) - (make-local-hook 'input-method-activate-hook) - (add-hook 'input-method-activate-hook 'its-set-mode-line-title nil t) - (if (eq (selected-window) (minibuffer-window)) - (add-hook 'minibuffer-exit-hook 'egg-exit-from-minibuffer)) - (run-hooks 'egg-mode-hook))) + (funcall (nth 1 arg)) + (setq egg-default-language its-current-language))) + (egg-set-conversion-backend (nthcdr 2 arg)) + (egg-set-conversion-backend + (list (assq its-current-language (nthcdr 2 arg))) t) + (setq egg-last-method-name (car arg) + egg-activated t) + (egg-activate-keymap) + + (let ((mode (assoc egg-mode-preference egg-input-mode-alist))) + (set (modename mode) t) + (if (nth 3 mode) + (its-define-select-keys (symbol-value (mapname mode))))) + + (setq inactivate-current-input-method-function 'egg-mode) + (setq describe-current-input-method-function 'egg-help) + (make-local-hook 'input-method-activate-hook) + (add-hook 'input-method-activate-hook 'its-set-mode-line-title nil t) + (if (eq (selected-window) (minibuffer-window)) + (add-hook 'minibuffer-exit-hook 'egg-exit-from-minibuffer)) + (run-hooks 'egg-mode-hook))) ;;; 最後に input-method-after-insert-chunk-hook を呼び出すようにする -(defun egg-decide-first-char () - (interactive) - (let* ((inhibit-read-only t) - (buffer-invisibility-spec nil) - (start (if (get-text-property (1- (point)) 'egg-start) + (defun egg-decide-first-char () + (interactive) + (let* ((inhibit-read-only t) + (buffer-invisibility-spec nil) + (start (if (get-text-property (1- (point)) 'egg-start) + (point) + (previous-single-property-change (point) 'egg-start))) + (end (if (get-text-property (point) 'egg-end) (point) - (previous-single-property-change (point) 'egg-start))) - (end (if (get-text-property (point) 'egg-end) - (point) - (next-single-property-change (point) 'egg-end))) - (bunsetsu (egg-get-bunsetsu-info start))) - (delete-region - (previous-single-property-change start 'egg-start nil (point-min)) - (next-single-property-change end 'egg-end nil (point-max))) - (egg-end-conversion (list bunsetsu) nil) - (insert (egg-string-to-char-at (egg-get-bunsetsu-converted bunsetsu) 0)) - (run-hooks 'input-method-after-insert-chunk-hook))) + (next-single-property-change (point) 'egg-end))) + (bunsetsu (egg-get-bunsetsu-info start))) + (delete-region + (previous-single-property-change start 'egg-start nil (point-min)) + (next-single-property-change end 'egg-end nil (point-max))) + (egg-end-conversion (list bunsetsu) nil) + (insert (egg-string-to-char-at (egg-get-bunsetsu-converted bunsetsu) 0)) + (run-hooks 'input-method-after-insert-chunk-hook)))) ;;;;==== ;;;; 機能拡張用の追加コード @@ -255,11 +268,13 @@ (defsubst mapname (mode) (intern (format "egg-%s-map" (nth 1 mode)))) -(defvar egg-input-mode-alist '(("egg" "modefull" t its-restart its-exit-mode) - ("mlh" "modeless" nil its-restart its-exit-mode) - ("remix" "remix" t remix-restart remix-exit-mode) - (t "modefull" t its-restart its-exit-mode) - (nil "modeless" nil its-restart its-exit-mode)) +(defvar egg-input-mode-alist + '(("egg" "modefull" t its-restart its-exit-mode) + ("mlh" "modeless" nil its-restart its-exit-mode) + ("remix" "remix" t remix-restart remix-exit-mode) + (t "modefull" t its-restart its-exit-mode) + (nil "modeless" nil its-restart its-exit-mode) + ) "Egg の入力モードのリスト。 各要素は\"モード名\", \"内部識別名\", modefullフラグ, 変換モードからの復帰関数, フェンスモードの終了関数のリストである。 \"モード名\"を egg-mode-preference に設定することで、入力モードを切り替える") @@ -309,6 +324,9 @@ このリストが nil ならばシステムの辞書は使わない。 辞書は1行1単語の形式である必要がある") +(defvar remix-sysdict-length 2 + "*システム英単語辞書の検索対象の最短文字数") + (defvar remix-usrdict (expand-file-name "~/.remix-freq") "*ユーザ用の単語辞書のファイル名。 最後にローマ字綴りとみなしたか非ローマ字綴りとみなしたかも記録する。 @@ -324,6 +342,9 @@ nil ならば text property を使う。 数値ならばその値を priority とする overlay を使う。") +(defvar remix-setup-hook nil + "*Egg-remix の初期化時に呼ぶフック") + ;;;;==== ;;;; Egg-ReMix の内部で使う変数 ;;;;==== @@ -333,30 +354,16 @@ (defvar remix-usrdictbuf " *remix-usrdict*" "ユーザ辞書を格納するバッファの名前") -(defvar remix-state-indicator-alist '((remix-kanaseq . "あ") ; ローマ字綴り - (remix-uncertain . "◇") ; 状態未確定 - (remix-nokanaseq . "◆") ; 非ローマ字綴り - (remix-indictkana . "☆") ; 辞書内のローマ字綴り - (remix-indictnokana . "★") ; 辞書内の非ローマ字綴り - (remix-inedit . "▽") ; フェンス編集中 - ) +(defvar remix-state-indicator-alist + '((remix-kanaseq . "あ") ; ローマ字綴り + (remix-uncertain . "◇") ; 状態未確定 + (remix-nokanaseq . "◆") ; 非ローマ字綴り + (remix-indictkana . "☆") ; 辞書内のローマ字綴り + (remix-indictnokana . "★") ; 辞書内の非ローマ字綴り + (remix-inedit . "▽") ; フェンス編集中 + ) "*ReMixの状態とモードライン行のインジケータの対応リスト") -;;; 初期状態(フォールバック)のインジケータ -(or (assq 'remix-default remix-state-indicator-alist) - (setq remix-state-indicator-alist (append remix-state-indicator-alist - (list - (cons 'remix-default - (its-get-indicator - (symbol-value its-current-map))))))) - -(define-egg-mode-map remix - (define-key map "\C-^" 'egg-simple-input-method) - (let ((i 33)) - (while (< i 127) - (define-key map (vector i) 'remix-self-insert-char) - (setq i (1+ i))))) - (defvar remix-its-mode-map (let ((map (make-sparse-keymap)) (i 33)) @@ -393,12 +400,6 @@ (defvar remix-its-fence-mode nil) (fset 'remix-its-mode-map remix-its-mode-map) -(make-variable-buffer-local 'remix-its-fence-mode) -(put 'remix-its-fence-mode 'permanent-local t) -(or (assq 'remix-its-fence-mode egg-sub-mode-map-alist) - (setq egg-sub-mode-map-alist (cons '(remix-its-fence-mode . remix-its-mode-map) - egg-sub-mode-map-alist))) - (defvar remix-context nil) (defvar remix-fence-operation nil) (defvar remix-usrdict-modified nil) @@ -995,8 +996,8 @@ (goto-char (point-min)) (re-search-forward entry nil t)) ; ユーザ辞書から検索 nil) - (if (< (length seq) 2) - nil ; 2文字未満は検索しない + (if (< (length seq) remix-sysdict-length) + nil ; 指定文字数より短ければ検索しない (if remix-sysdict (progn (set-buffer remix-sysdictbuf) @@ -1171,6 +1172,7 @@ (get-text-property pos 'egg-lang) (get-text-property pos 'egg-start))))) +(defvar mew-draft-attach-map nil) ;; avoid Warning for defadvice (defadvice remix-self-insert-char (around remix-self-insert-char-mew-attach activate) "Mewの添付領域で透過的にコマンドを実行できるようにする" @@ -1178,6 +1180,81 @@ (mew-in-attach-p)) (funcall (lookup-key mew-draft-attach-map (this-command-keys))) ad-do-it)) + +(defun remix-initialize-egg () + "Tamago を初期化する" + (when (featurep 'egg) + (unload-feature 'egg t)) + + (run-hooks 'remix-egg-preinit-hook) + + (require 'egg) + (activate-input-method default-input-method) + (activate-input-method nil) + + (remix-override-egg)) + +;;;###autoload +(defun remix-setup () + "Egg-ReMix を起ち上げる" + (interactive) + (remix-initialize-egg) + (run-hooks 'remix-setup-hook) + (unless (featurep 'egg-remix) + ;; 初期状態(フォールバック)のインジケータ + (or (assq 'remix-default remix-state-indicator-alist) + (setq remix-state-indicator-alist + (append remix-state-indicator-alist + (list + (cons 'remix-default + (its-get-indicator + (symbol-value its-current-map))))))) + + (define-egg-mode-map remix + (define-key map "\C-^" 'egg-simple-input-method) + (let ((i 33)) + (while (< i 127) + (define-key map (vector i) 'remix-self-insert-char) + (setq i (1+ i))))) + + (fset 'remix-its-mode-map remix-its-mode-map) + + (make-variable-buffer-local 'remix-its-fence-mode) + (put 'remix-its-fence-mode 'permanent-local t) + (or (assq 'remix-its-fence-mode egg-sub-mode-map-alist) + (setq egg-sub-mode-map-alist + (cons '(remix-its-fence-mode . remix-its-mode-map) + egg-sub-mode-map-alist))) + + ;; remix-remix-fence が non-nil なら、フェンスの外観を + ;; remix のもので初期化する + (if remix-remix-fence + (setq its-fence-invisible remix-fence-invisible + its-fence-open remix-fence-open + its-fence-continue remix-fence-continue + its-fence-close remix-fence-close + its-fence-face remix-fence-face + egg-conversion-fence-invisible remix-fence-invisible + egg-conversion-fence-open remix-fence-open + egg-conversion-fence-continue remix-fence-continue + egg-conversion-fence-close remix-fence-close + egg-conversion-face remix-fence-face)) + + ;; remix-use-overlay の妥当性チェック + ;; nil: overlay を使わない + ;; number: overlay の priority にする + (or + (null remix-use-overlay) + (numberp remix-use-overlay) + (setq remix-use-overlay nil))) + + (make-variable-buffer-local 'remix-its-fence-mode) + (put 'remix-its-fence-mode 'permanent-local t) + (or (assq 'remix-its-fence-mode egg-sub-mode-map-alist) + (setq egg-sub-mode-map-alist (cons '(remix-its-fence-mode . remix-its-mode-map) + egg-sub-mode-map-alist)))) + +(remix-setup) (provide 'egg-remix)