Open
Description
First, let me thank @bdarcus and the rest of the contributors for all the hard thought and work that went into citar
.
Describe the bug
I have encountered three issues while using the citar-export-local-bib-file
function.
- The most significant one occurs within the call to
citar--insert-bibtex
. If the latter is called with acitekey
which is not found in any of thebibtex-files
, then it returns the first bibtex entry within the file instead ofnil
. The reason, I believe, is that while(bibtex-search-entry citekey)
does returnnil
, subsequent calls tobibtex-beginning-of-entry
andbibtex-end-of-entry
are unconditional and point to the first bibtex entry within the file. This can be fixed by making these calls conditional on the returned value ofbibtex-search-entry
:
(if (bibtex-search-entry citekey)
(let ((beg (bibtex-beginning-of-entry))
(end (bibtex-end-of-entry)))
(buffer-substring-no-properties beg end))
"")
- The doc string for
citar-bibliography
does say explicitly that it is expected to be a list of files, but the implementation ofcitar--bibliography-files
allows (rather conveniently) forcitar-bibliography
to be a string provided there is only one bibliography file to be specified. The current implementation ofcitar-export-local-bib-file
, however, does assume thatcitar-bibliography
is a genuine list, since it calls(car citar-bibliography)
to determineext
of the bibliography file. One way to fix this would to be defineext
via
(ext (file-name-extension (car (citar--bibliography-files 'global))))
- The last thing is that the current implementation of
citar-export-local-bib-file
searches for keys only among the global bibliography files and ignores the local ones. This, I believe, is because(citar--insert-bibtex citekey)
is called withinwith-temp-file
and therefore looses access to the local bibliography of the buffer from whichcitar-export-local-bib-file
is called. I am not sure if this behavior is intentional or not. If it is, I think it would be appropriate to mention it in the doc string ofcitar-export-local-bib-file
. But if local bibliography entries should be taken into account, then here is one way to accomplish this. We can letcitar--insert-bibtex
take an optional list of bibtex files to find thecitekey
in:
(defun citar--insert-bibtex (citekey &optional bibtex-files-list)
and the variable bibtex-files
would then be bound as follows
(bibtex-files (or bibtex-files-list (citar--bibliography-files)))
Finally, the call to citar--insert-bibtex
within citar-export-local-bib-file
would supply the list of bibtex files.
With all the changes above, citar--insert-bibtex
and citar-export-local-bib-file
would look something like this:
(defun citar--insert-bibtex (citekey &optional bibtex-files-list)
"Insert the bibtex entry for CITEKEY at point."
(let* ((bibtex-files
(or bibtex-files-list (citar--bibliography-files)))
(entry
(with-temp-buffer
(bibtex-set-dialect)
(dolist (bib-file bibtex-files)
(insert-file-contents bib-file))
(if (bibtex-search-entry citekey)
(let ((beg (bibtex-beginning-of-entry))
(end (bibtex-end-of-entry)))
(buffer-substring-no-properties beg end))
""))))
(unless (equal entry "")
(insert entry "\n\n"))))
;;;###autoload
(defun citar-export-local-bib-file ()
"Create a new bibliography file from citations in current buffer.
The file is titled \"local-bib\", given the same extension as
the first entry in `citar-bibliography', and created in the same
directory as current buffer."
(interactive)
(let* ((citekeys (citar--major-mode-function 'list-keys #'ignore))
(ext (file-name-extension (car (citar--bibliography-files 'global))))
(file (format "%slocal-bib.%s" (file-name-directory buffer-file-name) ext))
(bibtex-files (citar--bibliography-files)))
(with-temp-file file
(dolist (citekey citekeys)
(citar--insert-bibtex citekey bibtex-files)))))