Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
;;; Patching Citar
;; Prerequisites
(require 'org)
(require 'ol-bibtex)
(require 'citeproc-bibtex)
(require 'citar)
;; Make org-bibtex work with biblatex fields, not needed for BibTeX
(setq org-bibtex-export-arbitrary-fields t
org-bibtex-prefix "") ; Prefix could be something meaningful, this instructs org-bibtex
; to use the field names as property names directly.
;; Overriding advices, at least for now...
;; both functions are copied from Citar with code added for org-bibtex
;; Make Citar aware of org-bib(la)tex bibs.
;; TODO: handle props correctly for Org files
(define-advice citar-cache--update-bibliography (:override (bib &optional props))
(let* ((filename (citar-cache--bibliography-filename bib))
(props (or props (citar-cache--get-bibliography-props filename)))
(entries (citar-cache--bibliography-entries bib))
(messagestr (format "Updating bibliography %s" (abbreviate-file-name filename)))
(starttime (current-time)))
(message "%s..." messagestr)
(redisplay) ; Make sure message is displayed before Emacs gets busy parsing
(clrhash entries)
(if (string= (file-name-extension filename) "org")
(org-map-entries
(lambda ()
(when-let ((key-w-entry (citeproc-bt-from-org-headline)))
(condition-case err
(puthash (car key-w-entry) (cdr key-w-entry)
entries)
(error
(user-error
"Couldn't parse the bib(la)tex entry with key '%s', the error was: %s"
(car key-w-entry) err)))))
t (list filename))
(parsebib-parse filename :entries entries :fields (plist-get props :fields)))
(setf (citar-cache--bibliography-props bib) props)
(citar-cache--preformat-bibliography bib)
(message "%s...done (%.3f seconds)" messagestr (float-time (time-since starttime)))))
;; Open corresponding headlines in org-bib(la)tex files too.
(define-advice citar--open-entry (:override (key bib-files))
(catch 'break
(dolist (bib-file bib-files)
(let ((buf (or (get-file-buffer bib-file)
(find-buffer-visiting bib-file))))
(find-file bib-file)
(widen)
(goto-char (point-min))
(let ((orgp (string= "org" (file-name-extension bib-file))))
(when (re-search-forward
(if orgp (concat ":CUSTOM_ID: " (regexp-quote key))
(concat "^@\\(" parsebib--bibtex-identifier
"\\)[[:space:]]*[\\(\\{][[:space:]]*"
(regexp-quote key) "[[:space:]]*,")) nil t)
(when orgp
(re-search-backward "^\\*")
(org-fold-show-context))
(throw 'break t)))
(unless buf
(kill-buffer))))))
;;; Add entry from url with Zotra
;;; could be used directly from the browser via org-protocol in the long run.
(require 'zotra)
;; Needs a working Zotra + Zotero translator service combination.
;; TODO: Handle errors gracefully.
;; Code is based on Zotra's `zotra-add-entry-from-url'
(defun org-bibtex-add-entry-from-url (url)
(interactive "surl: ")
(mapc (lambda (x)
(setq url (funcall x url)))
zotra-url-cleanup-functions)
(let ((entry (zotra-get-entry-from-json (zotra-get-json url))))
(with-temp-buffer
(goto-char (point-min))
(insert (decode-coding-string entry 'utf-8))
(goto-char (point-min))
(re-search-forward "@")
(org-bibtex-read)))
(org-bibtex-yank))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment