邪悪な設定編
設定ファイルを自動的にバイトコンパイル
問題
- Emacs や Gnus 等のアプリケーションの起動が遅くなる
- 一部の elisp の実行速度が遅くなる
原因
解決方法
- 多少遅くても我慢する
- 設定ファイルをバイトコンパイルする
- バッファセーブ時にバイトコンパイルする
- Emacs 終了時にバイトコンパイルする
一方、少しでも速い方がいいのであれば、 バイトコンパイルを試してみる価値はあります。
以下に、設定ファイルを自動的にバイトコンパイルするための設定を示します。
次の設定は、バッファセーブ時にバイトコンパイルするためのものです。 バッファセーブ時に、カレントバッファがバイトコンパイル対象であるか調べて、 対象であればバイトコンパイルします。 私は、この設定のほうが、 後述する Emacs 終了時にバイトコンパイル設定よりも、使いやすいと思います。
;; バッファセーブ時に、カレントバッファがバイトコンパイル対象ならバイ
;; トコンパイルする
(add-hook 'after-save-hook
(lambda ()
(mapcar
(lambda (file)
(setq file (expand-file-name file))
(when (string= file (buffer-file-name))
(save-excursion (byte-compile-file file))))
'("~/.emacs" "~/.gnus.el" "~/.wl"))))
;; Emacs 終了時に、バイトコンパイル対象が更新されているときだけバイト
;; コンパイルする
(add-hook 'kill-emacs-hook
(lambda ()
(mapcar
(lambda (file)
(setq file (expand-file-name file))
(when (file-newer-than-file-p file
(byte-compile-dest-file file))
(save-excursion (byte-compile-file file))))
'("~/.emacs" "~/.gnus.el" "~/.wl"))))
備考
Wanderlust でバナー広告を消す
問題
このような考えに基づき、Gnus/gnus では、 グループパラメタを使ってバナー広告を消す機能が提供されています。
しかしながら、Wanderlust では、このような機能は提供されておらず、 簡単に広告を消すことができません。
原因
解決方法
処理の手順は次のようになります。
- 見たくないバナー広告を正規表現で指定する
- Wanderlust でメールを閲覧するときに、 上記の正規表現にマッチする部分を非表示とする
なお、この設定は、あくまでも、広告を非表示にするだけであり、 メールの元データから削除するわけではありません。
;;;
;;; バナー広告を消すための設定
;;;
;; 見たくないバナー広告を正規表現で指定
;; リストで複数指定可能
(setq my-wl-banner-list
'(
;; eGroups のバナー
"^-+ eGroups Sponsor -+~-->\n\\(.\\|\n\\)+-+~->\n\\(.\\|\n\\)+"
;; Yahoo! BB のバナー
"^_+\nDo You Yahoo!\\?\\(.\\|\n\\)+http://bb\\.yahoo\\.co\\.jp/\n"))
;; メール表示時にバナー広告を削除
(add-hook 'wl-message-display-internal-hook
(lambda ()
(let (buffer-read-only)
(goto-char (point-min))
(while (re-search-forward
(concat "\\(" (mapconcat 'identity
my-wl-banner-list "\\|") "\\)")
(point-max) t)
(replace-match ""))
(set-buffer-modified-p nil))))
備考
例えば、次のようなバナー広告を消す場合を考えます。
----- banner start ------ 毎回変わる複数行の広告 ... ... ----- banner end ------
"^----- banner start ------\n\\(.\\|\n\\)+----- banner end ------\n"
"^-+ banner start -+\n\\(.\\|\n\\)+-+ banner end -+\n"
Wanderlust で快適に POP 経由でメールを取得する
問題
しかしながら、私の環境では、 Wanderlust で POP + パイプフォルダを使った場合、 非常に遅いと言う問題がありました。 新着メールのチェックに20秒程度、 小さなメール1 通を取ってくるのに1 分近くもかかっていました。
特に、 スピード狂で知られる Gnus/gnus から Wanderlustに移行してきた私にとっては、 耐えられるものではありませんでした。 Gnus/gnus では、 上記のような新着メールのチェックや取得は瞬時(コンマ数秒程度) に終わっていたものでした。
原因
- 私が使っている DTI の POP サーバは連続アクセスを許していない。 少なくとも10秒は間隔を空ける必要がある。
- Wanderlust では POP のコネクションを複数回張る。 prefetch すると、サーバにメールがないときで2回、 メールがあるときで5回、コネクションを張っては閉じているようである。
さらに、現状の Wanderlust の実装では、Gnus/gnus ほど性能を重視してチューニングされていないことも一因だと考えられます。
解決方法
- Wanderlust をチューニングして速くする
- Wanderlust 以外の速い実装を利用する
- 外部プログラムを使う -> fetchmail
- Elisp を使う -> Gnus
- Wanderlust から fetchmail を起動してメールを取得する
- procmail でメールを振り分ける
- prom-wl で新着メールをチェックする
処理のおおまかな流れは次のようになります。
- Gnus を利用してメールを取得する
- elmo-split でメールを振り分ける
- prom-wl で新着メールをチェックする
elmo-split は Wanderlust に含まれています。
prom-wl は Prom-WL -- Procmail reader for Wanderlust -- から取得してください。
以下に設定を示します。この設定を ~/.wl に追加することで、Gnus/gnus と 同じ感覚で、メールを取得できるようになります。メールを取得するには、 Wanderlust のフォルダーバッファにて `g' を入力します。
;;;
;;; Gnus を使って POP 経由でメールを取得
;;;
;; 取得したメールの保存先の指定
(setq my-mail-spool-directory "spool")
(require 'nnml)
(require 'nnmail)
(defun my-wl-fetch-mail (&optional arg)
(interactive "P")
(when wl-plugged ; off-line の場合は何もしない
(let (
;; メールディレクトリの設定
(mail-source-directory elmo-localdir-folder-path)
(nnml-directory elmo-localdir-folder-path)
;; 取得したメールの保存先の設定
(nnmail-split-methods `((,my-mail-spool-directory)))
;; メール取得用の一時ファイルを削除
(mail-source-delete-incoming t)
;; ???
(nnmail-fetched-sources '(t))
;; POP サーバの指定
(mail-sources '((pop :server "your.pop.server"
;; APOP の場合は下記を指定する
;; :authentication apop
;; 詳しくは`(gnus)Mail Source
;; Specifiers' を参照
)))
;; Message-ID cache を残さない
nnmail-treat-duplicates)
;; メールの取得
(nnmail-get-new-mail 'nnml nil nnml-directory))
;; メール振り分けのために prom-wl を起動する
(when (fboundp 'prom-wl)
(prom-wl))))
(add-hook 'wl-folder-mode-hook
(lambda ()
(define-key wl-folder-mode-map "g" 'my-wl-fetch-mail)))
;;;
;;; elmo-split の設定
;;;
(autoload 'elmo-split "elmo-split" "Split messages on the folder." t)
;; 振り分けの対象となるフォルダを指定
(setq elmo-split-folder (list (concat "+" my-mail-spool-directory)))
;; ログファイルの指定
(setq elmo-split-log-file "~/.elmo/split-log")
;; 振り分けルールの指定
(setq elmo-split-rule
'(
;; Wanderlust の info を見て、自分流の振り分け規則を書くべし
;; ...
;; X-ML-Name: があれば、それを名前とするフォルダに移動
((match x-ml-name "\\(.*\\)") "+\\1")
;; ...
;; どれにもマッチしなかったものを `+inbox' へ
(t "+inbox")))
;;;
;;; prom-wl の設定
;;;
(cond
((locate-library "prom-wl")
(autoload 'prom-wl "prom-wl" "Prom for Wanderlust" t)
;; elmo-split のログファイルの指定
(setq proc-log-list (list elmo-split-log-file))
;; elmo-split のログからフォルダ名を抽出するパターンの指定
(setq proc-folder-regexp "^ Folder: \\+\\([^ \t\n]+\\)")
;; prom-wl のログファイル指定
(setq proc-keep-log
(expand-file-name "listlog" elmo-localdir-folder-path))
;; Windows の場合は、シンボリックリンクがうまく動かないので、ファイ
;; ルのロックを自前で処理
(when (eq system-type 'windows-nt)
;; lockfile を使わない
(setq prom-use-lockfile nil)
;; ファイルのロックは自前で処理
(eval-after-load "prom-wl"
'(defun prom-make-lock (lockfile)
(if (file-exists-p lockfile)
(progn
(message "lock file exists!!")
nil)
(write-region "" nil lockfile nil 0)
t))))
;; prom-wl から elmo-split を実行
(add-hook 'prom-wl-get-new-mail-pre-hook 'elmo-split)))
備考
ちょっとした設定編
フレームのサイズをディスプレイに合わせる
この設定を .emacs に記述することで、 フレームの高さをディスプレイの高さの92%とすることができます。 つまり、ディスプレイの解像度が低い場合は小さなフレームが、 解像度が高い場合は大きなフレームが開くようになります。
フレームで使用するフォントの設定が完了しているのであれば、 行の高さを知るのに frame-char-height() を利用できます。 ところが、下記のような設定では、この前提が必ずしも成立しません。 したがって、利用するにはそれなりの工夫が必要でしょう。
(let* ((line-height 16) ; 行の高さ
(scale 0.92) ; ディスプレイの高さを1としたときの
; フレームの高さの割合
;; ディスプレイの高さを行の高さで割り行数に変換して、scale 倍する
(height (round (* (/ (x-display-pixel-height) line-height) scale))))
;; フレームパラメタに設定
(setq default-frame-alist
(cons (cons 'height height) default-frame-alist)))
(setq resolution-alist
'((480 . 29) ; 480ピクセル -> 29行
(600 . 33) ; 600ピクセル -> 33行
(768 . 43) ; 768ピクセル -> 43行
(1024 . 59))) ; 9999ピクセル -> 59行
(setq default-frame-alist
(cons (cons 'height
(cdr (assoc (x-display-pixel-height) resolution-alist)))
default-frame-alist)))
(setq resolution-alist
'((480 . 29) ; 480ピクセル以下 -> 29行
(600 . 33) ; 600ピクセル以下 -> 33行
(768 . 43) ; 768ピクセル以下 -> 43行
(9999 . 59))) ; 9999ピクセル以下 -> 59行
(setq default-frame-alist
(cons (cons 'height
(assoc-default (x-display-pixel-height)
resolution-alist '>=))
default-frame-alist)))