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.

1
  • I add 52 dashes with C-5 C-2 -. :) Commented Dec 1, 2021 at 15:32

1 Answer 1

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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.