Gnus development mailing list
 help / color / mirror / Atom feed
From: TSUCHIYA Masatoshi <tsuchiya@namazu.org>
Subject: Re: Continuation lines for persistent articles
Date: Thu, 17 Oct 2002 22:19:46 +0900	[thread overview]
Message-ID: <8765w1td71.fsf@pine.kuee.kyoto-u.ac.jp> (raw)
In-Reply-To: <87znti2qs6.fsf@crybaby.cs.uni-dortmund.de>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=iso-2022-jp-2, Size: 2102 bytes --]

Hi,

>> On Sun, 13 Oct 2002 19:27:05 +0200
>> Kai.Grossjohann@CS.Uni-Dortmund.DE (Kai Gro^[.A^[N_johann) said as follows:

>> I am worry that all functions which call nnheader-parse-head() must
>> unfold continuation lines before calling it.  If this observation
>> is right, a better approach would be to make nnheader-parse-head()
>> unfold them.

>I think this is a good idea.

I see.

I think that related changes can be splited into 2 parts.

The first part is installed to nnheader.el.  This change introduces
some new functions and makes nnheader-parse-head() unfold continuation
lines.

        nnheader.el (nnheader-parse-naked-head): New function.
        (nnheader-parse-head): Use the above function, in order to
        handle continuation lines properly.
        (nnheader-remove-body): New function.
        (nnheader-remove-cr-followed-by-lf): New function.
        (nnheader-ms-strip-cr): Use the above function.

I hope that this change can be installed to Gnus without ill effects.
However, I suppose that it makes Gnus slow, because the new version of
nnheader-parse-head() copies headers to temporary buffer in order to
avoid side effects.

The second part is required to reduce excessive header copy.  I hope
that these changes will make Gnus as fast as the older version.

        gnus-agent.el (gnus-agent-regenerate-group): Call
        `nnheader-remove-body'; Use `nnheader-parse-naked-head'
        instead of `nnheader-parse-head'.
        gnus-cache.el (gnus-cache-possibly-enter-article): Ditto.
        gnus-msg.el (gnus-inews-yank-articles): Do not unfold
        continuation lines by itself;  Call `nnheader-parse-naked-head'
        instead of `nnheader-parse-head'.
        nndiary.el (nndiary-parse-head): Ditto.
        nnfolder.el (nnfolder-parse-head): Ditto.
        nnimap.el (nnimap-retrieve-headers-progress): Ditto.
        nnmaildir.el (nnmaildir--update-nov): Ditto.
        nnml.el (nnml-parse-head): Ditto.

I checked changes of gnus-cache.el and nnml.el, but the other changes
are not tested.

Thanks to Mr. Yamaoka for his advices about these changes.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 14750 bytes --]

Index: gnus-agent.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-agent.el,v
retrieving revision 6.82
diff -u -r6.82 gnus-agent.el
--- gnus-agent.el	2002/10/15 10:15:48	6.82
+++ gnus-agent.el	2002/10/17 06:57:36
@@ -2031,11 +2031,8 @@
 	      (mm-with-unibyte-buffer
 		(nnheader-insert-file-contents
 		 (concat dir (number-to-string (car arts))))
-		(goto-char (point-min))
-		(if (search-forward "\n\n" nil t)
-		    (delete-region (point) (point-max))
-		  (goto-char (point-max)))
-		(setq header (nnheader-parse-head t)))
+		(nnheader-remove-body)
+		(setq header (nnheader-parse-naked-head)))
 	      (mail-header-set-number header (car arts))
 	      (nnheader-insert-nov header)
 	      (setq changed t)
Index: gnus-cache.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-cache.el,v
retrieving revision 6.18
diff -u -r6.18 gnus-cache.el
--- gnus-cache.el	2002/06/16 09:49:28	6.18
+++ gnus-cache.el	2002/10/17 06:57:36
@@ -179,7 +179,8 @@
 	    (when (> (buffer-size) 0)
 	      (let ((coding-system-for-write gnus-cache-coding-system))
 		(gnus-write-buffer file))
-	      (setq headers (nnheader-parse-head t))
+	      (nnheader-remove-body)
+	      (setq headers (nnheader-parse-naked-head))
 	      (mail-header-set-number headers number)
 	      (gnus-cache-change-buffer group)
 	      (set-buffer (cdr gnus-cache-buffer))
Index: gnus-msg.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/gnus-msg.el,v
retrieving revision 6.100
diff -u -r6.100 gnus-msg.el
--- gnus-msg.el	2002/09/25 23:45:17	6.100
+++ gnus-msg.el	2002/10/17 06:57:37
@@ -719,8 +719,7 @@
 	     (with-current-buffer gnus-article-copy
 	       (save-restriction
 		 (nnheader-narrow-to-headers)
-		 (ietf-drums-unfold-fws)
-		 (nnheader-parse-head t)))))
+		 (nnheader-parse-naked-head)))))
 	(message-yank-original)
 	(setq beg (or beg (mark t))))
       (when articles
Index: nndiary.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nndiary.el,v
retrieving revision 1.6
diff -u -r1.6 nndiary.el
--- nndiary.el	2002/05/15 19:55:38	1.6
+++ nndiary.el	2002/10/17 06:57:37
@@ -1123,13 +1123,7 @@
 	(narrow-to-region
 	 (goto-char (point-min))
 	 (if (search-forward "\n\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	(replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      (let ((headers (nnheader-parse-head t)))
+      (let ((headers (nnheader-parse-naked-head)))
 	(mail-header-set-chars headers chars)
 	(mail-header-set-number headers number)
 	headers))))
Index: nnfolder.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnfolder.el,v
retrieving revision 6.42
diff -u -r6.42 nnfolder.el
--- nnfolder.el	2002/07/20 14:41:21	6.42
+++ nnfolder.el	2002/10/17 06:57:37
@@ -1150,13 +1150,7 @@
 	(if (search-forward "\n\n" e t) (setq e (1- (point)))))
       (with-temp-buffer
 	(insert-buffer-substring buf b e)
-	;; Fold continuation lines.
-	(goto-char (point-min))
-	(while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	  (replace-match " " t t))
-	;; Remove any tabs; they are too confusing.
-	(subst-char-in-region (point-min) (point-max) ?\t ? )
-	(let ((headers (nnheader-parse-head t)))
+	(let ((headers (nnheader-parse-naked-head)))
 	  (mail-header-set-chars headers chars)
 	  (mail-header-set-number headers number)
 	  headers)))))
Index: nnheader.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnheader.el,v
retrieving revision 6.28
diff -u -r6.28 nnheader.el
--- nnheader.el	2002/08/20 09:12:50	6.28
+++ nnheader.el	2002/10/17 06:57:37
@@ -213,120 +213,135 @@
 
 ;; Parsing headers and NOV lines.
 
+(defsubst nnheader-remove-cr-followed-by-lf ()
+  (goto-char (point-max))
+  (while (search-backward "\r\n" nil t)
+    (delete-char 1)))
+
 (defsubst nnheader-header-value ()
   (skip-chars-forward " \t")
   (buffer-substring (point) (gnus-point-at-eol)))
 
-(defun nnheader-parse-head (&optional naked)
+(defun nnheader-parse-naked-head (&optional number)
+  ;; This function unfolds continuation lines in this buffer
+  ;; destructively.  When this side effect is unwanted, use
+  ;; `nnheader-parse-head' instead of this function.
   (let ((case-fold-search t)
-	(cur (current-buffer))
 	(buffer-read-only nil)
-	in-reply-to lines p ref)
-    (goto-char (point-min))
-    (when naked
-      (insert "\n"))
-    ;; Search to the beginning of the next header.  Error messages
-    ;; do not begin with 2 or 3.
+	(cur (current-buffer))
+	(p (point-min))
+	in-reply-to lines ref)
+    (nnheader-remove-cr-followed-by-lf)
+    (ietf-drums-unfold-fws)
+    (subst-char-in-region (point-min) (point-max) ?\t ? )
+    (goto-char p)
+    (insert "\n")
     (prog1
-	(when (or naked (re-search-forward "^[23][0-9]+ " nil t))
-	  ;; This implementation of this function, with nine
-	  ;; search-forwards instead of the one re-search-forward and
-	  ;; a case (which basically was the old function) is actually
-	  ;; about twice as fast, even though it looks messier.	 You
-	  ;; can't have everything, I guess.  Speed and elegance
-	  ;; don't always go hand in hand.
-	  (vector
-	   ;; Number.
-	   (if naked
-	       (progn
-		 (setq p (point-min))
-		 0)
-	     (prog1
-		 (read cur)
-	       (end-of-line)
-	       (setq p (point))
-	       (narrow-to-region (point)
-				 (or (and (search-forward "\n.\n" nil t)
-					  (- (point) 2))
-				     (point)))))
-	   ;; Subject.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nsubject:" nil t)
-		 (nnheader-header-value) "(none)"))
-	   ;; From.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nfrom:" nil t)
-		 (nnheader-header-value) "(nobody)"))
-	   ;; Date.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\ndate:" nil t)
-		 (nnheader-header-value) ""))
-	   ;; Message-ID.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nmessage-id:" nil t)
-		 (buffer-substring
-		  (1- (or (search-forward "<" (gnus-point-at-eol) t)
-			  (point)))
-		  (or (search-forward ">" (gnus-point-at-eol) t) (point)))
-	       ;; If there was no message-id, we just fake one to make
-	       ;; subsequent routines simpler.
-	       (nnheader-generate-fake-message-id)))
-	   ;; References.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nreferences:" nil t)
-		 (nnheader-header-value)
-	       ;; Get the references from the in-reply-to header if there
-	       ;; were no references and the in-reply-to header looks
-	       ;; promising.
-	       (if (and (search-forward "\nin-reply-to:" nil t)
-			(setq in-reply-to (nnheader-header-value))
-			(string-match "<[^\n>]+>" in-reply-to))
-		   (let (ref2)
-		     (setq ref (substring in-reply-to (match-beginning 0)
-					  (match-end 0)))
-		     (while (string-match "<[^\n>]+>"
-					  in-reply-to (match-end 0))
-		       (setq ref2 (substring in-reply-to (match-beginning 0)
-					     (match-end 0)))
-		       (when (> (length ref2) (length ref))
-			 (setq ref ref2)))
-		     ref)
-		 nil)))
-	   ;; Chars.
-	   0
-	   ;; Lines.
-	   (progn
-	     (goto-char p)
-	     (if (search-forward "\nlines: " nil t)
-		 (if (numberp (setq lines (read cur)))
-		     lines 0)
-	       0))
-	   ;; Xref.
-	   (progn
-	     (goto-char p)
-	     (and (search-forward "\nxref:" nil t)
-		  (nnheader-header-value)))
-
-	   ;; Extra.
-	   (when nnmail-extra-headers
-	     (let ((extra nnmail-extra-headers)
-		   out)
-	       (while extra
-		 (goto-char p)
-		 (when (search-forward
-			(concat "\n" (symbol-name (car extra)) ":") nil t)
-		   (push (cons (car extra) (nnheader-header-value))
-			 out))
-		 (pop extra))
-	       out))))
-      (when naked
-	(goto-char (point-min))
-	(delete-char 1)))))
+	;; This implementation of this function, with nine
+	;; search-forwards instead of the one re-search-forward and a
+	;; case (which basically was the old function) is actually
+	;; about twice as fast, even though it looks messier.  You
+	;; can't have everything, I guess.  Speed and elegance don't
+	;; always go hand in hand.
+	(vector
+	 ;; Number.
+	 (or number 0)
+	 ;; Subject.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nsubject:" nil t)
+	       (nnheader-header-value) "(none)"))
+	 ;; From.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nfrom:" nil t)
+	       (nnheader-header-value) "(nobody)"))
+	 ;; Date.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\ndate:" nil t)
+	       (nnheader-header-value) ""))
+	 ;; Message-ID.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nmessage-id:" nil t)
+	       (buffer-substring
+		(1- (or (search-forward "<" (gnus-point-at-eol) t)
+			(point)))
+		(or (search-forward ">" (gnus-point-at-eol) t) (point)))
+	     ;; If there was no message-id, we just fake one to make
+	     ;; subsequent routines simpler.
+	     (nnheader-generate-fake-message-id)))
+	 ;; References.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nreferences:" nil t)
+	       (nnheader-header-value)
+	     ;; Get the references from the in-reply-to header if
+	     ;; there were no references and the in-reply-to header
+	     ;; looks promising.
+	     (if (and (search-forward "\nin-reply-to:" nil t)
+		      (setq in-reply-to (nnheader-header-value))
+		      (string-match "<[^\n>]+>" in-reply-to))
+		 (let (ref2)
+		   (setq ref (substring in-reply-to (match-beginning 0)
+					(match-end 0)))
+		   (while (string-match "<[^\n>]+>"
+					in-reply-to (match-end 0))
+		     (setq ref2 (substring in-reply-to (match-beginning 0)
+					   (match-end 0)))
+		     (when (> (length ref2) (length ref))
+		       (setq ref ref2)))
+		   ref)
+	       nil)))
+	 ;; Chars.
+	 0
+	 ;; Lines.
+	 (progn
+	   (goto-char p)
+	   (if (search-forward "\nlines: " nil t)
+	       (if (numberp (setq lines (read cur)))
+		   lines 0)
+	     0))
+	 ;; Xref.
+	 (progn
+	   (goto-char p)
+	   (and (search-forward "\nxref:" nil t)
+		(nnheader-header-value)))
+	 ;; Extra.
+	 (when nnmail-extra-headers
+	   (let ((extra nnmail-extra-headers)
+		 out)
+	     (while extra
+	       (goto-char p)
+	       (when (search-forward
+		      (concat "\n" (symbol-name (car extra)) ":") nil t)
+		 (push (cons (car extra) (nnheader-header-value))
+		       out))
+	       (pop extra))
+	     out)))
+      (goto-char p)
+      (delete-char 1))))
+
+(defun nnheader-parse-head (&optional naked)
+  (let ((cur (current-buffer)) num beg end)
+    (when (if naked
+	      (setq num 0
+		    beg (point-min)
+		    end (point-max))
+	    (goto-char (point-min))
+	    ;; Search to the beginning of the next header.  Error
+	    ;; messages do not begin with 2 or 3.
+	    (when (re-search-forward "^[23][0-9]+ " nil t)
+	      (end-of-line)
+	      (setq num (read cur)
+		    beg (point)
+		    end (if (search-forward "\n.\n" nil t)
+			    (- (point) 2)
+			  (point)))))
+      (with-temp-buffer
+	(insert-buffer-substring cur beg end)
+	(nnheader-parse-naked-head num)))))
 
 (defmacro nnheader-nov-skip-field ()
   '(search-forward "\t" eol 'move))
@@ -615,6 +630,13 @@
      (point-max)))
   (goto-char (point-min)))
 
+(defun nnheader-remove-body ()
+  "Remove the body from an article in this current buffer."
+  (goto-char (point-min))
+  (when (or (search-forward "\n\n" nil t)
+	    (search-forward "\n\r\n" nil t))
+    (delete-region (point) (point-max))))
+
 (defun nnheader-set-temp-buffer (name &optional noerase)
   "Set-buffer to an empty (possibly new) buffer called NAME with undo disabled."
   (set-buffer (get-buffer-create name))
@@ -834,9 +856,7 @@
 (defun nnheader-ms-strip-cr ()
   "Strip ^M from the end of all lines."
   (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "\r$" nil t)
-      (delete-backward-char 1))))
+    (nnheader-remove-cr-followed-by-lf)))
 
 (defun nnheader-file-size (file)
   "Return the file size of FILE or 0."
Index: nnimap.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnimap.el,v
retrieving revision 6.48
diff -u -r6.48 nnimap.el
--- nnimap.el	2002/10/10 02:40:50	6.48
+++ nnimap.el	2002/10/17 06:57:38
@@ -528,10 +528,7 @@
        (with-temp-buffer
 	 (buffer-disable-undo)
 	 (insert headers)
-	 (nnheader-ms-strip-cr)
-	 (nnheader-fold-continuation-lines)
-	 (subst-char-in-region (point-min) (point-max) ?\t ? )
-	 (let ((head (nnheader-parse-head 'naked)))
+	 (let ((head (nnheader-parse-naked-head)))
 	   (mail-header-set-number head uid)
 	   (mail-header-set-chars head chars)
 	   (mail-header-set-lines head lines)
Index: nnmaildir.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnmaildir.el,v
retrieving revision 6.21
diff -u -r6.21 nnmaildir.el
--- nnmaildir.el	2002/10/03 18:16:25	6.21
+++ nnmaildir.el	2002/10/17 06:57:38
@@ -371,8 +371,7 @@
 	    (setq nov-mid 0))
 	  (goto-char (point-min))
 	  (delete-char 1)
-	  (nnheader-fold-continuation-lines)
-	  (setq nov (nnheader-parse-head 'naked)
+	  (setq nov (nnheader-parse-naked-head)
 		field (or (mail-header-lines nov) 0)))
 	(unless (or (zerop field) (nnmaildir--param pgname 'distrust-Lines:))
 	  (setq nov-mid field))
Index: nnml.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/nnml.el,v
retrieving revision 6.40
diff -u -r6.40 nnml.el
--- nnml.el	2002/05/13 15:29:09	6.40
+++ nnml.el	2002/10/17 06:57:38
@@ -701,16 +701,12 @@
       (unless (zerop (buffer-size))
 	(narrow-to-region
 	 (goto-char (point-min))
-	 (if (re-search-forward "\n\r?\n" nil t) (1- (point)) (point-max))))
-      ;; Fold continuation lines.
-      (goto-char (point-min))
-      (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
-	(replace-match " " t t))
-      ;; Remove any tabs; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\t ? )
-      ;; Remove any ^M's; they are too confusing.
-      (subst-char-in-region (point-min) (point-max) ?\r ? )
-      (let ((headers (nnheader-parse-head t)))
+	 (if (search-forward "\n\n" nil t)
+	     (1- (point))
+	   (if (search-forward "\n\r\n" nil t)
+	       (- (point) 2)
+	     (point-max)))))
+      (let ((headers (nnheader-parse-naked-head)))
 	(mail-header-set-chars headers chars)
 	(mail-header-set-number headers number)
 	headers))))

[-- Attachment #3: Type: application/octet-stream, Size: 23 bytes --]

-- 
TSUCHIYA Masatoshi

  reply	other threads:[~2002-10-17 13:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-10-13  5:47 TSUCHIYA Masatoshi
2002-10-13 17:27 ` Kai Großjohann
2002-10-17 13:19   ` TSUCHIYA Masatoshi [this message]
2002-10-17 13:32   ` TSUCHIYA Masatoshi
2002-10-17 15:09     ` Katsumi Yamaoka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8765w1td71.fsf@pine.kuee.kyoto-u.ac.jp \
    --to=tsuchiya@namazu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).