1 Return-Path: <dme@dme.org>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 53982431FBC
\r
6 for <notmuch@notmuchmail.org>; Thu, 18 Feb 2010 01:44:17 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-2.318 tagged_above=-999 required=5 tests=[AWL=0.281,
\r
12 BAYES_00=-2.599] autolearn=ham
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id oiEenqhIVFng for <notmuch@notmuchmail.org>;
\r
16 Thu, 18 Feb 2010 01:44:15 -0800 (PST)
\r
17 Received: from mail-ew0-f222.google.com (mail-ew0-f222.google.com
\r
19 by olra.theworths.org (Postfix) with ESMTP id 948BE431FAE
\r
20 for <notmuch@notmuchmail.org>; Thu, 18 Feb 2010 01:44:15 -0800 (PST)
\r
21 Received: by ewy22 with SMTP id 22so3269242ewy.30
\r
22 for <notmuch@notmuchmail.org>; Thu, 18 Feb 2010 01:44:14 -0800 (PST)
\r
23 Received: by 10.213.43.9 with SMTP id u9mr1931376ebe.4.1266486254736;
\r
24 Thu, 18 Feb 2010 01:44:14 -0800 (PST)
\r
25 Received: from aw.hh.sledj.net (gmp-ea-fw-1b.sun.com [192.18.8.1])
\r
26 by mx.google.com with ESMTPS id 28sm1597390eye.31.2010.02.18.01.44.12
\r
27 (version=TLSv1/SSLv3 cipher=RC4-MD5);
\r
28 Thu, 18 Feb 2010 01:44:13 -0800 (PST)
\r
29 Received: by aw.hh.sledj.net (Postfix, from userid 1000)
\r
30 id 912017031E; Thu, 18 Feb 2010 09:43:55 +0000 (GMT)
\r
31 To: notmuch@notmuchmail.org
\r
32 In-Reply-To: <1266415452-25108-2-git-send-email-dme@dme.org>
\r
33 References: <1266415452-25108-1-git-send-email-dme@dme.org>
\r
34 <1266415452-25108-2-git-send-email-dme@dme.org>
\r
35 From: David Edmondson <dme@dme.org>
\r
36 Date: Thu, 18 Feb 2010 09:43:55 +0000
\r
37 Message-ID: <873a0yho9w.fsf@aw.hh.sledj.net>
\r
39 Content-Type: multipart/mixed; boundary="=-=-="
\r
40 Subject: Re: [notmuch] [PATCH 2/2] notmuch.el: Replace inline function calls
\r
41 for body cleaning with a hook mechanism.
\r
42 X-BeenThere: notmuch@notmuchmail.org
\r
43 X-Mailman-Version: 2.1.13
\r
45 List-Id: "Use and development of the notmuch mail system."
\r
46 <notmuch.notmuchmail.org>
\r
47 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
48 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
49 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
50 List-Post: <mailto:notmuch@notmuchmail.org>
\r
51 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
52 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
53 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
54 X-List-Received-Date: Thu, 18 Feb 2010 09:44:17 -0000
\r
58 On Wed, 17 Feb 2010 14:04:12 +0000, David Edmondson <dme@dme.org> wrote:
\r
59 > In-lining every possible body cleaning function is difficult to
\r
60 > maintain and doesn't allow users any flexibility. Rather, use a hook
\r
61 > mechanism so that users can choose what cleaning takes place.
\r
63 Improved version attached, including a new washing function to clean up
\r
64 citation blocks (suggested by Sebastian in #notmuch, though perhaps I
\r
65 went a bit further than he intended).
\r
69 Content-Type: text/x-diff; charset=utf-8
\r
70 Content-Disposition: inline;
\r
71 filename=0001-notmuch.el-Replace-inline-function-calls-for-body-cl.patch
\r
72 Content-Transfer-Encoding: quoted-printable
\r
74 >From 545e2a0936a19620bf4f91282ca2aca1da0504b7 Mon Sep 17 00:00:00 2001
\r
75 From: David Edmondson <dme@dme.org>
\r
76 Date: Wed, 17 Feb 2010 14:03:24 +0000
\r
77 Subject: [PATCH] notmuch.el: Replace inline function calls for body cleanin=
\r
81 In-lining every possible body cleaning function is difficult to
\r
82 maintain and doesn't allow users any flexibility. Rather, use a hook
\r
83 mechanism so that users can choose what cleaning takes place.
\r
85 notmuch-washing.el: Sample cleaning functions.
\r
87 Makefile.local | 6 ++-
\r
88 notmuch-washing.el | 113 ++++++++++++++++++++++++++++++++++++++++++++++++=
\r
90 notmuch.el | 104 +++++++++++++++++++++++++-----------------------
\r
91 3 files changed, 171 insertions(+), 52 deletions(-)
\r
92 create mode 100644 notmuch-washing.el
\r
94 diff --git a/Makefile.local b/Makefile.local
\r
95 index 0a1f203..7124af7 100644
\r
96 --- a/Makefile.local
\r
97 +++ b/Makefile.local
\r
99 # -*- mode:makefile -*-
\r
101 -emacs: notmuch.elc coolj.elc
\r
102 +emacs: notmuch.elc coolj.elc notmuch-washing.elc
\r
104 notmuch_client_srcs =3D \
\r
105 $(notmuch_compat_srcs) \
\r
106 @@ -46,6 +46,8 @@ install-emacs: install emacs
\r
107 install -m0644 notmuch.elc $(DESTDIR)$(emacs_lispdir)
\r
108 install -m0644 coolj.el $(DESTDIR)$(emacs_lispdir)
\r
109 install -m0644 coolj.elc $(DESTDIR)$(emacs_lispdir)
\r
110 + install -m0644 notmuch-washing.el $(DESTDIR)$(emacs_lispdir)
\r
111 + install -m0644 notmuch-washing.elc $(DESTDIR)$(emacs_lispdir)
\r
114 install -d $(DESTDIR)$(desktop_dir)
\r
115 @@ -62,4 +64,4 @@ install-zsh:
\r
116 $(DESTDIR)$(zsh_completion_dir)/notmuch
\r
118 SRCS :=3D $(SRCS) $(notmuch_client_srcs)
\r
119 -CLEAN :=3D $(CLEAN) notmuch $(notmuch_client_modules) notmuch.elc coolj.el=
\r
121 +CLEAN :=3D $(CLEAN) notmuch $(notmuch_client_modules) notmuch.elc coolj.el=
\r
122 c notmuch-washing.elc notmuch.1.gz
\r
123 diff --git a/notmuch-washing.el b/notmuch-washing.el
\r
124 new file mode 100644
\r
125 index 0000000..fc7b257
\r
127 +++ b/notmuch-washing.el
\r
129 +;; notmuch-washing.el --- functions to clean body parts
\r
131 +;; Copyright =C2=A9 David Edmondson
\r
133 +;; This file is not (yet) part of Notmuch.
\r
135 +;; Notmuch is free software: you can redistribute it and/or modify it
\r
136 +;; under the terms of the GNU General Public License as published by
\r
137 +;; the Free Software Foundation, either version 3 of the License, or
\r
138 +;; (at your option) any later version.
\r
140 +;; Notmuch is distributed in the hope that it will be useful, but
\r
141 +;; WITHOUT ANY WARRANTY; without even the implied warranty of
\r
142 +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
143 +;; General Public License for more details.
\r
145 +;; You should have received a copy of the GNU General Public License
\r
146 +;; along with Notmuch. If not, see <http://www.gnu.org/licenses/>.
\r
148 +;; Authors: David Edmondson <dme@dme.org>
\r
152 +;; Add these functions to `notmuch-show-markup-body-hook' using
\r
153 +;; `add-hook'. Something like:
\r
155 +;; (eval-after-load "notmuch"
\r
157 +;; (require 'notmuch-washing)
\r
158 +;; (setq notmuch-show-markup-body-hook nil)
\r
159 +;; (add-hook 'notmuch-show-markup-body-hook 'notmuch-show-washing-coo=
\r
161 +;; (add-hook 'notmuch-show-markup-body-hook 'notmuch-show-washing-cit=
\r
163 +;; (add-hook 'notmuch-show-markup-body-hook 'notmuch-show-washing-com=
\r
165 +;; (add-hook 'notmuch-show-markup-body-hook 'notmuch-show-markup-cita=
\r
169 +;; Note that the ordering of the functions is significant, given that
\r
170 +;; later functions operate on the results of the earlier functions.
\r
172 +(defun notmuch-show-washing-coolj (depth)
\r
173 + "Wrap text in the region whilst maintaining the correct prefix."
\r
174 + (coolj-wrap-region (point-min) (point-max)))
\r
176 +;; Utility functions.
\r
177 +(defun remove-prefix (depth)
\r
178 + (let ((prefix-regexp (format (format "^%%%ds" depth) "")))
\r
179 + (while (and (not (eobp))
\r
180 + (re-search-forward prefix-regexp nil t))
\r
181 + (replace-match "" nil nil)
\r
182 + (forward-line))))
\r
184 +(defun insert-prefix (depth)
\r
185 + (let ((prefix (format (format "%%%ds" depth) "")))
\r
186 + (while (not (eobp))
\r
188 + (forward-line))))
\r
190 +(defun notmuch-show-washing-compress-blanks (depth)
\r
191 + "Compress successive blank lines into one blank line."
\r
193 + ;; Algorithm derived from `article-strip-multiple-blank-lines' in
\r
194 + ;; `gnus-art.el'.
\r
196 + (goto-char (point-min))
\r
197 + (remove-prefix depth)
\r
199 + ;; Make all blank lines empty.
\r
200 + (goto-char (point-min))
\r
201 + (while (re-search-forward "^[ \t]+$" nil t)
\r
202 + (replace-match "" nil t))
\r
204 + ;; Replace multiple empty lines with a single empty line.
\r
205 + (goto-char (point-min))
\r
206 + (while (re-search-forward "\n\n\\(\n+\\)" nil t)
\r
207 + (delete-region (match-beginning 1) (match-end 1)))
\r
209 + (goto-char (point-min))
\r
210 + (insert-prefix depth))
\r
212 +(defun notmuch-show-washing-citations (depth)
\r
213 + "Clean up citations."
\r
215 + (goto-char (point-min))
\r
216 + (remove-prefix depth)
\r
218 + ;; Remove lines of repeated citation leaders with no other content.
\r
219 + (goto-char (point-min))
\r
220 + (while (re-search-forward "\\(^>[> ]*\n\\)\\{2,\\}" nil t)
\r
221 + (replace-match "\\1"))
\r
223 + ;; Remove citation leaders standing alone before a block of cited
\r
225 + (goto-char (point-min))
\r
226 + (while (re-search-forward "\\(\n\\|^[^>].*\\)\n\\(^>[> ]*\n\\)" nil t)
\r
227 + (replace-match "\\1\n"))
\r
229 + ;; Remove citation trailers standing alone after a block of cited
\r
231 + (goto-char (point-min))
\r
232 + (while (re-search-forward "\\(^>[> ]*\n\\)\\(^$\\|^[^>].*\\)" nil t)
\r
233 + (replace-match "\\2"))
\r
235 + ;; Remove blank lines between "Bill wrote:" and the citation.
\r
236 + (goto-char (point-min))
\r
237 + (while (re-search-forward "^\\([^>].*\\):\n\n>" nil t)
\r
238 + (replace-match "\\1:\n>"))
\r
240 + (goto-char (point-min))
\r
241 + (insert-prefix depth))
\r
245 +(provide 'notmuch-washing)
\r
246 diff --git a/notmuch.el b/notmuch.el
\r
247 index 040fb5e..9d86a3f 100644
\r
256 (defvar notmuch-show-mode-map
\r
257 (let ((map (make-sparse-keymap)))
\r
258 @@ -157,6 +156,12 @@ collapse remaining lines into a button.")
\r
259 (defvar notmuch-show-signatures-visible nil)
\r
260 (defvar notmuch-show-headers-visible nil)
\r
262 +(defun notmuch-show-markup-body-hook '(notmuch-show-markup-citations)
\r
263 + "List of functions used to clean up body parts.
\r
265 +Each is passed one argument: the indentation depth of the region
\r
268 ; XXX: This should be a generic function in emacs somewhere, not here
\r
269 (defun point-invisible-p ()
\r
270 "Return whether the character at point is invisible.
\r
271 @@ -703,52 +708,48 @@ is what to put on the button."
\r
276 -(defun notmuch-show-markup-citations-region (beg end depth)
\r
277 - "Markup citations, and up to one signature in the given region"
\r
278 - ;; it would be nice if the untabify was not required, but
\r
279 - ;; that would require notmuch to indent with spaces.
\r
280 - (untabify beg end)
\r
281 - (let ((citation-regexp (notmuch-show-citation-regexp depth))
\r
282 - (signature-regexp (concat (format "^[[:space:]]\\{%d\\}" depth)
\r
283 - notmuch-show-signature-regexp))
\r
284 - (indent (concat "\n" (make-string depth ? ))))
\r
286 - (beginning-of-line)
\r
287 - (while (and (< (point) end)
\r
288 - (re-search-forward citation-regexp end t))
\r
289 - (let* ((cite-start (match-beginning 0))
\r
290 - (cite-end (match-end 0))
\r
291 - (cite-lines (count-lines cite-start cite-end)))
\r
292 - (overlay-put (make-overlay cite-start cite-end) 'face 'message-cited-text=
\r
294 - (when (> cite-lines (1+ (+ notmuch-show-citation-lines-prefix notmuch-sho=
\r
295 w-citation-lines-suffix)))
\r
296 - (goto-char cite-start)
\r
297 - (forward-line notmuch-show-citation-lines-prefix)
\r
298 - (let ((hidden-start (point)))
\r
299 - (goto-char cite-end)
\r
300 - (forward-line (- notmuch-show-citation-lines-suffix))
\r
301 - (notmuch-show-region-to-button
\r
302 - hidden-start (point)
\r
305 - (format notmuch-show-citation-button-format
\r
306 - (- cite-lines notmuch-show-citation-lines-prefix notmuch-show-citat=
\r
309 - (if (and (< (point) end)
\r
310 - (re-search-forward signature-regexp end t))
\r
311 - (let* ((sig-start (match-beginning 0))
\r
312 - (sig-end (match-end 0))
\r
313 - (sig-lines (1- (count-lines sig-start end))))
\r
314 - (if (<=3D sig-lines notmuch-show-signature-lines-max)
\r
316 - (overlay-put (make-overlay sig-start end) 'face 'message-cited-text-face)
\r
317 - (notmuch-show-region-to-button
\r
322 - (format notmuch-show-signature-button-format sig-lines)
\r
324 +(defun notmuch-show-markup-citations (depth)
\r
325 + "Markup citations, and up to one signature in the buffer."
\r
326 + (let ((citation-regexp (notmuch-show-citation-regexp depth))
\r
327 + (signature-regexp (concat (format "^[[:space:]]\\{%d\\}" depth)
\r
328 + notmuch-show-signature-regexp))
\r
329 + (indent (concat "\n" (make-string depth ? ))))
\r
330 + (goto-char (point-min))
\r
331 + (beginning-of-line)
\r
332 + (while (and (< (point) (point-max))
\r
333 + (re-search-forward citation-regexp nil t))
\r
334 + (let* ((cite-start (match-beginning 0))
\r
335 + (cite-end (match-end 0))
\r
336 + (cite-lines (count-lines cite-start cite-end)))
\r
337 + (overlay-put (make-overlay cite-start cite-end) 'face 'message-cited-te=
\r
339 + (when (> cite-lines (1+ (+ notmuch-show-citation-lines-prefix notmuch-s=
\r
340 how-citation-lines-suffix)))
\r
341 + (goto-char cite-start)
\r
342 + (forward-line notmuch-show-citation-lines-prefix)
\r
343 + (let ((hidden-start (point)))
\r
344 + (goto-char cite-end)
\r
345 + (forward-line (- notmuch-show-citation-lines-suffix))
\r
346 + (notmuch-show-region-to-button
\r
347 + hidden-start (point)
\r
350 + (format notmuch-show-citation-button-format
\r
351 + (- cite-lines notmuch-show-citation-lines-prefix notmuch-show-cit=
\r
352 ation-lines-suffix))
\r
354 + (if (and (not (eobp))
\r
355 + (re-search-forward signature-regexp nil t))
\r
356 + (let* ((sig-start (match-beginning 0))
\r
357 + (sig-end (match-end 0))
\r
358 + (sig-lines (1- (count-lines sig-start (point-max)))))
\r
359 + (if (<=3D sig-lines notmuch-show-signature-lines-max)
\r
361 + (overlay-put (make-overlay sig-start (point-max)) 'face 'message-cited=
\r
363 + (notmuch-show-region-to-button
\r
368 + (format notmuch-show-signature-button-format sig-lines)
\r
371 (defun notmuch-show-markup-part (beg end depth)
\r
372 (if (re-search-forward notmuch-show-buttonize-begin-regexp nil t)
\r
373 @@ -791,9 +792,12 @@ is what to put on the button."
\r
374 (mm-display-part mime-message))))
\r
376 (if (equal mime-type "text/plain")
\r
378 - (coolj-wrap-region beg end)
\r
379 - (notmuch-show-markup-citations-region beg end depth)))
\r
380 + (save-restriction
\r
381 + (narrow-to-region beg end)
\r
382 + ;; it would be nice if the untabify was not required, but
\r
383 + ;; that would require notmuch to indent with spaces.
\r
384 + (untabify (point-min) (point-max))
\r
385 + (run-hook-with-args 'notmuch-show-markup-body-hook depth)))
\r
386 ; Advance to the next part (if any) (so the outer loop can
\r
387 ; determine whether we've left the current message.
\r
388 (if (re-search-forward notmuch-show-buttonize-begin-regexp n=
\r
399 David Edmondson, http://dme.org
\r