From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Eric Schulte" Subject: Re: [ANN] org-bibtex.el --- convert between Org headings and bibtex entries Date: Sat, 23 Apr 2011 18:52:14 -0600 Message-ID: <87liz0zd1d.fsf@gmail.com> References: <87y6357q81.fsf@gmail.com> <027A8D96-05AB-452C-87D3-85D90D24AFB1@tsdye.com> <87vcy81xtv.fsf@gmail.com> <877hanwbyb.fsf@gmail.com> <89A178C3-C2E4-493D-BE84-12200512B766@tsdye.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([140.186.70.92]:55400) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QDnYn-0005Sv-4C for emacs-orgmode@gnu.org; Sat, 23 Apr 2011 20:52:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QDnYk-0005gi-4a for emacs-orgmode@gnu.org; Sat, 23 Apr 2011 20:52:25 -0400 Received: from mail-pv0-f169.google.com ([74.125.83.169]:64210) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QDnYj-0005gd-Lf for emacs-orgmode@gnu.org; Sat, 23 Apr 2011 20:52:22 -0400 Received: by pvc12 with SMTP id 12so763707pvc.0 for ; Sat, 23 Apr 2011 17:52:20 -0700 (PDT) In-Reply-To: (Alan E. Davis's message of "Sun, 24 Apr 2011 08:59:32 +1000") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: "Alan E. Davis" Cc: Org Mode --=-=-= Content-Type: text/plain "Alan E. Davis" writes: > Some notes on initially trying out this new tool. I have some reservations > as to whether it use it. There are certain good reasons in its favor. > > This works to both store bibtex database entries and export to .bib files. > I REALLY like the automagical harvesting of data using cb2Bib. It is > unique, and I don't see how to recruit it to produce a database in an org > file, or pipe it into this org-bibtex tool. > Org-bibtex can be used to collect bibtex entries from .bib files, and (with this most recent attached version) directly from the clipboard with `org-bibtex-yank'. Is there a more natural way that this could integrate with external tools like cb2bib? I've just now installed cb2bib, and I'm not sure I fully grasp its usage. > > The need to represent the bibtex database entry as a PROPERTY list would > appear to me to limit its usefulness to me. > in any particular way? > > A nit: I would prefer to be free to enter any optional field type I wished, > when I am entering the data. It is possible to add arbitrary properties to a headline with `org-set-property'. Or you could customize the variables holding bibtex field and entry types. For example to add a personal :mynotes field to every bibtex type just execute the following elisp code (or add it to your configuration). You will then be prompted for a mynotes field on every bibtex entry. You could also change the :required keyword to add your field as an option field. #+begin_src emacs-lisp (dolist (type org-bibtex-types) (push :mynotes (cdr (assoc :required (cdr type))))) (push (cons :mynotes "My personal field for notes") org-bibtex-fields) #+end_src > Of course, the tool as it stands helped me to filter out duplicate > fields and unused optional fields from the one bibtex entry I tried > using org-bibtex-read: the output of org-bibtex-write was cleaner, and > correctly incorporated aligning tabs where I'd carelessly left them > out.) > This functionality is all due to the formatting functions provided by the existing bibtex.el package. > > My INPUT ENTRY > > @INCOLLECTION{AED-IER-CR, > author = {Junior Noitall}, > title = {Specific disruption strategies}, > booktitle = {How to annoy the teacher}, > publisher = {Noitall Notes}, > year = {2011}, > editor = {Senior Noitall}, > chapter = {13}, > pages = {218--243}, > address = {Concentric Orbit}, > altauthor = {John Smith}, > alteditor = {Carl Pumpkin}, > isbn = {1-8777753-31-9}, > optaddress = {Room X777}, > optpages = {\frac{1}{2}} > } > > In the following output, the isbn field is missing. > > OUTPUT from org-bibtex-write > > @incollection{AED-IER-CR, > author = {Junior Noitall}, > title = {Specific disruption strategies}, > booktitle = {How to annoy the teacher}, > publisher = {Noitall Notes}, > year = 2011, > editor = {Senior Noitall}, > type = {incollection}, > chapter = 13, > pages = {218--243}, > address = {Concentric Orbit} > } > > > I understand I may add to the types variable. When using org-bibtex-create, > I can enter any arbitrary field as a PROPERTY; however, org-bibtex ignores > anything outside of the universe it knows about. Would it be bad practice > to allow the export of any arbitrary field type one has recorded? If a type is added as with the code given above, then it will be exported to .bib files along with the default fields. > I think the emacs bibtex-mode may recognize erroneous bibtex entries. > Somewhere there is code that does that. I do not know if bibtex-mode does that or not. I think that bibtex itself is supposed to simply ignore any fields which it does not recognize allowing extensibility. > It would be a huge and excellent addition to be able to pass other > types, while checking for proper formatting. Bibtex itself, and the > .bst files (at least for bibtex itself; I don't know about biblatex, > etc.) will cherry pick the needed fields. Am I wrong about this? > The above sounds correct to me. Given that org properties will likely contain non-bibtex content, I wouldn't want the default behavior to be exporting every property entry to bibtex. However if the above solution of adding to the org-bibtex-types/fields variables is not sufficient, it shouldn't be difficult to change the org-bibtex command so that if it is called with a prefix argument it will export *all* properties to the .bib file. > > > I am confused by the duplication of file names, though I can see that at > some point one of the two will lose. (Gauss's law of competitive exclusion, > referring to the biological case of two species occupying the same > ecological niche). > I think that rather than competing these files may be merging into a single file (as with the attached patch). However this remains to be seen. Thanks for the feedback and suggestions -- Eric > > > Alan Davis --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: inline; filename=0001-org-bibtex-translating-between-Org-mode-headings-and.patch Content-Transfer-Encoding: quoted-printable >From c9e76873e346e3eaf0a99c07458dfac28200490b Mon Sep 17 00:00:00 2001 From: Eric Schulte Date: Sat, 23 Apr 2011 08:05:08 -0600 Subject: [PATCH] org-bibtex: translating between Org-mode headings and Bibt= ex entries * lisp/org-bibtex.el: Updating Copyright dates, author information, commentary and history notes. (org-bibtex-types): List of bibtex types with descriptions and required and optional fields. (org-bibtex-fields): List of bibtex fields with descriptions. (*org-bibtex-entries*): Special variable to hold parsed bibtex entries. (org-bibtex-autogen-keys): Custom variable controlling whether bibtex keys are automatically generated (org-bibtex-prefix): Custom variable allowing use of optional prefix for bibtex properties in Org-mode headlines. (org-bibtex-get): Helper function for accessing bibtex elements of a property list. (org-bibtex-put): Helper function for inserting bibtex element into a property list. (org-bibtex-headline): Return a bibtex entry of the given headline as a string. (org-bibtex-ask): Prompt the user to fill in the value of a bibtex field. (org-bibtex-autokey): Generate a bibtex key for the current headline. (org-bibtex-fleshout): Fill in missing bibtex properties of the current headline. (org-bibtex): Export the current Org-mode buffer to a bibtex buffer. (org-bibtex-check): Check that all bibtex properties are present in the current headline. (org-bibtex-check-all): Check all headlines in the current buffer. (org-bibtex-create): Create a new bibtex headline at the current level. (org-bibtex-read): Read the current bibtex entry from a bibtex file. (org-bibtex-write): Write the most recently read bibtex entry into an Org-mode file. --- lisp/org-bibtex.el | 331 ++++++++++++++++++++++++++++++++++++++++++++++++= +--- 1 files changed, 317 insertions(+), 14 deletions(-) diff --git a/lisp/org-bibtex.el b/lisp/org-bibtex.el index b7b7416..818be67 100644 --- a/lisp/org-bibtex.el +++ b/lisp/org-bibtex.el @@ -1,9 +1,10 @@ ;;; org-bibtex.el --- Org links to BibTeX entries ;; -;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +;; Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, In= c. ;; ;; Author: Bastien Guerry ;; Carsten Dominik +;; Eric Schulte ;; Keywords: org, wp, remember ;; Version: 7.5 ;; @@ -66,12 +67,30 @@ ;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ;; * READ <=3D=3D [point here] ;; -;; [[file:/file.bib::dolev83][Dolev & Yao 1983: security of public key pro= tocols]] +;; [[file:file.bib::dolev83][Dolev & Yao 1983: security of public key prot= ocols]] ;; ;; Danny Dolev and Andrew C. Yao (1983): On the security of public-key pro= tocols ;; In IEEE Transaction on Information Theory, 198--208. ;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D ;; +;; Additionally, the following functions are now available for storing +;; bibtex entries within Org-mode documents. +;; +;; - Run `org-bibtex' to export the current file to a .bib. +;; +;; - Run `org-bibtex-check' or `org-bibtex-check-all' to check and +;; fill in missing field of either the current, or all headlines +;; +;; - Run `org-bibtex-create' to add a bibtex entry +;; +;; - Use `org-bibtex-read' to read a bibtex entry after `point' or in +;; the active region, then call `org-bibtex-write' in a .org file to +;; insert a heading for the read bibtex entry +;; +;; - All Bibtex information is taken from the document compiled by +;; Andrew Roberts from the Bibtex manual, available at +;; http://www.andy-roberts.net/misc/latex/sessions/bibtex/bibentries.pdf +;; ;;; History: ;; ;; The link creation part has been part of Org-mode for a long time. @@ -80,12 +99,17 @@ ;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112 ;; and then implemented by Bastien Guerry. ;; +;; Eric Schulte eventually added the functions for translating between +;; Org-mode headlines and Bibtex entries, and for fleshing out the Bibtex +;; fields of existing Org-mode headlines. +;; ;; Org-mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. =20 ;;; Code: =20 (require 'org) +(require 'bibtex) =20 (defvar description nil) ; dynamically scoped from org.el =20 @@ -93,21 +117,209 @@ (declare-function bibtex-generate-autokey "bibtex" ()) (declare-function bibtex-parse-entry "bibtex" (&optional content)) (declare-function bibtex-url "bibtex" (&optional pos no-browse)) +(declare-function longlines-mode "longlines" (&optional arg)) + + +;;; Bibtex data +(defvar org-bibtex-types + '((:article + (:description . "An article from a journal or magazine") + (:required :author :title :journal :year) + (:optional :volume :number :pages :month :note)) + (:book + (:description . "A book with an explicit publisher") + (:required (:editor :author) :title :publisher :year) + (:optional (:volume :number) :series :address :edition :month :note)) + (:booklet + (:description . "A work that is printed and bound, but without a name= d publisher or sponsoring institution.") + (:required :title) + (:optional :author :howpublished :address :month :year :note)) + (:conference + (:description . "") + (:required :author :title :booktitle :year) + (:optional :editor :pages :organization :publisher :address :month :n= ote)) + (:inbook + (:description . "A part of a book, which may be a chapter (or section= or whatever) and/or a range of pages.") + (:required (:author :editor) :title (:chapter :pages) :publisher :yea= r) + (:optional (:volume :number) :series :type :address :edition :month := note)) + (:incollection + (:description . "A part of a book having its own title.") + (:required :author :title :booktitle :publisher :year) + (:optional :editor (:volume :number) :series :type :chapter :pages :a= ddress :edition :month :note)) + (:inproceedings + (:description . "An article in a conference proceedings") + (:required :author :title :booktitle :year) + (:optional :editor (:volume :number) :series :pages :address :month := organization :publisher :note)) + (:manual + (:description . "Technical documentation.") + (:required :title) + (:optional :author :organization :address :edition :month :year :note= )) + (:mastersthesis + (:description . "A Master=E2=80=99s thesis.") + (:required :author :title :school :year) + (:optional :type :address :month :note)) + (:misc + (:description . "Use this type when nothing else fits.") + (:required) + (:optional :author :title :howpublished :month :year :note)) + (:phdthesis + (:description . "A PhD thesis.") + (:required :author :title :school :year) + (:optional :type :address :month :note)) + (:proceedings + (:description . "The proceedings of a conference.") + (:required :title :year) + (:optional :editor (:volume :number) :series :address :month :organiz= ation :publisher :note)) + (:techreport + (:description . "A report published by a school or other institution.= ") + (:required :author :title :institution :year) + (:optional :type :address :month :note)) + (:unpublished + (:description . "A document having an author and title, but not forma= lly published.") + (:required :author :title :note) + (:optional :month :year))) + "Bibtex entry types with required and optional parameters.") + +(defvar org-bibtex-fields + '((:address . "Usually the address of the publisher or other type o= f institution. For major publishing houses, van Leunen recommends omitting = the information entirely. For small publishers, on the other hand, you can= help the reader by giving the complete address.") + (:annote . "An annotation. It is not used by the standard biblio= graphy styles, but may be used by others that produce an annotated bibliogr= aphy.") + (:author . "The name(s) of the author(s), in the format describe= d in the LaTeX book. Remember, all names are separated with the and keywor= d, and not commas.") + (:booktitle . "Title of a book, part of which is being cited. See t= he LaTeX book for how to type titles. For book entries, use the title field= instead.") + (:chapter . "A chapter (or section or whatever) number.") + (:crossref . "The database key of the entry being cross referenced= .") + (:edition . "The edition of a book for example, 'Second'. This sh= ould be an ordinal, and should have the first letter capitalized, as shown = here; the standard styles convert to lower case when necessary.") + (:editor . "Name(s) of editor(s), typed as indicated in the LaTe= X book. If there is also an author field, then the editor field gives the e= ditor of the book or collection in which the reference appears.") + (:howpublished . "How something strange has been published. The first = word should be capitalized.") + (:institution . "The sponsoring institution of a technical report.") + (:journal . "A journal name.") + (:key . "Used for alphabetizing, cross-referencing, and creat= ing a label when the author information is missing. This field should not b= e confused with the key that appears in the \cite command and at the beginn= ing of the database entry.") + (:month . "The month in which the work was published or, for an= unpublished work, in which it was written. You should use the standard thr= ee-letter abbreviation,") + (:note . "Any additional information that can help the reader.= The first word should be capitalized.") + (:number . "Any additional information that can help the reader.= The first word should be capitalized.") + (:organization . "The organization that sponsors a conference or that = publishes a manual.") + (:pages . "One or more page numbers or range of numbers, such a= s 42-111 or 7,41,73-97 or 43+ (the =E2=80=98+=E2=80=99 in this last example= indicates pages following that don=E2=80=99t form simple range). BibTEX re= quires double dashes for page ranges (--).") + (:publisher . "The publisher=E2=80=99s name.") + (:school . "The name of the school where a thesis was written.") + (:series . "The name of a series or set of books. When citing an= entire book, the the title field gives its title and an optional series fi= eld gives the name of a series or multi-volume set in which the book is pub= lished.") + (:title . "The work=E2=80=99s title, typed as explained in the = LaTeX book.") + (:type . "The type of a technical report for example, 'Researc= h Note'.") + (:volume . "The volume of a journal or multi-volume book.") + (:year . "The year of publication or, for an unpublished work,= the year it was written. Generally it should consist of four numerals, su= ch as 1984, although the standard styles can handle any year whose last fou= r nonpunctuation characters are numerals, such as '(about 1984)'")) + "Bibtex fields with descriptions.") + +(defvar *org-bibtex-entries* nil + "List to hold parsed bibtex entries.") + +(defcustom org-bibtex-autogen-keys nil + "Set to a truthy value to use `bibtex-generate-autokey' to generate keys= ." + :group 'org-bibtex + :type 'boolean) + +(defcustom org-bibtex-prefix nil + "Optional prefix for all bibtex property names. +For example setting to 'BIB_' would allow interoperability with fireforg." + :group 'org-bibtex + :type 'string) + + +;;; Utility functions +(defun org-bibtex-get (property) + (or (org-entry-get (point) (upcase property)) + (org-entry-get (point) (concat org-bibtex-prefix (upcase property)))= )) =20 +(defun org-bibtex-put (property value) + (let ((prop (upcase (if (keywordp property) + (substring (symbol-name property) 1) + property)))) + (org-set-property + (concat (unless (string=3D "CUSTOM_ID" prop) org-bibtex-prefix) prop) + value))) + +(defun org-bibtex-headline () + "Return a bibtex entry of the given headline as a string." + (flet ((get (key lst) (cdr (assoc key lst))) + (to-k (string) (intern (concat ":" string))) + (from-k (key) (substring (symbol-name key) 1)) + (flatten (&rest lsts) + (apply #'append (mapcar + (lambda (e) + (if (listp e) (apply #'flatten e) (li= st e))) + lsts)))) + (let ((notes (buffer-string)) + (id (org-bibtex-get "custom_id")) + (type (org-bibtex-get "type"))) + (when type + (let ((entry (format + "@%s{%s,\n%s\n}\n" type id + (mapconcat + (lambda (pair) (format " %s=3D{%s}" (car pair) (cd= r pair))) + (remove nil + (mapcar + (lambda (field) + (let ((value (or (org-bibtex-get (from-k field)) + (and (equal :title field) + (org-get-heading))))) + (when value (cons (from-k field) value)))) + (flatten + (get :required (get (to-k type) org-bibtex-types)) + (get :optional (get (to-k type) org-bibtex-types))))) + ",\n")))) + (with-temp-buffer + (insert entry) + (bibtex-reformat) (buffer-string))))))) + +(defun org-bibtex-ask (field) + (unless (assoc field org-bibtex-fields) + (error "field:%s is not known" field)) + (save-window-excursion + (let* ((name (substring (symbol-name field) 1)) + (buf-name (format "*Bibtex Help %s*" name))) + (with-output-to-temp-buffer buf-name + (princ (cdr (assoc field org-bibtex-fields)))) + (with-current-buffer buf-name (longlines-mode t)) + (org-fit-window-to-buffer (get-buffer-window buf-name)) + ((lambda (result) (when (> (length result) 0) result)) + (read-from-minibuffer (format "%s: " name)))))) + +(defun org-bibtex-autokey () + "Generate an autokey for the current headline" + (org-bibtex-put "CUSTOM_ID" + (if org-bibtex-autogen-keys + (let ((entry (org-bibtex-headline))) + (with-temp-buffer + (insert entry) + (bibtex-generate-autokey))) + (read-from-minibuffer "id: ")))) + +(defun org-bibtex-fleshout (type &optional optional) + "Fleshout the current heading, ensuring that all required fields are pre= sent. +With optional argument OPTIONAL, also prompt for optional fields." + (flet ((get (key lst) (cdr (assoc key lst))) + (keyword (name) (intern (concat ":" (downcase name)))) + (name (keyword) (upcase (substring (symbol-name keyword) 1)))) + (dolist (field (append + (remove :title (get :required (get type org-bibtex-types))) + (when optional (get :optional (get type org-bibtex-types))))) + (when (consp field) ; or'd pair of fields e.g., (:editor :author) + (let ((present (first (remove nil + (mapcar + (lambda (f) (when (org-bibtex-get (name f= )) f)) + field))))) + (setf field (or present (keyword (org-icompleting-read + "Field: " (mapcar #'name field))))))) + (let ((name (name field))) + (unless (org-bibtex-get name) + (let ((prop (org-bibtex-ask field))) + (when prop (org-bibtex-put name prop))))))) + (when (and type (assoc type org-bibtex-types) + (not (org-bibtex-get "CUSTOM_ID"))) + (org-bibtex-autokey))) + + +;;; Bibtex link functions (org-add-link-type "bibtex" 'org-bibtex-open) (add-hook 'org-store-link-functions 'org-bibtex-store-link) =20 -;; (defun org-bibtex-publish (path) -;; "Build the description of the BibTeX entry for publishing." -;; (let* ((search (when (string-match "::\\(.+\\)\\'" path) -;; (match-string 1 path))) -;; (path (substring path 0 (match-beginning 0))) -;; key) -;; (with-temp-buffer -;; (org-open-file path t nil search) -;; (setq key (org-create-file-search-functions))) -;; (or description key))) - (defun org-bibtex-open (path) "Visit the bibliography entry on PATH." (let* ((search (when (string-match "::\\(.+\\)\\'" path) @@ -192,12 +404,103 @@ (goto-char p) (bibtex-url))) (recenter 0)) ; Move entry start to beginning of window - ;; return t to indicate that the search is done. + ;; return t to indicate that the search is done. t)) =20 ;; Finally add the link search function to the right hook. (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-b= ibtex) =20 + +;;; Bibtex <-> Org-mode headline translation functions +(defun org-bibtex () + "Export each headline in the current file to a bibtex entry. +Headlines are exported using `org-bibtex-export-headline'." + (interactive) + (let ((bibtex-entries (remove nil (org-map-entries #'org-bibtex-headline= )))) + (with-temp-file (concat (file-name-sans-extension (buffer-file-name)) = ".bib") + (insert (mapconcat #'identity bibtex-entries "\n"))))) + +(defun org-bibtex-check (&optional optional) + "Check the current headline for required fields. +With prefix argument OPTIONAL also prompt for optional fields." + (interactive "P") + (save-restriction + (org-narrow-to-subtree) + (let ((type ((lambda (name) (when name (intern (concat ":" name)))) + (org-bibtex-get "TYPE")))) + (when type (org-bibtex-fleshout type optional))))) + +(defun org-bibtex-check-all (&optional optional) + "Check all headlines in the current file. +With prefix argument OPTIONAL also prompt for optional fields." + (interactive) (org-map-entries (lambda () (org-bibtex-check optional)))) + +(defun org-bibtex-create (type) + "Create a new entry at the given level." + (interactive + (list (org-icompleting-read + "Type: " + (mapcar (lambda (type) (symbol-name (car type))) org-bibtex-types)))) + (let ((type (if (keywordp type) type (intern type)))) + (unless (assoc type org-bibtex-types) + (error "type:%s is not known" type)) + (org-insert-heading) + (let ((title (org-bibtex-ask :title))) + (insert title) (org-bibtex-put "TITLE" title)) + (org-bibtex-put "TYPE" (substring (symbol-name type) 1)) + (org-bibtex-fleshout type))) + +(defun org-bibtex-read () + "Read a bibtex entry and save to `*org-bibtex-entries*'. +This uses `bibtex-parse-entry'." + (interactive) + (flet ((keyword (str) (intern (concat ":" (downcase str)))) + (clean-space (str) (replace-regexp-in-string + "[[:space:]\n\r]+" " " str)) + (strip-delim (str) ; strip enclosing "..." and {...} + (dolist (pair '((34 . 34) (123 . 125) (123 . 125))) + (when (and (=3D (aref str 0) (car pair)) + (=3D (aref str (1- (length str))) (cdr pair))) + (setf str (subseq str 1 (1- (length str)))))) str)) + (push (mapcar + (lambda (pair) + (cons (let ((field (keyword (car pair)))) + (case field + (:=3Dtype=3D :type) + (:=3Dkey=3D :key) + (otherwise field))) + (clean-space (strip-delim (cdr pair))))) + (save-excursion (bibtex-beginning-of-entry) (bibtex-parse-entry= ))) + *org-bibtex-entries*))) + +(defun org-bibtex-write () + "Insert a heading built from the first element of `*org-bibtex-entries*'= ." + (interactive) + (when (=3D (length *org-bibtex-entries*) 0) + (error "No entries in `*org-bibtex-entries*'.")) + (let ((entry (pop *org-bibtex-entries*)) + (org-special-properties nil)) ; avoids errors with `org-entry-put' + (flet ((get (field) (cdr (assoc field entry)))) + (org-insert-heading) + (insert (get :title)) + (org-bibtex-put "TITLE" (get :title)) + (org-bibtex-put "TYPE" (downcase (get :type))) + (dolist (pair entry) + (case (car pair) + (:title nil) + (:type nil) + (:key (org-bibtex-put "CUSTOM_ID" (cdr pair))) + (otherwise (org-bibtex-put (car pair) (cdr pair)))))))) + +(defun org-bibtex-yank () + "If kill ring holds a bibtex entry yank it as an Org-mode headline." + (interactive) + (let (entry) + (with-temp-buffer (yank 1) (setf entry (org-bibtex-read))) + (if entry + (org-bibtex-write) + (error "yanked text does not appear to contain a bibtex entry")))) + (provide 'org-bibtex) =20 ;; arch-tag: 83987d5a-01b8-41c7-85bc-77700f1285f5 --=20 1.7.1 --=-=-= Content-Type: text/plain -- Eric Schulte http://cs.unm.edu/~eschulte/ --=-=-=--