Commit | Line | Data |
---|---|---|
20908596 CD |
1 | ;;; org-bibtex.el --- Org links to BibTeX entries |
2 | ;; | |
3 | ;; Copyright 2007, 2008 Free Software Foundation, Inc. | |
4 | ;; | |
5 | ;; Author: Bastien Guerry <bzg at altern dot org> | |
6 | ;; Carsten Dominik <carsten dot dominik at gmail dot com> | |
7 | ;; Keywords: org, wp, remember | |
ce4fdcb9 | 8 | ;; Version: 6.13 |
20908596 CD |
9 | ;; |
10 | ;; This file is part of GNU Emacs. | |
11 | ;; | |
b1fc2b50 | 12 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
20908596 | 13 | ;; it under the terms of the GNU General Public License as published by |
b1fc2b50 GM |
14 | ;; the Free Software Foundation, either version 3 of the License, or |
15 | ;; (at your option) any later version. | |
20908596 CD |
16 | |
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
b1fc2b50 | 23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
20908596 CD |
24 | ;; |
25 | ;;; Commentary: | |
26 | ;; | |
27 | ;; This file implements links to database entries in BibTeX files. | |
28 | ;; Instead of defining a special link prefix, it uses the normal file | |
29 | ;; links combined with a custom search mechanism to find entries | |
30 | ;; by reference key. And it constucts a nice description tag for | |
31 | ;; the link that contains the author name, the year and a short title. | |
32 | ;; | |
33 | ;; It also stores detailed information about the entry so that | |
34 | ;; remember templates can access and enter this information easily. | |
35 | ;; | |
36 | ;; The available properties for each entry are listed here: | |
37 | ;; | |
38 | ;; :author :publisher :volume :pages | |
39 | ;; :editor :url :number :journal | |
40 | ;; :title :year :series :address | |
41 | ;; :booktitle :month :annote :abstract | |
42 | ;; :key :btype | |
43 | ;; | |
44 | ;; Here is an example of a remember template that use some of this | |
45 | ;; information (:author :year :title :journal :pages): | |
46 | ;; | |
47 | ;; (setq org-remember-templates | |
48 | ;; '((?b "* READ %?\n\n%a\n\n%:author (%:year): %:title\n \ | |
49 | ;; In %:journal, %:pages."))) | |
50 | ;; | |
51 | ;; Let's say you want to remember this BibTeX entry: | |
52 | ;; | |
53 | ;; @Article{dolev83, | |
54 | ;; author = {Danny Dolev and Andrew C. Yao}, | |
55 | ;; title = {On the security of public-key protocols}, | |
56 | ;; journal = {IEEE Transaction on Information Theory}, | |
57 | ;; year = 1983, | |
58 | ;; volume = 2, | |
59 | ;; number = 29, | |
60 | ;; pages = {198--208}, | |
61 | ;; month = {Mars} | |
62 | ;; } | |
63 | ;; | |
64 | ;; M-x `org-remember' on this entry will produce this buffer: | |
65 | ;; | |
66 | ;; ===================================================================== | |
67 | ;; * READ <== [point here] | |
68 | ;; | |
69 | ;; [[file:/file.bib::dolev83][Dolev & Yao 1983: security of public key protocols]] | |
70 | ;; | |
71 | ;; Danny Dolev and Andrew C. Yao (1983): On the security of public-key protocols | |
72 | ;; In IEEE Transaction on Information Theory, 198--208. | |
73 | ;; ===================================================================== | |
74 | ;; | |
75 | ;;; History: | |
76 | ;; | |
77 | ;; The link creation part has been part of Org-mode for a long time. | |
78 | ;; | |
79 | ;; Creating better remember template information was inspired by a request | |
80 | ;; of Austin Frank: http://article.gmane.org/gmane.emacs.orgmode/4112 | |
81 | ;; and then imlemented by Bastien Guerry. | |
82 | ;; | |
83 | ;; Org-mode loads this module by default - if this is not what you want, | |
84 | ;; configure the variable `org-modules'. | |
85 | ||
86 | ;;; Code: | |
87 | ||
88 | (require 'org) | |
89 | ||
90 | (defvar description nil) ; dynamically scoped from org.el | |
91 | ||
92 | (declare-function bibtex-beginning-of-entry "bibtex" ()) | |
93 | (declare-function bibtex-generate-autokey "bibtex" ()) | |
94 | (declare-function bibtex-parse-entry "bibtex" (&optional content)) | |
95 | (declare-function bibtex-url "bibtex" (&optional pos no-browse)) | |
96 | ||
97 | (org-add-link-type "bibtex" 'org-bibtex-open) | |
98 | (add-hook 'org-store-link-functions 'org-bibtex-store-link) | |
99 | ||
100 | ;; (defun org-bibtex-publish (path) | |
101 | ;; "Build the description of the BibTeX entry for publishing." | |
102 | ;; (let* ((search (when (string-match "::\\(.+\\)\\'" path) | |
103 | ;; (match-string 1 path))) | |
104 | ;; (path (substring path 0 (match-beginning 0))) | |
105 | ;; key) | |
106 | ;; (with-temp-buffer | |
107 | ;; (org-open-file path t nil search) | |
108 | ;; (setq key (org-create-file-search-functions))) | |
109 | ;; (or description key))) | |
110 | ||
111 | (defun org-bibtex-open (path) | |
112 | "Visit the bibliography entry on PATH." | |
113 | (let* ((search (when (string-match "::\\(.+\\)\\'" path) | |
114 | (match-string 1 path))) | |
115 | (path (substring path 0 (match-beginning 0)))) | |
116 | (org-open-file path t nil search))) | |
117 | ||
118 | (defun org-bibtex-store-link () | |
119 | "Store a link to a BibTeX entry." | |
120 | (when (eq major-mode 'bibtex-mode) | |
121 | (let* ((search (org-create-file-search-in-bibtex)) | |
122 | (link (concat "file:" (abbreviate-file-name buffer-file-name) | |
123 | "::" search)) | |
124 | (entry (mapcar ; repair strings enclosed in "..." or {...} | |
125 | (lambda(c) | |
126 | (if (string-match | |
127 | "^\\(?:{\\|\"\\)\\(.*\\)\\(?:}\\|\"\\)$" (cdr c)) | |
128 | (cons (car c) (match-string 1 (cdr c))) c)) | |
129 | (save-excursion | |
130 | (bibtex-beginning-of-entry) | |
131 | (bibtex-parse-entry))))) | |
132 | (org-store-link-props | |
133 | :key (cdr (assoc "=key=" entry)) | |
134 | :author (or (cdr (assoc "author" entry)) "[no author]") | |
135 | :editor (or (cdr (assoc "editor" entry)) "[no editor]") | |
136 | :title (or (cdr (assoc "title" entry)) "[no title]") | |
137 | :booktitle (or (cdr (assoc "booktitle" entry)) "[no booktitle]") | |
138 | :journal (or (cdr (assoc "journal" entry)) "[no journal]") | |
139 | :publisher (or (cdr (assoc "publisher" entry)) "[no publisher]") | |
140 | :pages (or (cdr (assoc "pages" entry)) "[no pages]") | |
141 | :url (or (cdr (assoc "url" entry)) "[no url]") | |
142 | :year (or (cdr (assoc "year" entry)) "[no year]") | |
143 | :month (or (cdr (assoc "month" entry)) "[no month]") | |
144 | :address (or (cdr (assoc "address" entry)) "[no address]") | |
145 | :volume (or (cdr (assoc "volume" entry)) "[no volume]") | |
146 | :number (or (cdr (assoc "number" entry)) "[no number]") | |
147 | :annote (or (cdr (assoc "annote" entry)) "[no annotation]") | |
148 | :series (or (cdr (assoc "series" entry)) "[no series]") | |
149 | :abstract (or (cdr (assoc "abstract" entry)) "[no abstract]") | |
150 | :btype (or (cdr (assoc "=type=" entry)) "[no type]") | |
151 | :type "bibtex" | |
152 | :link link | |
153 | :description description)))) | |
154 | ||
155 | (defun org-create-file-search-in-bibtex () | |
156 | "Create the search string and description for a BibTeX database entry." | |
157 | ;; Make a good description for this entry, using names, year and the title | |
158 | ;; Put it into the `description' variable which is dynamically scoped. | |
159 | (let ((bibtex-autokey-names 1) | |
160 | (bibtex-autokey-names-stretch 1) | |
161 | (bibtex-autokey-name-case-convert-function 'identity) | |
162 | (bibtex-autokey-name-separator " & ") | |
163 | (bibtex-autokey-additional-names " et al.") | |
164 | (bibtex-autokey-year-length 4) | |
165 | (bibtex-autokey-name-year-separator " ") | |
166 | (bibtex-autokey-titlewords 3) | |
167 | (bibtex-autokey-titleword-separator " ") | |
168 | (bibtex-autokey-titleword-case-convert-function 'identity) | |
169 | (bibtex-autokey-titleword-length 'infty) | |
170 | (bibtex-autokey-year-title-separator ": ")) | |
171 | (setq description (bibtex-generate-autokey))) | |
172 | ;; Now parse the entry, get the key and return it. | |
173 | (save-excursion | |
174 | (bibtex-beginning-of-entry) | |
175 | (cdr (assoc "=key=" (bibtex-parse-entry))))) | |
176 | ||
177 | (defun org-execute-file-search-in-bibtex (s) | |
178 | "Find the link search string S as a key for a database entry." | |
179 | (when (eq major-mode 'bibtex-mode) | |
180 | ;; Yes, we want to do the search in this file. | |
181 | ;; We construct a regexp that searches for "@entrytype{" followed by the key | |
182 | (goto-char (point-min)) | |
183 | (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*" | |
184 | (regexp-quote s) "[ \t\n]*,") nil t) | |
185 | (goto-char (match-beginning 0))) | |
186 | (if (and (match-beginning 0) (equal current-prefix-arg '(16))) | |
187 | ;; Use double prefix to indicate that any web link should be browsed | |
188 | (let ((b (current-buffer)) (p (point))) | |
189 | ;; Restore the window configuration because we just use the web link | |
190 | (set-window-configuration org-window-config-before-follow-link) | |
191 | (save-excursion (set-buffer b) (goto-char p) | |
192 | (bibtex-url))) | |
193 | (recenter 0)) ; Move entry start to beginning of window | |
194 | ;; return t to indicate that the search is done. | |
195 | t)) | |
196 | ||
197 | ;; Finally add the link search function to the right hook. | |
198 | (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex) | |
199 | ||
200 | (provide 'org-bibtex) | |
201 | ||
88ac7b50 | 202 | ;; arch-tag: 83987d5a-01b8-41c7-85bc-77700f1285f5 |
b349f79f | 203 | |
20908596 | 204 | ;;; org-bibtex.el ends here |