9

I would like the have a simple keyboard shortcut/command in emacs that opens the .bib file of the current (possible multifile) document. This should be possible with RefTeX, as it can figure out the name of the .bib file (uses it for the C-[ command), but I could not find a command that just opens the file in the editor without any fancy selection feature.

This command would be useful, because usually what happens is that you find a bibtex entry online and you just need to paste it into your .bib file.

  • 1
    In general there can be more than one bibfile. The simplest way to open one of the relevant buffers is to find a \cite command in the document and type C-c &. This will pop open another buffer containing the relevant bibfile centered on the bibtex entry referred to. The list of files ought to be accessible via reftex-get-bibfile-list, but it doesn't seem to work on my set-up. – Andrew Swann Nov 20 '13 at 11:48
5

This requires AUCTeX:

(defun mg-LaTeX-find-bibliography ()
  "Visit bibliography file of the current document."
  (interactive)
  (let ((length (length (LaTeX-bibliography-list)))
    bib)
    (if (= length 1)
    (progn
      (setq bib (car (car (LaTeX-bibliography-list))))
      (unless (file-name-extension bib)
        (setq bib (concat bib ".bib")))
      (mg-TeX-kpsewhich-find-file bib))
      (if (< length 1)
      ;; If there is no element in `LaTeX-bibliography-list' use a `.bib'
      ;; file with the same base name of the TeX master as an educated
      ;; guess.
      (mg-TeX-kpsewhich-find-file (TeX-master-file "bib"))
    (setq bib (completing-read "Bibliography database: "
                   (LaTeX-bibliography-list)))
    (unless (file-name-extension bib)
      (setq bib (concat bib ".bib")))
    (mg-TeX-kpsewhich-find-file bib)))))

mg-TeX-kpsewhich-find-file is defined here.

| improve this answer | |
  • Thanks, it works, but there are two issues. First, it seems that we need to call TeX-normal-mode to reparse the file. Second, this is weird, but if the main .tex and .bib files have the same name (e.g., foo.tex and foo.bib), then the database is not found (as LaTeX-bibliography is empty in this case). – user41347 Nov 20 '13 at 13:37
  • 1) If you insert the \bibliography macro with C-c RET bibliography RET you don't need to reparse the document. 2) Unfortunately that's a known bug with AUCTeX :-( I suggest you to always use different base names for the document and the bibliography file. – giordano Nov 20 '13 at 13:51
  • 2) Can't we use then the name of the tex master file? – user41347 Nov 20 '13 at 14:04
  • Sorry, I'm not sure I understand your question. If you are asking whether is it possible to use the same base name for the TeX master file and the bibliography file then the answer is "no" (I'm talking about AUCTeX ability to parse files with the same base name, not about TeX). – giordano Nov 20 '13 at 14:07
  • I'm suggesting the workaround that if the function detects that LaTeX-bibliography-list is empty, then we try to open (basename of tex master)+".bib" as an educated guess. – user41347 Nov 20 '13 at 14:15
3

Since you're using reftex anyways, you can use the reftex function reftex-get-bibfile-list to find all the .bib files associated with your file, and use those as completion targets for find-file:

(defun open-current-bib-file ()
  "Visit the bib file for the current document.
Only works when reftex is in use, otherwise returns nil."
  (interactive)
  (unless (not reftex-mode)
    (find-file (completing-read ".bib file to open: " 
                                (reftex-get-bibfile-list)))))
| improve this answer | |
0

This should work without AUCTeX. It is based on the code given by @giordano and the mg-TeX-kpsewhich-find-file function, defined here.

What it does:

  1. It finds all \bibliography{...} commands in the current buffer. Be warned that it does not skip LaTeX comments or anything else that semantically does not correspond to a BibTeX file.

  2. It creates a list of bibliography files find in such commands. It correctly treats multiple files in the same command, e.g., \bibliography{file1,file2}.

  3. It finds all files in the list using kpsewhich.

  4. It opens all files, possibly reusing existing buffers. The first file of the list takes the focus (find-file) and the rest are just opened (find-file-noselect).

It should be easy to modify this behavior, if something else is preferred.

(defun kpsewhich-find-file (name)
  "Find a file using kpsewhich."
  (interactive "fFilename: ")
  (if (executable-find "kpsewhich")
      (let* ((file (replace-regexp-in-string
                    "[\n\r]*\\'" ""
                    (shell-command-to-string (concat "kpsewhich " name)))))
        (if (and (not (zerop (length file))) (file-exists-p file))
            file
          (message (concat "File " name " not found."))))
    (message "Executable kpsewhich not available.")))

(defun open-bibtex-file ()
  "Open all bibliography files attached to this document."
  (interactive)
  (goto-char (point-min))
  (let ((biblist nil))
    (while (search-forward-regexp
            "\\\\bibliography[ \t]*{\\([^}\n]+\\)}"
            nil t)
      (let* ((bibpar (buffer-substring-no-properties
                      (match-beginning 1)
                      (match-end 1)))
             (bibs (split-string bibpar ",")))
        (mapcar (lambda (bib)
                  (unless (file-name-extension bib)
                    (setq bib (concat bib ".bib")))
                  (setq bib (kpsewhich-find-file bib))
                  (setq biblist (append biblist (cons bib nil)))) bibs)))
    (mapcar 'find-file-noselect (cdr biblist))
    (find-file (car biblist))))
| improve this answer | |
  • 1
    But this won't work if open-bibtex-file is run while in an inputted or included file, is it correct? – giordano Nov 20 '13 at 13:59
  • You're right, it won't. You have to parse the .aux file, if you want that. – nickie Nov 20 '13 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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