Mercurial > emacs
comparison lisp/textmodes/refer.el @ 16473:4ef76e689d69
(refer-bib-directory): New variable, list of
directories where to look for bib files. Special values `texinputs'
and `bibinputs' mean take directory list from corresponding
environment variable.
(refer-bib-files): New special value `auto', for looking up all
files in directories pointed to by refer-bib-directory.
I have the feeling that this isn't really my code but came from
the net (copylefted). However, I cannot trace this down any
more. If it isn't mine, it's probably Ashwin's.
(refer-get-bib-files): Support `auto' value of refer-bib-files.
Support `texinputs', `bibinputs' value of refer-bib-directory.
(refer-saved-state, refer-previous-keywords, refer-saved-pos,
refer-same-file): Properly declared (defvar) these variables.
(refer-yank-key): New function.
(refer-find-entry-internal): Find bibliography entries in other
window, with minimal reconfiguration of windows.
(refer-expand-files): New function.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 26 Oct 1996 18:15:32 +0000 |
parents | 83f275dcd93a |
children | 9b831f34ff7d |
comparison
equal
deleted
inserted
replaced
16472:dbfab9e8b6d8 | 16473:4ef76e689d69 |
---|---|
1 ;;; refer.el --- look up references in bibliography files. | 1 ;;; refer.el --- look up references in bibliography files. |
2 | 2 |
3 ;; Copyright (C) 1992 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1992, 1996 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Ashwin Ram <Ram-Ashwin@cs.yale.edu> | 5 ;; Author: Ashwin Ram <ashwin@cc.gatech.edu> |
6 ;; Maintainer: Gernot Heiser <gernot@jungfrau.disy.cse.unsw.EDU.AU> | |
6 ;; Adapted-By: ESR | 7 ;; Adapted-By: ESR |
7 ;; Keywords: bib | 8 ;; Keywords: bib |
8 | 9 |
9 ;; This file is part of GNU Emacs. | 10 ;; This file is part of GNU Emacs. |
10 | 11 |
40 ;; as search strings). | 41 ;; as search strings). |
41 ;; | 42 ;; |
42 ;; To continue the previous search, i.e., to search for the next occurrence | 43 ;; To continue the previous search, i.e., to search for the next occurrence |
43 ;; of the keywords, use refer-find-next-entry, or invoke refer-find-entry | 44 ;; of the keywords, use refer-find-next-entry, or invoke refer-find-entry |
44 ;; with a prefix argument. | 45 ;; with a prefix argument. |
46 ;; | |
47 ;; Once you've found the entry you want to reference, invoke | |
48 ;; refer-yank-key to insert it at point in the current buffer | |
49 ;; (typically as the argument of a \cite{} command). | |
50 ;; | |
51 ;; I use (define-key tex-mode-map "\C-c\C-y" 'refer-yank-key) | |
52 ;; to bind this often-used function to a key in (la)tex-mode. | |
45 ;; | 53 ;; |
46 ;; If the list of bibliography files changes, reinitialize the variable | 54 ;; If the list of bibliography files changes, reinitialize the variable |
47 ;; refer-bib-files. | 55 ;; refer-bib-files. |
48 ;; | 56 ;; |
49 ;; To customize: | 57 ;; To customize: |
58 ;; specified. So you should be able to use pretty much any bib file with | 66 ;; specified. So you should be able to use pretty much any bib file with |
59 ;; this code. If your bib file does not use paragraphs to separate | 67 ;; this code. If your bib file does not use paragraphs to separate |
60 ;; entries, try setting the paragraph-start/separate variables, or changing | 68 ;; entries, try setting the paragraph-start/separate variables, or changing |
61 ;; the (forward-paragraph 1) call in refer-find-entry-in-file. | 69 ;; the (forward-paragraph 1) call in refer-find-entry-in-file. |
62 | 70 |
63 ;;; ChangeLog: | |
64 | |
65 ;; 01/08/89 Ashwin Ram <Ram-Ashwin@cs.yale.edu> | |
66 ;; Initial release. | |
67 ;; | |
68 | |
69 ;;; Code: | 71 ;;; Code: |
70 | 72 |
71 (provide 'refer) | 73 (provide 'refer) |
74 | |
75 (defvar refer-bib-directory nil | |
76 "Directory, or list of directories, to search for \\.bib files. Can | |
77 be set to 'bibinputs or 'texinputs, in which case the environment | |
78 variable BIBINPUTS or TEXINPUTS, respectively, is used to obtain a | |
79 list of directories. Useful only if refer-bib-files is set to 'dir or | |
80 a list of file names (without directory). A value of nil indicates the | |
81 current working directory. | |
82 | |
83 If refer-bib-directory is 'bibinputs or 'texinputs, it is setq'd to | |
84 the appropriate list of directories when it is first used. | |
85 | |
86 Note that an empty directory is interpreted by BibTeX as indicating | |
87 the default search path. Since Refer does not know that default path, | |
88 it cannot search it. Include that path explicitly in your BIBINPUTS | |
89 environment if you really want it searched (which is not likely to | |
90 happen anyway).") | |
72 | 91 |
73 (defvar refer-bib-files 'dir | 92 (defvar refer-bib-files 'dir |
74 "*List of \\.bib files to search for references, | 93 "*List of \\.bib files to search for references, |
75 or one of the following special values: | 94 or one of the following special values: |
76 nil = prompt for \\.bib file (if visiting a \\.bib file, use it as default) | 95 nil = prompt for \\.bib file (if visiting a \\.bib file, use it as default) |
77 auto = read \\.bib file names from appropriate command in buffer (see refer-bib-files-regexp) | 96 auto = read \\.bib file names from appropriate command in buffer (see |
78 dir = use all \\.bib files in current directory. | 97 refer-bib-files-regexp) unless the buffer's mode is bibtex-mode, |
98 in which case only the buffer is searched | |
99 dir = use all \\.bib files in directories referenced by refer-bib-directory. | |
79 | 100 |
80 If a specified file doesn't exist and has no extension, a \\.bib extension | 101 If a specified file doesn't exist and has no extension, a \\.bib extension |
81 is automatically tried. | 102 is automatically tried. |
82 | 103 |
83 If refer-bib-files is nil, auto or dir, it is setq'd to the appropriate | 104 If refer-bib-files is nil, auto or dir, it is setq'd to the appropriate |
94 (defvar refer-bib-files-regexp "\\\\bibliography" | 115 (defvar refer-bib-files-regexp "\\\\bibliography" |
95 "*Regexp matching a bibliography file declaration. | 116 "*Regexp matching a bibliography file declaration. |
96 The current buffer is expected to contain a line such as | 117 The current buffer is expected to contain a line such as |
97 \\bibliography{file1,file2,file3} | 118 \\bibliography{file1,file2,file3} |
98 which is read to set up refer-bib-files. The regexp must specify the command | 119 which is read to set up refer-bib-files. The regexp must specify the command |
99 \(such as \\bibliography) that is used to specify the list of bib files. The | 120 (such as \\bibliography) that is used to specify the list of bib files. The |
100 command is expected to specify a file name, or a list of comma-separated file | 121 command is expected to specify a file name, or a list of comma-separated file |
101 names, within curly braces. | 122 names, within curly braces. |
102 If a specified file doesn't exist and has no extension, a \\.bib extension | 123 If a specified file doesn't exist and has no extension, a \\.bib extension |
103 is automatically tried.") | 124 is automatically tried.") |
104 | 125 |
105 (make-variable-buffer-local 'refer-bib-files) | 126 (make-variable-buffer-local 'refer-bib-files) |
106 (make-variable-buffer-local 'refer-cache-bib-files) | 127 (make-variable-buffer-local 'refer-cache-bib-files) |
128 (make-variable-buffer-local 'refer-bib-directory) | |
129 | |
130 ;;; Internal variables | |
131 (defvar refer-saved-state nil) | |
132 (defvar refer-previous-keywords nil) | |
133 (defvar refer-saved-pos nil) | |
134 (defvar refer-same-file nil) | |
107 | 135 |
108 (defun refer-find-entry (keywords &optional continue) | 136 (defun refer-find-entry (keywords &optional continue) |
109 "Find entry in refer-bib-files containing KEYWORDS. | 137 "Find entry in refer-bib-files containing KEYWORDS. |
110 If KEYWORDS is nil, prompt user for blank-separated list of keywords. | 138 If KEYWORDS is nil, prompt user for blank-separated list of keywords. |
111 If CONTINUE is t, or if called interactively with a prefix arg, look for next | 139 If CONTINUE is t, or if called interactively with a prefix arg, look for next |
112 entry by continuing search from previous point." | 140 entry by continuing search from previous point." |
113 (interactive (list nil current-prefix-arg)) | 141 (interactive (list nil current-prefix-arg)) |
114 (or keywords (setq keywords (if continue | 142 (or keywords (setq keywords (if continue |
115 refer-previous-keywords | 143 refer-previous-keywords |
116 (read-string "Keywords: ")))) | 144 (read-string "Keywords: ")))) |
117 (setq refer-previous-keywords keywords) | 145 (setq refer-previous-keywords keywords) |
118 (refer-find-entry-internal keywords continue)) | 146 (refer-find-entry-internal keywords continue)) |
119 | 147 |
120 (defun refer-find-next-entry () | 148 (defun refer-find-next-entry () |
121 "Find next occurrence of entry in refer-bib-files. See refer-find-entry." | 149 "Find next occurrence of entry in refer-bib-files. See refer-find-entry." |
122 (interactive) | 150 (interactive) |
123 (refer-find-entry-internal refer-previous-keywords t)) | 151 (refer-find-entry-internal refer-previous-keywords t)) |
124 | 152 |
153 (defun refer-yank-key () | |
154 "Inserts at point in current buffer the \"key\" field of the entry | |
155 found on the last refer-find-entry or refer-find-next-entry." | |
156 (interactive) | |
157 (let ((old-point (point))) | |
158 (insert | |
159 (save-window-excursion | |
160 (save-excursion | |
161 (find-file (car refer-saved-state)) | |
162 (if (looking-at | |
163 "[ \t\n]*@\\s-*[a-zA-Z][a-zA-Z0-9]*\\s-*{\\s-*\\([^ \t\n,]+\\)\\s-*,") | |
164 (buffer-substring (match-beginning 1) (match-end 1)) | |
165 (error "Cannot find key for entry in file %s." | |
166 (car refer-saved-state)))))) | |
167 (if (not (= (point) old-point)) | |
168 (set-mark old-point)))) | |
169 | |
125 (defun refer-find-entry-internal (keywords continue) | 170 (defun refer-find-entry-internal (keywords continue) |
126 (let ((keywords-list (refer-convert-string-to-list-of-strings keywords)) | 171 (let ((keywords-list (refer-convert-string-to-list-of-strings keywords)) |
172 (old-buffer (current-buffer)) | |
173 (old-window (selected-window)) | |
174 (new-window (selected-window)) | |
127 (files (if continue | 175 (files (if continue |
128 refer-saved-state | 176 refer-saved-state |
129 (refer-get-bib-files)))) | 177 (setq refer-saved-pos nil) |
130 (catch 'found | 178 (refer-get-bib-files))) |
131 (while files | 179 (n 0) |
132 (let ((file (cond ((file-exists-p (car files)) (car files)) | 180 (found nil) |
133 ((file-exists-p (concat (car files) ".bib")) (concat (car files) ".bib"))))) | 181 (file nil)) |
134 (setq refer-saved-state files) | 182 ;; find window in which to display bibliography file. |
135 (if file | 183 ;; if a bibliography file is already displayed in a window, use |
136 (if (refer-find-entry-in-file keywords-list file continue) | 184 ;; that one, otherwise use any window other than the current one |
137 (throw 'found (find-file file)) | 185 (while (not found) |
138 (setq files (cdr files))) | 186 (while (and (not (null (setq file (nth n files)))) |
139 (progn (message "Scanning %s... No such file" (car files) (ding)) | 187 (setq n (1+ n)) |
140 (sit-for 1) | 188 (not (string-equal file |
141 (setq files (cdr files)))))) | 189 (buffer-file-name |
142 (message "Keywords \"%s\" not found in any \.bib file" keywords (ding))))) | 190 (window-buffer new-window)))))) |
143 | 191 (setq found |
144 (defun refer-find-entry-in-file (keywords-list file &optional continue) | 192 (if (null file) |
145 (message "Scanning %s..." file) ; (expand-file-name file) | 193 (eq (setq new-window (next-window new-window 'nomini)) |
194 old-window) | |
195 't))) | |
196 (if (null file) ; didn't find bib file in any window: | |
197 (progn (if (one-window-p 'nomini) | |
198 (setq old-window (split-window))) | |
199 (setq new-window (next-window old-window 'nomini)))) | |
200 (select-window (if refer-same-file | |
201 old-window | |
202 new-window)) ; the window in which to show the bib file | |
203 (catch 'found | |
204 (while files | |
205 (let ((file (cond ((file-exists-p (car files)) (car files)) | |
206 ((file-exists-p (concat (car files) ".bib")) | |
207 (concat (car files) ".bib"))))) | |
208 (setq refer-saved-state files) | |
209 (if file | |
210 (if (refer-find-entry-in-file keywords-list file refer-saved-pos) | |
211 (progn | |
212 (setq refer-saved-pos (point)) | |
213 (recenter 0) | |
214 (throw 'found (find-file file))) | |
215 (setq refer-saved-pos nil | |
216 files (cdr files))) | |
217 (progn (message "Scanning %s... No such file" (car files) (ding)) | |
218 (sit-for 1) | |
219 (setq files (cdr files)))))) | |
220 (message "Keywords \"%s\" not found in any \.bib file" keywords (ding))) | |
221 (select-window old-window))) | |
222 | |
223 (defun refer-find-entry-in-file (keywords-list file &optional old-pos) | |
224 (message "Scanning %s..." file) | |
225 (expand-file-name file) | |
146 (set-buffer (find-file-noselect file)) | 226 (set-buffer (find-file-noselect file)) |
147 (if continue | 227 (find-file file) |
148 (forward-paragraph 1) | 228 (if (not old-pos) |
149 (goto-char (point-min))) | 229 (goto-char (point-min)) |
230 (goto-char old-pos) | |
231 (forward-paragraph 1)) | |
150 (let ((begin (point)) | 232 (let ((begin (point)) |
151 (end 0) | 233 (end 0) |
152 (found nil)) | 234 (found nil)) |
153 (while (and (not found) | 235 (while (and (not found) |
154 (not (eobp))) | 236 (not (eobp))) |
155 (forward-paragraph 1) | 237 (forward-paragraph 1) |
156 (setq end (point)) | 238 (setq end (point)) |
157 (setq found | 239 (setq found |
158 (refer-every (function (lambda (keyword) | 240 (refer-every (function (lambda (keyword) |
159 (goto-char begin) | 241 (goto-char begin) |
160 (re-search-forward keyword end t))) | 242 (re-search-forward keyword end t))) |
161 keywords-list)) | 243 keywords-list)) |
162 (if (not found) | 244 (if (not found) |
163 (progn | 245 (progn |
164 (setq begin end) | 246 (setq begin end) |
165 (goto-char begin)))) | 247 (goto-char begin)))) |
166 (if found | 248 (if found |
167 (progn (goto-char begin) | 249 (progn (goto-char begin) |
168 (re-search-forward "\\W" nil t) | 250 (re-search-forward "\\W" nil t) |
169 (message "Scanning %s... found" file)) | 251 (message "Scanning %s... found" file)) |
170 (progn (message "Scanning %s... not found" file) | 252 (progn (message "Scanning %s... not found" file) |
171 nil)))) | 253 nil)))) |
172 | 254 |
173 (defun refer-every (pred l) | 255 (defun refer-every (pred l) |
174 (cond ((null l) nil) | 256 (cond ((null l) nil) |
175 ((funcall pred (car l)) | 257 ((funcall pred (car l)) |
176 (or (null (cdr l)) | 258 (or (null (cdr l)) |
177 (refer-every pred (cdr l)))))) | 259 (refer-every pred (cdr l)))))) |
178 | 260 |
179 (defun refer-convert-string-to-list-of-strings (s) | 261 (defun refer-convert-string-to-list-of-strings (s) |
180 (let ((current (current-buffer)) | 262 (let ((current (current-buffer)) |
181 (temp-buffer (get-buffer-create "*refer-temp*"))) | 263 (temp-buffer (get-buffer-create "*refer-temp*"))) |
182 (set-buffer temp-buffer) | 264 (set-buffer temp-buffer) |
190 (insert "\")") | 272 (insert "\")") |
191 (goto-char (point-min)) | 273 (goto-char (point-min)) |
192 (prog1 (read temp-buffer) | 274 (prog1 (read temp-buffer) |
193 (set-buffer current)))) | 275 (set-buffer current)))) |
194 | 276 |
277 (defun refer-expand-files (file-list dir-list) | |
278 (let (file files dir dirs) | |
279 (while (setq file (car file-list)) | |
280 (setq dirs (copy-alist dir-list)) | |
281 (while (setq dir (car dirs)) | |
282 (if (file-exists-p (expand-file-name file dir)) | |
283 (setq files (append files (list (expand-file-name file dir))) | |
284 dirs nil) | |
285 (if (file-exists-p (expand-file-name (concat file ".bib") dir)) | |
286 (setq files (append files (list (expand-file-name (concat file ".bib") | |
287 dir))) | |
288 dirs nil) | |
289 (setq dirs (cdr dirs))))) | |
290 (setq file-list (cdr file-list))) | |
291 files)) | |
292 | |
195 (defun refer-get-bib-files () | 293 (defun refer-get-bib-files () |
196 (let ((files | 294 (let* ((dir-list |
197 (cond ((null refer-bib-files) | 295 (cond |
198 (list (expand-file-name | 296 ((null refer-bib-directory) |
199 (if (eq major-mode 'bibtex-mode) | 297 '(".")) |
200 (read-file-name (format ".bib file: (default %s) " (file-name-nondirectory (buffer-file-name))) | 298 ((or (eq refer-bib-directory 'texinputs) |
201 (file-name-directory (buffer-file-name)) | 299 (eq refer-bib-directory 'bibinputs)) |
202 (file-name-nondirectory (buffer-file-name)) | 300 (let ((envvar (getenv (if (eq refer-bib-directory 'texinputs) |
203 t) | 301 "TEXINPUTS" |
204 (read-file-name ".bib file: " nil nil t))))) | 302 "BIBINPUTS"))) |
205 ((listp refer-bib-files) refer-bib-files) | 303 (dirs nil)) |
206 ((eq refer-bib-files 'auto) | 304 (if (null envvar) |
207 (save-excursion | 305 (setq envvar ".")) |
208 (if (progn (goto-char (point-min)) | 306 (while (string-match ":" envvar) |
209 (re-search-forward (concat refer-bib-files-regexp "\{") nil t)) | 307 (let ((dir (substring envvar 0 (match-beginning 0)))) |
210 (let ((files (list (buffer-substring (point) | 308 (if (and (not (string-equal "" dir)) |
211 (progn (re-search-forward "[,\}]" nil t) | 309 (file-directory-p dir)) |
212 (backward-char 1) | 310 (setq dirs (append (list (expand-file-name dir nil)) |
213 (point)))))) | 311 dirs)))) |
214 (while (not (looking-at "\}")) | 312 (setq envvar (substring envvar (match-end 0)))) |
215 (setq files (append files | 313 (if (and (not (string-equal "" envvar)) |
216 (list (buffer-substring (progn (forward-char 1) | 314 (file-directory-p envvar)) |
217 (point)) | 315 (setq dirs (append (list envvar) dirs))) |
218 (progn (re-search-forward "[,\}]" nil t) | 316 (setq dirs (nreverse dirs)))) |
219 (backward-char 1) | 317 ((listp refer-bib-directory) |
220 (point))))))) | 318 refer-bib-directory) |
221 files) | 319 (t |
222 (error "No \\\\bibliography command in this buffer, can't read refer-bib-files")))) | 320 (list refer-bib-directory)))) |
223 ((eq refer-bib-files 'dir) | 321 (files |
224 (directory-files "." t "\\.bib$")) | 322 (cond |
225 (t (error "Illegal value for refer-bib-files: %s" refer-bib-files))))) | 323 ((null refer-bib-files) |
226 (if refer-cache-bib-files | 324 (list (expand-file-name |
227 (setq refer-bib-files files)) | 325 (if (eq major-mode 'bibtex-mode) |
228 files)) | 326 (read-file-name |
327 (format ".bib file: (default %s) " | |
328 (file-name-nondirectory | |
329 (buffer-file-name))) | |
330 (file-name-directory (buffer-file-name)) | |
331 (file-name-nondirectory (buffer-file-name)) | |
332 t) | |
333 (read-file-name ".bib file: " nil nil t))))) | |
334 ((eq refer-bib-files 'auto) | |
335 (let ((files | |
336 (save-excursion | |
337 (if (setq refer-same-file (eq major-mode 'bibtex-mode)) | |
338 (list buffer-file-name) | |
339 (if (progn | |
340 (goto-char (point-min)) | |
341 (re-search-forward (concat refer-bib-files-regexp | |
342 "\\s-*\{") nil t)) | |
343 (let ((files (list (buffer-substring | |
344 (point) | |
345 (progn | |
346 (re-search-forward "[,\}]" | |
347 nil t) | |
348 (backward-char 1) | |
349 (point)))))) | |
350 (while (not (looking-at "\}")) | |
351 (setq files (append files | |
352 (list (buffer-substring | |
353 (progn (forward-char 1) | |
354 (point)) | |
355 (progn (re-search-forward | |
356 "[,\}]" nil t) | |
357 (backward-char 1) | |
358 (point))))))) | |
359 files) | |
360 (error (concat "No \\\\bibliography command in this " | |
361 "buffer, can't read refer-bib-files"))))))) | |
362 (refer-expand-files files dir-list))) | |
363 ((eq refer-bib-files 'dir) | |
364 (let ((dirs (nreverse dir-list)) | |
365 dir files) | |
366 (while (setq dir (car dirs)) | |
367 (setq files | |
368 (append (directory-files dir t "\\.bib$") | |
369 files)) | |
370 (setq dirs (cdr dirs))) | |
371 files)) | |
372 ((and (listp refer-bib-files) | |
373 (or (eq refer-bib-directory 'texinputs) | |
374 (eq refer-bib-directory 'bibinputs))) | |
375 (refer-expand-files refer-bib-files dir-list)) | |
376 ((listp refer-bib-files) refer-bib-files) | |
377 (t (error "Illegal value for refer-bib-files: %s" | |
378 refer-bib-files))))) | |
379 (if (or (eq refer-bib-directory 'texinputs) | |
380 (eq refer-bib-directory 'bibinputs)) | |
381 (setq refer-bib-directory dir-list)) | |
382 (if refer-cache-bib-files | |
383 (setq refer-bib-files files)) | |
384 files)) | |
229 | 385 |
230 ;;; refer.el ends here | 386 ;;; refer.el ends here |
387 |