--- egg-remix.0209.el Tue Mar 8 21:40:33 2005 +++ egg-remix.0300.el Wed Mar 9 22:39:41 2005 @@ -63,6 +63,17 @@ ;; の設定ができます。 ;; Change Log: +;; Mar 9 2005: version 0.300 +;; ・ユーザ辞書とシステム辞書の内部表現をバッファからシンボルに +;; 変更して辞書検索を高速化 (Thanks to Hideyuki SHIRAI) +;; ・ユーザ辞書を alist 形式で保存するように変更 +;; (Thanks to Hideyuki SHIRAI) +;; ・ユーザ辞書のバックアップ作成機能を追加 +;; (Thanks to Hideyuki SHIRAI) +;; ・複数のシステム辞書を指定すると、辞書の読み込みに失敗する +;; バグを fix (Thanks to Hideyuki SHIRAI) +;; ・ユーザ辞書を保存する際のファイルモードの指定機能を追加 +;; ・辞書の内部表現の変更に合わせ、バージョン番号を 0.3xx に変更 ;; Mar 6 2005: version 0.209 ;; ・ユーザ辞書へ登録する最短文字数を、remix-sysdict-length で ;; 設定できるように変更 (Thanks to Hideyuki SHIRAI) @@ -114,9 +125,9 @@ ;; Code: -(defconst remix-version "0.209" +(defconst remix-version "0.300" "Egg ReMix のバージョン") -(defconst remix-version-date "Feb 17 2005" +(defconst remix-version-date "Mar 9 2005" "Egg ReMix の最終更新日") (defvar remix-egg-preinit-hook nil @@ -332,6 +343,20 @@ 最後にローマ字綴りとみなしたか非ローマ字綴りとみなしたかも記録する。 nil ならばユーザ用単語辞書を使わない") +(defvar remix-usrdict-alist-file (expand-file-name "~/.remix-freq.alist") + "*alist 形式のユーザ辞書のファイル名") + +(defvar remix-usrdict-alist-file-backup nil + "*ユーザ辞書のバックアップを作成するかどうかのフラグ。 +non-nil なら、ユーザ辞書を保存する前に古いファイルを .bak という拡張子を +追加した名前に変更する") + +(defvar remix-usrdict-file-mode nil + "*ユーザ辞書のファイルモード。 +ファイルモードを表す数値か8進数文字列を設定する。 +nil ならばファイルモードの変更操作をしない。 +ユーザ辞書の内容を他のユーザに見られたくなければ、\"600\" などと設定する") + (defvar remix-auto-add-entry t "*ユーザ辞書にない綴りを自動的に追加するかどうかのフラグ。 値が non-nil なら、ユーザ辞書にない綴りがシステム辞書にあったときに @@ -348,11 +373,11 @@ ;;;;==== ;;;; Egg-ReMix の内部で使う変数 ;;;;==== -(defvar remix-sysdictbuf " *remix-sysdict*" - "システム辞書を格納するバッファの名前") +(defvar remix-usrdict-db nil + "ユーザ辞書の hash table") -(defvar remix-usrdictbuf " *remix-usrdict*" - "ユーザ辞書を格納するバッファの名前") +(defvar remix-sysdict-db nil + "システム辞書の hash table") (defvar remix-state-indicator-alist '((remix-kanaseq . "あ") ; ローマ字綴り @@ -624,11 +649,9 @@ (interactive) (remix-end-of-input-buffer) (let* ((p (point)) - (seq (get-text-property p 'remix-keyseq-before)) - dict) - (when (and seq - (setq dict (remix-seq-indict-p seq))) - (remix-set-usrdict seq "1" dict) + (seq (get-text-property p 'remix-keyseq-before))) + (when (and seq (remix-seq-indict-p seq)) + (remix-set-usrdict seq 1) (remix-input)))) (defun remix-select-nokana () @@ -650,7 +673,7 @@ (delete-region (remix-search-beginning-seq) (remix-search-end-seq)) (insert seq) (remix-put-cursor) - (remix-set-usrdict seq "0" (remix-seq-indict-p seq)))) + (remix-set-usrdict seq 0))) (remix-exit-mode-internal))) (defun remix-hiragana () @@ -709,7 +732,6 @@ (defun remix-start (key context) (let ((remix-context context)) - (remix-initialize) (remix-setup-fence-mode) (remix-input key))) @@ -769,18 +791,16 @@ (add-text-properties p (1+ p) (list 'remix-keyseq-before seq-before)))) (when seq-before (setq dict (remix-seq-indict-p seq-before)) ; 辞書にある綴りか調べる + ;; dict: 0 => 非ローマ字, 1 => ローマ字, 2 => system dict, null => not found (cond - ((null dict) ; 辞書にはない綴り + ((null dict) ; 辞書にはない綴り (setq status 'remix-uncertain)) - ((zerop dict) ; システム辞書にある単語(ユーザ辞書に登録せず) - (setq status 'remix-indictnokana)) - (t - (let ((flag (save-excursion - (set-buffer remix-usrdictbuf) - (char-after dict)))) - (if (= flag ?0) - (setq status 'remix-indictnokana) ; 辞書内にある非ローマ字綴り - (setq status 'remix-indictkana)))))) ; 辞書内にあるローマ字綴り + ((= dict 0) + (setq status 'remix-indictnokana)) ; 辞書内にある非ローマ字綴り + ((= dict 1) + (setq status 'remix-indictkana)) ; 辞書内にあるローマ字綴り + (t ;; (= dict 2) ; システム辞書にある単語(ユーザ辞書に登録せず) + (setq status 'remix-indictnokana)))) (remix-update-fence status (and key (symbolp key))))) (defun remix-update-fence (status &optional last) @@ -946,89 +966,104 @@ (setq p (next-single-property-change p 'remix-end))) p)) +(defun remix-initialize-db-size (size) + (cond + ((<= size 1511) 401) + ((<= size 7211) 1511) + ((<= size 32611) 7211) + ((<= size 99991) 32611) + (t 99991))) + (defun remix-initialize () - "必要ならばシステム辞書とユーザ辞書を読み込み、参照に備える" - (save-excursion - ;; システム辞書のセッティング - (if remix-sysdict - (let ((dictfiles remix-sysdict) - file - (buf (get-buffer remix-sysdictbuf))) - (if (null buf) + "必要ならばシステム辞書とユーザ辞書を読み込み、hash table を作成して参照に備える" + ;; システム辞書のセッティング + (when (and remix-sysdict (null remix-sysdict-db)) + (let ((dictfiles remix-sysdict) + file size str) + (with-temp-buffer + (message "ReMix: システム辞書を読み込み中...") + (while (setq file (car dictfiles)) + (goto-char (point-max)) + (if (file-readable-p file) (progn - (setq buf (get-buffer-create remix-sysdictbuf)) - (set-buffer buf) - (while (setq file (car dictfiles)) - (if (file-readable-p file) - (progn - (insert-file-contents file t) - (goto-char (point-max)) - ;; 辞書ファイルの末尾が改行ではない場合に備える - (or (bolp) - (insert ?\n))) - (message (format - "ReMix: 報告: 指定されたシステム辞書 (%s) を読めませんでした" - file))) - (setq dictfiles (cdr dictfiles))) - (set-buffer-modified-p nil) - (setq buffer-read-only t))))) ; システム辞書は書換えない - - ;; ユーザ辞書のセッティング - (if (and remix-usrdict (null (get-buffer remix-usrdictbuf))) - (let ((buf (find-file-noselect remix-usrdict t))) - (set-buffer buf) - (rename-buffer remix-usrdictbuf) - (make-local-variable 'make-backup-files) - (setq make-backup-files nil))))) ; ユーザ辞書ファイルのバックアップは作らない - + (insert-file-contents file) + (goto-char (point-max)) + ;; 辞書ファイルの末尾が改行ではない場合は改行を挿入 + (or (bolp) (insert ?\n))) + (message "ReMix: 報告: 指定されたシステム辞書 (%s) を読めませんでした" + file)) + (setq dictfiles (cdr dictfiles))) + (message "ReMix: システム辞書を読み込み中...完了") + (setq size (remix-initialize-db-size (count-lines (point-min) (point-max)))) + (setq remix-sysdict-db (make-vector size 0)) + (goto-char (point-min)) + (message "ReMix: システム辞書を変換中...") + (while (not (eobp)) + (setq str (buffer-substring (line-beginning-position) + (line-end-position))) + (when (> (length str) 0) + (intern str remix-sysdict-db)) + (forward-line 1)) + (message "ReMix: システム辞書を変換中...完了")))) + ;; ユーザ辞書のセッティング + (when (and remix-usrdict (null remix-usrdict-db)) + (let (alist size) + (cond + ((file-exists-p remix-usrdict-alist-file) + ;; alist 形式の辞書を読み込む + (message "ReMix: ユーザ辞書(alist)を読み込み中...") + (with-temp-buffer + (insert-file-contents remix-usrdict-alist-file) + (setq alist (condition-case nil + (read (current-buffer)) + (error "ReMix: 報告: ユーザ辞書にエラーがあります")))) + (message "ReMix: ユーザ辞書(alist)を読み込み中...完了")) + ((and (stringp remix-usrdict) + (file-exists-p remix-usrdict)) + ;; 古い形式のファイルを alist 形式に変換する + (setq remix-usrdict-modified t) + (message "ReMix: ユーザ辞書(旧形式)を読み込み中...") + (with-temp-buffer + (insert-file-contents remix-usrdict) + (goto-char (point-min)) + (while (re-search-forward "^\\([^ ]+\\) \\([01]\\)\n" nil t) + (setq alist + (cons (cons (match-string 1) + (string-to-number (match-string 2))) + alist))) + (setq alist (nreverse alist))) + (message "ReMix: ユーザ辞書(旧形式)を読み込み中...完了"))) + ;; (delete-file remix-usrdict) + (setq size (remix-initialize-db-size (length alist))) + (setq remix-usrdict-db (make-vector size 0)) + (message "ReMix: ユーザ辞書を変換中...") + (mapcar + (lambda (entry) + (set (intern (car entry) remix-usrdict-db) (cdr entry))) + alist) + (message "ReMix: ユーザ辞書を変換中...完了")))) (defun remix-seq-indict-p (seq) "SEQ が辞書にあるかどうかを調べる。 -ユーザ辞書にあった場合は、SEQ の綴りフラグの point を返す。 -システム辞書にあった場合は remix-auto-add-entry に従ってユーザ辞書に SEQ を登録し、 -綴りフラグの point を返す。また、登録しなかった場合は 0 を、見つからなければ -nil を返す" - (save-excursion - (let ((entry (format "^%s " (regexp-quote seq)))) - (or (if remix-usrdict - (progn - (set-buffer remix-usrdictbuf) - (goto-char (point-min)) - (re-search-forward entry nil t)) ; ユーザ辞書から検索 - nil) - (if (< (length seq) remix-sysdict-length) - nil ; 指定文字数より短ければ検索しない - (if remix-sysdict - (progn - (set-buffer remix-sysdictbuf) - (goto-char (point-min)) - (setq entry (format "^%s$" (regexp-quote seq))) - (if (re-search-forward entry nil t) ; システム辞書から検索 - (if remix-auto-add-entry ; エントリ(seq)を自動で追加するか? - (remix-set-usrdict seq "0" 0) - 0) - nil)) - nil)))))) - -(defun remix-set-usrdict (seq flag dict) - "SEQ の綴りフラグを FLAG に変更する。 -FLAG を挿入した point を返す" - (save-excursion - (set-buffer remix-usrdictbuf) - (if (or (null dict) - (zerop dict)) - (progn - (goto-char (point-min)) - (insert (format "%s %s\n" seq flag))) - (goto-char dict) - (end-of-line) - (delete-region dict (point)) - (insert flag)) - (set-buffer-modified-p nil) - (clear-visited-file-modtime) - (setq remix-usrdict-modified t) - (forward-word -1) - (point))) +ユーザ辞書にあった場合は、非ローマ字綴りなら 0, ローマ字綴りなら 1 を返す。 +システム辞書にあった場合は remix-auto-add-entry に従ってユーザ辞書に SEQ を +登録し 0 を返す。また、登録しなかった場合は 2 を、見つからなければ nil を返す" + (or (if remix-usrdict + (let ((sym (intern-soft seq remix-usrdict-db))) + (if sym (symbol-value sym)))) + (if (< (length seq) remix-sysdict-length) + nil ; 検索しない + (if remix-sysdict-db + (if (intern-soft seq remix-sysdict-db) + (if remix-auto-add-entry ; エントリ(seq)を自動で追加するか? + (remix-set-usrdict seq 0) + 2) ;; システム辞書にあった + nil))))) + +(defun remix-set-usrdict (seq flag) + "ユーザ辞書の SEQ の綴りフラグを FLAG に変更し、flag を返す。" + (setq remix-usrdict-modified t) + (set (intern seq remix-usrdict-db) flag)) (defun remix-kick-convert-region-or-self-insert () "状況に応じて文字を入力するか漢字変換を呼び出す。 @@ -1133,11 +1168,32 @@ (substring seq i))) (defun remix-save-dict () - (if (and remix-usrdict-modified - (get-buffer remix-usrdictbuf)) - (save-excursion - (set-buffer remix-usrdictbuf) - (write-file remix-usrdict)))) + "ユーザ辞書を alist 形式に変換して保存する。" + (when (and remix-usrdict-modified + remix-usrdict-db) + (when (and remix-usrdict-alist-file-backup + (file-readable-p remix-usrdict-alist-file) + (file-writable-p (concat remix-usrdict-alist-file ".bak"))) + (rename-file remix-usrdict-alist-file + (concat remix-usrdict-alist-file ".bak") 'ok)) + (let (alist print-length print-level) ;; for Emacs 21 + (mapatoms + (lambda (sym) + (setq alist (cons (cons (symbol-name sym) + (symbol-value sym)) + alist))) + remix-usrdict-db) + (setq alist (sort alist (lambda (x y) (string< (car x) (car y))))) + (with-temp-buffer + (pp alist (current-buffer)) + (write-region (point-min) (point-max) + remix-usrdict-alist-file nil 'nomsg) + (when remix-usrdict-file-mode + (if (numberp remix-usrdict-file-mode) + (set-file-modes remix-usrdict-alist-file remix-usrdict-file-mode) + (set-file-modes remix-usrdict-alist-file + (string-to-int remix-usrdict-file-mode 8)))))) + (setq remix-usrdict-modified nil))) (defun remix-mode () "\\{remix-its-mode-map}" @@ -1199,6 +1255,7 @@ "Egg-ReMix を起ち上げる" (interactive) (remix-initialize-egg) + (remix-initialize) (run-hooks 'remix-setup-hook) (unless (featurep 'egg-remix) ;; 初期状態(フォールバック)のインジケータ