From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Sandra Snan via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#71017: [PATCH] Flow single-paragraph messages Date: Sun, 7 Jul 2024 12:02:52 +0200 Message-ID: <20240707100252.2553609-1-sandra.snan@idiomdrottning.org> References: <87le2dblzz.fsf@ellen.idiomdrottning.org> Reply-To: Sandra Snan Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="715"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Sandra Snan To: 71017@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Jul 07 12:04:18 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sQOkj-000AVT-83 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 07 Jul 2024 12:04:17 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sQOkS-0002j9-0Q; Sun, 07 Jul 2024 06:04:00 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sQOkQ-0002ik-M4 for bug-gnu-emacs@gnu.org; Sun, 07 Jul 2024 06:03:58 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sQOkQ-0007EJ-A6 for bug-gnu-emacs@gnu.org; Sun, 07 Jul 2024 06:03:58 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1sQOkU-0004oe-EI for bug-gnu-emacs@gnu.org; Sun, 07 Jul 2024 06:04:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Sandra Snan Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 07 Jul 2024 10:04:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 71017 X-GNU-PR-Package: emacs Original-Received: via spool by 71017-submit@debbugs.gnu.org id=B71017.172034661418479 (code B ref 71017); Sun, 07 Jul 2024 10:04:02 +0000 Original-Received: (at 71017) by debbugs.gnu.org; 7 Jul 2024 10:03:34 +0000 Original-Received: from localhost ([127.0.0.1]:47392 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sQOk2-0004ny-43 for submit@debbugs.gnu.org; Sun, 07 Jul 2024 06:03:34 -0400 Original-Received: from halsen.idiomdrottning.org ([74.207.231.133]:54818) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1sQOjz-0004np-Kf for 71017@debbugs.gnu.org; Sun, 07 Jul 2024 06:03:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=idiomdrottning.org; s=idiomdrottningorg; t=1720346576; bh=uQqaOZhGUrFHaabyMbvirHH/NJ5sVn1KviiTsenJuKk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WY6KaiATl1aZR00GgzZ3pqoL9Td2BDwbiM7/a9si/6FX4jXA29SzVsdoPdlAr5Ymc zIBwjT70yBMxryHuDinYvLNF5Emtbtaodki3VOhbahKOAkbHlLyMiaZzf7HrUcDAMz edHv7pfp5GK4wprHFOloifoV/h8tFrSEAT6equVJJht+Ie7e+SZYebuDL7HMGCBqCi x3Ozcl3hiXtEmIpvpEt91JM8Buezlw9hUFy41E7P8z/DubXQPHmgVtTvCOcnohPdN0 GXAbdmzCbGqjNDqQRSF6IWfm52GGQsRBLyd/KbvdPdNOtoKdFZ2MXgE+P8arz0mwrg FnIn/oRL5+Qzw== Original-Received: from localhost (31-211-247-254.customers.ownit.se [31.211.247.254]) by halsen.idiomdrottning.org (Postfix) with ESMTPSA id 0239C21B94; Sun, 7 Jul 2024 12:02:55 +0200 (CEST) X-Mailer: git-send-email 2.39.2 In-Reply-To: <87le2dblzz.fsf@ellen.idiomdrottning.org> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:288553 Archived-At: See discussion in #71017. In short: if mml-flowed-enable is nil: no change to behavior if mml-flowed-enable is t and use-hard-newlines is on: several bugs fixed, some (multi-paragraph messages) of which were counter to documentation and some (single-paragraph messages) that were along documentation lines but which messed up messages royally. if mml-flowed-enable is t but use-hard-newlines was accidentally forgotten by user: new behavior; reflow but don't reflow together separate paragraphs nor reflow across lines that markdown would've considered hard. --- doc/misc/emacs-mime.texi | 7 +-- lisp/gnus/mml.el | 29 ++++++------- lisp/mail/flow-fill.el | 93 ++++++++++++++++++++++++---------------- 3 files changed, 69 insertions(+), 60 deletions(-) diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi index ef7ea61..7621a9a 100644 --- a/doc/misc/emacs-mime.texi +++ b/doc/misc/emacs-mime.texi @@ -1087,13 +1087,10 @@ terminated by soft newline characters are filled together and wrapped after the column decided by @code{fill-flowed-encode-column}. Quotation marks (matching @samp{^>* ?}) are respected. The variable controls how the text will look in a client that does not support -flowed text, the default is to wrap after 66 characters. If hard -newline characters are not present in the buffer, no flow encoding -occurs. +flowed text, the default is to wrap after 66 characters. You can customize the value of the @code{mml-enable-flowed} variable -to enable or disable the flowed encoding usage when newline -characters are present in the buffer. +to enable or disable the flowed encoding usage. On decoding flowed text, lines with soft newline characters are filled together and wrapped after the column decided by diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el index e3bc393..2db39dc 100644 --- a/lisp/gnus/mml.el +++ b/lisp/gnus/mml.el @@ -691,23 +691,18 @@ type detected." (t ;; Only perform format=flowed filling on text/plain ;; parts where there either isn't a format parameter - ;; in the mml tag or it says "flowed" and there - ;; actually are hard newlines in the text. - (let (use-hard-newlines) - (when (and mml-enable-flowed - (string= type "text/plain") - (not (string= (cdr (assq 'sign cont)) "pgp")) - (or (null (assq 'format cont)) - (string= (cdr (assq 'format cont)) - "flowed")) - (setq use-hard-newlines - (text-property-any - (point-min) (point-max) 'hard 't))) - (fill-flowed-encode) - ;; Indicate that `mml-insert-mime-headers' should - ;; insert a "; format=flowed" string unless the - ;; user has already specified it. - (setq flowed (null (assq 'format cont))))) + ;; in the mml tag or it says "flowed". + (when (and mml-enable-flowed + (string= type "text/plain") + (not (string= (cdr (assq 'sign cont)) "pgp")) + (or (null (assq 'format cont)) + (string= (cdr (assq 'format cont)) + "flowed"))) + (fill-flowed-encode) + ;; Indicate that `mml-insert-mime-headers' should + ;; insert a "; format=flowed" string unless the + ;; user has already specified it. + (setq flowed (null (assq 'format cont)))) ;; Prefer `utf-8' for text/calendar parts. (if (or charset (not (string= type "text/calendar"))) diff --git a/lisp/mail/flow-fill.el b/lisp/mail/flow-fill.el index 919490e..793088a 100644 --- a/lisp/mail/flow-fill.el +++ b/lisp/mail/flow-fill.el @@ -73,50 +73,67 @@ RFC 2646 suggests 66 characters for readability." ;;;###autoload (defun fill-flowed-encode (&optional buffer) (with-current-buffer (or buffer (current-buffer)) - ;; No point in doing this unless hard newlines is used. - (when use-hard-newlines - (let ((start (point-min)) end) - ;; Go through each paragraph, filling it and adding SPC - ;; as the last character on each line. - (while (setq end (text-property-any start (point-max) 'hard 't)) - (save-restriction - (narrow-to-region start end) - (let ((fill-column (eval fill-flowed-encode-column t))) - (fill-flowed-fill-buffer)) - (goto-char (point-min)) - (while (re-search-forward "\n" nil t) - (replace-match " \n" t t)) - (goto-char (setq start (1+ (point-max))))))) - t))) - -(defun fill-flowed-fill-buffer () - (let ((prefix nil) - (prev-prefix nil) - (start (point-min))) - (goto-char (point-min)) - (while (not (eobp)) - (setq prefix (and (looking-at "[> ]+") - (match-string 0))) - (if (equal prefix prev-prefix) - (forward-line 1) + (let ((fill-column (eval fill-flowed-encode-column t)) + (start (point-min)) + (end (point-max))) + ;; Only when we've been called to reflow a buffer that doesn't + ;; have any hard newlines: + (unless (text-property-any start end 'hard 't) + (save-excursion + ;; Harden between paras: + (goto-char start) + (while (re-search-forward "\n[> ]*\n" end t) + (set-hard-newline-properties + (match-beginning 0) (point)) + (backward-char)) + ;; Harden before a quote starts: + (goto-char start) + (while (re-search-forward "\n[^>][^\n]*\n>" end t) + (backward-char) + (set-hard-newline-properties + (1- (point)) (point))) + ;; Harden " $" + (goto-char start) + (while (search-forward " \n" end t) + (backward-char) + (backward-delete-char 2) + (set-hard-newline-properties + (point) (1+ (point)))) + ;; Harden "^ " + (goto-char start) + (while (search-forward "\n " end t) + (set-hard-newline-properties + (- (point) 5) (- (point) 4))))) + ;; Go through each paragraph, filling it and adding SPC + ;; as the last character on each line. + (while (and (< start (point-max)) + (setq end (or (text-property-any start (point-max) 'hard 't) + (point-max)))) (save-restriction - (narrow-to-region start (point)) - (let ((fill-prefix prev-prefix)) - (fill-region (point-min) (point-max) t 'nosqueeze 'to-eop)) - (goto-char (point-max))) - (setq prev-prefix prefix - start (point)))) - (save-restriction - (narrow-to-region start (point)) - (let ((fill-prefix prev-prefix)) - (fill-region (point-min) (point-max) t 'nosqueeze 'to-eop))))) + (narrow-to-region start end) + (let ((prefix + (concat "\n" + (or (and (looking-at ">[> ]*") + (match-string 0)) "")))) + (goto-char start) + (while (search-forward prefix nil t) + (replace-match " " t t)) + (goto-char start) + (while (< (+ (point) fill-column) (point-max)) + (let ((start (point))) + (forward-char fill-column) + (when (search-backward " " start t) + (forward-char) + (insert prefix))))) + (setq start (1+ (point-max)))))) + t)) ;;;###autoload (defun fill-flowed (&optional buffer delete-space) "Apply RFC2646 decoding to BUFFER. If BUFFER is nil, default to the current buffer. -If DELETE-SPACE, delete RFC2646 spaces padding at the end of +If DELETE-SPACE, delete RFC3676 spaces padding at the end of lines." (with-current-buffer (or buffer (current-buffer)) (let ((fill-column (eval fill-flowed-display-column t))) @@ -154,7 +171,7 @@ lines." ;; Delete the newline. (when (eq (following-char) ?\s) (delete-char 1)) - ;; Hack: Don't do the flowing on the signature line. + ;; As per RFC3767: Don't do the flowing on the signature line. (when (and (not (looking-at "-- $")) (eq (char-before (line-end-position)) ?\s)) (while (and (not (eobp)) -- 2.39.2