From 044f84632ecf8518184f45802a97a9fa91f9a6d6 Mon Sep 17 00:00:00 2001 From: Aaron Ecay Date: Thu, 7 Mar 2013 00:22:07 -0500 Subject: [PATCH] Support export of bibliography links (WIP) --- lisp/ox-bib.el | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lisp/ox-latex.el | 8 +++++ lisp/ox.el | 1 + 3 files changed, 117 insertions(+) create mode 100644 lisp/ox-bib.el diff --git a/lisp/ox-bib.el b/lisp/ox-bib.el new file mode 100644 index 0000000..d726e31 --- /dev/null +++ b/lisp/ox-bib.el @@ -0,0 +1,108 @@ +(require 'bibtex) +(require 'ox) + +(defvar ox-bib-find-entries-in-org-file nil + "Whether to look for bibliogrpahy entries in an org mode file +or a bibtex file.") + +(defun ox-bib-get-bibliography () + (mapcar (lambda (s) + (org-no-properties s)) + ;; Don't explode if before the first headline + (or + (condition-case nil + (plist-get (org-export-get-environment nil t) :bibliography) + (error nil)) + (save-excursion + (widen) + (goto-char (point-min)) + (plist-get (org-export-get-environment) :bibliography))))) + +(defun ox-bib-get-key (path &optional desc) + "Extract cite key from a link path and desc. + +Currently expects links in the format: +\[[type:key;pre;post;][desc]]" + (nth 0 (split-string path ";"))) + +(defun ox-bib-get-pre (path &optional desc) + "Extract pre-citation arg from a link path and desc. + +Currently expects links in the format: +\[[type:key;pre;post;][desc]]" + (or (nth 1 (split-string path ";")) "")) + +(defun ox-bib-get-post (path &optional desc) + "Extract post-citation arg from a link path and desc. + +Currently expects links in the format: +\[[type:key;pre;post;][desc]]" + (or (nth 2 (split-string path ";")) "")) + +;; Adapted from org-find-entry-with-custom-id; there might be a better +;; way to do this +(defun org-find-entry-with-custom-id (ident) + (let ((id ident) + (case-fold-search nil)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (when (re-search-forward + (concat "^[ \t]*:CUSTOM_ID:[ \t]+" (regexp-quote id) "[ \t]*$") + nil t) + (org-back-to-heading t) + (point)))))) + +(defun ox-bib-cite-follow (path) + (let* ((files (ox-bib-get-bibliography)) + (key (ox-bib-get-key path)) + file done) + (when ox-bib-find-entries-in-org-file + (setq files + (mapcar (lambda (s) + (replace-regexp-in-string "\\.bib\\'" ".org" s)) + files))) + (while (and (car-safe files) (not done)) + (setq file (car-safe files)) + (when (file-exists-p file) + (let* ((buf (find-file-noselect file)) + + (pos (with-current-buffer buf + (cond + (ox-bib-find-entries-in-org-file + (org-find-entry-with-custom-id key)) + (t (bibtex-search-entry key)))))) + (when pos + (setq done (cons buf pos))))) + (setq files (cdr files))) + (if done + (progn + (pop-to-buffer (car done)) + (goto-char (cdr done)) + (when ox-bib-find-entries-in-org-file + (org-show-context))) + (message "Citation not found: %s" key)))) + +(defun ox-bib-textcite-export (path desc format) + (cond + ((org-export-derived-backend-p format 'latex) + (let ((key (ox-bib-get-key path desc)) + (pre (ox-bib-get-pre path desc)) + (post (ox-bib-get-post path desc))) + (format "\\textcite[%s][%s]{%s}" pre post key))) + (t + (format "" path)))) + +(defun ox-bib-parencite-export (path desc format) + (cond + ((org-export-derived-backend-p format 'latex) + (let ((key (ox-bib-get-key path desc)) + (pre (ox-bib-get-pre path desc)) + (post (ox-bib-get-post path desc))) + (format "\\parencite[%s][%s]{%s}" pre post key))) + (t + (format "" path)))) + +(org-add-link-type "textcite" #'ox-bib-cite-follow #'ox-bib-textcite-export) +(org-add-link-type "parencite" #'ox-bib-cite-follow #'ox-bib-parencite-export) diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 8a5b6a6..ed5dcad 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -1153,6 +1153,14 @@ holding export options." (or (plist-get info :description) "") (if (not (plist-get info :with-creator)) "" (plist-get info :creator)))) + ;; Bibliography + (let* ((bibs (plist-get info :bibliography)) + (bib-cmds (mapconcat (lambda (s) + (format "\\addbibresource{%s}" s)) + bibs "\n"))) + (if bibs + (concat bib-cmds "\n") + "")) ;; Document start. "\\begin{document}\n\n" ;; Title command. diff --git a/lisp/ox.el b/lisp/ox.el index 3a0764d..bdff5ee 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -118,6 +118,7 @@ (:select-tags "SELECT_TAGS" nil org-export-select-tags split) (:time-stamp-file nil "timestamp" org-export-time-stamp-file) (:title "TITLE" nil nil space) + (:bibliography "BIBLIOGRAPHY" nil nil split) (:with-archived-trees nil "arch" org-export-with-archived-trees) (:with-author nil "author" org-export-with-author) (:with-clocks nil "c" org-export-with-clocks) -- 1.8.1.5