Search code examples
emacsbibtex

Emacs bibtex-mode unable to parse un-visited file


I'm not sure the best way to phrase this question, but hopefully my examples will make clear what's going on.

I have some code where I want to insert the contents of a bibtex file in a temporary buffer and move through the entries one at a time, grabbing the entry using bibtex-parse-entry for later use. However, whenever I run the code on a bibtex file that I haven't visited during this emacs session, bibtex-parse-entry returns a (wrong-type-argument stringp nil) error.

Once I visit the file, even if I then close the buffer, the code runs without any issues. And if I remove the bibtex-parse-entry call, bibtex-kill-entry has the same issue.

Here's the elisp code I'm using:

(with-temp-buffer
  (insert-file-contents "~/test.bib")
  (goto-char (point-min))
  (bibtex-mode)
  (while (not (eobp))
    (let* ((entry (bibtex-parse-entry t)))
      (message "i'm here"))
    (bibtex-kill-entry)
    (bibtex-beginning-of-entry)
    )
  )

and a dummy .bib file:

@Article{test,
  author =   {joe shmo},
  title =    {lorem ipsum},
  journal =      {something},
  year =     {1990},
}

With these you should be able to reproduce my error.

I have no idea what's going on, so I'd greatly appreciate any help!


Solution

  • I am not really an expert at this. I just debugged the situation a bit (try M-x toggle-debug-on-error in cases like this) and found a call to looking-at with a nil value. The stack-trace tells us that the problem is in the bibtex function bibtex-valid-entry. There, I found the variable bibtex-entry-maybe-empty-head which --according to its docstring-- is set by bibtex-set-dialect.

    Thus, adding a call to bibtex-set-dialect to your function after calling bibtex-mode seems to fix the issue. As I do not really know, what you want to achieve in the end, I am not sure it actually fixes your problem. At least the function does raise an error anymore.

    Hope, that makes sense and helps.

    (with-temp-buffer
      (insert-file-contents "~/test.bib")
      (goto-char (point-min))
      (bibtex-mode)
      (bibtex-set-dialect) ;; <-- add this
      (while (not (eobp))
        (let* ((entry (bibtex-parse-entry t)))
        (message "i'm here"))
        (bibtex-kill-entry)
        (bibtex-beginning-of-entry)))