Changes
[emacs.git] / .emacs.d / elisp / org / org-bibtex.el
index 39902c0..7b2ed48 100644 (file)
@@ -1,8 +1,8 @@
 ;;; org-bibtex.el --- Org links to BibTeX entries
 ;;
-;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
 ;;
-;; Authors: Bastien Guerry <bzg at gnu dot org>
+;; Authors: Bastien Guerry <bzg@gnu.org>
 ;;       Carsten Dominik <carsten dot dominik at gmail dot com>
 ;;       Eric Schulte <schulte dot eric at gmail dot com>
 ;; Keywords: org, wp, capture
@@ -44,7 +44,7 @@
 ;; Here is an example of a capture template that use some of this
 ;; information (:author :year :title :journal :pages):
 ;;
-;; (setq org-capure-templates
+;; (setq org-capture-templates
 ;;   '((?b "* READ %?\n\n%a\n\n%:author (%:year): %:title\n   \
 ;;          In %:journal, %:pages.")))
 ;;
     (:pages        . "One or more page numbers or range of numbers, such as 42-111 or 7,41,73-97 or 43+ (the ‘+’ in this last example indicates pages following that don’t form simple range). BibTEX requires double dashes for page ranges (--).")
     (:publisher    . "The publisher’s 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 field gives the name of a series or multi-volume set in which the book is published.")
+    (:series       . "The name of a series or set of books.  When citing an entire book, the title field gives its title and an optional series field gives the name of a series or multi-volume set in which the book is published.")
     (:title        . "The work’s title, typed as explained in the LaTeX book.")
     (:type         . "The type of a technical report for example, 'Research Note'.")
     (:volume       . "The volume of a journal or multi-volume book.")
 For example setting to 'BIB_' would allow interoperability with fireforg."
   :group 'org-bibtex
   :version "24.1"
-  :type  'string)
+  :type  '(choice
+          (const nil)
+          (string)))
 
 (defcustom org-bibtex-treat-headline-as-title t
   "Treat headline text as title if title property is absent.
@@ -262,26 +264,39 @@ IDs must be unique."
 
 (defcustom org-bibtex-tags-are-keywords nil
   "Convert the value of the keywords field to tags and vice versa.
-If set to t, comma-separated entries in a bibtex entry's keywords
-field will be converted to org tags.  Note: spaces will be escaped
-with underscores, and characters that are not permitted in org
+
+When non-nil, comma-separated entries in a bibtex entry's keywords
+field will be converted to Org tags.  Note: spaces will be escaped
+with underscores, and characters that are not permitted in Org
 tags will be removed.
 
-If t, local tags in an org entry will be exported as a
-comma-separated string of keywords when exported to bibtex.  Tags
-defined in `org-bibtex-tags' or `org-bibtex-no-export-tags' will
-not be exported."
+When non-nil, local tags in an Org entry will be exported as
+a comma-separated string of keywords when exported to bibtex.
+If `org-bibtex-inherit-tags' is non-nil, inherited tags will also
+be exported as keywords.  Tags defined in `org-bibtex-tags' or
+`org-bibtex-no-export-tags' will not be exported."
   :group 'org-bibtex
   :version "24.1"
   :type 'boolean)
 
 (defcustom org-bibtex-no-export-tags nil
   "List of tag(s) that should not be converted to keywords.
-This variable is relevant only if `org-bibtex-export-tags-as-keywords' is t."
+This variable is relevant only if `org-bibtex-tags-are-keywords'
+is non-nil."
   :group 'org-bibtex
   :version "24.1"
   :type '(repeat :tag "Tag" (string)))
 
+(defcustom org-bibtex-inherit-tags nil
+  "Controls whether inherited tags are converted to bibtex keywords.
+It is relevant only if `org-bibtex-tags-are-keywords' is non-nil.
+Tag inheritence itself is controlled by `org-use-tag-inheritence'
+and `org-exclude-tags-from-inheritence'."
+  :group 'org-bibtex
+  :version "25.1"
+  :package-version '(Org . "8.3")
+  :type 'boolean)
+
 (defcustom org-bibtex-type-property-name "btype"
   "Property in which to store bibtex entry type (e.g., article)."
   :group 'org-bibtex
@@ -291,12 +306,13 @@ This variable is relevant only if `org-bibtex-export-tags-as-keywords' is t."
 \f
 ;;; Utility functions
 (defun org-bibtex-get (property)
-  ((lambda (it) (when it (org-babel-trim it)))
-   (let ((org-special-properties
-         (delete "FILE" (copy-sequence org-special-properties))))
-     (or
-      (org-entry-get (point) (upcase property))
-      (org-entry-get (point) (concat org-bibtex-prefix (upcase property)))))))
+  (let ((it (let ((org-special-properties
+                   (delete "FILE" (copy-sequence org-special-properties))))
+              (or
+               (org-entry-get (point) (upcase property))
+               (org-entry-get (point) (concat org-bibtex-prefix
+                                              (upcase property)))))))
+    (when it (org-babel-trim it))))
 
 (defun org-bibtex-put (property value)
   (let ((prop (upcase (if (keywordp property)
@@ -329,7 +345,9 @@ This variable is relevant only if `org-bibtex-export-tags-as-keywords' is t."
                                          (append org-bibtex-tags
                                                  org-bibtex-no-export-tags))
                            tag))
-                       (org-get-local-tags-at))))))
+                       (if org-bibtex-inherit-tags
+                           (org-get-tags-at)
+                         (org-get-local-tags-at)))))))
     (when type
       (let ((entry (format
                    "@%s{%s,\n%s\n}\n" type id
@@ -368,7 +386,9 @@ This variable is relevant only if `org-bibtex-export-tags-as-keywords' is t."
            (bibtex-beginning-of-entry)
            (if (re-search-forward "keywords.*=.*{\\(.*\\)}" nil t)
                (progn (goto-char (match-end 1)) (insert ", "))
-             (bibtex-make-field "keywords" t t))
+             (search-forward ",\n" nil t)
+             (insert "  keywords={},\n")
+             (search-backward "}," nil t))
            (insert (mapconcat #'identity tags ", ")))
          (buffer-string))))))
 
@@ -382,8 +402,8 @@ This variable is relevant only if `org-bibtex-export-tags-as-keywords' is t."
        (princ (cdr (assoc field org-bibtex-fields))))
       (with-current-buffer buf-name (visual-line-mode 1))
       (org-fit-window-to-buffer (get-buffer-window buf-name))
-      ((lambda (result) (when (> (length result) 0) result))
-       (read-from-minibuffer (format "%s: " name))))))
+      (let ((result (read-from-minibuffer (format "%s: " name))))
+        (when (> (length result) 0) result)))))
 
 (defun org-bibtex-autokey ()
   "Generate an autokey for the current headline."
@@ -531,26 +551,27 @@ With optional argument OPTIONAL, also prompt for optional fields."
 ;;; Bibtex <-> Org-mode headline translation functions
 (defun org-bibtex (&optional filename)
   "Export each headline in the current file to a bibtex entry.
-Headlines are exported using `org-bibtex-export-headline'."
+Headlines are exported using `org-bibtex-headline'."
   (interactive
    (list (read-file-name
          "Bibtex file: " nil nil nil
          (file-name-nondirectory
           (concat (file-name-sans-extension (buffer-file-name)) ".bib")))))
-  ((lambda (error-point)
-     (when error-point
-       (goto-char error-point)
-       (message "Bibtex error at %S" (nth 4 (org-heading-components)))))
-   (catch 'bib
-     (let ((bibtex-entries (remove nil (org-map-entries
-                                       (lambda ()
-                                         (condition-case foo
-                                             (org-bibtex-headline)
-                                           (error (throw 'bib (point)))))))))
-       (with-temp-file filename
-        (insert (mapconcat #'identity bibtex-entries "\n")))
-       (message "Successfully exported %d BibTeX entries to %s"
-               (length bibtex-entries) filename) nil))))
+  (let ((error-point
+         (catch 'bib
+           (let ((bibtex-entries
+                  (remove nil (org-map-entries
+                               (lambda ()
+                                 (condition-case foo
+                                     (org-bibtex-headline)
+                                   (error (throw 'bib (point)))))))))
+             (with-temp-file filename
+               (insert (mapconcat #'identity bibtex-entries "\n")))
+             (message "Successfully exported %d BibTeX entries to %s"
+                      (length bibtex-entries) filename) nil))))
+    (when error-point
+      (goto-char error-point)
+      (message "Bibtex error at %S" (nth 4 (org-heading-components))))))
 
 (defun org-bibtex-check (&optional optional)
   "Check the current headline for required fields.
@@ -558,8 +579,8 @@ 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 org-bibtex-type-property-name))))
+    (let ((type (let ((name (org-bibtex-get org-bibtex-type-property-name)))
+                  (when name (intern (concat ":" name))))))
       (when type (org-bibtex-fleshout type optional)))))
 
 (defun org-bibtex-check-all (&optional optional)
@@ -609,7 +630,8 @@ This uses `bibtex-parse-entry'."
        (strip-delim
         (lambda (str)       ; strip enclosing "..." and {...}
           (dolist (pair '((34 . 34) (123 . 125) (123 . 125)))
-            (when (and (= (aref str 0) (car pair))
+            (when (and (> (length str) 1)
+                       (= (aref str 0) (car pair))
                        (= (aref str (1- (length str))) (cdr pair)))
               (setf str (substring str 1 (1- (length str)))))) str)))
     (push (mapcar
@@ -626,7 +648,7 @@ This uses `bibtex-parse-entry'."
 (defun org-bibtex-read-buffer (buffer)
   "Read all bibtex entries in BUFFER and save to `org-bibtex-entries'.
 Return the number of saved entries."
-  (interactive "bbuffer: ")
+  (interactive "bBuffer: ")
   (let ((start-length (length org-bibtex-entries)))
     (with-current-buffer buffer
       (save-excursion
@@ -636,12 +658,12 @@ Return the number of saved entries."
          (org-bibtex-read)
          (bibtex-beginning-of-entry))))
     (let ((added (- (length org-bibtex-entries) start-length)))
-      (message "parsed %d entries" added)
+      (message "Parsed %d entries" added)
       added)))
 
 (defun org-bibtex-read-file (file)
   "Read FILE with `org-bibtex-read-buffer'."
-  (interactive "ffile: ")
+  (interactive "fFile: ")
   (org-bibtex-read-buffer (find-file-noselect file 'nowarn 'rawfile)))
 
 (defun org-bibtex-write ()
@@ -687,7 +709,7 @@ Return the number of saved entries."
 
 (defun org-bibtex-import-from-file (file)
   "Read bibtex entries from FILE and insert as Org-mode headlines after point."
-  (interactive "ffile: ")
+  (interactive "fFile: ")
   (dotimes (_ (org-bibtex-read-file file))
     (save-excursion (org-bibtex-write))
     (re-search-forward org-property-end-re)