comparison lisp/modes/bibtex.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; bibtex.el --- BibTeX mode for GNU Emacs
2
3 ;; Copyright (C) 1992 Free Software Foundation, Inc.
4
5 ;; Author: Bengt Martensson <ubrinf!mond!bengt>
6 ;; Mark Shapiro <shapiro@corto.inria.fr>
7 ;; Mike Newton <newton@gumby.cs.caltech.edu>
8 ;; Aaron Larson <alarson@src.honeywell.com>
9 ;; Version: 1.3.1
10 ;; Maintainer:Aaron Larson <alarson@src.honeywell.com>
11 ;; Adapted-By: ESR
12 ;; Keywords: tex, bib
13
14 ;; This file is part of XEmacs.
15
16 ;; XEmacs is free software; you can redistribute it and/or modify it
17 ;; under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; any later version.
20
21 ;; XEmacs is distributed in the hope that it will be useful, but
22 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 ;; General Public License for more details.
25
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with XEmacs; see the file COPYING. If not, write to the Free
28 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29
30 ;;; TODO distribute texinfo file.
31
32 ;;; LCD Archive Entry:
33 ;;; bibtex-mode|Bengt Martensson, Marc Shapiro, Aaron Larson|
34 ;;; alarson@src.honeywell.com|
35 ;;; Support for maintaining BibTeX format bibliography databases|
36 ;;; 93-03-29|version 1.3|~/modes/bibtex-mode.el.Z|
37
38 ;;; Commentary:
39
40 ;;; BUGS:
41 ;;; 1. using regular expressions to match the entire bibtex entry dies
42 ;;; on long bibtex entires (e.g. those containing abstracts) since
43 ;;; the length of regular expression matches is fairly limited.
44 ;;; 2. When inserting a string (with \C-C\C-E\s) hitting a TAB results
45 ;;; in the error message "Can't find enclosing Bibtex field" instead
46 ;;; of moving to the empty string. [reported by gernot@cs.unsw.oz.au]
47 ;;; 3. Function string-equalp should be in a library file, not in this
48 ;;; file.
49
50 ;;; (current keeper: alarson@src.honeywell.com
51 ;;; previous: shapiro@corto.inria.fr)
52
53 ;;; Change Log:
54
55 ;; Mon Mar 29 14:06:06 1993 Aaron Larson (alarson at gendibal)
56 ;;
57 ;; * bibtex.el: V1.3 released Mar 30, 1993
58 ;; (bibtex-field-name): Fix to match definition if latex manual,
59 ;; specifically letters, digits, and punctuation other than comma.
60 ;; Underscore is retained for historical reasons.
61 ;; (bibtex-make-field): Fix to work around bug in Lucid prin1-to-string
62 ;; function as reported by Martin Sjolin <marsj@ida.liu.se>.
63 ;; (bibtex-entry): minor code cleanup.
64 ;; (bibtex-mode-map): Remove key binding (C-c n) for
65 ;; narrow-to-bibtex-entry, previous binding violated emacs policy of
66 ;; reserving C-c followed by a letter for user customization.
67 ;; revise modification history to better conform to FSF changelog
68 ;; standards.
69 ;; (bibtex-refile-entry): Removed. Would need disclaimer papers to
70 ;; incorporate it into official sources, and unable to contact author.
71 ;; Fix minor "syntax" errors in documentation strings and such found
72 ;; by new byte compiler. Funs bibtex-mode, bibtex-remove-double-quotes
73 ;;
74 ;;
75 ;; Fri Jan 15 14:06:06 1993 Aaron Larson (alarson at gendibal)
76 ;;
77 ;; * bibtex.el: V1.2 released Feb 15 1993
78 ;; (find-bibtex-entry-location bibtex-make-field): Fixed placement of
79 ;; "interactive specification". [Bug report from
80 ;; mernst@theory.lcs.mit.edu]
81 ;; Fixed problem where bibtex-entry would fail if user typed entry
82 ;; name in wrong case.
83 ;; (bibtex-inside-field) Position the cursor _before_ the last comma
84 ;; on a line (the comma is not necessarily "inside" the field); this
85 ;; does not seem to break any existing code. ref sct@dcs.edinburgh.ac.uk
86 ;; (bibtex-enclosing-field, bibtex-enclosing-reference): leave
87 ;; point unmoved if no enclosing field/reference is found. As a
88 ;; result of changes (3) and (4) bibtex-next-field works properly,
89 ;; even when called from the entry key position.
90 ;; (bibtex-remove-OPT): realign the '=' after removing the 'opt'.
91 ;; (bibtex-clean-entry): always remove any trailing comma from the
92 ;; end of a bibtex entry (these commas get stripped automatically when
93 ;; optional fields are killed by bibtex-kill-optional-field, but can be
94 ;; left if optional fields are removed by other means).
95 ;; (bibtex-x-help) Replace tab with spaces in X menu as noted by
96 ;; khera@cs.duke.edu
97 ;; (bibtex-refile-entry): Added (from brannon@jove.cs.caltech.edu)
98 ;; (bibtex-sort-ignore-string-entries sort-bibtex-entries,
99 ;; map-bibtex-entries): Added variable as requested by
100 ;; gernot@cs.unsw.oz.au, required changes to funs.
101 ;; (bibtex-current-entry-label): Added at request of
102 ;; yasuro@maekawa.is.uec.ac.jp
103 ;; (bibtex-DEAthesis:) Deleted along with corresponding entry from
104 ;; bibtex-x-help per shapiro@corto.inria.fr
105 ;; Moved narrow-to-bibtex-entry from C-c C-n to C-c n (the previous
106 ;; binding was in conflict with the binding for bibtex-pop-next.
107 ;; bug report from [shapiro@corto.inria.fr]
108 ;;
109
110 ;;;
111 ;;; alarson@src.honeywell.com 92-Feb-13
112 ;;; 1. Made bibtex-entry user callable, now prompts for entry type (e.g.
113 ;;; Article), with completion, and bound it to a key. This is now my
114 ;;; preferred way to add most entries.
115 ;;; 2. Made fields of a bibtex entry derived from the alist bibtex-entry-
116 ;;; field-alist.
117 ;;; 3. Fixed handling of escaped double quotes, e.g. "Schr{\"o}dinger".
118 ;;; 4. Fixed bug where unhiding bibtex entries moved point.
119 ;;; 5. Made "field name" specs permit (name . value) for defaulting. E.g.
120 ;;; (setq bibtex-mode-user-optional-fields '(("library" . "alarson")))
121 ;;; will generate the field:
122 ;;; library = "alarson",
123 ;;; 6. Added binding for narrow-to-bibtex-entry
124 ;;; 7. Adding a bibtex entry now runs hook: bibtex-add-entry-hook
125 ;;; 8. Made bibtex-clean-entry fixup text alignment, and eliminated the
126 ;;; dependency on bibtex-enclosing-reference which has a problem with
127 ;;; long entries (e.g. those containing abstracts).
128 ;;;
129 ;;; alarson@src.honeywell.com 92-Jan-31
130 ;;; Added support for: ispell, beginning/end of entry movement, a simple
131 ;;; outline like mode (hide the bodies of bibtex entries), support for
132 ;;; sorting bibtex entries, and maintaining them in sorted order, and
133 ;;; simple buffer validation.
134 ;;; User visible functions added:
135 ;;; ispell-{abstract,bibtex-entry}, {beginning,end}-of-bibtex-entry
136 ;;; hide-bibtex-entry-bodies, sort-bibtex-entries, validate-bibtex-
137 ;;; buffer, find-bibtex-duplicates
138 ;;; user visible variables added:
139 ;;; bibtex-maintain-sorted-entries
140 ;;; new local keybindings:
141 ;;; " tex-insert-quote
142 ;;; C-c$ ispell-bibtex-entry
143 ;;; M-C-a beginning-of-bibtex-entry
144 ;;; M-C-e end-of-bibtex-entry
145 ;;; Mike Newton (newton@gumby.cs.caltech.edu) 90.11.17
146 ;;; * Handle items like
147 ;;; title = poft # "Fifth Tri-quarterly" # random-conf,
148 ;;; and title = {This title is inside curlies}
149 ;;; * added user settable, always present, optional fields
150 ;;; * fixed 'bibtex-find-it's doc string's location
151 ;;; * bibtex-field-text made more general (it wouldn't handle the # construct)
152 ;;; and it now handles a small subset of the {} cases
153
154 ;;; Bengt Martensson, March 6
155 ;;; Adapted to Bibtex 0.99 by updating the optional fields according
156 ;;; to the document BibTeXing, Oren Patashnik, dated January 31, 1988.
157 ;;; Updated documentation strings accordingly. Added (provide 'bibtex).
158 ;;; If bibtex-include-OPT-crossref is non-nil, every entry will have
159 ;;; an OPTcrossref field, analogously for bibtex-include-OPTkey and
160 ;;; bibtex-include-OPTannote. Added bibtex-preamble, bound to ^C^EP,
161 ;;; and also found in X- and sun-menus. Cleaned up the sun-menu
162 ;;; stuff, and made it more uniform with the X-menu stuff. Marc: I
163 ;;; strongly suspect that I broke your parsing... (Or, more
164 ;;; correctly, BibTeX 0.99 broke it.)
165 ;;; Added bibtex-clean-entry-zap-empty-opts, defvar'd to t. If it
166 ;;; is nil, bibtex-clean-entry will leave empty optional fields alone.
167
168 ;;; Marc Shapiro 1-feb-89: integrated changes by Bengt Martensson 88-05-06:
169 ;;; Added Sun menu support. Locally bound to right mouse button in
170 ;;; bibtex-mode. Emacs 18.49 allows local mouse bindings!!
171 ;;; Commented out DEAthesis.
172
173 ;;; Marc Shapiro 6-oct-88
174 ;;; * skip-whitespace replaced by skip-chars-forward
175 ;;; * use indent-to-column instead of inserting tabs (changes to
176 ;;; bibtex-entry, bibtex-make-entry, bibtex-make-OPT-entry, renamed to
177 ;;; bibtex-make-optional-entry)
178 ;;; * C-c C-k deletes the current OPT entry entirely
179 ;;; * C-c C-d replaces text of field with ""
180 ;;; * renamed bibtex-find-it to bibtex-find-text. With arg, now goes to
181 ;;; start of text. Fixed bugs in it.
182
183 ;;; Marc Shapiro 23-sep-88
184 ;;; * bibtex-clean-entry moves past end of entry.
185 ;;; * bibtex-clean-entry signals mandatory fields left empty.
186
187 ;;; Marc Shapiro 18-jul-88
188 ;;; * Fixed bug in bibtex-flash-entry
189 ;;; * Moved all the entry type keystrokes to "C-c C-e something" (instead of
190 ;;; "C-c something" previously) to make room for more. C-c C-e is
191 ;;; supposed to stand for "entry" [idea taken from mail-mode]. Moved
192 ;;; bibtex-pop-previous to C-c C-p and bibtex-pop-next to C-c C-n.
193 ;;; * removed binding for "\e[25~"
194 ;;; * replaced bibtex-clean-optionals by bibtex-clean-entry, bound to
195 ;;; C-c C-c
196
197 ;;; Marc Shapiro 13-jul-88 [based on ideas by Sacha Krakowiak of IMAG]
198 ;;; * bibtex-pop-previous replaces current field with value of
199 ;;; similar field in previous entry. May be called n times in a row
200 ;;; (or with arg n) to pop similar field of n'th previous entry.
201 ;;; There is also a bibtex-pop-next to get similar field of next
202 ;;; entry.
203 ;;; * C-c C-k now kills all empty optional fields of current entry, and
204 ;;; removes "OPT" for those optional fields which have text.
205
206 ;;; Marc Shapiro 14-dec-87
207 ;;; Cosmetic fixes. Fixed small bug in bibtex-move-outside-of-entry.
208 ;;; Skip Montanaro <steinmetz!sprite!montanaro> 7-dec-87, Shapiro 10-dec-87
209 ;;; before inserting an entry, make sure we are outside of a bib entry
210 ;;; Marc Shapiro 3-nov-87
211 ;;; addition for France: DEAthesis
212 ;;; Marc Shapiro 19-oct-1987
213 ;;; add X window menu option; bug fixes. TAB, LFD, C-c " and C-c C-o now
214 ;;; behave consistently; deletion never occurs blindly.
215 ;;; Marc Shapiro <shapiro@inria.inria.fr> 15-oct-1986
216 ;;; align long lines nicely; C-c C-o checks for the "OPT" string;
217 ;;; TAB goes to the end of the string; use lower case; use
218 ;;; run-hooks
219
220 ;;; Bengt Martensson <ubrinf!mond!bengt> 87-06-28
221 ;;; Bengt Martensson <bengt@mathematik.uni-Bremen.de> 87-06-28
222 ;;; Original version
223
224 ;;; Code:
225
226 ;;; NOTE by Marc Shapiro, 14-dec-87:
227 ;;; (bibtex-x-environment) binds an X menu for bibtex mode to x-button-c-right.
228 ;;; Trouble is, in Emacs 18.44 you can't have a mode-specific mouse binding,
229 ;;; so it will remain active in all windows. Yuck!
230
231 (provide 'bibtex)
232
233 ;;; these guys typically don't have autoloads...[alarson:19920131.1548CST]
234 ;;; Check for fboundp first so that if user autoloads them from non standard
235 ;;; places, the users bindings will take precedence.
236 (if (not (fboundp 'tex-insert-quote))
237 (autoload 'tex-insert-quote "tex-mode"))
238 (if (not (fboundp 'sort-subr))
239 (autoload 'sort-subr "sort"))
240
241 ;;; These should be in a more generally accessible location.
242
243 (defun string-equalp (s1 s2)
244 "Like string= except differences in case are ignored."
245 (let ((ss1 (if (symbolp s1) (symbol-name s1) s1))
246 (ss2 (if (symbolp s2) (symbol-name s2) s2)))
247 (and (= (length ss1) (length ss2))
248 (string-equal (upcase ss1) (upcase ss2)))))
249
250 ;;; This should be moved into simple.el, and the functions there modified
251 ;;; to call it rather than doing it themselves.
252 (defun put-string-on-kill-ring (string)
253 "Make STRING be the first element of the kill ring."
254 (setq kill-ring (cons string kill-ring))
255 (if (> (length kill-ring) kill-ring-max)
256 (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))
257 (setq kill-ring-yank-pointer kill-ring))
258
259
260
261
262 (defvar bibtex-clean-entry-zap-empty-opts t
263 "*If non-nil, bibtex-clean-entry will delete all empty optional fields.")
264
265 (defvar bibtex-include-OPTcrossref t
266 "*If non-nil, all entries will have an OPTcrossref field.")
267 (defvar bibtex-include-OPTkey t
268 "*If non-nil, all entries will have an OPTkey field.")
269 (defvar bibtex-include-OPTannote t
270 "*If non-nil, all entries will have an OPTannote field.")
271
272 ;; note: the user should be allowed to have their own list of always
273 ;; available optional fields. exs: "keywords" "categories"
274
275 (defvar bibtex-mode-user-optional-fields nil ;no default value
276 "*List of optional fields that user want to have as always present
277 when making a bibtex entry. One possibility is for ``keywords''.
278 Entries can be either strings or conses, in which case the car should be
279 string and the cdr the value to be inserted.")
280
281 (defvar bibtex-mode-syntax-table
282 (let ((st (make-syntax-table)))
283 ;; [alarson:19920214.1004CST] make double quote a string quote
284 (modify-syntax-entry ?\" "\"" st)
285 (modify-syntax-entry ?$ "$$ " st)
286 (modify-syntax-entry ?% "< " st)
287 (modify-syntax-entry ?' "w " st)
288 (modify-syntax-entry ?@ "w " st)
289 (modify-syntax-entry ?\\ "\\" st)
290 (modify-syntax-entry ?\f "> " st)
291 (modify-syntax-entry ?\n "> " st)
292 (modify-syntax-entry ?~ " " st)
293 st))
294
295 (defvar bibtex-mode-abbrev-table nil "")
296 (define-abbrev-table 'bibtex-mode-abbrev-table ())
297 (defvar bibtex-mode-map
298 (let ((km (make-sparse-keymap)))
299
300 (define-key km "\t" 'bibtex-find-text)
301 (define-key km "\n" 'bibtex-next-field)
302 (define-key km "\C-c\"" 'bibtex-remove-double-quotes)
303 (define-key km "\C-c\C-c" 'bibtex-clean-entry)
304 (define-key km "\C-c?" 'describe-mode)
305 (define-key km "\C-c\C-p" 'bibtex-pop-previous)
306 (define-key km "\C-c\C-n" 'bibtex-pop-next)
307 (define-key km "\C-c\C-k" 'bibtex-kill-optional-field)
308 (define-key km "\C-c\C-d" 'bibtex-empty-field)
309
310 ;; [alarson:19920131.1543CST]
311 (define-key km "\"" 'tex-insert-quote)
312 (define-key km "\C-c$" 'ispell-bibtex-entry)
313 (define-key km "\M-\C-a" 'beginning-of-bibtex-entry)
314 (define-key km "\M-\C-e" 'end-of-bibtex-entry)
315 (define-key km "\C-c\C-b" 'bibtex-entry)
316 ; (define-key km "\C-cn" 'narrow-to-bibtex-entry)
317
318 (define-key km "\C-c\C-e\C-a" 'bibtex-Article)
319 (define-key km "\C-c\C-e\C-b" 'bibtex-Book)
320 ; (define-key km "\C-c\C-e\C-d" 'bibtex-DEAthesis)
321 (define-key km "\C-c\C-e\C-c" 'bibtex-InProceedings)
322 (define-key km "\C-c\C-e\C-i" 'bibtex-InBook)
323 (define-key km "\C-c\C-ei" 'bibtex-InCollection)
324 (define-key km "\C-c\C-eI" 'bibtex-InProceedings)
325 (define-key km "\C-c\C-e\C-m" 'bibtex-Manual)
326 (define-key km "\C-c\C-em" 'bibtex-MastersThesis)
327 (define-key km "\C-c\C-eM" 'bibtex-Misc)
328 (define-key km "\C-c\C-o" 'bibtex-remove-OPT)
329 (define-key km "\C-c\C-e\C-p" 'bibtex-PhdThesis)
330 (define-key km "\C-c\C-ep" 'bibtex-Proceedings)
331 (define-key km "\C-c\C-eP" 'bibtex-preamble)
332 (define-key km "\C-c\C-e\C-t" 'bibtex-TechReport)
333 (define-key km "\C-c\C-e\C-s" 'bibtex-string)
334 (define-key km "\C-c\C-e\C-u" 'bibtex-Unpublished)
335
336 (define-key km 'button3 'bibtex-menu)
337 km))
338
339 (defvar bibtex-pop-previous-search-point nil
340 "Next point where bibtex-pop-previous should start looking for a similar
341 entry.")
342
343 (defvar bibtex-pop-next-search-point nil
344 "Next point where bibtex-pop-next should start looking for a similar
345 entry.")
346
347 (defvar bibtex-entry-field-alist
348 '(
349 ("Article" . ((("author" "title" "journal" "year")
350 ("volume" "number" "pages" "month" "note"))
351 (("author" "title")
352 ("journal" "year" "volume" "number" "pages"
353 "month" "note"))))
354 ("Book" . ((("author" "title" "publisher" "year")
355 ("editor" "volume" "number" "series" "address"
356 "edition" "month" "note"))))
357 ("Booklet" . ((("title")
358 ("author" "howpublished" "address" "month" "year" "note"))))
359
360 ;; France: Dipl\^{o}me d'Etudes Approfondies (similar to Master's)
361 ; ("DEAthesis" . ((("author" "title" "school" "year")
362 ; ("address" "month" "note"))))
363
364 ("InBook" . ((("author" "title" "chapter" "publisher" "year")
365 ("editor" "pages" "volume" "number" "series" "address"
366 "edition" "month" "type" "note"))
367 (("author" "title" "chapter")
368 ("publisher" "year" "editor" "pages" "volume" "number"
369 "series" "address" "edition" "month" "type" "note"))))
370
371
372 ("InCollection" . ((("author" "title"
373 "booktitle" "publisher" "year")
374 ("editor" "volume" "number" "series" "type" "chapter"
375 "pages" "address" "edition" "month" "note"))
376 (("author" "title")
377 ("booktitle" "publisher" "year"
378 "editor" "volume" "number" "series" "type" "chapter"
379 "pages" "address" "edition" "month" "note"))))
380
381
382 ("InProceedings" . ((("author" "title" "booktitle" "year")
383 ("editor" "volume" "number" "series" "pages"
384 "organization" "publisher" "address" "month" "note"))
385 (("author" "title")
386 ("editor" "volume" "number" "series" "pages"
387 "booktitle" "year"
388 "organization" "publisher" "address" "month" "note"))))
389
390
391 ("Manual" . ((("title")
392 ("author" "organization" "address" "edition" "year"
393 "month" "note"))))
394
395 ("MastersThesis" . ((("author" "title" "school" "year")
396 ("address" "month" "note" "type"))))
397
398 ("Misc" . ((()
399 ("author" "title" "howpublished" "year" "month" "note"))))
400
401 ("PhdThesis" . ((("author" "title" "school" "year")
402 ("address" "month" "type" "note"))))
403
404 ("Proceedings" . ((("title" "year")
405 ("editor" "volume" "number" "series" "publisher"
406 "organization" "address" "month" "note"))))
407
408 ("TechReport" . ((("author" "title" "institution" "year")
409 ("type" "number" "address" "month" "note"))))
410
411 ("Unpublished" . ((("author" "title" "note")
412 ("year" "month"))))
413 )
414
415 "List of (entry-name (required optional) (crossref-required crossref-optional))
416 tripples. If the third element is nil, then the first pair can be used. Required
417 and optional are lists of strings. All entry creation functions use this variable
418 to generate entries, and bibtex-entry ensures the entry type is valid. This
419 variable can be used for example to make bibtex manipulate a different set of entry
420 types, e.g. a crossreference document of organization types.")
421
422
423 ;;; A bibtex file is a sequence of entries, either string definitions
424 ;;; or reference entries. A reference entry has a type part, a
425 ;;; key part, and a comma-separated sequence of fields. A string
426 ;;; entry has a single field. A field has a left and right part,
427 ;;; separated by a '='. The left part is the name, the right part is
428 ;;; the text. Here come the definitions allowing to create and/or parse
429 ;;; entries and fields:
430
431 ;;; fields
432 (defun bibtex-cfield (name text)
433 "Create a regexp for a bibtex field of name NAME and text TEXT"
434 (concat ",[ \t\n]*\\("
435 name
436 "\\)[ \t\n]*=[ \t\n]*\\("
437 text
438 "\\)"))
439 (defconst bibtex-name-in-cfield 1
440 "The regexp subexpression number of the name part in bibtex-cfield.")
441 (defconst bibtex-text-in-cfield 2
442 "The regexp subexpression number of the text part in bibtex-cfield.")
443
444 ;;; KAWATA Yasuro <yasuro@qqqq.maekawa.is.uec.ac.jp> reported bug that "/"
445 ;;; was not premitted in field names. The old value of this var was:
446 ;;; "[A-Za-z][---A-Za-z0-9:_+]*"
447 ;;; According to the LaTeX manual, page 71, the legal values are letters,
448 ;;; digits, and punctuation other than comma. Section 2.1 defines
449 ;;; punctuation as:
450 ;;; .:;,?!`'()[]-/*@
451 ;;; and says that += can be used in normal text. Specifically #$%&~_^\{}
452 ;;; are called out as special chars. Some experimentation with LaTeX
453 ;;; indicates that # and ~ definitely don't work, but that the following
454 ;;; citation does! \cite{a0.:;?!`'()[]-/*@_&$^+=|<>}. I chose here to
455 ;;; permit _ since it was previously allowed, but otherwise to only handle
456 ;;; punc and +=
457 ;;; Amendment: I couldn't get a regexp with both "[]"'s and hyphen to
458 ;;; work. It looks like you need them both to be the first entries in a
459 ;;; regexp pattern. [alarson:19930315.0900CST]
460
461 (defconst bibtex-field-name "[A-Za-z][---A-Za-z0-9.:;?!`'()/*@_+=]*"
462 "Regexp defining the name part of a bibtex field.")
463
464 ;; bibtex-field-text must be able to handle
465 ;; title = "Proc. Fifteenth Annual" # STOC,
466 ;; month = "10~" # jan,
467 ;; year = "{\noopsort{1973c}}1981",
468 ;; month = apr # "-" # may,
469 ;; key = {Volume-2},
470 ;; note = "Volume~2 is listed under Knuth \cite{book-full}"
471 ;; i have added a few of these, but not all! -- MON
472
473 (defconst bibtex-field-const
474 "[0-9A-Za-z][---A-Za-z0-9:_+]*"
475 "Format of a bibtex field constant.")
476
477 (defconst bibtex-field-string
478 (concat
479 "\"[^\"]*[^\\\\]\"\\|\"\"")
480 "Match either a string or an empty string.")
481
482 (defconst bibtex-field-string-or-const
483 (concat bibtex-field-const "\\|" bibtex-field-string)
484 "Match either bibtex-field-string or bibtex-field-const.")
485
486 (defconst bibtex-field-text
487 (concat
488 "\\(" bibtex-field-string-or-const "\\)"
489 "\\([ \t\n]+#[ \t\n]+\\(" bibtex-field-string-or-const "\\)\\)*\\|"
490 "{[^{}]*[^\\\\]}")
491 "Regexp defining the text part of a bibtex field: either a string, or
492 an empty string, or a constant followed by one or more # / constant pairs.
493 Also matches simple {...} patterns.")
494
495 ;(defconst bibtex-field-text
496 ; "\"[^\"]*[^\\\\]\"\\|\"\"\\|[0-9A-Za-z][---A-Za-z0-9:_+]*"
497 ; "Regexp defining the text part of a bibtex field: either a string, or an empty string, or a constant.")
498
499 (defconst bibtex-field
500 (bibtex-cfield bibtex-field-name bibtex-field-text)
501 "Regexp defining the format of a bibtex field")
502
503 (defconst bibtex-name-in-field bibtex-name-in-cfield
504 "The regexp subexpression number of the name part in bibtex-field")
505 (defconst bibtex-text-in-field bibtex-text-in-cfield
506 "The regexp subexpression number of the text part in bibtex-field")
507
508 ;;; references
509 (defconst bibtex-reference-type
510 "@[A-Za-z]+"
511 "Regexp defining the type part of a bibtex reference entry")
512 (defconst bibtex-reference-head
513 (concat "^[ \t]*\\("
514 bibtex-reference-type
515 "\\)[ \t]*[({]\\("
516 bibtex-field-name
517 "\\)")
518 "Regexp defining format of the header line of a bibtex reference entry")
519 (defconst bibtex-type-in-head 1
520 "The regexp subexpression number of the type part in bibtex-reference-head")
521 (defconst bibtex-key-in-head 2
522 "The regexp subexpression number of the key part in
523 bibtex-reference-head")
524
525 (defconst bibtex-reference
526 (concat bibtex-reference-head
527 "\\([ \t\n]*" bibtex-field "\\)*"
528 "[ \t\n]*[})]")
529 "Regexp defining the format of a bibtex reference entry")
530 (defconst bibtex-type-in-reference bibtex-type-in-head
531 "The regexp subexpression number of the type part in bibtex-reference")
532 (defconst bibtex-key-in-reference bibtex-key-in-head
533 "The regexp subexpression number of the key part in
534 bibtex-reference")
535
536 ;;; strings
537 (defconst bibtex-string
538 (concat "^[ \t]*@[sS][tT][rR][iI][nN][gG][ \t\n]*[({][ \t\n]*\\("
539 bibtex-field-name
540 "\\)[ \t\n]*=[ \t\n]*\\("
541 bibtex-field-text
542 "\\)[ \t\n]*[})]")
543 "Regexp defining the format of a bibtex string entry")
544 (defconst bibtex-name-in-string 1
545 "The regexp subexpression of the name part in bibtex-string")
546 (defconst bibtex-text-in-string 2
547 "The regexp subexpression of the text part in bibtex-string")
548
549 (defconst bibtex-name-alignment 2
550 "Alignment for the name part in BibTeX fields.
551 Chosen on aesthetic grounds only.")
552
553 (defconst bibtex-text-alignment (length " organization = ")
554 "Alignment for the text part in BibTeX fields.
555 Equal to the space needed for the longest name part.")
556
557 (defun bibtex-current-entry-label (&optional include-cite kill)
558 "Return the label of the bibtex entry containing, or preceding point.
559 Optional argument INCLUDE-CITE, if true means put a '\\cite{}' around the
560 returned value. Second optional argument KILL, if true, means place the
561 returned value in the kill buffer. Interactively; providing prefix
562 argument makes INCLUDE-CITE true, and kill is true by default.
563
564 Rationale:
565 The intention is that someone will write a function that can be bound to
566 a mouse key so that people entering TeX can just mouse on the bibtex entry
567 and have the citation key inserted at the current point (which will almost
568 certainly be in some other buffer). In the interim this function is
569 marginally useful for keyboard binding and is not bound by default.
570 Suggested binding is ^C-k."
571 (interactive (list current-prefix-arg t))
572 (save-excursion
573 (beginning-of-bibtex-entry)
574 (re-search-forward bibtex-reference-head (save-excursion (end-of-bibtex-entry) (point)))
575 (let* ((key (buffer-substring (match-beginning bibtex-key-in-head)
576 (match-end bibtex-key-in-head)))
577 (val (if include-cite
578 (format "\\cite{%s}" key)
579 key)))
580 (if kill
581 (put-string-on-kill-ring val))
582 val)))
583
584 ;;; bibtex mode:
585
586 ;;;###autoload
587 (defun bibtex-mode ()
588 "Major mode for editing bibtex files.
589
590 \\{bibtex-mode-map}
591
592 A command such as \\[bibtex-Book] will outline the fields for a BibTeX book entry.
593
594 The optional fields start with the string OPT, and thus ignored by BibTeX.
595 The OPT string may be removed from a field with \\[bibtex-remove-OPT].
596 \\[bibtex-kill-optional-field] kills the current optional field entirely.
597 \\[bibtex-remove-double-quotes] removes the double-quotes around the text of
598 the current field. \\[bibtex-empty-field] replaces the text of the current
599 field with the default \"\".
600
601 The command \\[bibtex-clean-entry] cleans the current entry, i.e. (i) removes
602 double-quotes from entirely numerical fields, (ii) removes OPT from all
603 non-empty optional fields, (iii) removes all empty optional fields, and (iv)
604 checks that no non-optional fields are empty.
605
606 Use \\[bibtex-find-text] to position the dot at the end of the current field.
607 Use \\[bibtex-next-field] to move to end of the next field.
608
609 The following may be of interest as well:
610
611 Functions:
612 find-bibtex-duplicates
613 find-bibtex-entry-location
614 hide-bibtex-entry-bodies
615 sort-bibtex-entries
616 validate-bibtex-buffer
617
618 Variables:
619 bibtex-clean-entry-zap-empty-opts
620 bibtex-entry-field-alist
621 bibtex-include-OPTannote
622 bibtex-include-OPTcrossref
623 bibtex-include-OPTkey
624 bibtex-maintain-sorted-entries
625 bibtex-mode-user-optional-fields
626
627 Fields:
628 address
629 Publisher's address
630 annote
631 Long annotation used for annotated bibliographies (begins sentence)
632 author
633 Name(s) of author(s), in BibTeX name format
634 booktitle
635 Book title when the thing being referenced isn't the whole book.
636 For book entries, the title field should be used instead.
637 chapter
638 Chapter number
639 crossref
640 The database key of the entry being cross referenced.
641 edition
642 Edition of a book (e.g., \"second\")
643 editor
644 Name(s) of editor(s), in BibTeX name format.
645 If there is also an author field, then the editor field should be
646 for the book or collection that the work appears in
647 howpublished
648 How something strange has been published (begins sentence)
649 institution
650 Sponsoring institution
651 journal
652 Journal name (macros are provided for many)
653 key
654 Alphabetizing and labeling key (needed when no author or editor)
655 month
656 Month (macros are provided)
657 note
658 To help the reader find a reference (begins sentence)
659 number
660 Number of a journal or technical report
661 organization
662 Organization (sponsoring a conference)
663 pages
664 Page number or numbers (use `--' to separate a range)
665 publisher
666 Publisher name
667 school
668 School name (for theses)
669 series
670 The name of a series or set of books.
671 An individual book will will also have it's own title
672 title
673 The title of the thing being referenced
674 type
675 Type of a technical report (e.g., \"Research Note\") to be used
676 instead of the default \"Technical Report\"
677 volume
678 Volume of a journal or multivolume work
679 year
680 Year---should contain only numerals
681 ---------------------------------------------------------
682 Entry to this mode calls the value of bibtex-mode-hook if that value is
683 non-nil."
684 (interactive)
685 (kill-all-local-variables)
686 (set-syntax-table bibtex-mode-syntax-table)
687 (use-local-map bibtex-mode-map)
688 (setq major-mode 'bibtex-mode)
689 (setq mode-name "BibTeX")
690 (set-syntax-table bibtex-mode-syntax-table)
691 (setq local-abbrev-table bibtex-mode-abbrev-table)
692 (make-local-variable 'paragraph-start)
693 (setq paragraph-start "^[ \f\n\t]*$")
694 (auto-fill-mode 1) ; nice alignments
695 (setq left-margin (+ bibtex-text-alignment 1))
696
697 (run-hooks 'bibtex-mode-hook))
698
699 (defun bibtex-move-outside-of-entry ()
700 "Make sure we are outside of a bib entry"
701 (cond ((or
702 (= (point) (point-max))
703 (= (point) (point-min))
704 (looking-at "[ \n]*@")
705 )
706 t)
707 (t
708 (backward-paragraph)
709 (forward-paragraph)))
710 (re-search-forward "[ \t\n]*" (point-max) t))
711
712 (defun ispell-abstract ()
713 (interactive)
714 (beginning-of-bibtex-entry)
715 (re-search-forward "^[ \t]*[OPT]*abstract[ \t]*=")
716 (ispell-region (point)
717 (save-excursion (forward-sexp) (point))))
718
719 (defun beginning-of-bibtex-entry ()
720 (interactive)
721 (re-search-backward "^@" nil 'move))
722
723 (defun skip-whitespace-and-comments ()
724 ;; It might be a good idea to have forward-sexp with argument 0 do what
725 ;; this function tries to do, namely skip whitespace and comments.
726 ;; Maybe a better name for this would be skip-to-next-sexp.
727 ;; alternative implementation:
728 ;; (let ((parse-sexp-ignore-comments t))
729 ;; (forward-sexp 1)
730 ;; (forward-sexp -1))
731 ;; but I've had problems with this not getting the parse of comments
732 ;; right going backward if they contain unbalanced expressions or string
733 ;; quotes. [alarson:19920217.1021CST]
734 (let ((md (match-data)))
735 (unwind-protect
736 (while (cond ((looking-at "\\s>+\\|\\s +")
737 ;; was whitespace
738 ;; NOTE: also checked end-comment. In latex and
739 ;; lisp modes, newline is an end comment, but it
740 ;; should also be a whitespace char.
741 (goto-char (match-end 0)))
742 ;; If looking at beginning of comment, skip to end.
743 ((looking-at "\\s<")
744 (re-search-forward "\\s>"))))
745 (store-match-data md))))
746
747 ;;; [alarson:19920214.1007CST]
748 (defun end-of-bibtex-entry ()
749 "If inside an entry, move to the end of it, otherwise move to the end
750 of the next entry."
751 (interactive)
752 ;; if point was previously at the end of an entry, this puts us
753 ;; inside the next entry, otherwise we remain in the current one.
754 (progn
755 (skip-whitespace-and-comments)
756 ;;; (skip-chars-forward " \t\n")
757 (end-of-line))
758 (beginning-of-bibtex-entry)
759 (let ((parse-sexp-ignore-comments t))
760 (forward-sexp) ; skip entry type
761 (forward-sexp) ; skip entry body
762 ))
763 ;(defun end-of-bibtex-entry ()
764 ; (interactive)
765 ; (re-search-forward "}$" nil 'move))
766
767 (defun ispell-bibtex-entry ()
768 (interactive)
769 (ispell-region (progn (beginning-of-bibtex-entry) (point))
770 (progn (end-of-bibtex-entry) (point))))
771
772 (defun narrow-to-bibtex-entry ()
773 (interactive)
774 (save-excursion
775 (narrow-to-region (progn (beginning-of-bibtex-entry) (point))
776 (progn (end-of-bibtex-entry) (point)))))
777
778
779 (defun beginning-of-first-bibtex-entry ()
780 (goto-char (point-min))
781 (cond
782 ((re-search-forward "^@" nil 'move)
783 (beginning-of-line))
784 ((and (bobp) (eobp))
785 nil)
786 (t
787 (message "Warning: No bibtex entries found!"))))
788
789 (defun hide-bibtex-entry-bodies (&optional arg)
790 "Hide all lines between first and last bibtex entries not beginning with @.
791 With argument, show all text."
792 (interactive "P")
793 (save-excursion
794 (beginning-of-first-bibtex-entry)
795 ;; subst-char-in-region modifies the buffer, despite what the
796 ;; documentation says...
797 (let ((modifiedp (buffer-modified-p))
798 (buffer-read-only nil))
799 (if arg
800 (subst-char-in-region (point) (point-max) ?\r ?\n t)
801 (while (save-excursion (re-search-forward "\n[^@]" (point-max) t))
802 (save-excursion (replace-regexp "\n\\([^@]\\)" "\r\\1"))))
803 (setq selective-display (not arg))
804 (set-buffer-modified-p modifiedp))))
805
806 (defvar bibtex-sort-ignore-string-entries nil
807 "*If true, bibtex @STRING entries are ignored when determining ordering
808 of the buffer (e.g. sorting, locating alphabetical position for new entries,
809 etc.)")
810
811 (defun sort-bibtex-entries ()
812 "Sort bibtex entries alphabetically by key.
813 Text before the first bibtex entry, and following the last is not affected.
814 If bibtex-sort-ignore-string-entries is true, @string entries will be ignored.
815
816 Bugs:
817 1. Text between the closing brace ending one bibtex entry, and the @ starting
818 the next, is considered part of the PRECEDING entry. Perhaps it should be
819 part of the following entry."
820 (interactive)
821 (save-restriction
822 (beginning-of-first-bibtex-entry)
823 (narrow-to-region (point)
824 (save-excursion
825 (goto-char (point-max))
826 (beginning-of-bibtex-entry)
827 (end-of-bibtex-entry)
828 (point)))
829 (sort-subr nil ; reversep
830 ;; beginning of record function
831 'forward-line
832 ;; end of record function
833 (function (lambda () (and (re-search-forward "}\\s-*\n[\n \t]*@" nil 'move)
834 (forward-char -2))))
835 ;; start of key function
836 (if bibtex-sort-ignore-string-entries
837 (function (lambda ()
838 (while (and (re-search-forward "^\\s-*\\([@a-zA-Z]*\\)\\s-*{\\s-*")
839 (string-equalp "@string"
840 (buffer-substring (match-beginning 1)
841 (match-end 1)))))
842 nil))
843 (function (lambda () (re-search-forward "{\\s-*") nil)))
844 ;; end of key function
845 (function (lambda () (search-forward ",")))
846 )))
847
848 (defun map-bibtex-entries (fun)
849 "Call FUN for each bibtex entry starting with the current, to the end of the file.
850 FUN is called with one argument, the key of the entry, and with point inside the entry.
851 If bibtex-sort-ignore-string-entries is true, FUN will not be called for @string entries."
852 (beginning-of-bibtex-entry)
853 (while (re-search-forward "^@[^{]*{[ \t]*\\([^, ]*\\)" nil t)
854 (if (and bibtex-sort-ignore-string-entries
855 (string-equalp "@string{"
856 (buffer-substring (match-beginning 0)
857 (match-beginning 1))))
858 nil ; ignore the @string entry.
859 (funcall fun (buffer-substring (match-beginning 1) (match-end 1))))))
860
861 (defun find-bibtex-entry-location (entry-name)
862 "Searches from beginning of current buffer looking for place to put the
863 bibtex entry named ENTRY-NAME. Buffer is assumed to be in sorted order,
864 without duplicates (see \\[sort-bibtex-entries]), if it is not, an error will
865 be signalled."
866 (interactive "sBibtex entry key: ")
867 (let ((previous nil)
868 point)
869 (beginning-of-first-bibtex-entry)
870 (or (catch 'done
871 (map-bibtex-entries (function (lambda (current)
872 (cond
873 ((string-equal entry-name current)
874 (error "Entry duplicates existing!"))
875 ((or (null previous)
876 (string< previous current))
877 (setq previous current
878 point (point))
879 (if (string< entry-name current)
880 (progn
881 (beginning-of-bibtex-entry)
882 ;; Many schemes append strings to
883 ;; existing entries to resolve them,
884 ;; so initial substring matches may
885 ;; indicate a duplicate entry.
886 (let ((idx (string-match (regexp-quote entry-name) current)))
887 (if (and (integerp idx)
888 (zerop idx))
889 (progn
890 (message "Warning: Entry %s may be a duplicate of %s!"
891 entry-name current)
892 (ding t))))
893 (throw 'done t))))
894 ((string-equal previous current)
895 (error "Duplicate here with previous!"))
896 (t (error "Entries out of order here!")))))))
897 (end-of-bibtex-entry))))
898
899 (defun validate-bibtex-buffer ()
900 "Find some typical errors in bibtex files.
901 1. At signs (@) not as first char of a line.
902 2. Double quotes (\") inside strings.
903 3. Closing braces (}) not the last character of a line."
904 (interactive)
905 (let ((point (point)))
906 (while (re-search-forward ".@" nil t)
907 (let* ((foo (parse-partial-sexp (save-excursion (beginning-of-bibtex-entry)
908 (point))
909 (point)))
910 (in-a-string (nth 3 foo)))
911 (if (not in-a-string)
912 (error "At sign (@) out of place!"))))
913 (goto-char point)
914 (while (search-forward "\"" nil t)
915 (or (looking-at "[,}][ \t]*$")
916 (char-equal (preceding-char) ?\")
917 ;; some versions put closing brace on separate line.
918 (looking-at "[ \t]*\n}")
919 (save-excursion
920 (save-restriction
921 (narrow-to-region (point)
922 (progn (beginning-of-line) (point)))
923 (looking-at "^[ \t]*[a-zA-Z]+[ \t]*=[ \t]*\"$")))
924 (error "Quote out of place, or missing \",\" or \"}\"!")))
925 (goto-char point)
926 ;; This is only approximate, should actually search for close braces,
927 ;; then see if they are inside a string, or at the end of a line.
928 ;; This just gets the typical case of whitespace after a closing brace.
929 (while (search-forward "}[ \t]+$" nil t)
930 (error "Brace not last char of line!"))
931 (goto-char point)
932 (message "Bibtex buffer appears o.k.")))
933
934 (defun find-bibtex-duplicates ()
935 "Searches forward in current buffer looking for duplicate bibtex entries.
936 Buffer is assumed to be sorted, see \\[sort-bibtex-entries]"
937 (interactive)
938 (let ((point (point)))
939 ;; errors if things are not right...
940 (find-bibtex-entry-location (make-string 10 255))
941 (goto-char point)
942 (message "No duplicates found!")))
943
944
945 ;;; assoc doesn't ignore case, so we need an assoc that does...
946 (defun assoc-string-equalp (thing alist)
947 (or (assoc thing alist)
948 (while (and alist
949 (not (string-equalp thing (car (car alist)))))
950 (setq alist (cdr alist)))
951 (car alist)))
952
953 (defvar bibtex-maintain-sorted-entries nil
954 "*If true, bibtex-mode will attempt to maintain all bibtex entries in
955 sorted order.
956
957 Note that this is more a property of a file than a personal preference and
958 as such should normally be set via a file local variable entry.")
959
960 (defun bibtex-entry (entry-type &optional required optional)
961 (interactive (let* ((completion-ignore-case t)
962 (e-t (completing-read "Entry Type: " bibtex-entry-field-alist
963 nil t)))
964 (list e-t)))
965 (if (and (null required) (null optional))
966 (let* ((e (assoc-string-equalp entry-type bibtex-entry-field-alist))
967 (r-n-o (elt e 1))
968 (c-ref (elt e 2)))
969 (if (null e)
970 (error "Bibtex entry type %s not defined!"))
971 (if (and bibtex-include-OPTcrossref c-ref)
972 (setq required (elt c-ref 0)
973 optional (elt c-ref 1))
974 (setq required (elt r-n-o 0)
975 optional (elt r-n-o 1)))))
976 (let ((key (if bibtex-maintain-sorted-entries
977 (read-string (format "%s key: " entry-type)))))
978 (if key
979 (find-bibtex-entry-location key))
980 (bibtex-move-outside-of-entry)
981 (insert "@" entry-type "{")
982 (if key
983 (insert key))
984 (save-excursion
985 (mapcar 'bibtex-make-field required)
986 (if bibtex-include-OPTcrossref
987 (bibtex-make-optional-field "crossref"))
988 (if bibtex-include-OPTkey
989 (bibtex-make-optional-field "key"))
990 (mapcar 'bibtex-make-optional-field optional)
991 (mapcar 'bibtex-make-optional-field
992 bibtex-mode-user-optional-fields)
993 (if bibtex-include-OPTannote
994 (bibtex-make-optional-field "annote"))
995 (insert "\n}\n\n"))
996 (if key
997 (bibtex-next-field t))
998 (run-hooks 'bibtex-add-entry-hook)))
999
1000 ;; (defun bibtex-entry (entry-type required optional)
1001 ;; (bibtex-move-outside-of-entry)
1002 ;; (insert (concat "@" entry-type "{,\n\n}\n\n"))
1003 ;; (previous-line 3)
1004 ;; (insert (mapconcat 'bibtex-make-entry required ",\n"))
1005 ;; (if required
1006 ;; (if optional
1007 ;; (insert ",\n")))
1008 ;; (insert (mapconcat 'bibtex-make-OPT-entry optional ",\n"))
1009 ;; (if bibtex-mode-user-optional-fields ;MON...
1010 ;; (progn
1011 ;; (if optional
1012 ;; (insert ",\n"))
1013 ;; (insert (mapconcat 'bibtex-make-OPT-entry
1014 ;; bibtex-mode-user-optional-fields
1015 ;; ",\n")))) ;MON
1016 ;; (up-list -1)
1017 ;; (forward-char 1))
1018
1019
1020 (defun bibtex-make-field (e-t)
1021 (interactive "sBibTeX entry type: ")
1022 (let ((name (if (consp e-t) (car e-t) e-t))
1023 (value (if (consp e-t) (cdr e-t) "")))
1024 (insert ",\n")
1025 (indent-to-column bibtex-name-alignment)
1026 (insert name " = ")
1027 (indent-to-column bibtex-text-alignment)
1028 ;; lucid emacs prin1-to-string breaks the undo chain. When they fix
1029 ;; that, the hack can be removed. [alarson:19930316.0805CST]
1030 ; (insert (prin1-to-string value))
1031 ;; begin hack
1032 (insert (format (if (stringp value) "\"%s\"" "%s")
1033 value))
1034 ;; end hack
1035 nil))
1036
1037 (defun bibtex-make-optional-field (e-t)
1038 (interactive "sOptional BibTeX entry type: ")
1039 (if (consp e-t)
1040 (setq e-t (cons (concat "OPT" (car e-t)) (cdr e-t)))
1041 (setq e-t (concat "OPT" e-t)))
1042 (bibtex-make-field e-t))
1043
1044 ;; What to do about crossref? if present, journal and year are
1045 ;; both optional. Due to this, i move all of them into optional. -- MON
1046
1047 (defun bibtex-Article ()
1048 (interactive)
1049 (bibtex-entry "Article"))
1050
1051 (defun bibtex-Book ()
1052 (interactive)
1053 (bibtex-entry "Book"))
1054
1055 (defun bibtex-Booklet ()
1056 (interactive)
1057 (bibtex-entry "Booklet"))
1058
1059 ;(defun bibtex-DEAthesis ()
1060 ; (interactive)
1061 ; (bibtex-entry "DEAthesis"))
1062
1063 (defun bibtex-InBook ()
1064 (interactive)
1065 (bibtex-entry "InBook"))
1066
1067 (defun bibtex-InCollection ()
1068 (interactive)
1069 (bibtex-entry "InCollection"))
1070
1071 (defun bibtex-InProceedings ()
1072 (interactive)
1073 (bibtex-entry "InProceedings"))
1074
1075 (defun bibtex-Manual ()
1076 (interactive)
1077 (bibtex-entry "Manual"))
1078
1079 (defun bibtex-MastersThesis ()
1080 (interactive)
1081 (bibtex-entry "MastersThesis"))
1082
1083 (defun bibtex-Misc ()
1084 (interactive)
1085 (bibtex-entry "Misc"))
1086
1087 (defun bibtex-PhdThesis ()
1088 (interactive)
1089 (bibtex-entry "PhdThesis"))
1090
1091 (defun bibtex-Proceedings ()
1092 (interactive)
1093 (bibtex-entry "Proceedings"))
1094
1095 (defun bibtex-TechReport ()
1096 (interactive)
1097 (bibtex-entry "TechReport"))
1098
1099 (defun bibtex-Unpublished ()
1100 (interactive)
1101 (bibtex-entry "Unpublished"))
1102
1103 (defun bibtex-string ()
1104 (interactive)
1105 (bibtex-move-outside-of-entry)
1106 (insert "@string{ = \"\"}\n")
1107 (previous-line 1)
1108 (forward-char 8))
1109
1110 (defun bibtex-preamble ()
1111 (interactive)
1112 (bibtex-move-outside-of-entry)
1113 (insert "@Preamble{}\n")
1114 (previous-line 1)
1115 (forward-char 10))
1116
1117 (defun bibtex-next-field (arg)
1118 "Finds end of text of next BibTeX field; with arg, to its beginning"
1119 (interactive "P")
1120 (bibtex-inside-field)
1121 (let ((start (point)))
1122 (condition-case ()
1123 (progn
1124 (bibtex-enclosing-field)
1125 (goto-char (match-end 0))
1126 (forward-char 2))
1127 (error
1128 (goto-char start)
1129 (end-of-line)
1130 (forward-char 1))))
1131 (bibtex-find-text arg))
1132
1133 ;; (defun bibtex-next-field ()
1134 ;; "Finds end of text of next field."
1135 ;; (interactive)
1136 ;; (condition-case ()
1137 ;; (progn
1138 ;; (bibtex-inside-field)
1139 ;; (re-search-forward ",[ \t\n]*" (point-max) 1)
1140 ;; (bibtex-enclosing-field)
1141 ;; (bibtex-inside-field))
1142 ;; (error nil)))
1143
1144 (defun bibtex-find-text (arg)
1145 "Go to end of text of current field; with arg, go to beginning."
1146 (interactive "P")
1147 (bibtex-inside-field)
1148 (bibtex-enclosing-field)
1149 (if arg
1150 (progn
1151 (goto-char (match-beginning bibtex-text-in-field))
1152 (if (looking-at "\"")
1153 (forward-char 1)))
1154 (goto-char (match-end bibtex-text-in-field))
1155 (if (= (preceding-char) ?\")
1156 (forward-char -1))))
1157
1158 ;; (defun bibtex-find-text ()
1159 ;; "Go to end of text of current field."
1160 ;; (interactive)
1161 ;; (condition-case ()
1162 ;; (progn
1163 ;; (bibtex-inside-field)
1164 ;; (bibtex-enclosing-field)
1165 ;; (goto-char (match-end bibtex-text-in-field))
1166 ;; (bibtex-inside-field))
1167 ;; (error nil)))
1168
1169 (defun bibtex-remove-OPT ()
1170 "Removes the 'OPT' starting optional arguments and goes to end of text"
1171 (interactive)
1172 (bibtex-inside-field)
1173 (bibtex-enclosing-field)
1174 (save-excursion
1175 (goto-char (match-beginning bibtex-name-in-field))
1176 (if (looking-at "OPT")
1177 ;; sct@dcs.edinburgh.ac.uk
1178 (progn
1179 (delete-char (length "OPT"))
1180 (search-forward "=")
1181 (delete-horizontal-space)
1182 (indent-to-column bibtex-text-alignment))))
1183 (bibtex-inside-field))
1184
1185 (defun bibtex-inside-field ()
1186 "Try to avoid point being at end of a bibtex field."
1187 (interactive)
1188 (end-of-line)
1189 (skip-chars-backward " \t") ;MON - maybe delete these chars?
1190 (cond ((= (preceding-char) ?,)
1191 (forward-char -2))) ; -1 --> -2 sct@dcs.edinburgh.ac.uk
1192 (cond ((= (preceding-char) ?\")
1193 (forward-char -1)))) ;MON - only go back if quote
1194
1195 (defun bibtex-remove-double-quotes ()
1196 "Removes \"\" around string."
1197 (interactive)
1198 (save-excursion
1199 (bibtex-inside-field)
1200 (bibtex-enclosing-field)
1201 (let ((start (match-beginning bibtex-text-in-field))
1202 (stop (match-end bibtex-text-in-field)))
1203 (goto-char stop)
1204 (forward-char -1)
1205 (if (looking-at "\"")
1206 (delete-char 1))
1207 (goto-char start)
1208 (if (looking-at "\"")
1209 (delete-char 1)))))
1210
1211 (defun bibtex-kill-optional-field ()
1212 "Kill the entire enclosing optional BibTeX field"
1213 (interactive)
1214 (bibtex-inside-field)
1215 (bibtex-enclosing-field)
1216 (goto-char (match-beginning bibtex-name-in-field))
1217 (let ((the-end (match-end 0))
1218 (the-beginning (match-beginning 0)))
1219 (if (looking-at "OPT")
1220 (progn
1221 (goto-char the-end)
1222 (skip-chars-forward " \t\n,")
1223 (kill-region the-beginning the-end))
1224 (error "Mandatory fields can't be killed"))))
1225
1226 (defun bibtex-empty-field ()
1227 "Delete the text part of the current field, replace with empty text"
1228 (interactive)
1229 (bibtex-inside-field)
1230 (bibtex-enclosing-field)
1231 (goto-char (match-beginning bibtex-text-in-field))
1232 (kill-region (point) (match-end bibtex-text-in-field))
1233 (insert "\"\"")
1234 (bibtex-find-text t))
1235
1236
1237 (defun bibtex-pop-previous (arg)
1238 "Replace text of current field with the text of similar field in previous entry.
1239 With arg, go up ARG entries. Repeated, goes up so many times. May be
1240 intermixed with \\[bibtex-pop-next] (bibtex-pop-next)."
1241 (interactive "p")
1242 (bibtex-inside-field)
1243 (save-excursion
1244 ; parse current field
1245 (bibtex-enclosing-field)
1246 (let ((start-old-text (match-beginning bibtex-text-in-field))
1247 (stop-old-text (match-end bibtex-text-in-field))
1248 (start-name (match-beginning bibtex-name-in-field))
1249 (stop-name (match-end bibtex-name-in-field))
1250 (new-text))
1251 (goto-char start-name)
1252 ; construct regexp for previous field with same name as this one
1253 (let ((matching-entry
1254 (bibtex-cfield
1255 (buffer-substring (if (looking-at "OPT")
1256 (+ (point) (length "OPT"))
1257 (point))
1258 stop-name)
1259 bibtex-field-text)))
1260
1261 ; if executed several times in a row, start each search where the
1262 ; last one finished
1263 (cond ((or (eq last-command 'bibtex-pop-previous)
1264 (eq last-command 'bibtex-pop-next))
1265 t
1266 )
1267 (t
1268 (bibtex-enclosing-reference)
1269 (setq bibtex-pop-previous-search-point (match-beginning 0))
1270 (setq bibtex-pop-next-search-point (match-end 0))))
1271 (goto-char bibtex-pop-previous-search-point)
1272
1273 ; Now search for arg'th previous similar field
1274 (cond
1275 ((re-search-backward matching-entry (point-min) t arg)
1276 (setq new-text
1277 (buffer-substring (match-beginning bibtex-text-in-cfield)
1278 (match-end bibtex-text-in-cfield)))
1279 ; Found a matching field. Remember boundaries.
1280 (setq bibtex-pop-next-search-point (match-end 0))
1281 (setq bibtex-pop-previous-search-point (match-beginning 0))
1282 (bibtex-flash-head)
1283 ; Go back to where we started, delete old text, and pop new.
1284 (goto-char stop-old-text)
1285 (delete-region start-old-text stop-old-text)
1286 (insert new-text))
1287 (t ; search failed
1288 (error "No previous matching BibTeX field."))))))
1289 (setq this-command 'bibtex-pop-previous))
1290
1291 (defun bibtex-pop-next (arg)
1292 "Replace text of current field with the text of similar field in next entry.
1293 With arg, go up ARG entries. Repeated, goes up so many times. May be
1294 intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)."
1295 (interactive "p")
1296 (bibtex-inside-field)
1297 (save-excursion
1298 ; parse current field
1299 (bibtex-enclosing-field)
1300 (let ((start-old-text (match-beginning bibtex-text-in-field))
1301 (stop-old-text (match-end bibtex-text-in-field))
1302 (start-name (match-beginning bibtex-name-in-field))
1303 (stop-name (match-end bibtex-name-in-field))
1304 (new-text))
1305 (goto-char start-name)
1306 ; construct regexp for next field with same name as this one,
1307 ; ignoring possible OPT's
1308 (let ((matching-entry
1309 (bibtex-cfield
1310 (buffer-substring (if (looking-at "OPT")
1311 (+ (point) (length "OPT"))
1312 (point))
1313 stop-name)
1314 bibtex-field-text)))
1315
1316 ; if executed several times in a row, start each search where the
1317 ; last one finished
1318 (cond ((or (eq last-command 'bibtex-pop-next)
1319 (eq last-command 'bibtex-pop-previous))
1320 t
1321 )
1322 (t
1323 (bibtex-enclosing-reference)
1324 (setq bibtex-pop-previous-search-point (match-beginning 0))
1325 (setq bibtex-pop-next-search-point (match-end 0))))
1326 (goto-char bibtex-pop-next-search-point)
1327
1328 ; Now search for arg'th next similar field
1329 (cond
1330 ((re-search-forward matching-entry (point-max) t arg)
1331 (setq new-text
1332 (buffer-substring (match-beginning bibtex-text-in-cfield)
1333 (match-end bibtex-text-in-cfield)))
1334 ; Found a matching field. Remember boundaries.
1335 (setq bibtex-pop-next-search-point (match-end 0))
1336 (setq bibtex-pop-previous-search-point (match-beginning 0))
1337 (bibtex-flash-head)
1338 ; Go back to where we started, delete old text, and pop new.
1339 (goto-char stop-old-text)
1340 (delete-region start-old-text stop-old-text)
1341 (insert new-text))
1342 (t ; search failed
1343 (error "No next matching BibTeX field."))))))
1344 (setq this-command 'bibtex-pop-next))
1345
1346 (defun bibtex-flash-head ()
1347 "Flash at BibTeX reference head before point, if exists. (Moves point)."
1348 (let ((flash))
1349 (cond ((re-search-backward bibtex-reference-head (point-min) t)
1350 (goto-char (match-beginning bibtex-type-in-head))
1351 (setq flash (match-end bibtex-key-in-reference)))
1352 (t
1353 (end-of-line)
1354 (skip-chars-backward " \t")
1355 (setq flash (point))
1356 (beginning-of-line)
1357 (skip-chars-forward " \t")))
1358 (if (pos-visible-in-window-p (point))
1359 (sit-for 1)
1360 (message "From: %s"
1361 (buffer-substring (point) flash)))))
1362
1363
1364
1365 (defun bibtex-enclosing-field ()
1366 "Search for BibTeX field enclosing point.
1367 Point moves to end of field; also, use match-beginning and match-end
1368 to parse the field."
1369 ;; sct@dcs.edinburgh.ac.uk
1370 (let ((old-point (point)))
1371 (condition-case errname
1372 (bibtex-enclosing-regexp bibtex-field)
1373 (search-failed
1374 (goto-char old-point)
1375 (error "Can't find enclosing BibTeX field.")))))
1376
1377 (defun bibtex-enclosing-reference ()
1378 "Search for BibTeX reference enclosing point.
1379 Point moves to end of reference; also, use match-beginning and match-end
1380 to parse the reference."
1381 ;; sct@dcs.edinburgh.ac.uk
1382 (let ((old-point (point)))
1383 (condition-case errname
1384 (bibtex-enclosing-regexp bibtex-reference)
1385 (search-failed
1386 (goto-char old-point)
1387 (error "Can't find enclosing BibTeX reference.")))))
1388
1389 (defun bibtex-enclosing-regexp (regexp)
1390 "Search for REGEXP enclosing point.
1391 Point moves to end of REGEXP. See also match-beginning and match-end.
1392 If an enclosing REGEXP is not found, signals search-failed; point is left in
1393 an undefined location.
1394
1395 [Doesn't something like this exist already?]"
1396
1397 (interactive "sRegexp: ")
1398 ; compute reasonable limits for the loop
1399 (let* ((initial (point))
1400 (right (if (re-search-forward regexp (point-max) t)
1401 (match-end 0)
1402 (point-max)))
1403 (left
1404 (progn
1405 (goto-char initial)
1406 (if (re-search-backward regexp (point-min) t)
1407 (match-beginning 0)
1408 (point-min)))))
1409 ; within the prescribed limits, loop until a match is found
1410 (goto-char left)
1411 (re-search-forward regexp right nil 1)
1412 (if (> (match-beginning 0) initial)
1413 (signal 'search-failed (list regexp)))
1414 (while (<= (match-end 0) initial)
1415 (re-search-forward regexp right nil 1)
1416 (if (> (match-beginning 0) initial)
1417 (signal 'search-failed (list regexp))))
1418 ))
1419
1420 (defun bibtex-clean-entry ()
1421 "For all optional fields of current BibTeX entry: if empty, kill the whole field; otherwise, remove the \"OPT\" string in the name; if text numerical, remove double-quotes. For all mandatory fields: if empty, signal error."
1422 (interactive)
1423 (beginning-of-bibtex-entry)
1424 (let ((start (point)))
1425 (save-restriction
1426 (narrow-to-region start (save-excursion (end-of-bibtex-entry) (point)))
1427 (while (re-search-forward bibtex-field (point-max) t 1)
1428 (let ((begin-field (match-beginning 0))
1429 (end-field (match-end 0))
1430 (begin-name (match-beginning bibtex-name-in-field))
1431 (end-name (match-end bibtex-name-in-field))
1432 (begin-text (match-beginning bibtex-text-in-field))
1433 (end-text (match-end bibtex-text-in-field))
1434 )
1435 (goto-char begin-name)
1436 (cond ((and
1437 (looking-at "OPT")
1438 bibtex-clean-entry-zap-empty-opts)
1439 (goto-char begin-text)
1440 (if (looking-at "\"\"") ; empty: delete whole field
1441 (delete-region begin-field end-field)
1442 ; otherwise: not empty, delete "OPT"
1443 (goto-char begin-name)
1444 (delete-char (length "OPT"))
1445 (progn
1446 ;; fixup alignment. [alarson:19920309.2047CST]
1447 (search-forward "=")
1448 (delete-horizontal-space)
1449 (indent-to-column bibtex-text-alignment))
1450 (goto-char begin-field) ; and loop to go through next test
1451 ))
1452 (t
1453 (goto-char begin-text)
1454 (cond ((looking-at "\"[0-9]+\"") ; if numerical,
1455 (goto-char end-text)
1456 (delete-char -1) ; delete enclosing double-quotes
1457 (goto-char begin-text)
1458 (delete-char 1)
1459 (goto-char end-field) ; go to end for next search
1460 (forward-char -2) ; to compensate for the 2 quotes deleted
1461 )
1462 ((looking-at "\"\"") ; if empty quotes, complain
1463 (forward-char 1)
1464 (if (not (or (equal (buffer-substring
1465 begin-name
1466 (+ begin-name 3))
1467 "OPT")
1468 (equal (buffer-substring
1469 begin-name
1470 (+ begin-name 3))
1471 "opt")))
1472 (error "Mandatory field ``%s'' is empty"
1473 (buffer-substring begin-name end-name))))
1474 (t
1475 (goto-char end-field))))))))
1476 (goto-char start)
1477 (end-of-bibtex-entry)
1478 ;; sct@dcs.edinburgh.ac.uk
1479 (save-excursion
1480 (previous-line 1)
1481 (end-of-line)
1482 (if (eq (preceding-char) ?,)
1483 (backward-delete-char 1)))
1484 (skip-whitespace-and-comments)))
1485
1486
1487 ;;; Menus for bibtex mode
1488
1489 (defconst bibtex-menu
1490 '("BibTeX Commands"
1491 "Entry Types"
1492 "---"
1493 ["Article in Conference Proceedings" bibtex-InProceedings t]
1494 ["Article in Journal" bibtex-Article t]
1495 ["Book" bibtex-Book t]
1496 ["Booklet" bibtex-Booklet t]
1497 ["Conference" bibtex-InProceedings t]
1498 ["Master's Thesis" bibtex-MastersThesis t]
1499 ["DEA Thesis" bibtex-DEAthesis t]
1500 ["Phd. Thesis" bibtex-PhdThesis t]
1501 ["Technical Report" bibtex-TechReport t]
1502 ["Technical Manual" bibtex-Manual t]
1503 ["Conference Proceedings" bibtex-Proceedings t]
1504 ["A Chapter in a Book" bibtex-InBook t]
1505 ["An Article in a Collection" bibtex-InCollection t]
1506 ["Miscellaneous" bibtex-Misc t]
1507 ["Unpublished" bibtex-Unpublished t]
1508 ["String" bibtex-string t]
1509 ["Preamble" bibtex-preamble t]
1510 "---"
1511 "Bibtex Edit"
1512 "---"
1513 ["Next Field" bibtex-next-field t]
1514 ["To End of Field" bibtex-find-text t]
1515 ["Snatch From Similar Preceding Field" bibtex-pop-previous t]
1516 ["Snatch From Similar Following Field" bibtex-pop-next t]
1517 ["Remove OPT" bibtex-remove-OPT t]
1518 ["Remove Quotes" bibtex-remove-double-quotes t]
1519 ["Clean Up Entry" bibtex-clean-entry t]
1520 ["Find Duplicates" find-bibtex-duplicates t]
1521 ["Sort Entries" sort-bibtex-entries t]
1522 ["Validate Entries" validate-bibtex-buffer t]
1523 ))
1524
1525 (defun bibtex-menu ()
1526 (interactive)
1527 (let ((popup-menu-titles nil))
1528 (popup-menu bibtex-menu)))
1529
1530 ;;; bibtex.el ends here