[Mew-dist 369] mew-my-refile.el
Tomoyuki Kudou
kudou at example.com
1997年 1月 7日 (火) 16:16:11 JST
工藤@Pacifitech です。
社内の mew ユーザから refile を一括で行う際に毎回 minibuffer で
パターン(プロンプト)を打たなくてはいけないのが煩わしいので、これ
をユーザ設定しておいてキー一発で refile できないかという要望があ
りました。特に流量の激しいメーリングリストに参加している場合には、
この機能があるとメールの一括処理ができてとても便利です。
mew の機能を調べたところ、どうもこのような機能がないようなので、
作ってしまいました(作ったといっても既にある関数をもとに多少変更
しただけですが)。ひょっとしたらもっと手軽な方法があるかもしれま
せんが、これで結構満足しています。次の mew のリリースでデフォル
トでこの機能を組み込んでもらえればとっても嬉しいです。バグとかが
あれば教えてください。
使い方は +inbox で my とタイプすると、.emacs 内で指定したパターン
のメールが、自動的に 指定したフォルダへの refile 対象として "o"
マークが付けられます。実際に refile するには、その後で、x とタイプ
します。
この機能を使うには、オリジナルの mew.el と mew-summary.el を少し
だけ変更します。
-- mew.el -- の一番後ろ
(require 'mew-my-refile) ;; <== ここ
-- mew-summary.el --
(if mew-summary-mode-map
()
(setq mew-summary-mode-map (make-sparse-keymap))
(define-key mew-summary-mode-map " " 'mew-summary-show)
...
(define-key mew-summary-mode-map "mu" 'mew-summary-mark-undo-all)
(define-key mew-summary-mode-map "my" 'mew-summary-my-refile) ;; <== このへん
...
また次のファイル mew-my-refile.el を適当な elisp のパスの通った
場所に置きます。
-- mew-my-refile.el --
;; mew-my-refile.el
;; $Header: /d/salt/sd7g/home/kudou/elisp/mew-my-refile.el,v 1.3 1997/01/07 06:59:57 kudou Exp $
(defconst mew-summary-my-refile "mew-my-refile.el version 0.02")
(require 'mew)
(defvar mew-my-refile-alist '()
"alist which consists of mail pattern and folder name")
(defun mew-summary-my-refile ()
(interactive)
(let ((a mew-my-refile-alist)
prompt folder)
(while (not (null a))
(progn
(setq prompt (car (car a)))
(setq folder (cdr (car a)))
(mew-summary-my-refile-x prompt folder)
(setq a (cdr a))))))
(defun mew-summary-my-refile-x (prompt &optional folder)
(interactive)
(progn
(mew-summary-search-mark-x prompt)
(mew-summary-mark-refile-x folder)))
(defun mew-summary-mark-refile-x (folder)
(interactive)
(let ((regex (concat mew-summary-message-regex
(regexp-quote (char-to-string mew-mark-hop))))
(mew-summary-buffer-disp-msg nil)
)
(save-excursion
(goto-char (point-min))
(if (not (re-search-forward regex nil t))
(message "No marked messages")
(beginning-of-line)
(let ((mew-summary-refile-last-destination nil)
(mew-analysis nil))
(if (if (null folder)
(setq folder (mew-decide-folder))
folder)
(while (re-search-forward regex nil t)
(let ((buffer-read-only nil));; mew-summary-unmark
(delete-backward-char 1)
(insert " "))
(mew-summary-refile-mark folder)
(forward-line 1))
))
)
))
)
(defun mew-summary-search-mark-x (prompt)
(interactive)
(if (equal (point-min) (point-max))
(message "No messages in this buffer.")
(let ((folder (buffer-name))
(pattern nil)
(first nil)
(last nil)
(range nil))
(setq pattern (mew-pick-input-pattern-x prompt))
(message "Picking messages in %s ..." folder)
(goto-char (point-min))
(setq first (mew-summary-message-number))
(goto-char (point-max))
(forward-line -1)
(setq last (mew-summary-message-number))
(setq range (mew-summary-pick folder pattern (concat first "-" last)))
(message "Picking messages in %s ... done" folder)
(if (null range)
()
(message "Marking messages ... ")
(goto-char (point-min))
(while (not (eobp))
(if (and (null (mew-summary-marked-p))
(mew-member-del (mew-summary-message-number) range))
(mew-summary-mark mew-mark-hop))
(forward-line))
(message "Marking messages ... done")
)
)))
(defun mew-pick-input-pattern-x (&optional prompt)
(mew-pick-macro-expand
(mew-pick-input-pattern-raw-x prompt)))
(defun mew-pick-input-pattern-raw-x (&optional prompt)
(let ((pat nil))
(if (string= prompt "")
(setq pat (read-from-minibuffer
(format "Pattern%s (%s) : "
(if prompt prompt "")
mew-prog-pick-default-arg)
"-" mew-pick-map nil))
(setq pat prompt))
(setq pat (downcase pat))
(cond
((string-match " " pat)
(mapcar (function mew-summary-search-blace)
(mew-header-delete-nullstring-list
(mew-header-split pat 32))));; 32 is " "
(t
(if (or (string= pat "") (string= pat "-"))
(setq pat mew-prog-pick-default-arg))
(cond
((mew-member pat mew-prog-pick-arglogic-unary)
(cons pat (mew-pick-input-pattern-raw (format " for %s" pat))))
((mew-member pat mew-prog-pick-arglogic-binary)
(mew-pick-input-logic pat))
((mew-member pat mew-prog-pick-argdate)
(cons pat (mew-pick-input-value (format "Date for %s" pat)
mew-prog-pick-argdatealist)))
((assoc pat mew-pick-macro-alist)
(let* ((assoc (assoc pat mew-pick-macro-alist))
(args (nth 1 assoc)) arg n datep res)
(setq res (list pat))
(while args
(setq arg (car args))
(setq args (cdr args))
(setq n (and (string-match "[0-9]+" arg) (mew-match 0 arg)))
(setq datep (string-match "d" arg))
(setq res
(nconc
(mew-pick-input-value
(cond ((and n datep)
(format "Date arg %s for %s" n pat))
(n
(format "Arg %s for %s" n pat))
(datep
(format "Date for %s" pat))
(t
(format "Value for %s" pat)))
(and datep mew-prog-pick-argdatealist))
res)))
(nreverse res)))
(t (cons pat (mew-pick-input-value (format "Value for %s" pat))))
)
)
)))
(provide 'mew-my-refile)
<--- ココマデ
最後に、.emacs の中で自分の好みに合わせて、次のように
mew-my-refile-alist という連想リストを定義すれば設定は完了です。
(setq mew-my-refile-alist
'(("-to mew-dist at example.com" . "+mew-dist")
("-subject test" . "+test")
("-subject baz")
("-subject foo" . "+foo")
("-subject bar" . "+bar")
))
連想リストの各要素の car 部分(左側)は +inbox で ? をタイプした
時に minibuffer に入力するパターンと同じです。いわゆるプロンプト
というやつです。
cdr 部分(右側)は folder の名称を指定します。文字列の頭に + を
付けるのに気を付けてください。cdr 部分は省略することが可能で、
その場合には、folder 名は +inbox で mo とタイプした時と同じよ
うにフォルダ名が推測されインタラクティブに処理されます。上記の
例では "-subuject baz" にあたります。
作ったあとで後悔したのですが、mew-my-refile というのはちょっと
名前が悪かったかなと思っています。もっといいネーミングがあるか
もしれませんが、キーバインドも my ということで勘弁してください。
---
Pacifitech Corporation
Tomoyuki Kudou <kudou at example.com>
Mew-dist メーリングリストの案内