4

I'd like to have linebreaks within fields of a BibTeX entry that are preserved even after I format the entry with C-q. Currently, what happens in my BibTeX buffer is this. I produce an entry with a long annotation that includes a linebreak, like so:

@InCollection{Godfrey-Smith:induction,
  author =   {Peter Godfrey-Smith},
  title =    {Induction, Samples, and Kinds},
  booktitle =    {Carving Nature at Its Joints},
  publisher =    {MIT Press},
  year =     {2011},
  pages =    {33--52},
  address =  {Cambridge, MA},
  editors =  {Joseph K. Campbell and Michael O'Rourke and Matthew
                  H. Slater},
  Annote =   {Distinguishes two kinds of induction, one where all
                  that matters is an appropriately random sample
                  without any need for naturalness or causal
                  connection, and another that only requires a causal
                  connection, but where numbers don't matter.

                  He argues
                  (more controversially) that the picture we get from
                  Goodman in {\em Fact, Fiction, Forecast} is a bad
                  one because Goodman mixes the two up: naturalness is
                  required just in order to rule out the bad
                  predicates, but the induction still relies on having
                  suitably large numbers.}
}

Then I hit C-q to make the entry look nice, and I get this:

@InCollection{Godfrey-Smith:induction,
  author =   {Peter Godfrey-Smith},
  title =    {Induction, Samples, and Kinds},
  booktitle =    {Carving Nature at Its Joints},
  publisher =    {MIT Press},
  year =     {2011},
  pages =    {33--52},
  address =  {Cambridge, MA},
  editors =  {Joseph K. Campbell and Michael O'Rourke and Matthew
                  H. Slater},
  Annote =   {Distinguishes two kinds of induction, one where all
                  that matters is an appropriately random sample
                  without any need for naturalness or causal
                  connection, and another that only requires a causal
                  connection, but where numbers don't matter.  He
                  argues (more controversially) that the picture we
                  get from Goodman in {\em Fact, Fiction, Forecast} is
                  a bad one because Goodman mixes the two up:
                  naturalness is required just in order to rule out
                  the bad predicates, but the induction still relies
                  on having suitably large numbers.}
}

I'd like to figure out how I can force line-breaks that will be retained even after hitting C-q.

I've tried adding a percentage mark at the end of the line, which keeps the line break, but for purposes of readability, it'd be great to have a blank line between paragraphs in a bibTeX field, and I can't do that with the % commenting symbol.

Bernhard
  • 355
  • 1
  • 9

1 Answers1

1

You can try the following Elisp code. It handles fill-paragraph but not bibtex-fill-entry.

(defun my-bibtex-fill-field (&optional justify)
  "Like \\[fill-paragraph], but fill current BibTeX field.
If optional prefix JUSTIFY is non-nil justify as well.
In BibTeX mode this function is bound to `fill-paragraph-function'."
  (interactive "*P")
  (let ((pnt (point-marker))
        (bounds (bibtex-enclosing-field t)))
    (save-restriction
      ;; See `bitex-start-of-field' and related for the structure of BOUNDS.
      (narrow-to-region (bibtex-start-of-text-in-field bounds)
            (bibtex-end-of-text-in-field bounds))
      (let ((fill-paragraph-function t))
    (goto-char (point-min))
    (fill-paragraph justify)
    (while (eq (forward-paragraph) 0)
      (fill-paragraph justify)))
      )
    (goto-char pnt)))

(advice-add 'bibtex-fill-field :override #'my-bibtex-fill-field)

There is another version that also handles filling of entries. But, this has the disadvantage that there is no extra indent after the first newline in a field.

(defun fill-region-paragraphs (b e &optional justify)
  "Fill region between B and E like `fill-paragraph' for each paragraph.
JUSTIFY when called with prefix arg."
  (interactive "r\nP")
  (goto-char b)
  (while (< (point) e)
    (fill-paragraph justify)
    (forward-paragraph)
    ))

(defun my-bibtex-fill-field (&optional justify)
  "Like \\[fill-paragraph], but fill current BibTeX field.
If optional prefix JUSTIFY is non-nil justify as well.
In BibTeX mode this function is bound to `fill-paragraph-function'."
  (interactive "*P")
  (let ((pnt (point-marker))
        (bounds (bibtex-enclosing-field t)))
    (save-restriction
      ;; See `bitex-start-of-field' and related for the structure of BOUNDS.
      (narrow-to-region (bibtex-start-of-text-in-field bounds)
            (bibtex-end-of-text-in-field bounds))
      (let ((fill-paragraph-function t))
    (goto-char (point-min))
    (fill-paragraph justify)
    (while (eq (forward-paragraph) 0)
      (fill-paragraph justify)))
      )
    (goto-char pnt)))

(defun my-bibtex-fill-field-bounds (fun &rest args)
  "Fill like `bibtex-fill-field-bonds' but retain paragraphs in fields.
Can be used as around advice with args FUN and ARGS for `bibtex-fill-field-bounds'."
  (cl-letf*  ((old-fill-region-as-paragraph (symbol-function 'fill-region-as-paragraph))
          ((symbol-function 'fill-region-as-paragraph)
           (lambda (from to &optional justify nosqueeze squeeze-after)
         ;; `fill-region-as-paragraph' is used in `fill-paragraph'
         ;; Thus, we need to roll-back our override for `fill-region-paragraphs'.
         (cl-letf (((symbol-function 'fill-region-as-paragraph) old-fill-region-as-paragraph)
               (fill-paragraph-function #'my-bibtex-fill-field))
           (fill-region-paragraphs from to justify)))))
    (apply fun args)))

(advice-add 'bibtex-fill-field-bounds :around #'my-bibtex-fill-field-bounds)
Tobias
  • 32,569
  • 1
  • 34
  • 75