Subject: bug#38249: 12.2.0; reftex-create-bibtex-file and biblatex

From: Arash Esbati <[email-masked]>
Date: Thu, 11 Apr 2024 10:36:44 +0200

Hi Gustavo,

Gustavo Barros <[email-masked]> writes:

> `reftex-create-bibtex-file' is a neat RefTeX utility, but it doesn’t 
> seem to handle some peculiarities of `biblatex', namely:
>
> - `reftex-all-used-citation-keys', the  auxiliary function used by 
>   `reftex-create-bibtex-file' to generate the list of entries cited in 
>   the document, does not include entries cited in qualified citation 
>   lists.

How do you write these citation lists, especially the long one?  I mean,
what is the syntax of the TeX parser for this?  For example, do you
write:

  \textcites(See, for example)()[45]{sigfridsson}[67]{reese}[24]{companion}

or

\textcites(See, for example)()[45]{sigfridsson}%
  [67]{reese}[24]{companion}

and some such?  I'm asking because for the version with everything in a
single line, the following change should work:

--8<---------------cut here---------------start------------->8---
(defun reftex-all-used-citation-keys ()
  "Return a list of all citation keys used in document."
  (reftex-access-scan-info)
  ;; FIXME: multicites macros provided by biblatex
  ;; are not covered in this function.
  (let ((files (reftex-all-document-files))
        (re (concat "\\\\"
                    "\\(?:"
                    ;; biblatex volcite macros take these args:
                    ;; \volcite[prenote]{volume}[pages]{key}
                    ;; so cater for the first 3 args:
                    (regexp-opt '("volcite"  "Volcite"
                                  "pvolcite" "Pvolcite"
                                  "fvolcite" "ftvolcite"
                                  "svolcite" "Svolcite"
                                  "tvolcite" "Tvolcite"
                                  "avolcite" "Avolcite"))
                    "\\(?:\\[[^]]*\\]\\)?"
                    "{[^}]*}"
                    "\\(?:\\[[^]]*\\]\\)?"
                    "\\|"
                    ;; Other cite macros usually go like:
                    ;; \cite[prenote][postnote]{key}
                    ;; so cater for the optional args:
                    "\\(?:bibentry\\|[a-zA-Z]*[Cc]ite[a-zA-Z*]*\\)"
                    "\\(?:\\[[^]]*\\]\\)\\{0,2\\}"
                    "\\)"
                    ;; Now match the key:
                    "{\\([^}]+\\)}"))
        (re2 (concat "\\\\"
                     (regexp-opt '("cites"       "Cites"
                                   "parencites"  "Parencites"
                                   "footcites"   "footcitetexts"
                                   "smartcites"  "Smartcites"
                                   "textcites"   "Textcites"
                                   "supercites"
                                   "autocites"   "Autocites"
                                   "volcites"    "Volcites"
                                   "pvolcites"   "Pvolcites"
                                   "fvolcites"   "Fvolcites"
                                   "svolcites"   "Svolcites"
                                   "tvolcites"   "Tvolcites"
                                   "avolcites"   "Avolcites"))
                     "\\(?:([^)]*)\\)\\{0,2\\}"))
        (re3 (concat "\\(?:\\[[^]]*\\]\\)\\{0,2\\}"
                     "{\\([^}]+\\)}"))
        file keys kk k)
    (save-current-buffer
      (while (setq file (pop files))
        (set-buffer (reftex-get-file-buffer-force file 'mark))
        (save-excursion
          (save-restriction
            (widen)
            (goto-char (point-min))
            (while (re-search-forward re nil t)
              ;; Make sure we're not inside a comment:
              (unless (save-match-data
                        (nth 4 (syntax-ppss)))
                (setq kk (match-string-no-properties 1))
                (while (string-match "%.*\n?" kk)
                  (setq kk (replace-match "" t t kk)))
                (setq kk (split-string kk "[, \t\r\n]+"))
                (while (setq k (pop kk))
                  (or (member k keys)
                      (setq keys (cons k keys)))))))))
      ;; Re-set `files':
      (setq files (reftex-all-document-files))
      ;; And now search for citation lists:
      (while (setq file (pop files))
        (set-buffer (reftex-get-file-buffer-force file 'mark))
        (save-excursion
          (save-restriction
            (widen)
            (goto-char (point-min))
            (while (re-search-forward re2 nil t)
              ;; Make sure we're not inside a comment:
              (unless (save-match-data
                        (nth 4 (syntax-ppss)))
                (while (and (looking-at re3)
                            (goto-char (match-end 0)))
                  (setq kk (match-string-no-properties 1))
                  (while (string-match "%.*\n?" kk)
                    (setq kk (replace-match "" t t kk)))
                  (setq kk (split-string kk "[, \t\r\n]+"))
                  (while (setq k (pop kk))
                    (or (member k keys)
                        (setq keys (cons k keys)))))))))))
    (reftex-kill-temporary-buffers)
    keys))
--8<---------------cut here---------------end--------------->8---

Do you want to give it a roll?

> - `reftex-create-bibtex-file' handles the traditional BibTeX `crossref' 
>   and `string' fields, but biblatex extends data inheritance and entry 
>   cross-reference with such fields as `xref', `xdata' and `set', which 
>   are not taken care of.

I have to think about this one.

Best, Arash