Subject: bug#48937: 13.0.12; Paragraph filling with line that ends in % followed by comment

From: Tassilo Horn <[email-masked]>
Date: Thu, 10 Jun 2021 07:20:16 +0200

Gustavo Barros <[email-masked]> writes:

Hi Gustavo,

>> Indeed, that's a corner case nobody has bothered to handle yet.  I've
>> pushed a fix to master.  Please give it a try.
>>
>> If you don't have a git checkout handy, you can also `eval-defun' the
>> function below containing the fix.
>
> Thank you very much for the quick answer and fix.
>
> I did try it out, and I admit that that regexp is a little daunting to
> me.  But I was particularly not understanding why the "[^\r\n\\]"
> before `TeX-comment-start-regexp' in the patch.

Indeed, that was a leftover from playing with the regexp which isn't
needed and produces the problem you describe below.

> I still don't get its intent well, but I could get it to fail again by
> a small adjustment of the ECM, namely by removing the space between
> the `\%' and the comment character, so that we have `\%%'.

Right.  Should be fixed in git master or with the new definition below.

--8<---------------cut here---------------start------------->8---
(defun LaTeX-fill-region-as-paragraph (from to &optional justify-flag)
  "Fill region as one paragraph.
Break lines to fit `fill-column', but leave all lines ending with
\\\\ \(plus its optional argument) alone.  Lines with code
comments and lines ending with `\\par' are included in filling but
act as boundaries.  Prefix arg means justify too.  From program,
pass args FROM, TO and JUSTIFY-FLAG.

You can disable filling inside a specific environment by adding
it to `LaTeX-indent-environment-list', only indentation is
performed in that case."
  (interactive "*r\nP")
  (let ((end-marker (save-excursion (goto-char to) (point-marker))))
    (if (or (assoc (LaTeX-current-environment) LaTeX-indent-environment-list)
            (member (TeX-current-macro) LaTeX-fill-excluded-macros)
            ;; This could be generalized, if there are more cases where
            ;; a special string at the start of a region to fill should
            ;; inhibit filling.
            (progn (save-excursion (goto-char from)
                                   (looking-at (concat TeX-comment-start-regexp
                                                       "+[ \t]*"
                                                       "Local Variables:")))))
        ;; Filling disabled, only do indentation.
        (indent-region from to nil)
      (save-restriction
        (goto-char from)
        (while (< (point) end-marker)
          (if (re-search-forward
               (concat "\\("
                       ;; Code comments.
                       "\\([^ \r\n%\\]\\|\\\\%\\)\\([ \t]\\|\\\\\\\\\\)*"
                       TeX-comment-start-regexp
                       "\\|"
                       ;; Lines ending with `\par'.
                       "\\(\\=\\|[^" TeX-esc "\n]\\)\\("
                       (regexp-quote (concat TeX-esc TeX-esc))
                       "\\)*"
                       (regexp-quote TeX-esc) "par[ \t]*"
                       "\\({[ \t]*}\\)?[ \t]*$"
                       "\\)\\|\\("
                       ;; Lines ending with `\\'.
                       (regexp-quote TeX-esc)
                       (regexp-quote TeX-esc)
                       "\\(\\s-*\\*\\)?"
                       "\\(\\s-*\\[[^]]*\\]\\)?"
                       "\\s-*$\\)")
               end-marker t)
              (progn
                (goto-char (line-end-position))
                (delete-horizontal-space)
                ;; I doubt very much if we want justify -
                ;; this is a line with \\
                ;; if you think otherwise - uncomment the next line
                ;; (and justify-flag (justify-current-line))
                (forward-char)
                ;; keep our position in a buffer
                (save-excursion
                  ;; Code comments and lines ending with `\par' are
                  ;; included in filling.  Lines ending with `\\' are
                  ;; skipped.
                  (if (match-string 1)
                      (LaTeX-fill-region-as-para-do from (point) justify-flag)
                    (LaTeX-fill-region-as-para-do
                     from (line-beginning-position 0) justify-flag)
                    ;; At least indent the line ending with `\\'.
                    (indent-according-to-mode)))
                (setq from (point)))
            ;; ELSE part follows - loop termination relies on a fact
            ;; that (LaTeX-fill-region-as-para-do) moves point past
            ;; the filled region
            (LaTeX-fill-region-as-para-do from end-marker justify-flag)))))))
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo