(sgml-fill-nobreak): New fun.
[bpt/emacs.git] / lisp / textmodes / bibtex.el
CommitLineData
c0274f38
ER
1;;; bibtex.el --- BibTeX mode for GNU Emacs
2
a9d77f1f 3;; Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004
8bf38a9b 4;; Free Software Foundation, Inc.
9750e079 5
31bc4210 6;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
7fbf4804
SM
7;; Bengt Martensson <bengt@mathematik.uni-Bremen.de>
8;; Mark Shapiro <shapiro@corto.inria.fr>
9;; Mike Newton <newton@gumby.cs.caltech.edu>
10;; Aaron Larson <alarson@src.honeywell.com>
11;; Dirk Herrmann <D.Herrmann@tu-bs.de>
e04464bb 12;; Maintainer: Roland Winkler <roland.winkler@physik.uni-erlangen.de>
cb4ad359 13;; Keywords: BibTeX, LaTeX, TeX
f961a17c 14
745bc783
JB
15;; This file is part of GNU Emacs.
16
17;; GNU Emacs is free software; you can redistribute it and/or modify
18;; it under the terms of the GNU General Public License as published by
a1ddedc6 19;; the Free Software Foundation; either version 2, or (at your option)
745bc783
JB
20;; any later version.
21
22;; GNU Emacs is distributed in the hope that it will be useful,
23;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25;; GNU General Public License for more details.
26
27;; You should have received a copy of the GNU General Public License
b578f267
EN
28;; along with GNU Emacs; see the file COPYING. If not, write to the
29;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30;; Boston, MA 02111-1307, USA.
745bc783 31
5c69dbfc 32;;; Commentary:
b578f267 33
cb4ad359 34;; Major mode for editing and validating BibTeX files.
e5167999 35
5c69dbfc 36;; Usage:
02c8032e
SM
37;; See documentation for function bibtex-mode or type "\M-x describe-mode"
38;; when you are in BibTeX mode.
e5167999 39
5c69dbfc
RS
40;; Todo:
41;; Distribute texinfo file.
9ae11a89 42
5c69dbfc 43;;; Code:
b578f267 44
e0dc0c55
SM
45(require 'button)
46
28f2ee66 47\f
5c69dbfc 48;; User Options:
e5167999 49
f754fb7b 50(defgroup bibtex nil
7fbf4804 51 "BibTeX mode"
f754fb7b
RS
52 :group 'tex
53 :prefix "bibtex-")
54
55(defgroup bibtex-autokey nil
7fbf4804 56 "Generate automatically a key from the author/editor and the title field"
f754fb7b 57 :group 'bibtex
ab2d0cdb 58 :prefix "bibtex-autokey-")
f754fb7b
RS
59
60(defcustom bibtex-mode-hook nil
61 "List of functions to call on entry to BibTeX mode."
62 :group 'bibtex
ab2d0cdb 63 :type 'hook)
f754fb7b
RS
64
65(defcustom bibtex-field-delimiters 'braces
02c8032e 66 "Type of field delimiters. Allowed values are `braces' or `double-quotes'."
f754fb7b
RS
67 :group 'bibtex
68 :type '(choice (const braces)
7fbf4804 69 (const double-quotes)))
50e4b39e 70
f754fb7b 71(defcustom bibtex-entry-delimiters 'braces
02c8032e 72 "Type of entry delimiters. Allowed values are `braces' or `parentheses'."
f754fb7b
RS
73 :group 'bibtex
74 :type '(choice (const braces)
7fbf4804 75 (const parentheses)))
cb4ad359 76
f754fb7b 77(defcustom bibtex-include-OPTcrossref '("InProceedings" "InCollection")
02c8032e 78 "List of BibTeX entries that get an OPTcrossref field."
f754fb7b
RS
79 :group 'bibtex
80 :type '(repeat string))
e5167999 81
f754fb7b 82(defcustom bibtex-include-OPTkey t
d10e87a2
SM
83 "If non-nil, all newly created entries get an OPTkey field.
84If this is a string, use it as the initial field text.
85If this is a function, call it to generate the initial field text."
f754fb7b
RS
86 :group 'bibtex
87 :type '(choice (const :tag "None" nil)
7fbf4804
SM
88 (string :tag "Initial text")
89 (function :tag "Initialize Function" :value fun)
90 (other :tag "Default" t)))
f754fb7b
RS
91
92(defcustom bibtex-user-optional-fields
50e4b39e 93 '(("annote" "Personal annotation (ignored)"))
02c8032e 94 "List of optional fields the user wants to have always present.
50e4b39e 95Entries should be of the same form as the OPTIONAL and
02c8032e 96CROSSREF-OPTIONAL lists in `bibtex-entry-field-alist' (which see)."
f754fb7b 97 :group 'bibtex
7fbf4804
SM
98 :type '(repeat (group (string :tag "Field")
99 (string :tag "Comment")
100 (option (group :inline t
101 :extra-offset -4
102 (choice :tag "Init" :value ""
103 string
104 function))))))
105
106(defcustom bibtex-entry-format
107 '(opts-or-alts required-fields numerical-fields)
02c8032e 108 "Type of formatting performed by `bibtex-clean-entry'.
f0cb6034 109It may be t, nil, or a list of symbols out of the following:
d0388eac
RS
110opts-or-alts Delete empty optional and alternative fields and
111 remove OPT and ALT prefixes from used fields.
7fbf4804 112required-fields Signal an error if a required field is missing.
d0388eac
RS
113numerical-fields Delete delimiters around numeral fields.
114page-dashes Change double dashes in page field to single dash
115 (for scribe compatibility).
d10e87a2
SM
116inherit-booktitle If entry contains a crossref field and the booktitle
117 field is empty, set the booktitle field to the content
118 of the title field of the crossreferenced entry.
d0388eac 119realign Realign entries, so that field texts and perhaps equal
50e4b39e 120 signs (depending on the value of
f0cb6034 121 `bibtex-align-at-equal-sign') begin in the same column.
d0388eac
RS
122last-comma Add or delete comma on end of last field in entry,
123 according to value of `bibtex-comma-after-last-field'.
124delimiters Change delimiters according to variables
125 `bibtex-field-delimiters' and `bibtex-entry-delimiters'.
126unify-case Change case of entry and field names.
127
128The value t means do all of the above formatting actions.
129The value nil means do no formatting at all."
f754fb7b
RS
130 :group 'bibtex
131 :type '(choice (const :tag "None" nil)
7fbf4804
SM
132 (const :tag "All" t)
133 (set :menu-tag "Some"
134 (const opts-or-alts)
135 (const required-fields)
136 (const numerical-fields)
137 (const page-dashes)
138 (const inherit-booktitle)
139 (const realign)
140 (const last-comma)
141 (const delimiters)
142 (const unify-case))))
50e4b39e 143
f754fb7b 144(defcustom bibtex-clean-entry-hook nil
02c8032e 145 "List of functions to call when entry has been cleaned.
d0388eac 146Functions are called with point inside the cleaned entry, and the buffer
f754fb7b
RS
147narrowed to just the entry."
148 :group 'bibtex
ab2d0cdb 149 :type 'hook)
cb4ad359 150
f754fb7b 151(defcustom bibtex-maintain-sorted-entries nil
d10e87a2 152 "If non-nil, BibTeX mode maintains all entries in sorted order.
d715b065 153Allowed non-nil values are:
7fbf4804
SM
154plain All entries are sorted alphabetically.
155crossref All entries are sorted alphabetically unless an entry has a
a9d77f1f 156 crossref field. These crossrefed entries are placed in
7fbf4804
SM
157 alphabetical order immediately preceding the main entry.
158entry-class The entries are divided into classes according to their
a9d77f1f 159 entry name, see `bibtex-sort-entry-class'. Within each class
7fbf4804
SM
160 the entries are sorted alphabetically.
161See also `bibtex-sort-ignore-string-entries'."
162 :group 'bibtex
163 :type '(choice (const nil)
164 (const plain)
165 (const crossref)
166 (const entry-class)))
167
02c8032e 168(defcustom bibtex-sort-entry-class
7fbf4804 169 '(("String")
d715b065
KG
170 (catch-all)
171 ("Book" "Proceedings"))
d10e87a2 172 "List of classes of BibTeX entry names, used for sorting entries.
d715b065 173If value of `bibtex-maintain-sorted-entries' is `entry-class'
a9d77f1f
SM
174entries are ordered according to the classes they belong to. Each
175class contains a list of entry names. An entry `catch-all' applies
02c8032e
SM
176to all entries not explicitely mentioned."
177 :group 'BibTeX
178 :type '(repeat (choice :tag "Class"
179 (const :tag "catch-all" (catch-all))
180 (repeat :tag "Entry name" string))))
7fbf4804 181
d715b065 182(defcustom bibtex-sort-ignore-string-entries t
d10e87a2 183 "If non-nil, BibTeX @String entries are not sort-significant.
7fbf4804
SM
184That means they are ignored when determining ordering of the buffer
185\(e.g., sorting, locating alphabetical position for new entries, etc.)."
f754fb7b
RS
186 :group 'bibtex
187 :type 'boolean)
9ae11a89 188
f754fb7b 189(defcustom bibtex-field-kill-ring-max 20
d10e87a2 190 "Max length of `bibtex-field-kill-ring' before discarding oldest elements."
f754fb7b
RS
191 :group 'bibtex
192 :type 'integer)
50e4b39e 193
d715b065 194(defcustom bibtex-entry-kill-ring-max 20
d10e87a2 195 "Max length of `bibtex-entry-kill-ring' before discarding oldest elements."
d715b065
KG
196 :group 'bibtex
197 :type 'integer)
198
f754fb7b 199(defcustom bibtex-parse-keys-timeout 60
d10e87a2 200 "Time interval in seconds for parsing BibTeX buffers during idle time.
02c8032e 201Parsing initializes `bibtex-reference-keys' and `bibtex-strings'."
f754fb7b
RS
202 :group 'bibtex
203 :type 'integer)
af6fb89d 204
d715b065 205(defcustom bibtex-parse-keys-fast t
d10e87a2 206 "If non-nil, use fast but simplified algorithm for parsing BibTeX keys.
d715b065
KG
207If parsing fails, try to set this variable to nil."
208 :group 'bibtex
209 :type 'boolean)
210
cb4ad359 211(defvar bibtex-entry-field-alist
02c8032e 212 '(("Article"
7fbf4804 213 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
214 ("title" "Title of the article (BibTeX converts it to lowercase)")
215 ("journal" "Name of the journal (use string, remove braces)")
216 ("year" "Year of publication"))
217 (("volume" "Volume of the journal")
218 ("number" "Number of the journal (only allowed if entry contains volume)")
219 ("pages" "Pages in the journal")
220 ("month" "Month of the publication as a string (remove braces)")
221 ("note" "Remarks to be put at the end of the \\bibitem")))
222 ((("author" "Author1 [and Author2 ...] [and others]")
223 ("title" "Title of the article (BibTeX converts it to lowercase)"))
224 (("pages" "Pages in the journal")
225 ("journal" "Name of the journal (use string, remove braces)")
226 ("year" "Year of publication")
227 ("volume" "Volume of the journal")
228 ("number" "Number of the journal")
229 ("month" "Month of the publication as a string (remove braces)")
230 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804 231 ("Book"
02c8032e
SM
232 ((("author" "Author1 [and Author2 ...] [and others]" nil t)
233 ("editor" "Editor1 [and Editor2 ...] [and others]" nil t)
d715b065
KG
234 ("title" "Title of the book")
235 ("publisher" "Publishing company")
236 ("year" "Year of publication"))
237 (("volume" "Volume of the book in the series")
238 ("number" "Number of the book in a small series (overwritten by volume)")
239 ("series" "Series in which the book appeared")
240 ("address" "Address of the publisher")
241 ("edition" "Edition of the book as a capitalized English word")
242 ("month" "Month of the publication as a string (remove braces)")
243 ("note" "Remarks to be put at the end of the \\bibitem")))
02c8032e
SM
244 ((("author" "Author1 [and Author2 ...] [and others]" nil t)
245 ("editor" "Editor1 [and Editor2 ...] [and others]" nil t)
d715b065
KG
246 ("title" "Title of the book"))
247 (("publisher" "Publishing company")
248 ("year" "Year of publication")
249 ("volume" "Volume of the book in the series")
250 ("number" "Number of the book in a small series (overwritten by volume)")
251 ("series" "Series in which the book appeared")
252 ("address" "Address of the publisher")
253 ("edition" "Edition of the book as a capitalized English word")
254 ("month" "Month of the publication as a string (remove braces)")
255 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
256 ("Booklet"
257 ((("title" "Title of the booklet (BibTeX converts it to lowercase)"))
d715b065
KG
258 (("author" "Author1 [and Author2 ...] [and others]")
259 ("howpublished" "The way in which the booklet was published")
260 ("address" "Address of the publisher")
261 ("month" "Month of the publication as a string (remove braces)")
262 ("year" "Year of publication")
263 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804 264 ("InBook"
02c8032e
SM
265 ((("author" "Author1 [and Author2 ...] [and others]" nil t)
266 ("editor" "Editor1 [and Editor2 ...] [and others]" nil t)
d715b065
KG
267 ("title" "Title of the book")
268 ("chapter" "Chapter in the book")
269 ("publisher" "Publishing company")
270 ("year" "Year of publication"))
271 (("volume" "Volume of the book in the series")
272 ("number" "Number of the book in a small series (overwritten by volume)")
273 ("series" "Series in which the book appeared")
274 ("type" "Word to use instead of \"chapter\"")
275 ("address" "Address of the publisher")
276 ("edition" "Edition of the book as a capitalized English word")
277 ("month" "Month of the publication as a string (remove braces)")
278 ("pages" "Pages in the book")
279 ("note" "Remarks to be put at the end of the \\bibitem")))
02c8032e
SM
280 ((("author" "Author1 [and Author2 ...] [and others]" nil t)
281 ("editor" "Editor1 [and Editor2 ...] [and others]" nil t)
d715b065
KG
282 ("title" "Title of the book")
283 ("chapter" "Chapter in the book"))
284 (("pages" "Pages in the book")
285 ("publisher" "Publishing company")
286 ("year" "Year of publication")
287 ("volume" "Volume of the book in the series")
288 ("number" "Number of the book in a small series (overwritten by volume)")
289 ("series" "Series in which the book appeared")
290 ("type" "Word to use instead of \"chapter\"")
291 ("address" "Address of the publisher")
292 ("edition" "Edition of the book as a capitalized English word")
293 ("month" "Month of the publication as a string (remove braces)")
294 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
295 ("InCollection"
296 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
297 ("title" "Title of the article in book (BibTeX converts it to lowercase)")
298 ("booktitle" "Name of the book")
299 ("publisher" "Publishing company")
300 ("year" "Year of publication"))
301 (("editor" "Editor1 [and Editor2 ...] [and others]")
302 ("volume" "Volume of the book in the series")
303 ("number" "Number of the book in a small series (overwritten by volume)")
304 ("series" "Series in which the book appeared")
305 ("type" "Word to use instead of \"chapter\"")
306 ("chapter" "Chapter in the book")
307 ("pages" "Pages in the book")
308 ("address" "Address of the publisher")
309 ("edition" "Edition of the book as a capitalized English word")
310 ("month" "Month of the publication as a string (remove braces)")
311 ("note" "Remarks to be put at the end of the \\bibitem")))
312 ((("author" "Author1 [and Author2 ...] [and others]")
313 ("title" "Title of the article in book (BibTeX converts it to lowercase)")
314 ("booktitle" "Name of the book"))
315 (("pages" "Pages in the book")
316 ("publisher" "Publishing company")
317 ("year" "Year of publication")
318 ("editor" "Editor1 [and Editor2 ...] [and others]")
319 ("volume" "Volume of the book in the series")
320 ("number" "Number of the book in a small series (overwritten by volume)")
321 ("series" "Series in which the book appeared")
322 ("type" "Word to use instead of \"chapter\"")
323 ("chapter" "Chapter in the book")
324 ("address" "Address of the publisher")
325 ("edition" "Edition of the book as a capitalized English word")
326 ("month" "Month of the publication as a string (remove braces)")
327 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
328 ("InProceedings"
329 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
330 ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")
331 ("booktitle" "Name of the conference proceedings")
332 ("year" "Year of publication"))
333 (("editor" "Editor1 [and Editor2 ...] [and others]")
334 ("volume" "Volume of the conference proceedings in the series")
335 ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
336 ("series" "Series in which the conference proceedings appeared")
337 ("pages" "Pages in the conference proceedings")
338 ("address" "Location of the Proceedings")
339 ("month" "Month of the publication as a string (remove braces)")
340 ("organization" "Sponsoring organization of the conference")
341 ("publisher" "Publishing company, its location")
342 ("note" "Remarks to be put at the end of the \\bibitem")))
343 ((("author" "Author1 [and Author2 ...] [and others]")
344 ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)"))
345 (("booktitle" "Name of the conference proceedings")
346 ("pages" "Pages in the conference proceedings")
347 ("year" "Year of publication")
348 ("editor" "Editor1 [and Editor2 ...] [and others]")
349 ("volume" "Volume of the conference proceedings in the series")
350 ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
351 ("series" "Series in which the conference proceedings appeared")
352 ("address" "Location of the Proceedings")
353 ("month" "Month of the publication as a string (remove braces)")
354 ("organization" "Sponsoring organization of the conference")
355 ("publisher" "Publishing company, its location")
356 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
357 ("Manual"
358 ((("title" "Title of the manual"))
d715b065
KG
359 (("author" "Author1 [and Author2 ...] [and others]")
360 ("organization" "Publishing organization of the manual")
361 ("address" "Address of the organization")
362 ("edition" "Edition of the manual as a capitalized English word")
363 ("month" "Month of the publication as a string (remove braces)")
364 ("year" "Year of publication")
365 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
366 ("MastersThesis"
367 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
368 ("title" "Title of the master\'s thesis (BibTeX converts it to lowercase)")
369 ("school" "School where the master\'s thesis was written")
370 ("year" "Year of publication"))
371 (("type" "Type of the master\'s thesis (if other than \"Master\'s thesis\")")
372 ("address" "Address of the school (if not part of field \"school\") or country")
373 ("month" "Month of the publication as a string (remove braces)")
374 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
375 ("Misc"
376 (()
d715b065
KG
377 (("author" "Author1 [and Author2 ...] [and others]")
378 ("title" "Title of the work (BibTeX converts it to lowercase)")
379 ("howpublished" "The way in which the work was published")
380 ("month" "Month of the publication as a string (remove braces)")
381 ("year" "Year of publication")
382 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
383 ("PhdThesis"
384 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
385 ("title" "Title of the PhD. thesis")
386 ("school" "School where the PhD. thesis was written")
387 ("year" "Year of publication"))
388 (("type" "Type of the PhD. thesis")
389 ("address" "Address of the school (if not part of field \"school\") or country")
390 ("month" "Month of the publication as a string (remove braces)")
391 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
392 ("Proceedings"
393 ((("title" "Title of the conference proceedings")
d715b065
KG
394 ("year" "Year of publication"))
395 (("booktitle" "Title of the proceedings for cross references")
396 ("editor" "Editor1 [and Editor2 ...] [and others]")
397 ("volume" "Volume of the conference proceedings in the series")
398 ("number" "Number of the conference proceedings in a small series (overwritten by volume)")
399 ("series" "Series in which the conference proceedings appeared")
400 ("address" "Location of the Proceedings")
401 ("month" "Month of the publication as a string (remove braces)")
402 ("organization" "Sponsoring organization of the conference")
403 ("publisher" "Publishing company, its location")
404 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
405 ("TechReport"
406 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
407 ("title" "Title of the technical report (BibTeX converts it to lowercase)")
408 ("institution" "Sponsoring institution of the report")
409 ("year" "Year of publication"))
410 (("type" "Type of the report (if other than \"technical report\")")
411 ("number" "Number of the technical report")
412 ("address" "Address of the institution (if not part of field \"institution\") or country")
413 ("month" "Month of the publication as a string (remove braces)")
414 ("note" "Remarks to be put at the end of the \\bibitem"))))
7fbf4804
SM
415 ("Unpublished"
416 ((("author" "Author1 [and Author2 ...] [and others]")
d715b065
KG
417 ("title" "Title of the unpublished work (BibTeX converts it to lowercase)")
418 ("note" "Remarks to be put at the end of the \\bibitem"))
419 (("month" "Month of the publication as a string (remove braces)")
02c8032e
SM
420 ("year" "Year of publication")))))
421
422 "List of BibTeX entry types and their associated fields.
423List elements are triples
424\(ENTRY-NAME (REQUIRED OPTIONAL) (CROSSREF-REQUIRED CROSSREF-OPTIONAL)).
425ENTRY-NAME is the name of a BibTeX entry. The remaining pairs contain
426the required and optional fields of the BibTeX entry.
427The second pair is used if a crossref field is present
428and the first pair is used if a crossref field is absent.
429If the second pair is nil, the first pair is always used.
f0cb6034 430REQUIRED, OPTIONAL, CROSSREF-REQUIRED and CROSSREF-OPTIONAL are lists.
50e4b39e 431Each element of these lists is a list of the form
73cc75b5 432\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG).
50e4b39e 433COMMENT-STRING, INIT, and ALTERNATIVE-FLAG are optional.
02c8032e
SM
434FIELD-NAME is the name of the field, COMMENT-STRING is the comment that
435appears in the echo area, INIT is either the initial content of the
50e4b39e
RS
436field or a function, which is called to determine the initial content
437of the field, and ALTERNATIVE-FLAG (either nil or t) marks if the
d0388eac 438field is an alternative. ALTERNATIVE-FLAG may be t only in the
50e4b39e
RS
439REQUIRED or CROSSREF-REQUIRED lists.")
440
02c8032e
SM
441(defcustom bibtex-comment-start "@Comment"
442 "String starting a BibTeX comment."
443 :group 'bibtex
444 :type 'string)
ab2d0cdb 445
f754fb7b 446(defcustom bibtex-add-entry-hook nil
02c8032e 447 "List of functions to call when BibTeX entry has been inserted."
f754fb7b 448 :group 'bibtex
ab2d0cdb 449 :type 'hook)
50e4b39e 450
f754fb7b 451(defcustom bibtex-predefined-month-strings
7fbf4804
SM
452 '(("jan" . "January")
453 ("feb" . "February")
454 ("mar" . "March")
455 ("apr" . "April")
456 ("may" . "May")
457 ("jun" . "June")
458 ("jul" . "July")
459 ("aug" . "August")
460 ("sep" . "September")
461 ("oct" . "October")
462 ("nov" . "November")
463 ("dec" . "December"))
464 "Alist of month string definitions used in the BibTeX style files.
d715b065 465Each element is a pair of strings (ABBREVIATION . EXPANSION)."
f754fb7b 466 :group 'bibtex
7fbf4804
SM
467 :type '(repeat (cons (string :tag "Month abbreviation")
468 (string :tag "Month expansion"))))
50e4b39e 469
f754fb7b 470(defcustom bibtex-predefined-strings
50e4b39e
RS
471 (append
472 bibtex-predefined-month-strings
7fbf4804
SM
473 '(("acmcs" . "ACM Computing Surveys")
474 ("acta" . "Acta Informatica")
475 ("cacm" . "Communications of the ACM")
476 ("ibmjrd" . "IBM Journal of Research and Development")
477 ("ibmsj" . "IBM Systems Journal")
478 ("ieeese" . "IEEE Transactions on Software Engineering")
479 ("ieeetc" . "IEEE Transactions on Computers")
480 ("ieeetcad" . "IEEE Transactions on Computer-Aided Design of Integrated Circuits")
481 ("ipl" . "Information Processing Letters")
482 ("jacm" . "Journal of the ACM")
483 ("jcss" . "Journal of Computer and System Sciences")
484 ("scp" . "Science of Computer Programming")
485 ("sicomp" . "SIAM Journal on Computing")
486 ("tcs" . "Theoretical Computer Science")
487 ("tocs" . "ACM Transactions on Computer Systems")
488 ("tods" . "ACM Transactions on Database Systems")
489 ("tog" . "ACM Transactions on Graphics")
490 ("toms" . "ACM Transactions on Mathematical Software")
491 ("toois" . "ACM Transactions on Office Information Systems")
492 ("toplas" . "ACM Transactions on Programming Languages and Systems")))
493 "Alist of string definitions used in the BibTeX style files.
d715b065 494Each element is a pair of strings (ABBREVIATION . EXPANSION)."
f754fb7b 495 :group 'bibtex
7fbf4804
SM
496 :type '(repeat (cons (string :tag "String")
497 (string :tag "String expansion"))))
cb4ad359 498
f754fb7b 499(defcustom bibtex-string-files nil
d10e87a2 500 "List of BibTeX files containing string definitions.
02c8032e
SM
501List elements can be absolute file names or file names relative
502to the directories specified in `bibtex-string-file-path'."
f754fb7b
RS
503 :group 'bibtex
504 :type '(repeat file))
50e4b39e
RS
505
506(defvar bibtex-string-file-path (getenv "BIBINPUTS")
28f2ee66 507 "*Colon separated list of paths to search for `bibtex-string-files'.")
cb4ad359 508
e0dc0c55 509(defcustom bibtex-files nil
02c8032e 510 "List of BibTeX files that are searched for entry keys.
e0dc0c55
SM
511List elements can be absolute file names or file names relative to the
512directories specified in `bibtex-file-path'. If an element is a directory,
513check all BibTeX files in this directory. If an element is the symbol
514`bibtex-file-path', check all BibTeX files in `bibtex-file-path'."
515 :group 'bibtex
516 :type '(repeat file))
517
518(defvar bibtex-file-path (getenv "BIBINPUTS")
519 "*Colon separated list of paths to search for `bibtex-files'.")
520
f754fb7b 521(defcustom bibtex-help-message t
d10e87a2 522 "If non-nil print help messages in the echo area on entering a new field."
f754fb7b
RS
523 :group 'bibtex
524 :type 'boolean)
cb4ad359 525
f754fb7b 526(defcustom bibtex-autokey-prefix-string ""
02c8032e 527 "String prefix for automatically generated reference keys.
d715b065 528See `bibtex-generate-autokey' for details."
f754fb7b
RS
529 :group 'bibtex-autokey
530 :type 'string)
50e4b39e 531
f754fb7b 532(defcustom bibtex-autokey-names 1
d10e87a2 533 "Number of names to use for the automatically generated reference key.
d0388eac 534Possibly more names are used according to `bibtex-autokey-names-stretch'.
d715b065
KG
535If this variable is nil, all names are used.
536See `bibtex-generate-autokey' for details."
f754fb7b 537 :group 'bibtex-autokey
ab2d0cdb 538 :type '(choice (const :tag "All" infty)
7fbf4804 539 integer))
cb4ad359 540
f754fb7b 541(defcustom bibtex-autokey-names-stretch 0
02c8032e 542 "Number of names that can additionally be used for reference keys.
50e4b39e 543These names are used only, if all names are used then.
d715b065 544See `bibtex-generate-autokey' for details."
f754fb7b
RS
545 :group 'bibtex-autokey
546 :type 'integer)
50e4b39e 547
f754fb7b 548(defcustom bibtex-autokey-additional-names ""
02c8032e 549 "String to append to the generated key if not all names could be used.
d715b065 550See `bibtex-generate-autokey' for details."
f754fb7b
RS
551 :group 'bibtex-autokey
552 :type 'string)
50e4b39e
RS
553
554(defvar bibtex-autokey-transcriptions
7fbf4804
SM
555 '(;; language specific characters
556 ("\\\\aa" . "a") ; \aa -> a
557 ("\\\\AA" . "A") ; \AA -> A
558 ("\\\"a\\|\\\\\\\"a\\|\\\\ae" . "ae") ; "a,\"a,\ae -> ae
559 ("\\\"A\\|\\\\\\\"A\\|\\\\AE" . "Ae") ; "A,\"A,\AE -> Ae
560 ("\\\\i" . "i") ; \i -> i
561 ("\\\\j" . "j") ; \j -> j
562 ("\\\\l" . "l") ; \l -> l
563 ("\\\\L" . "L") ; \L -> L
564 ("\\\"o\\|\\\\\\\"o\\|\\\\o\\|\\\\oe" . "oe") ; "o,\"o,\o,\oe -> oe
565 ("\\\"O\\|\\\\\\\"O\\|\\\\O\\|\\\\OE" . "Oe") ; "O,\"O,\O,\OE -> Oe
566 ("\\\"s\\|\\\\\\\"s\\|\\\\3" . "ss") ; "s,\"s,\3 -> ss
567 ("\\\"u\\|\\\\\\\"u" . "ue") ; "u,\"u -> ue
568 ("\\\"U\\|\\\\\\\"U" . "Ue") ; "U,\"U -> Ue
50e4b39e 569 ;; accents
7fbf4804 570 ("\\\\`\\|\\\\'\\|\\\\\\^\\|\\\\~\\|\\\\=\\|\\\\\\.\\|\\\\u\\|\\\\v\\|\\\\H\\|\\\\t\\|\\\\c\\|\\\\d\\|\\\\b" . "")
d715b065
KG
571 ;; braces, quotes, concatenation.
572 ("[`'\"{}#]" . "")
7fbf4804 573 ;; spaces
e0dc0c55 574 ("\\\\?[ \t\n]+\\|~" . " "))
d715b065 575 "Alist of (OLD-REGEXP . NEW-STRING) pairs.
d0388eac
RS
576Used by the default values of `bibtex-autokey-name-change-strings' and
577`bibtex-autokey-titleword-change-strings'. Defaults to translating some
578language specific characters to their ASCII transcriptions, and
50e4b39e
RS
579removing any character accents.")
580
f754fb7b 581(defcustom bibtex-autokey-name-change-strings
50e4b39e 582 bibtex-autokey-transcriptions
d715b065 583 "Alist of (OLD-REGEXP . NEW-STRING) pairs.
02c8032e 584Any part of a name matching OLD-REGEXP is replaced by NEW-STRING.
d0388eac 585Case is significant in OLD-REGEXP. All regexps are tried in the
7fbf4804 586order in which they appear in the list.
d715b065 587See `bibtex-generate-autokey' for details."
f754fb7b 588 :group 'bibtex-autokey
7fbf4804
SM
589 :type '(repeat (cons (regexp :tag "Old")
590 (string :tag "New"))))
cb4ad359 591
ab2d0cdb 592(defcustom bibtex-autokey-name-case-convert 'downcase
d10e87a2 593 "Function called for each name to perform case conversion.
d715b065 594See `bibtex-generate-autokey' for details."
ab2d0cdb
RS
595 :group 'bibtex-autokey
596 :type '(choice (const :tag "Preserve case" identity)
7fbf4804
SM
597 (const :tag "Downcase" downcase)
598 (const :tag "Capitalize" capitalize)
599 (const :tag "Upcase" upcase)
600 (function :tag "Conversion function")))
ab2d0cdb 601
f754fb7b 602(defcustom bibtex-autokey-name-length 'infty
d10e87a2 603 "Number of characters from name to incorporate into key.
cb4ad359 604If this is set to anything but a number, all characters are used.
d715b065 605See `bibtex-generate-autokey' for details."
f754fb7b
RS
606 :group 'bibtex-autokey
607 :type '(choice (const :tag "All" infty)
7fbf4804 608 integer))
cb4ad359 609
f754fb7b 610(defcustom bibtex-autokey-name-separator ""
d10e87a2 611 "String that comes between any two names in the key.
d715b065 612See `bibtex-generate-autokey' for details."
f754fb7b
RS
613 :group 'bibtex-autokey
614 :type 'string)
cb4ad359 615
f754fb7b 616(defcustom bibtex-autokey-year-length 2
d10e87a2 617 "Number of rightmost digits from the year field to incorporate into key.
d715b065 618See `bibtex-generate-autokey' for details."
f754fb7b
RS
619 :group 'bibtex-autokey
620 :type 'integer)
50e4b39e 621
7fbf4804 622(defcustom bibtex-autokey-use-crossref t
d10e87a2 623 "If non-nil use fields from crossreferenced entry if necessary.
7fbf4804
SM
624If this variable is non-nil and some field has no entry, but a
625valid crossref entry, the field from the crossreferenced entry is used.
d715b065 626See `bibtex-generate-autokey' for details."
f754fb7b
RS
627 :group 'bibtex-autokey
628 :type 'boolean)
cb4ad359 629
f754fb7b 630(defcustom bibtex-autokey-titlewords 5
d10e87a2 631 "Number of title words to use for the automatically generated reference key.
cb4ad359 632If this is set to anything but a number, all title words are used.
50e4b39e 633Possibly more words from the title are used according to
d0388eac 634`bibtex-autokey-titlewords-stretch'.
d715b065 635See `bibtex-generate-autokey' for details."
f754fb7b
RS
636 :group 'bibtex-autokey
637 :type '(choice (const :tag "All" infty)
7fbf4804 638 integer))
cb4ad359 639
02c8032e
SM
640(defcustom bibtex-autokey-title-terminators "[.!?:;]\\|--"
641 "Regexp defining the termination of the main part of the title.
642Case of the regexps is ignored. See `bibtex-generate-autokey' for details."
f754fb7b 643 :group 'bibtex-autokey
02c8032e 644 :type 'regexp)
cb4ad359 645
f754fb7b 646(defcustom bibtex-autokey-titlewords-stretch 2
d10e87a2 647 "Number of words that can additionally be used from the title.
cb4ad359 648These words are used only, if a sentence from the title can be ended then.
d715b065 649See `bibtex-generate-autokey' for details."
f754fb7b
RS
650 :group 'bibtex-autokey
651 :type 'integer)
cb4ad359 652
ab2d0cdb
RS
653(defcustom bibtex-autokey-titleword-ignore
654 '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das"
d528bff7 655 "[^A-Z].*" ".*[^A-Z0-9].*")
d10e87a2 656 "Determines words from the title that are not to be used in the key.
ab2d0cdb
RS
657Each item of the list is a regexp. If a word of the title matchs a
658regexp from that list, it is not included in the title part of the key.
d715b065 659See `bibtex-generate-autokey' for details."
f754fb7b
RS
660 :group 'bibtex-autokey
661 :type '(repeat regexp))
cb4ad359 662
ab2d0cdb 663(defcustom bibtex-autokey-titleword-case-convert 'downcase
d10e87a2 664 "Function called for each titleword to perform case conversion.
d715b065 665See `bibtex-generate-autokey' for details."
ab2d0cdb
RS
666 :group 'bibtex-autokey
667 :type '(choice (const :tag "Preserve case" identity)
7fbf4804
SM
668 (const :tag "Downcase" downcase)
669 (const :tag "Capitalize" capitalize)
670 (const :tag "Upcase" upcase)
671 (function :tag "Conversion function")))
ab2d0cdb 672
f754fb7b 673(defcustom bibtex-autokey-titleword-abbrevs nil
d10e87a2 674 "Determines exceptions to the usual abbreviation mechanism.
d715b065 675An alist of (OLD-REGEXP . NEW-STRING) pairs. Case is ignored
d0388eac 676in matching against OLD-REGEXP, and the first matching pair is used.
d715b065 677See `bibtex-generate-autokey' for details."
7fbf4804
SM
678 :group 'bibtex-autokey
679 :type '(repeat (cons (regexp :tag "Old")
680 (string :tag "New"))))
cb4ad359 681
f754fb7b 682(defcustom bibtex-autokey-titleword-change-strings
50e4b39e 683 bibtex-autokey-transcriptions
d715b065 684 "Alist of (OLD-REGEXP . NEW-STRING) pairs.
d0388eac
RS
685Any part of title word matching a OLD-REGEXP is replaced by NEW-STRING.
686Case is significant in OLD-REGEXP. All regexps are tried in the
7fbf4804 687order in which they appear in the list.
d715b065 688See `bibtex-generate-autokey' for details."
f754fb7b 689 :group 'bibtex-autokey
7fbf4804
SM
690 :type '(repeat (cons (regexp :tag "Old")
691 (string :tag "New"))))
cb4ad359 692
f754fb7b 693(defcustom bibtex-autokey-titleword-length 5
d10e87a2 694 "Number of characters from title words to incorporate into key.
cb4ad359 695If this is set to anything but a number, all characters are used.
d715b065 696See `bibtex-generate-autokey' for details."
f754fb7b
RS
697 :group 'bibtex-autokey
698 :type '(choice (const :tag "All" infty)
7fbf4804 699 integer))
cb4ad359 700
f754fb7b 701(defcustom bibtex-autokey-titleword-separator "_"
d10e87a2 702 "String to be put between the title words.
d715b065 703See `bibtex-generate-autokey' for details."
f754fb7b
RS
704 :group 'bibtex-autokey
705 :type 'string)
cb4ad359 706
f754fb7b 707(defcustom bibtex-autokey-name-year-separator ""
d10e87a2 708 "String to be put between name part and year part of key.
d715b065 709See `bibtex-generate-autokey' for details."
f754fb7b
RS
710 :group 'bibtex-autokey
711 :type 'string)
cb4ad359 712
f754fb7b 713(defcustom bibtex-autokey-year-title-separator ":_"
d10e87a2 714 "String to be put between name part and year part of key.
d715b065 715See `bibtex-generate-autokey' for details."
f754fb7b
RS
716 :group 'bibtex-autokey
717 :type 'string)
50e4b39e 718
f754fb7b 719(defcustom bibtex-autokey-edit-before-use t
d10e87a2 720 "If non-nil, user is allowed to edit the generated key before it is used."
f754fb7b
RS
721 :group 'bibtex-autokey
722 :type 'boolean)
cb4ad359 723
ab2d0cdb 724(defcustom bibtex-autokey-before-presentation-function nil
02c8032e
SM
725 "If non-nil, function to call before generated key is presented.
726The function must take one argument (the automatically generated key),
727and must return a string (the key to use)."
f754fb7b 728 :group 'bibtex-autokey
b4a64de4 729 :type '(choice (const nil) function))
50e4b39e 730
f754fb7b 731(defcustom bibtex-entry-offset 0
d10e87a2 732 "Offset for BibTeX entries.
f754fb7b
RS
733Added to the value of all other variables which determine colums."
734 :group 'bibtex
735 :type 'integer)
50e4b39e 736
f754fb7b 737(defcustom bibtex-field-indentation 2
d10e87a2 738 "Starting column for the name part in BibTeX fields."
f754fb7b
RS
739 :group 'bibtex
740 :type 'integer)
50e4b39e 741
f754fb7b 742(defcustom bibtex-text-indentation
7fbf4804
SM
743 (+ bibtex-field-indentation
744 (length "organization = "))
d10e87a2 745 "Starting column for the text part in BibTeX fields.
f754fb7b
RS
746Should be equal to the space needed for the longest name part."
747 :group 'bibtex
748 :type 'integer)
50e4b39e 749
f754fb7b 750(defcustom bibtex-contline-indentation
50e4b39e 751 (+ bibtex-text-indentation 1)
d10e87a2 752 "Starting column for continuation lines of BibTeX fields."
f754fb7b
RS
753 :group 'bibtex
754 :type 'integer)
50e4b39e 755
f754fb7b 756(defcustom bibtex-align-at-equal-sign nil
d10e87a2 757 "If non-nil, align fields at equal sign instead of field text.
7fbf4804
SM
758If non-nil, the column for the equal sign is the value of
759`bibtex-text-indentation', minus 2."
f754fb7b
RS
760 :group 'bibtex
761 :type 'boolean)
762
763(defcustom bibtex-comma-after-last-field nil
d10e87a2 764 "If non-nil, a comma is put at end of last field in the entry template."
f754fb7b
RS
765 :group 'bibtex
766 :type 'boolean)
50e4b39e 767
d715b065
KG
768(defcustom bibtex-autoadd-commas t
769 "If non-nil automatically add missing commas at end of BibTeX fields."
e0dc0c55 770 :group 'bibtex
d715b065
KG
771 :type 'boolean)
772
773(defcustom bibtex-autofill-types '("Proceedings")
774 "Automatically fill fields if possible for those BibTeX entry types."
e0dc0c55 775 :group 'bibtex
d715b065
KG
776 :type '(repeat string))
777
e0dc0c55
SM
778(defcustom bibtex-summary-function 'bibtex-summary
779 "Function to call for generating a one-line summary of a BibTeX entry.
780It takes one argument, the key of the entry.
02c8032e 781Used by `bibtex-complete-crossref-cleanup' and `bibtex-copy-summary-as-kill'."
e0dc0c55
SM
782 :group 'bibtex
783 :type '(choice (const :tag "Default" bibtex-summary)
784 (function :tag "Personalized function")))
785
d528bff7 786(defcustom bibtex-generate-url-list
a9d77f1f
SM
787 '((("url" . ".*:.*"))
788 ;; Example of a complex setup.
789 (("journal" . "\\<\\(PR[ABCDEL]?\\|RMP\\)\\>")
02c8032e 790 "http://link.aps.org/abstract/"
a9d77f1f
SM
791 ("journal" ".*" downcase)
792 "/v"
793 ("volume" ".*" 0)
794 "/p"
795 ("pages" "\\`\\([0-9]+\\)" 1)))
d528bff7
SM
796 "List of schemes for generating the URL of a BibTeX entry.
797These schemes are used by `bibtex-url'.
798
a9d77f1f 799Each scheme is of the form ((FIELD . REGEXP) STEP...).
d528bff7
SM
800
801FIELD is a field name as returned by `bibtex-parse-entry'.
e0dc0c55 802REGEXP is matched against the text of FIELD. If the match succeeds, then
d10e87a2
SM
803this scheme is used. If no STEPs are specified the matched text is used
804as the URL, otherwise the URL is built by concatenating the STEPs.
a9d77f1f
SM
805
806A STEP can be a string or a list (FIELD REGEXP REPLACE) in which case
807the text of FIELD is matched against REGEXP, and is replaced with REPLACE.
808REPLACE can be a string, or a number (which selects the corresponding submatch)
809or a function called with the field's text as argument and with the
810`match-data' properly set.
811
812Case is always ignored. Always remove the field delimiters."
d528bff7
SM
813 :group 'bibtex
814 :type '(repeat
a9d77f1f 815 (list :tag "Scheme"
d528bff7
SM
816 (cons :tag "Matcher" :extra-offset 4
817 (string :tag "BibTeX field")
a9d77f1f 818 (regexp :tag "Regexp"))
d528bff7
SM
819 (repeat :tag "Steps to generate URL" :inline t
820 (choice
821 (string :tag "Literal text")
822 (list (string :tag "BibTeX field")
a9d77f1f
SM
823 (regexp :tag "Regexp")
824 (choice (string :tag "Replacement")
825 (integer :tag "Sub-match")
826 (function :tag "Filter"))))))))
7fbf4804 827
31bc4210
RS
828;; bibtex-font-lock-keywords is a user option as well, but since the
829;; patterns used to define this variable are defined in a later
50e4b39e 830;; section of this file, it is defined later.
28f2ee66
GM
831
832\f
5c69dbfc 833;; Syntax Table, Keybindings and BibTeX Entry List
9ae11a89
ER
834(defvar bibtex-mode-syntax-table
835 (let ((st (make-syntax-table)))
50e4b39e 836 (modify-syntax-entry ?\" "\"" st)
9ae11a89
ER
837 (modify-syntax-entry ?$ "$$ " st)
838 (modify-syntax-entry ?% "< " st)
50e4b39e
RS
839 (modify-syntax-entry ?' "w " st)
840 (modify-syntax-entry ?@ "w " st)
9ae11a89
ER
841 (modify-syntax-entry ?\\ "\\" st)
842 (modify-syntax-entry ?\f "> " st)
843 (modify-syntax-entry ?\n "> " st)
7fbf4804
SM
844 ;; Keys cannot have = in them (wrong font-lock of @string{foo=bar}).
845 (modify-syntax-entry ?= "." st)
9ae11a89 846 (modify-syntax-entry ?~ " " st)
7fbf4804
SM
847 st)
848 "Syntax table used in BibTeX mode buffers.")
9ae11a89 849
9ae11a89
ER
850(defvar bibtex-mode-map
851 (let ((km (make-sparse-keymap)))
28f2ee66 852 ;; The Key `C-c&' is reserved for reftex.el
9ae11a89
ER
853 (define-key km "\t" 'bibtex-find-text)
854 (define-key km "\n" 'bibtex-next-field)
7fbf4804 855 (define-key km "\M-\t" 'bibtex-complete)
50e4b39e
RS
856 (define-key km "\C-c\"" 'bibtex-remove-delimiters)
857 (define-key km "\C-c{" 'bibtex-remove-delimiters)
858 (define-key km "\C-c}" 'bibtex-remove-delimiters)
9ae11a89 859 (define-key km "\C-c\C-c" 'bibtex-clean-entry)
50e4b39e 860 (define-key km "\C-c\C-q" 'bibtex-fill-entry)
d528bff7 861 (define-key km "\C-c\C-s" 'bibtex-find-entry)
02c8032e 862 (define-key km "\C-c\C-x" 'bibtex-find-crossref)
e0dc0c55 863 (define-key km "\C-c\C-t" 'bibtex-copy-summary-as-kill)
cb4ad359 864 (define-key km "\C-c?" 'bibtex-print-help-message)
9ae11a89
ER
865 (define-key km "\C-c\C-p" 'bibtex-pop-previous)
866 (define-key km "\C-c\C-n" 'bibtex-pop-next)
50e4b39e
RS
867 (define-key km "\C-c\C-k" 'bibtex-kill-field)
868 (define-key km "\C-c\M-k" 'bibtex-copy-field-as-kill)
869 (define-key km "\C-c\C-w" 'bibtex-kill-entry)
870 (define-key km "\C-c\M-w" 'bibtex-copy-entry-as-kill)
871 (define-key km "\C-c\C-y" 'bibtex-yank)
872 (define-key km "\C-c\M-y" 'bibtex-yank-pop)
9ae11a89 873 (define-key km "\C-c\C-d" 'bibtex-empty-field)
50e4b39e 874 (define-key km "\C-c\C-f" 'bibtex-make-field)
8bf38a9b 875 (define-key km "\C-c\C-u" 'bibtex-entry-update)
50e4b39e
RS
876 (define-key km "\C-c$" 'bibtex-ispell-abstract)
877 (define-key km "\M-\C-a" 'bibtex-beginning-of-entry)
878 (define-key km "\M-\C-e" 'bibtex-end-of-entry)
879 (define-key km "\C-\M-l" 'bibtex-reposition-window)
880 (define-key km "\C-\M-h" 'bibtex-mark-entry)
881 (define-key km "\C-c\C-b" 'bibtex-entry)
cb4ad359
RS
882 (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry)
883 (define-key km "\C-c\C-rw" 'widen)
d528bff7 884 (define-key km "\C-c\C-l" 'bibtex-url)
50e4b39e 885 (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT)
cb4ad359 886 (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings)
9ae11a89 887 (define-key km "\C-c\C-ei" 'bibtex-InCollection)
cb4ad359
RS
888 (define-key km "\C-c\C-eI" 'bibtex-InBook)
889 (define-key km "\C-c\C-e\C-a" 'bibtex-Article)
890 (define-key km "\C-c\C-e\C-b" 'bibtex-InBook)
891 (define-key km "\C-c\C-eb" 'bibtex-Book)
892 (define-key km "\C-c\C-eB" 'bibtex-Booklet)
893 (define-key km "\C-c\C-e\C-c" 'bibtex-InCollection)
9ae11a89
ER
894 (define-key km "\C-c\C-e\C-m" 'bibtex-Manual)
895 (define-key km "\C-c\C-em" 'bibtex-MastersThesis)
896 (define-key km "\C-c\C-eM" 'bibtex-Misc)
cb4ad359 897 (define-key km "\C-c\C-e\C-p" 'bibtex-InProceedings)
9ae11a89 898 (define-key km "\C-c\C-ep" 'bibtex-Proceedings)
cb4ad359 899 (define-key km "\C-c\C-eP" 'bibtex-PhdThesis)
50e4b39e
RS
900 (define-key km "\C-c\C-e\M-p" 'bibtex-Preamble)
901 (define-key km "\C-c\C-e\C-s" 'bibtex-String)
cb4ad359 902 (define-key km "\C-c\C-e\C-t" 'bibtex-TechReport)
9ae11a89 903 (define-key km "\C-c\C-e\C-u" 'bibtex-Unpublished)
7fbf4804
SM
904 km)
905 "Keymap used in BibTeX mode.")
9ae11a89 906
50e4b39e 907(easy-menu-define
7fbf4804
SM
908 bibtex-edit-menu bibtex-mode-map "BibTeX-Edit Menu in BibTeX mode"
909 '("BibTeX-Edit"
910 ("Moving inside an Entry"
911 ["End of Field" bibtex-find-text t]
912 ["Next Field" bibtex-next-field t]
913 ["Beginning of Entry" bibtex-beginning-of-entry t]
d10e87a2
SM
914 ["End of Entry" bibtex-end-of-entry t]
915 "--"
916 ["Make Entry Visible" bibtex-reposition-window t])
02c8032e 917 ("Moving in BibTeX Buffers"
d715b065
KG
918 ["Find Entry" bibtex-find-entry t]
919 ["Find Crossref Entry" bibtex-find-crossref t])
e0dc0c55 920 "--"
7fbf4804 921 ("Operating on Current Field"
d715b065 922 ["Fill Field" fill-paragraph t]
7fbf4804
SM
923 ["Remove Delimiters" bibtex-remove-delimiters t]
924 ["Remove OPT or ALT Prefix" bibtex-remove-OPT-or-ALT t]
925 ["Clear Field" bibtex-empty-field t]
926 "--"
927 ["Kill Field" bibtex-kill-field t]
928 ["Copy Field to Kill Ring" bibtex-copy-field-as-kill t]
929 ["Paste Most Recently Killed Field" bibtex-yank t]
930 ["Paste Previously Killed Field" bibtex-yank-pop t]
931 "--"
932 ["Make New Field" bibtex-make-field t]
933 "--"
934 ["Snatch from Similar Following Field" bibtex-pop-next t]
935 ["Snatch from Similar Preceding Field" bibtex-pop-previous t]
936 "--"
937 ["String or Key Complete" bibtex-complete t]
938 "--"
939 ["Help about Current Field" bibtex-print-help-message t])
d528bff7
SM
940 ("Operating on Current Entry"
941 ["Fill Entry" bibtex-fill-entry t]
942 ["Clean Entry" bibtex-clean-entry t]
943 ["Update Entry" bibtex-entry-update t]
944 "--"
945 ["Kill Entry" bibtex-kill-entry t]
946 ["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t]
947 ["Paste Most Recently Killed Entry" bibtex-yank t]
948 ["Paste Previously Killed Entry" bibtex-yank-pop t]
949 "--"
e0dc0c55 950 ["Copy Summary to Kill Ring" bibtex-copy-summary-as-kill t]
02c8032e 951 ["Browse URL" bibtex-url t]
e0dc0c55 952 "--"
d528bff7
SM
953 ["Ispell Entry" bibtex-ispell-entry t]
954 ["Ispell Entry Abstract" bibtex-ispell-abstract t]
02c8032e 955 "--"
d528bff7 956 ["Narrow to Entry" bibtex-narrow-to-entry t]
02c8032e 957 ["Mark Entry" bibtex-mark-entry t]
d528bff7
SM
958 "--"
959 ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex
960 (fboundp 'reftex-view-crossref-from-bibtex)])
7fbf4804
SM
961 ("Operating on Buffer or Region"
962 ["Validate Entries" bibtex-validate t]
963 ["Sort Entries" bibtex-sort-buffer t]
964 ["Reformat Entries" bibtex-reformat t]
d528bff7
SM
965 ["Count Entries" bibtex-count-entries t]
966 "--"
e0dc0c55
SM
967 ["Convert Alien Buffer" bibtex-convert-alien t])
968 ("Operating on Multiple Buffers"
969 ["Validate Entries" bibtex-validate-globally t])))
50e4b39e
RS
970
971(easy-menu-define
7fbf4804
SM
972 bibtex-entry-menu bibtex-mode-map "Entry-Types Menu in BibTeX mode"
973 (list "Entry-Types"
974 ["Article in Journal" bibtex-Article t]
975 ["Article in Conference Proceedings" bibtex-InProceedings t]
976 ["Article in a Collection" bibtex-InCollection t]
977 ["Chapter or Pages in a Book" bibtex-InBook t]
978 ["Conference Proceedings" bibtex-Proceedings t]
979 ["Book" bibtex-Book t]
980 ["Booklet (Bound, but no Publisher/Institution)" bibtex-Booklet t]
981 ["PhD. Thesis" bibtex-PhdThesis t]
982 ["Master's Thesis" bibtex-MastersThesis t]
983 ["Technical Report" bibtex-TechReport t]
984 ["Technical Manual" bibtex-Manual t]
985 ["Unpublished" bibtex-Unpublished t]
986 ["Miscellaneous" bibtex-Misc t]
02c8032e 987 "--"
7fbf4804
SM
988 ["String" bibtex-String t]
989 ["Preamble" bibtex-Preamble t]))
9ae11a89 990
31bc4210 991\f
5c69dbfc 992;; Internal Variables
9ae11a89 993
7fbf4804
SM
994(defvar bibtex-pop-previous-search-point nil
995 "Next point where `bibtex-pop-previous' starts looking for a similar entry.")
996
997(defvar bibtex-pop-next-search-point nil
998 "Next point where `bibtex-pop-next' starts looking for a similar entry.")
999
1000(defvar bibtex-field-kill-ring nil
1001 "Ring of least recently killed fields.
1002At most `bibtex-field-kill-ring-max' items are kept here.")
9ae11a89 1003
7fbf4804
SM
1004(defvar bibtex-field-kill-ring-yank-pointer nil
1005 "The tail of `bibtex-field-kill-ring' whose car is the last item yanked.")
745bc783 1006
7fbf4804
SM
1007(defvar bibtex-entry-kill-ring nil
1008 "Ring of least recently killed entries.
1009At most `bibtex-entry-kill-ring-max' items are kept here.")
50e4b39e 1010
7fbf4804
SM
1011(defvar bibtex-entry-kill-ring-yank-pointer nil
1012 "The tail of `bibtex-entry-kill-ring' whose car is the last item yanked.")
50e4b39e 1013
7fbf4804
SM
1014(defvar bibtex-last-kill-command nil
1015 "Type of the last kill command (either 'field or 'entry).")
50e4b39e 1016
d715b065
KG
1017(defvar bibtex-strings
1018 (lazy-completion-table bibtex-strings
1019 bibtex-parse-strings (bibtex-string-files-init))
1020 "Completion table for BibTeX string keys.
7fbf4804 1021Initialized from `bibtex-predefined-strings' and `bibtex-string-files'.")
d715b065 1022(make-variable-buffer-local 'bibtex-strings)
50e4b39e 1023
d715b065 1024(defvar bibtex-reference-keys
e0dc0c55
SM
1025 (lazy-completion-table bibtex-reference-keys bibtex-parse-keys nil t)
1026 "Completion table for BibTeX reference keys.
1027The CDRs of the elements are t for header keys and nil for crossref keys.")
d715b065 1028(make-variable-buffer-local 'bibtex-reference-keys)
50e4b39e 1029
7fbf4804 1030(defvar bibtex-buffer-last-parsed-tick nil
a9d77f1f 1031 "Value of `buffer-modified-tick' last time buffer was parsed for keys.")
745bc783 1032
7fbf4804
SM
1033(defvar bibtex-parse-idle-timer nil
1034 "Stores if timer is already installed.")
0640d7bf 1035
7fbf4804
SM
1036(defvar bibtex-progress-lastperc nil
1037 "Last reported percentage for the progress message.")
50e4b39e 1038
7fbf4804
SM
1039(defvar bibtex-progress-lastmes nil
1040 "Last reported progress message.")
50e4b39e 1041
7fbf4804
SM
1042(defvar bibtex-progress-interval nil
1043 "Interval for progress messages.")
50e4b39e 1044
7fbf4804
SM
1045(defvar bibtex-key-history nil
1046 "History list for reading keys.")
50e4b39e 1047
7fbf4804 1048(defvar bibtex-entry-type-history nil
d715b065 1049 "History list for reading entry types.")
50e4b39e 1050
7fbf4804
SM
1051(defvar bibtex-field-history nil
1052 "History list for reading field names.")
50e4b39e 1053
7fbf4804
SM
1054(defvar bibtex-reformat-previous-options nil
1055 "Last reformat options given.")
50e4b39e 1056
7fbf4804
SM
1057(defvar bibtex-reformat-previous-reference-keys nil
1058 "Last reformat reference keys option given.")
50e4b39e 1059
7fbf4804
SM
1060(defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*"
1061 "Regexp matching the name part of a BibTeX field.")
50e4b39e 1062
7fbf4804
SM
1063(defconst bibtex-entry-type (concat "@" bibtex-field-name)
1064 "Regexp matching the type part of a BibTeX entry.")
1065
1066(defconst bibtex-reference-key "[][a-zA-Z0-9.:;?!`'/*@+|()<>&_^$-]+"
1067 "Regexp matching the reference key part of a BibTeX entry.")
1068
1069(defconst bibtex-field-const "[][a-zA-Z0-9.:;?!`'/*@+=|<>&_^$-]+"
1070 "Regexp matching a BibTeX field constant.")
1071
1072(defconst bibtex-entry-head
1073 (concat "^[ \t]*\\("
1074 bibtex-entry-type
1075 "\\)[ \t]*[({][ \t\n]*\\("
1076 bibtex-reference-key
1077 "\\)")
1078 "Regexp matching the header line of a BibTeX entry.")
1079
1080(defconst bibtex-entry-maybe-empty-head
1081 (concat bibtex-entry-head "?")
d715b065 1082 "Regexp matching the header line of a BibTeX entry (possibly without key).")
7fbf4804
SM
1083
1084(defconst bibtex-type-in-head 1
1085 "Regexp subexpression number of the type part in `bibtex-entry-head'.")
1086
1087(defconst bibtex-key-in-head 2
1088 "Regexp subexpression number of the key part in `bibtex-entry-head'.")
1089
02c8032e
SM
1090(defconst bibtex-string-maybe-empty-head
1091 (concat "^[ \t]*\\(@String\\)[ \t]*[({]\\("
1092 bibtex-reference-key
1093 "\\)?")
1094 "Regexp matching the header line of a BibTeX String entry.")
1095
7fbf4804
SM
1096(defconst bibtex-entry-postfix "[ \t\n]*,?[ \t\n]*[})]"
1097 "Regexp matching the postfix of a BibTeX entry.")
1098
1099(defvar bibtex-known-entry-type-re
1100 (regexp-opt (mapcar 'car bibtex-entry-field-alist))
02c8032e 1101 "Regexp matching the name of a BibTeX entry.")
7fbf4804
SM
1102
1103(defvar bibtex-valid-entry-re
1104 (concat "@[ \t]*\\(" bibtex-known-entry-type-re "\\)")
1105 "Regexp matching the name of a valid BibTeX entry.")
1106
1107(defvar bibtex-valid-entry-whitespace-re
1108 (concat "[ \t\n]*\\(" bibtex-valid-entry-re "\\)")
1109 "Regexp matching the name of a valid BibTeX entry preceded by whitespace.")
1110
1111(defvar bibtex-any-valid-entry-re
1112 (concat "@[ \t]*"
1113 (regexp-opt (append '("String")
1114 (mapcar 'car bibtex-entry-field-alist))
1115 t))
1116 "Regexp matching the name of any valid BibTeX entry (including string).")
1117
1118
1119(defconst bibtex-empty-field-re "\"\"\\|{}"
1120 "Regexp matching an empty field.")
1121
7fbf4804
SM
1122(defconst bibtex-font-lock-syntactic-keywords
1123 `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)"
1124 (substring bibtex-comment-start 1) "\\>")
1125 1 '(11))))
1126
1127(defvar bibtex-font-lock-keywords
d528bff7
SM
1128 ;; entry type and reference key
1129 `((,bibtex-entry-maybe-empty-head
1130 (,bibtex-type-in-head font-lock-function-name-face)
1131 (,bibtex-key-in-head font-lock-constant-face nil t))
1132 ;; optional field names (treated as comments)
1133 (,(concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
1134 1 font-lock-comment-face)
1135 ;; field names
1136 (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
1137 1 font-lock-variable-name-face)
1138 ;; url
e0dc0c55 1139 bibtex-font-lock-url bibtex-font-lock-crossref)
7fbf4804
SM
1140 "*Default expressions to highlight in BibTeX mode.")
1141
d528bff7 1142(defvar bibtex-font-lock-url-regexp
e0dc0c55 1143 ;; Assume that field names begin at the beginning of a line.
d10e87a2
SM
1144 (concat "^[ \t]*"
1145 (regexp-opt (delete-dups (mapcar 'caar bibtex-generate-url-list)) t)
e0dc0c55 1146 "[ \t]*=[ \t]*")
d528bff7
SM
1147 "Regexp for `bibtex-font-lock-url'.")
1148
7fbf4804 1149(defvar bibtex-field-name-for-parsing nil
a9d77f1f
SM
1150 "Regexp of field name to be parsed by function `bibtex-parse-field-name'.
1151Passed by dynamic scoping.")
7fbf4804
SM
1152
1153(defvar bibtex-sort-entry-class-alist
1154 (let ((i -1) alist)
1155 (dolist (class bibtex-sort-entry-class alist)
1156 (setq i (1+ i))
1157 (dolist (entry class)
d715b065
KG
1158 ;; all entry names should be downcase (for ease of comparison)
1159 (push (cons (if (stringp entry) (downcase entry) entry) i) alist))))
a9d77f1f
SM
1160 "Alist mapping entry types to their sorting index.
1161Auto-generated from `bibtex-sort-entry-class'.
1162Used when `bibtex-maintain-sorted-entries' is `entry-class'.")
0640d7bf 1163
cb4ad359 1164\f
7fbf4804
SM
1165;; Support for hideshow minor mode
1166(defun bibtex-hs-forward-sexp (arg)
a9d77f1f
SM
1167 "Replacement for `forward-sexp' to be used by `hs-minor-mode'.
1168ARG is ignored."
1169 (if (looking-at "@\\S(*\\s(")
e0dc0c55 1170 (goto-char (1- (match-end 0))))
a9d77f1f 1171 (forward-sexp 1))
50e4b39e 1172
7fbf4804
SM
1173(add-to-list
1174 'hs-special-modes-alist
1175 '(bibtex-mode "@\\S(*\\s(" "\\s)" nil bibtex-hs-forward-sexp nil))
1176
1177\f
f9bd4abe 1178(defun bibtex-parse-association (parse-lhs parse-rhs)
7fbf4804 1179 "Parse a string of the format <left-hand-side = right-hand-side>.
f9bd4abe
GM
1180The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding
1181substrings. These functions are expected to return nil if parsing is not
1182successfull. If both functions return non-nil, a pair containing the returned
7fbf4804 1183values of the functions PARSE-LHS and PARSE-RHS is returned."
f9bd4abe 1184 (save-match-data
7fbf4804 1185 (save-excursion
d715b065
KG
1186 (let ((left (funcall parse-lhs))
1187 right)
1188 (if (and left
7fbf4804
SM
1189 (looking-at "[ \t\n]*=[ \t\n]*")
1190 (goto-char (match-end 0))
1191 (setq right (funcall parse-rhs)))
1192 (cons left right))))))
f9bd4abe
GM
1193
1194(defun bibtex-parse-field-name ()
7fbf4804 1195 "Parse the field name stored in `bibtex-field-name-for-parsing'.
f9bd4abe
GM
1196If the field name is found, return a triple consisting of the position of the
1197very first character of the match, the actual starting position of the name
a9d77f1f 1198part and end position of the match. Move point to end of field name.
d715b065
KG
1199If `bibtex-autoadd-commas' is non-nil add missing comma at end of preceeding
1200BibTeX field as necessary."
1201 (cond ((looking-at ",[ \t\n]*")
1202 (let ((start (point)))
1203 (goto-char (match-end 0))
1204 (when (looking-at bibtex-field-name-for-parsing)
1205 (goto-char (match-end 0))
1206 (list start (match-beginning 0) (match-end 0)))))
1207 ;; Maybe add a missing comma.
1208 ((and bibtex-autoadd-commas
1209 (looking-at (concat "[ \t\n]*\\(?:" bibtex-field-name-for-parsing
1210 "\\)[ \t\n]*=")))
1211 (skip-chars-backward " \t\n")
1212 (insert ",")
1213 (forward-char -1)
1214 ;; Now try again.
1215 (bibtex-parse-field-name))))
d30bfc76 1216
8bf38a9b
SM
1217(defconst bibtex-braced-string-syntax-table
1218 (let ((st (make-syntax-table)))
1219 (modify-syntax-entry ?\{ "(}" st)
1220 (modify-syntax-entry ?\} "){" st)
1221 (modify-syntax-entry ?\[ "." st)
1222 (modify-syntax-entry ?\] "." st)
1223 (modify-syntax-entry ?\( "." st)
1224 (modify-syntax-entry ?\) "." st)
1225 (modify-syntax-entry ?\\ "." st)
1226 (modify-syntax-entry ?\" "." st)
1227 st)
1228 "Syntax-table to parse matched braces.")
1229
1230(defconst bibtex-quoted-string-syntax-table
1231 (let ((st (make-syntax-table)))
1232 (modify-syntax-entry ?\\ "\\" st)
1233 (modify-syntax-entry ?\" "\"" st)
1234 st)
1235 "Syntax-table to parse matched quotes.")
1236
1237(defun bibtex-parse-field-string ()
02c8032e 1238 "Parse a BibTeX field string enclosed by braces or quotes.
8bf38a9b
SM
1239If a syntactically correct string is found, a pair containing the start and
1240end position of the field string is returned, nil otherwise."
1241 (let ((end-point
1242 (or (and (eq (following-char) ?\")
1243 (save-excursion
1244 (with-syntax-table bibtex-quoted-string-syntax-table
1245 (forward-sexp 1))
1246 (point)))
1247 (and (eq (following-char) ?\{)
1248 (save-excursion
1249 (with-syntax-table bibtex-braced-string-syntax-table
1250 (forward-sexp 1))
1251 (point))))))
1252 (if end-point
1253 (cons (point) end-point))))
1254
f9bd4abe 1255(defun bibtex-parse-field-text ()
7fbf4804 1256 "Parse the text part of a BibTeX field.
f9bd4abe
GM
1257The text part is either a string, or an empty string, or a constant followed
1258by one or more <# (string|constant)> pairs. If a syntactically correct text
1259is found, a pair containing the start and end position of the text is
a9d77f1f 1260returned, nil otherwise. Move point to end of field text."
f9bd4abe 1261 (let ((starting-point (point))
7fbf4804 1262 end-point failure boundaries)
d715b065 1263 (while (not (or end-point failure))
7fbf4804
SM
1264 (cond ((looking-at bibtex-field-const)
1265 (goto-char (match-end 0)))
1266 ((setq boundaries (bibtex-parse-field-string))
1267 (goto-char (cdr boundaries)))
1268 ((setq failure t)))
d528bff7
SM
1269 (if (looking-at "[ \t\n]*#[ \t\n]*")
1270 (goto-char (match-end 0))
1271 (setq end-point (point))))
7fbf4804
SM
1272 (if (and (not failure)
1273 end-point)
1274 (cons starting-point end-point))))
f9bd4abe
GM
1275
1276(defun bibtex-parse-field (name)
7fbf4804 1277 "Parse a BibTeX field of regexp NAME.
f9bd4abe
GM
1278If a syntactically correct field is found, a pair containing the boundaries of
1279the name and text parts of the field is returned."
7fbf4804
SM
1280 (let ((bibtex-field-name-for-parsing name))
1281 (bibtex-parse-association 'bibtex-parse-field-name
1282 'bibtex-parse-field-text)))
f9bd4abe 1283
7fbf4804 1284(defun bibtex-search-forward-field (name &optional bound)
02c8032e 1285 "Search forward to find a BibTeX field of name NAME.
f9bd4abe
GM
1286If a syntactically correct field is found, a pair containing the boundaries of
1287the name and text parts of the field is returned. The search is limited by
a9d77f1f
SM
1288optional arg BOUND. If BOUND is t the search is limited by the end of the
1289current entry. Do not move point."
f9bd4abe 1290 (save-match-data
7fbf4804 1291 (save-excursion
d715b065
KG
1292 (unless (integer-or-marker-p bound)
1293 (setq bound (if bound
1294 (save-excursion (bibtex-end-of-entry))
1295 (point-max))))
7fbf4804
SM
1296 (let ((case-fold-search t)
1297 (bibtex-field-name-for-parsing name)
1298 boundaries temp-boundaries)
1299 (while (and (not boundaries)
1300 (< (point) bound)
1301 (search-forward "," bound t))
1302 (goto-char (match-beginning 0))
1303 (if (and (setq temp-boundaries
1304 (bibtex-parse-association 'bibtex-parse-field-name
1305 'bibtex-parse-field-text))
1306 (<= (cddr temp-boundaries) bound))
1307 (setq boundaries temp-boundaries)
1308 (forward-char 1)))
1309 boundaries))))
1310
1311(defun bibtex-search-backward-field (name &optional bound)
02c8032e 1312 "Search backward to find a BibTeX field of name NAME.
f9bd4abe
GM
1313If a syntactically correct field is found, a pair containing the boundaries of
1314the name and text parts of the field is returned. The search is limited by
a9d77f1f
SM
1315optional arg BOUND. If BOUND is t the search is limited by the beginning of the
1316current entry. Do not move point."
f9bd4abe 1317 (save-match-data
7fbf4804 1318 (save-excursion
d715b065
KG
1319 (unless (integer-or-marker-p bound)
1320 (setq bound (if bound
1321 (save-excursion (bibtex-beginning-of-entry))
1322 (point-min))))
7fbf4804
SM
1323 (let ((case-fold-search t)
1324 (bibtex-field-name-for-parsing name)
1325 boundaries temp-boundaries)
1326 (while (and (not boundaries)
1327 (>= (point) bound)
1328 (search-backward "," bound t))
1329 (if (setq temp-boundaries
1330 (bibtex-parse-association 'bibtex-parse-field-name
1331 'bibtex-parse-field-text))
1332 (setq boundaries temp-boundaries)))
1333 boundaries))))
f9bd4abe 1334
d715b065 1335(defsubst bibtex-start-of-field (bounds)
7fbf4804 1336 (nth 0 (car bounds)))
d715b065 1337(defsubst bibtex-start-of-name-in-field (bounds)
7fbf4804 1338 (nth 1 (car bounds)))
d715b065 1339(defsubst bibtex-end-of-name-in-field (bounds)
7fbf4804 1340 (nth 2 (car bounds)))
d715b065 1341(defsubst bibtex-end-of-field (bounds)
7fbf4804 1342 (cddr bounds))
d715b065 1343(defsubst bibtex-start-of-text-in-field (bounds)
7fbf4804 1344 (cadr bounds))
d715b065 1345(defsubst bibtex-end-of-text-in-field (bounds)
7fbf4804
SM
1346 (cddr bounds))
1347
d528bff7
SM
1348(defun bibtex-name-in-field (bounds &optional remove-opt-alt)
1349 "Get content of name in BibTeX field defined via BOUNDS.
1350If optional arg REMOVE-OPT-ALT is non-nil remove \"OPT\" and \"ALT\"."
1351 (let ((name (buffer-substring-no-properties (nth 1 (car bounds))
1352 (nth 2 (car bounds)))))
1353 (if (and remove-opt-alt
1354 (string-match "\\`\\(OPT\\|ALT\\)" name))
1355 (substring name 3)
1356 name)))
7fbf4804
SM
1357
1358(defun bibtex-text-in-field-bounds (bounds &optional remove-delim)
1359 "Get content of text in BibTeX field defined via BOUNDS.
1360If optional arg REMOVE-DELIM is non-nil remove enclosing field delimiters
1361if present."
1362 (let ((content (buffer-substring-no-properties (cadr bounds)
1363 (cddr bounds))))
02c8032e
SM
1364 (if remove-delim
1365 (bibtex-remove-delimiters-string content)
7fbf4804
SM
1366 content)))
1367
1368(defun bibtex-text-in-field (field &optional follow-crossref)
02c8032e
SM
1369 "Get content of field FIELD of current BibTeX entry.
1370Return nil if not found.
7fbf4804
SM
1371If optional arg FOLLOW-CROSSREF is non-nil, follow crossref."
1372 (save-excursion
1373 (save-restriction
d715b065 1374 ;; We want to jump back and forth while searching FIELD
7fbf4804
SM
1375 (bibtex-narrow-to-entry)
1376 (goto-char (point-min))
1377 (let ((bounds (bibtex-search-forward-field field))
1378 crossref-field)
1379 (cond (bounds (bibtex-text-in-field-bounds bounds t))
1380 ((and follow-crossref
1381 (progn (goto-char (point-min))
1382 (setq bounds (bibtex-search-forward-field
1383 "\\(OPT\\)?crossref"))))
1384 (setq crossref-field (bibtex-text-in-field-bounds bounds t))
1385 (widen)
1386 (if (bibtex-find-crossref crossref-field)
1387 ;; Do not pass FOLLOW-CROSSREF because we want
1388 ;; to follow crossrefs only one level of recursion.
1389 (bibtex-text-in-field field))))))))
f9bd4abe
GM
1390
1391(defun bibtex-parse-string-prefix ()
7fbf4804 1392 "Parse the prefix part of a BibTeX string entry, including reference key.
f9bd4abe
GM
1393If the string prefix is found, return a triple consisting of the position of
1394the very first character of the match, the actual starting position of the
1395reference key and the end position of the match."
7fbf4804 1396 (let ((case-fold-search t))
f9bd4abe 1397 (if (looking-at "^[ \t]*@string[ \t\n]*[({][ \t\n]*")
7fbf4804
SM
1398 (let ((start (point)))
1399 (goto-char (match-end 0))
1400 (when (looking-at bibtex-reference-key)
1401 (goto-char (match-end 0))
1402 (list start
1403 (match-beginning 0)
1404 (match-end 0)))))))
f9bd4abe
GM
1405
1406(defun bibtex-parse-string-postfix ()
7fbf4804 1407 "Parse the postfix part of a BibTeX string entry, including the text.
f9bd4abe
GM
1408If the string postfix is found, return a triple consisting of the position of
1409the actual starting and ending position of the text and the very last
a9d77f1f 1410character of the string entry. Move point past BibTeX string entry."
f9bd4abe 1411 (let* ((case-fold-search t)
d715b065
KG
1412 (bounds (bibtex-parse-field-text)))
1413 (when bounds
1414 (goto-char (cdr bounds))
7fbf4804
SM
1415 (when (looking-at "[ \t\n]*[})]")
1416 (goto-char (match-end 0))
d715b065
KG
1417 (list (car bounds)
1418 (cdr bounds)
7fbf4804 1419 (match-end 0))))))
f9bd4abe
GM
1420
1421(defun bibtex-parse-string ()
7fbf4804 1422 "Parse a BibTeX string entry.
f9bd4abe 1423If a syntactically correct entry is found, a pair containing the boundaries of
7fbf4804
SM
1424the reference key and text parts of the entry is returned.
1425Move point past BibTeX string entry."
f9bd4abe 1426 (bibtex-parse-association 'bibtex-parse-string-prefix
7fbf4804 1427 'bibtex-parse-string-postfix))
f9bd4abe
GM
1428
1429(defun bibtex-search-forward-string ()
7fbf4804 1430 "Search forward to find a BibTeX string entry.
f9bd4abe 1431If a syntactically correct entry is found, a pair containing the boundaries of
a9d77f1f 1432the reference key and text parts of the string is returned. Do not move point."
7fbf4804
SM
1433 (save-excursion
1434 (save-match-data
1435 (let ((case-fold-search t)
1436 boundaries)
1437 (while (and (not boundaries)
1438 (search-forward-regexp
1439 "^[ \t]*@string[ \t\n]*[({][ \t\n]*" nil t))
1440 (goto-char (match-beginning 0))
1441 (unless (setq boundaries (bibtex-parse-string))
1442 (forward-char 1)))
1443 boundaries))))
f9bd4abe
GM
1444
1445(defun bibtex-search-backward-string ()
7fbf4804 1446 "Search backward to find a BibTeX string entry.
f9bd4abe 1447If a syntactically correct entry is found, a pair containing the boundaries of
a9d77f1f 1448the reference key and text parts of the field is returned. Do not move point."
7fbf4804
SM
1449 (save-excursion
1450 (save-match-data
1451 (let ((case-fold-search t)
1452 boundaries)
1453 (while (and (not boundaries)
1454 (search-backward-regexp
1455 "^[ \t]*@string[ \t\n]*[({][ \t\n]*" nil t))
1456 (goto-char (match-beginning 0))
1457 (setq boundaries (bibtex-parse-string)))
1458 boundaries))))
1459
1460(defun bibtex-reference-key-in-string (bounds)
1461 (buffer-substring-no-properties (nth 1 (car bounds))
1462 (nth 2 (car bounds))))
1463
1464(defun bibtex-text-in-string (bounds &optional remove-delim)
1465 "Get content of text in BibTeX string field defined via BOUNDS.
1466If optional arg REMOVE-DELIM is non-nil remove enclosing field
1467delimiters if present."
1468 (let ((content (buffer-substring-no-properties (nth 0 (cdr bounds))
1469 (nth 1 (cdr bounds)))))
02c8032e
SM
1470 (if remove-delim
1471 (bibtex-remove-delimiters-string content)
7fbf4804 1472 content)))
f9bd4abe 1473
d715b065 1474(defsubst bibtex-start-of-text-in-string (bounds)
7fbf4804 1475 (nth 0 (cdr bounds)))
d715b065 1476(defsubst bibtex-end-of-text-in-string (bounds)
7fbf4804 1477 (nth 1 (cdr bounds)))
d715b065 1478(defsubst bibtex-end-of-string (bounds)
7fbf4804 1479 (nth 2 (cdr bounds)))
745bc783 1480
d715b065 1481(defsubst bibtex-type-in-head ()
7fbf4804
SM
1482 "Extract BibTeX type in head."
1483 ;; ignore @
1484 (buffer-substring-no-properties (1+ (match-beginning bibtex-type-in-head))
1485 (match-end bibtex-type-in-head)))
31bc4210 1486
e0dc0c55 1487(defsubst bibtex-key-in-head (&optional empty)
a9d77f1f 1488 "Extract BibTeX key in head. Return optional arg EMPTY if key is empty."
e0dc0c55
SM
1489 (or (match-string-no-properties bibtex-key-in-head)
1490 empty))
f9bd4abe 1491
5c69dbfc 1492;; Helper Functions
e5167999 1493
d10e87a2
SM
1494(defun bibtex-remove-delimiters-string (str)
1495 "Remove delimiters of string STR."
1496 (if (and (memq (aref str 0) '(?\{ ?\"))
1497 (memq (aref str (1- (length str))) '(?\} ?\")))
1498 (substring str 1 -1)
1499 str))
1500
d528bff7 1501(defsubst bibtex-string= (str1 str2)
a9d77f1f 1502 "Return t if STR1 and STR2 are equal, ignoring case."
d528bff7
SM
1503 (eq t (compare-strings str1 0 nil str2 0 nil t)))
1504
55fe21fc 1505(defun bibtex-delete-whitespace ()
7fbf4804 1506 "Delete all whitespace starting at point."
50e4b39e
RS
1507 (if (looking-at "[ \t\n]+")
1508 (delete-region (point) (match-end 0))))
1509
55fe21fc 1510(defun bibtex-current-line ()
7fbf4804 1511 "Compute line number of point regardless whether the buffer is narrowed."
50e4b39e 1512 (+ (count-lines 1 (point))
e0dc0c55 1513 (if (bolp) 1 0)))
50e4b39e 1514
55fe21fc 1515(defun bibtex-skip-to-valid-entry (&optional backward)
a9d77f1f
SM
1516 "Move point to beginning of the next valid BibTeX entry.
1517Do not move if we are already at beginning of a valid BibTeX entry.
1518With optional argument BACKWARD non-nil, move backward to
1519beginning of previous valid one. A valid entry is a syntactical correct one
7fbf4804
SM
1520with type contained in `bibtex-entry-field-alist' or, if
1521`bibtex-sort-ignore-string-entries' is nil, a syntactical correct string
a9d77f1f 1522entry. Return buffer position of beginning and ending of entry if a valid
d715b065
KG
1523entry is found, nil otherwise."
1524 (interactive "P")
7fbf4804
SM
1525 (let ((case-fold-search t)
1526 found)
d715b065
KG
1527 (while (not (or found (if backward (bobp) (eobp))))
1528 (let ((pnt (point))
1529 bounds)
7fbf4804 1530 (cond ((or (and (looking-at bibtex-valid-entry-re)
d715b065 1531 (setq found (bibtex-search-entry nil nil t))
7fbf4804
SM
1532 (equal (match-beginning 0) pnt))
1533 (and (not bibtex-sort-ignore-string-entries)
d715b065
KG
1534 (setq bounds (bibtex-parse-string))
1535 (setq found (cons (bibtex-start-of-field bounds)
1536 (bibtex-end-of-string bounds)))))
7fbf4804
SM
1537 (goto-char pnt))
1538 (backward
7fbf4804
SM
1539 (if (re-search-backward "^[ \t]*\\(@\\)" nil 'move)
1540 (goto-char (match-beginning 1))))
d715b065 1541 (t (if (re-search-forward "\n[ \t]*@" nil 'move)
7fbf4804
SM
1542 (forward-char -1))))))
1543 found))
9ae11a89 1544
55fe21fc 1545(defun bibtex-map-entries (fun)
e0dc0c55
SM
1546 "Call FUN for each BibTeX entry in buffer (possibly narrowed).
1547FUN is called with three arguments, the key of the entry and the buffer
1548positions (marker) of beginning and end of entry. Point is inside the entry.
d10e87a2 1549If `bibtex-sort-ignore-string-entries' is non-nil, FUN is not called for
e0dc0c55 1550@String entries."
7fbf4804 1551 (let ((case-fold-search t))
e0dc0c55
SM
1552 (save-excursion
1553 (goto-char (point-min))
1554 (while (re-search-forward bibtex-entry-head nil t)
1555 (let ((entry-type (bibtex-type-in-head))
1556 (key (bibtex-key-in-head ""))
1557 (beg (copy-marker (match-beginning 0)))
1558 (end (copy-marker (save-excursion (bibtex-end-of-entry)))))
1559 (save-excursion
1560 (if (or (and (not bibtex-sort-ignore-string-entries)
1561 (bibtex-string= entry-type "string"))
1562 (assoc-string entry-type bibtex-entry-field-alist t))
1563 (funcall fun key beg end)))
1564 (goto-char end))))))
50e4b39e
RS
1565
1566(defun bibtex-progress-message (&optional flag interval)
7fbf4804
SM
1567 "Echo a message about progress of current buffer.
1568If FLAG is a string, the message is initialized (in this case a
1569value for INTERVAL may be given as well (if not this is set to 5)).
02c8032e 1570If FLAG is `done', the message is deinitialized.
8bf38a9b
SM
1571If FLAG is nil, a message is echoed if point was incremented at least
1572`bibtex-progress-interval' percent since last message was echoed."
7fbf4804 1573 (cond ((stringp flag)
02c8032e
SM
1574 (setq bibtex-progress-lastmes flag
1575 bibtex-progress-interval (or interval 5)
7fbf4804 1576 bibtex-progress-lastperc 0))
02c8032e 1577 ((eq flag 'done)
7fbf4804
SM
1578 (message "%s (done)" bibtex-progress-lastmes)
1579 (setq bibtex-progress-lastmes nil))
1580 (t
1581 (let* ((size (- (point-max) (point-min)))
1582 (perc (if (= size 0)
1583 100
1584 (/ (* 100 (- (point) (point-min))) size))))
1585 (when (>= perc (+ bibtex-progress-lastperc
1586 bibtex-progress-interval))
1587 (setq bibtex-progress-lastperc perc)
1588 (message "%s (%d%%)" bibtex-progress-lastmes perc))))))
50e4b39e
RS
1589
1590(defun bibtex-field-left-delimiter ()
7fbf4804 1591 "Return a string dependent on `bibtex-field-delimiters'."
02c8032e 1592 (if (eq bibtex-field-delimiters 'braces)
50e4b39e
RS
1593 "{"
1594 "\""))
1595
1596(defun bibtex-field-right-delimiter ()
7fbf4804 1597 "Return a string dependent on `bibtex-field-delimiters'."
02c8032e 1598 (if (eq bibtex-field-delimiters 'braces)
50e4b39e
RS
1599 "}"
1600 "\""))
1601
1602(defun bibtex-entry-left-delimiter ()
e0dc0c55 1603 "Return a string dependent on `bibtex-entry-delimiters'."
02c8032e 1604 (if (eq bibtex-entry-delimiters 'braces)
50e4b39e
RS
1605 "{"
1606 "("))
1607
1608(defun bibtex-entry-right-delimiter ()
e0dc0c55 1609 "Return a string dependent on `bibtex-entry-delimiters'."
02c8032e 1610 (if (eq bibtex-entry-delimiters 'braces)
50e4b39e
RS
1611 "}"
1612 ")"))
1613
7fbf4804 1614(defun bibtex-search-entry (empty-head &optional bound noerror backward)
d715b065 1615 "Search for a BibTeX entry (maybe without reference key if EMPTY-HEAD is t).
a9d77f1f 1616BOUND and NOERROR are exactly as in `re-search-forward'. If BACKWARD
02c8032e
SM
1617is non-nil, search in reverse direction. Move point past the closing
1618delimiter (at the beginning of entry if BACKWARD is non-nil).
d715b065
KG
1619Return a cons pair with buffer positions of beginning and end of entry.
1620After call to this function MATCH-BEGINNING and MATCH-END functions
1621are defined, but only for the head part of the entry
1622\(especially (match-end 0) just gives the end of the head part)."
50e4b39e 1623 (let ((pnt (point))
d715b065
KG
1624 (entry-head-re (if empty-head
1625 bibtex-entry-maybe-empty-head
1626 bibtex-entry-head)))
50e4b39e
RS
1627 (if backward
1628 (let (found)
1629 (while (and (not found)
d715b065 1630 (re-search-backward entry-head-re bound noerror))
f9bd4abe 1631 (setq found (bibtex-search-entry empty-head pnt t)))
50e4b39e 1632 (if found
d715b065
KG
1633 (progn (goto-char (match-beginning 0))
1634 found)
d528bff7 1635 (cond ((not noerror)
7fbf4804 1636 ;; yell
d715b065 1637 (error "Backward search of BibTeX entry failed"))
02c8032e 1638 ((eq noerror t)
7fbf4804
SM
1639 ;; don't move
1640 (goto-char pnt)))
50e4b39e 1641 nil))
02c8032e
SM
1642 (let (found)
1643 (unless bound (setq bound (point-max)))
50e4b39e 1644 (while (and (not found)
d715b065 1645 (re-search-forward entry-head-re bound noerror))
7fbf4804
SM
1646 (save-match-data
1647 (let ((entry-closer
1648 (if (save-excursion
1649 (goto-char (match-end bibtex-type-in-head))
1650 (looking-at "[ \t]*("))
1651 ;; entry opened with parenthesis
1652 ?\)
1653 ?\}))
1654 (infix-start (point))
1655 finished bounds)
1656 (while (not finished)
02c8032e 1657 (skip-chars-forward " \t\n" bound)
7fbf4804 1658 (if (and (setq bounds (bibtex-parse-field bibtex-field-name))
02c8032e 1659 (<= (bibtex-end-of-field bounds) bound))
7fbf4804
SM
1660 (setq infix-start (bibtex-end-of-field bounds))
1661 (setq finished t))
1662 (goto-char infix-start))
e0dc0c55 1663 ;; This matches the infix* part. The AND construction assures
7fbf4804
SM
1664 ;; that BOUND is respected.
1665 (when (and (looking-at bibtex-entry-postfix)
1666 (eq (char-before (match-end 0)) entry-closer)
02c8032e 1667 (<= (match-end 0) bound))
7fbf4804
SM
1668 (goto-char (match-end 0))
1669 (setq found t)))))
50e4b39e 1670 (if found
d715b065 1671 (cons (match-beginning 0) (point))
7fbf4804
SM
1672 (cond ((not noerror)
1673 ;; yell
1674 (error "Search of BibTeX entry failed"))
02c8032e 1675 ((eq noerror t)
7fbf4804
SM
1676 ;; don't move
1677 (goto-char pnt)))
50e4b39e 1678 nil)))))
e5167999 1679
cb4ad359 1680(defun bibtex-flash-head ()
7fbf4804
SM
1681 "Flash at BibTeX entry head before point, if exists."
1682 (let ((case-fold-search t)
1683 flash)
f9bd4abe 1684 (cond ((re-search-backward bibtex-entry-head nil t)
7fbf4804
SM
1685 (goto-char (match-beginning bibtex-type-in-head))
1686 (setq flash (match-end bibtex-key-in-head)))
1687 (t
1688 (end-of-line)
1689 (skip-chars-backward " \t")
1690 (setq flash (point))
1691 (beginning-of-line)
1692 (skip-chars-forward " \t")))
cb4ad359 1693 (if (pos-visible-in-window-p (point))
7fbf4804 1694 (sit-for 1)
cb4ad359 1695 (message "From: %s"
7fbf4804 1696 (buffer-substring (point) flash)))))
e5167999 1697
d715b065
KG
1698(defun bibtex-make-optional-field (field)
1699 "Make an optional field named FIELD in current BibTeX entry."
1700 (if (consp field)
1701 (bibtex-make-field (cons (concat "OPT" (car field)) (cdr field)))
1702 (bibtex-make-field (concat "OPT" field))))
50e4b39e 1703
cb4ad359 1704(defun bibtex-move-outside-of-entry ()
7fbf4804 1705 "Make sure point is outside of a BibTeX entry."
f0cb6034 1706 (let ((orig-point (point)))
28f2ee66 1707 (bibtex-end-of-entry)
0640e91a 1708 (when (< (point) orig-point)
7fbf4804
SM
1709 ;; We moved backward, so we weren't inside an entry to begin with.
1710 ;; Leave point at the beginning of a line, and preferably
1711 ;; at the beginning of a paragraph.
1712 (goto-char orig-point)
1713 (beginning-of-line 1)
0640e91a
RS
1714 (unless (= ?\n (char-before (1- (point))))
1715 (re-search-forward "^[ \t]*[@\n]" nil 'move)
1716 (backward-char 1)))
f0cb6034 1717 (skip-chars-forward " \t\n")))
50e4b39e
RS
1718
1719(defun bibtex-beginning-of-first-entry ()
a9d77f1f 1720 "Go to the beginning of the first BibTeX entry in buffer. Return point."
e5167999 1721 (goto-char (point-min))
50e4b39e
RS
1722 (if (re-search-forward "^[ \t]*@" nil 'move)
1723 (beginning-of-line))
1724 (point))
1725
1726(defun bibtex-beginning-of-last-entry ()
7fbf4804 1727 "Go to the beginning of the last BibTeX entry in buffer."
50e4b39e
RS
1728 (goto-char (point-max))
1729 (if (re-search-backward "^[ \t]*@" nil 'move)
1730 (beginning-of-line))
1731 (point))
e5167999 1732
cb4ad359 1733(defun bibtex-inside-field ()
7fbf4804 1734 "Try to avoid point being at end of a BibTeX field."
cb4ad359 1735 (end-of-line)
0640d7bf 1736 (skip-chars-backward " \t")
8bf38a9b
SM
1737 (if (= (preceding-char) ?,)
1738 (forward-char -2))
1739 (if (or (= (preceding-char) ?})
1740 (= (preceding-char) ?\"))
1741 (forward-char -1)))
9ae11a89 1742
50e4b39e 1743(defun bibtex-enclosing-field (&optional noerr)
d528bff7 1744 "Search for BibTeX field enclosing point.
02c8032e
SM
1745Unless NOERR is non-nil, signal an error if no enclosing field is found.
1746On success return bounds, nil otherwise. Do not move point."
d715b065 1747 (let ((bounds (bibtex-search-backward-field bibtex-field-name t)))
7fbf4804 1748 (if (and bounds
d715b065
KG
1749 (<= (bibtex-start-of-field bounds) (point))
1750 (>= (bibtex-end-of-field bounds) (point)))
7fbf4804
SM
1751 bounds
1752 (unless noerr
1753 (error "Can't find enclosing BibTeX field")))))
f9bd4abe
GM
1754
1755(defun bibtex-enclosing-entry-maybe-empty-head ()
a9d77f1f 1756 "Search for BibTeX entry enclosing point. Move point to end of entry.
7fbf4804
SM
1757Beginning (but not end) of entry is given by (`match-beginning' 0)."
1758 (let ((case-fold-search t)
1759 (old-point (point)))
1760 (unless (re-search-backward bibtex-entry-maybe-empty-head nil t)
d715b065
KG
1761 (goto-char old-point)
1762 (error "Can't find beginning of enclosing BibTeX entry"))
0640d7bf 1763 (goto-char (match-beginning bibtex-type-in-head))
7fbf4804 1764 (unless (bibtex-search-entry t nil t)
d715b065
KG
1765 (goto-char old-point)
1766 (error "Can't find end of enclosing BibTeX entry"))))
50e4b39e 1767
02c8032e
SM
1768(defun bibtex-insert-kill (n)
1769 "Reinsert the Nth stretch of killed BibTeX text."
50e4b39e 1770 (if (not bibtex-last-kill-command)
f0cb6034 1771 (error "BibTeX kill ring is empty")
02c8032e 1772 (let* ((kr (if (eq bibtex-last-kill-command 'field)
50e4b39e
RS
1773 'bibtex-field-kill-ring
1774 'bibtex-entry-kill-ring))
02c8032e 1775 (kryp (if (eq bibtex-last-kill-command 'field)
50e4b39e
RS
1776 'bibtex-field-kill-ring-yank-pointer
1777 'bibtex-entry-kill-ring-yank-pointer))
02c8032e
SM
1778 (current (car (set kryp (nthcdr (mod (- n (length (eval kryp)))
1779 (length (eval kr)))
1780 (eval kr))))))
1781 (if (eq bibtex-last-kill-command 'field)
1782 (let (bibtex-help-message)
1783 (bibtex-find-text)
1784 (if (looking-at "[}\"]")
1785 (forward-char))
1786 (set-mark (point))
1787 (message "Mark set")
1788 (bibtex-make-field current t))
d528bff7 1789 (unless (eobp) (bibtex-beginning-of-entry))
50e4b39e
RS
1790 (set-mark (point))
1791 (message "Mark set")
02c8032e 1792 (insert current)))))
f9bd4abe 1793
50e4b39e 1794(defun bibtex-format-entry ()
7fbf4804
SM
1795 "Helper function for `bibtex-clean-entry'.
1796Formats current entry according to variable `bibtex-entry-format'."
1797 (save-excursion
1798 (save-restriction
1799 (bibtex-narrow-to-entry)
1800 (let ((case-fold-search t)
02c8032e 1801 (format (if (eq bibtex-entry-format t)
7fbf4804
SM
1802 '(realign opts-or-alts required-fields
1803 numerical-fields
1804 last-comma page-dashes delimiters
1805 unify-case inherit-booktitle)
1806 bibtex-entry-format))
1807 crossref-key bounds alternatives-there non-empty-alternative
d528bff7 1808 entry-list req-field-list field-list)
7fbf4804
SM
1809
1810 ;; identify entry type
1811 (goto-char (point-min))
1812 (re-search-forward bibtex-entry-type)
1813 (let ((beg-type (1+ (match-beginning 0)))
1814 (end-type (match-end 0)))
c2fb6415
RS
1815 (setq entry-list (assoc-string (buffer-substring-no-properties
1816 beg-type end-type)
1817 bibtex-entry-field-alist
1818 t))
7fbf4804
SM
1819
1820 ;; unify case of entry name
1821 (when (memq 'unify-case format)
1822 (delete-region beg-type end-type)
1823 (insert (car entry-list)))
1824
1825 ;; update left entry delimiter
1826 (when (memq 'delimiters format)
1827 (goto-char end-type)
1828 (skip-chars-forward " \t\n")
1829 (delete-char 1)
1830 (insert (bibtex-entry-left-delimiter))))
1831
1832 ;; determine if entry has crossref field and if at least
1833 ;; one alternative is non-empty
1834 (goto-char (point-min))
8bf38a9b 1835 (let* ((fields-alist (bibtex-parse-entry))
d528bff7 1836 (field (assoc-string "crossref" fields-alist t)))
8bf38a9b
SM
1837 (setq crossref-key (and field
1838 (not (string-match bibtex-empty-field-re
1839 (cdr field)))
02c8032e 1840 (bibtex-remove-delimiters-string (cdr field)))
8bf38a9b 1841 req-field-list (if crossref-key
e0dc0c55
SM
1842 (nth 0 (nth 2 entry-list)) ; crossref part
1843 (nth 0 (nth 1 entry-list)))) ; required part
8bf38a9b
SM
1844
1845 (dolist (rfield req-field-list)
1846 (when (nth 3 rfield) ; we should have an alternative
1847 (setq alternatives-there t
d528bff7 1848 field (assoc-string (car rfield) fields-alist t))
8bf38a9b
SM
1849 (if (and field
1850 (not (string-match bibtex-empty-field-re
1851 (cdr field))))
1852 (cond ((not non-empty-alternative)
1853 (setq non-empty-alternative t))
1854 ((memq 'required-fields format)
02c8032e 1855 (error "More than one non-empty alternative")))))))
8bf38a9b 1856
50e4b39e 1857 (if (and alternatives-there
7fbf4804
SM
1858 (not non-empty-alternative)
1859 (memq 'required-fields format))
1860 (error "All alternatives are empty"))
1861
1862 ;; process all fields
1863 (goto-char (point-min))
1864 (while (setq bounds (bibtex-search-forward-field bibtex-field-name))
1865 (let* ((beg-field (copy-marker (bibtex-start-of-field bounds)))
02c8032e 1866 (end-field (copy-marker (bibtex-end-of-field bounds) t))
7fbf4804
SM
1867 (beg-name (copy-marker (bibtex-start-of-name-in-field bounds)))
1868 (end-name (copy-marker (bibtex-end-of-name-in-field bounds)))
1869 (beg-text (copy-marker (bibtex-start-of-text-in-field bounds)))
02c8032e 1870 (end-text (copy-marker (bibtex-end-of-text-in-field bounds) t))
7fbf4804 1871 (opt-alt (string-match "OPT\\|ALT"
02c8032e
SM
1872 (buffer-substring-no-properties
1873 beg-name (+ beg-name 3))))
7fbf4804
SM
1874 (field-name (buffer-substring-no-properties
1875 (if opt-alt (+ beg-name 3) beg-name) end-name))
1876 (empty-field (string-match bibtex-empty-field-re
02c8032e
SM
1877 (buffer-substring-no-properties
1878 beg-field end-field)))
7fbf4804
SM
1879 deleted)
1880
1881 ;; We have more elegant high-level functions for several
e0dc0c55 1882 ;; tasks done by bibtex-format-entry. However, they contain
7fbf4804 1883 ;; quite some redundancy compared with what we need to do
e0dc0c55 1884 ;; anyway. So for speed-up we avoid using them.
7fbf4804 1885
8bf38a9b
SM
1886 (if (memq 'opts-or-alts format)
1887 (cond ((and empty-field
1888 (or opt-alt
c2fb6415
RS
1889 (let ((field (assoc-string
1890 field-name req-field-list t)))
8bf38a9b
SM
1891 (or (not field) ; OPT field
1892 (nth 3 field))))) ; ALT field
e0dc0c55
SM
1893 ;; Either it is an empty ALT field. Then we have checked
1894 ;; already that we have one non-empty alternative. Or it
8bf38a9b
SM
1895 ;; is an empty OPT field that we do not miss anyway.
1896 ;; So we can safely delete this field.
1897 (delete-region beg-field end-field)
1898 (setq deleted t))
1899 ;; otherwise: not empty, delete "OPT" or "ALT"
1900 (opt-alt
1901 (goto-char beg-name)
1902 (delete-char 3))))
7fbf4804
SM
1903
1904 (unless deleted
1905 (push field-name field-list)
1906
1907 ;; remove delimiters from purely numerical fields
1908 (when (and (memq 'numerical-fields format)
1909 (progn (goto-char beg-text)
1910 (looking-at "\\(\"[0-9]+\"\\)\\|\\({[0-9]+}\\)")))
1911 (goto-char end-text)
1912 (delete-char -1)
1913 (goto-char beg-text)
1914 (delete-char 1))
1915
1916 ;; update delimiters
1917 (when (memq 'delimiters format)
1918 (goto-char beg-text)
1919 (when (looking-at "[{\"]")
1920 (delete-char 1)
1921 (insert (bibtex-field-left-delimiter)))
1922 (goto-char (1- (marker-position end-text)))
1923 (when (looking-at "[}\"]")
1924 (delete-char 1)
1925 (insert (bibtex-field-right-delimiter))))
1926
1927 ;; update page dashes
1928 (if (and (memq 'page-dashes format)
d528bff7 1929 (bibtex-string= field-name "pages")
7fbf4804
SM
1930 (progn (goto-char beg-text)
1931 (looking-at
1932 "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)")))
1933 (replace-match "\\1-\\2"))
1934
d715b065 1935 ;; use book title of crossref'd entry
7fbf4804 1936 (if (and (memq 'inherit-booktitle format)
7fbf4804 1937 empty-field
d528bff7 1938 (bibtex-string= field-name "booktitle")
7fbf4804 1939 crossref-key)
02c8032e
SM
1940 (let ((title (save-excursion
1941 (save-restriction
1942 (widen)
1943 (if (bibtex-find-entry crossref-key t)
1944 (bibtex-text-in-field "title"))))))
7fbf4804
SM
1945 (when title
1946 (setq empty-field nil)
1947 (goto-char (1+ beg-text))
1948 (insert title))))
1949
d715b065
KG
1950 ;; Use booktitle to set a missing title.
1951 (if (and empty-field
d528bff7 1952 (bibtex-string= field-name "title"))
d715b065
KG
1953 (let ((booktitle (bibtex-text-in-field "booktitle")))
1954 (when booktitle
1955 (setq empty-field nil)
1956 (goto-char (1+ beg-text))
1957 (insert booktitle))))
7fbf4804
SM
1958
1959 ;; if empty field, complain
1960 (if (and empty-field
1961 (memq 'required-fields format)
c2fb6415 1962 (assoc-string field-name req-field-list t))
7fbf4804
SM
1963 (error "Mandatory field `%s' is empty" field-name))
1964
1965 ;; unify case of field name
1966 (if (memq 'unify-case format)
c2fb6415
RS
1967 (let ((fname (car (assoc-string
1968 field-name
1969 (append (nth 0 (nth 1 entry-list))
1970 (nth 1 (nth 1 entry-list))
1971 bibtex-user-optional-fields)
1972 t))))
7fbf4804
SM
1973 (if fname
1974 (progn
1975 (delete-region beg-name end-name)
1976 (goto-char beg-name)
1977 (insert fname))
1978 ;; there are no rules we could follow
1979 (downcase-region beg-name end-name))))
1980
1981 ;; update point
1982 (goto-char end-field))))
1983
1984 ;; check whether all required fields are present
1985 (if (memq 'required-fields format)
8bf38a9b
SM
1986 (let ((found 0) altlist)
1987 (dolist (fname req-field-list)
7fbf4804
SM
1988 (if (nth 3 fname)
1989 (push (car fname) altlist))
1990 (unless (or (member (car fname) field-list)
1991 (nth 3 fname))
1992 (error "Mandatory field `%s' is missing" (car fname))))
1993 (when altlist
1994 (dolist (fname altlist)
1995 (if (member fname field-list)
1996 (setq found (1+ found))))
1997 (cond ((= found 0)
1998 (error "Alternative mandatory field `%s' is missing"
1999 altlist))
2000 ((> found 1)
8bf38a9b 2001 (error "Alternative fields `%s' are defined %s times"
7fbf4804
SM
2002 altlist found))))))
2003
2004 ;; update point
2005 (if (looking-at (bibtex-field-right-delimiter))
2006 (forward-char))
2007
2008 ;; update comma after last field
2009 (if (memq 'last-comma format)
2010 (cond ((and bibtex-comma-after-last-field
2011 (not (looking-at ",")))
2012 (insert ","))
2013 ((and (not bibtex-comma-after-last-field)
2014 (looking-at ","))
2015 (delete-char 1))))
2016
2017 ;; update right entry delimiter
2018 (if (looking-at ",")
2019 (forward-char))
2020 (when (memq 'delimiters format)
2021 (skip-chars-forward " \t\n")
2022 (delete-char 1)
2023 (insert (bibtex-entry-right-delimiter)))
2024
2025 ;; fill entry
2026 (if (memq 'realign format)
2027 (bibtex-fill-entry))))))
cb4ad359 2028
7fbf4804 2029\f
cb4ad359 2030(defun bibtex-autokey-abbrev (string len)
7fbf4804
SM
2031 "Return an abbreviation of STRING with at least LEN characters.
2032If LEN is positive the abbreviation is terminated only after a consonant
a9d77f1f
SM
2033or at the word end. If LEN is negative the abbreviation is strictly
2034enforced using abs (LEN) characters. If LEN is not a number, STRING
7fbf4804
SM
2035is returned unchanged."
2036 (cond ((or (not (numberp len))
2037 (<= (length string) (abs len)))
50e4b39e
RS
2038 string)
2039 ((equal len 0)
2040 "")
7fbf4804
SM
2041 ((< len 0)
2042 (substring string 0 (abs len)))
2043 (t (let* ((case-fold-search t)
2044 (abort-char (string-match "[^aeiou]" string (1- len))))
2045 (if abort-char
2046 (substring string 0 (1+ abort-char))
2047 string)))))
2048
2049(defun bibtex-autokey-get-field (field &optional change-list)
a9d77f1f 2050 "Get content of BibTeX field FIELD. Return empty string if not found.
7fbf4804 2051Optional arg CHANGE-LIST is a list of substitution patterns that is
a9d77f1f 2052applied to the content of FIELD. It is an alist with pairs
7fbf4804
SM
2053\(OLD-REGEXP . NEW-STRING\)."
2054 (let ((content (bibtex-text-in-field field bibtex-autokey-use-crossref))
2055 case-fold-search)
2056 (unless content (setq content ""))
2057 (dolist (pattern change-list content)
2058 (setq content (replace-regexp-in-string (car pattern)
2059 (cdr pattern)
e0dc0c55 2060 content t)))))
7fbf4804
SM
2061
2062(defun bibtex-autokey-get-names ()
2063 "Get contents of the name field of the current entry.
e0dc0c55
SM
2064Do some modifications based on `bibtex-autokey-name-change-strings'.
2065Return the names as a concatenated string obeying `bibtex-autokey-names'
2066and `bibtex-autokey-names-stretch'."
2067 (let ((names (bibtex-autokey-get-field "author\\|editor"
d528bff7
SM
2068 bibtex-autokey-name-change-strings)))
2069 ;; Some entries do not have a name field.
02c8032e
SM
2070 (if (string= "" names)
2071 names
e0dc0c55
SM
2072 (let* ((case-fold-search t)
2073 (name-list (mapcar 'bibtex-autokey-demangle-name
2074 (split-string names "[ \t\n]+and[ \t\n]+")))
2075 additional-names)
2076 (unless (or (not (numberp bibtex-autokey-names))
2077 (<= (length name-list)
2078 (+ bibtex-autokey-names
2079 bibtex-autokey-names-stretch)))
2080 ;; Take bibtex-autokey-names elements from beginning of name-list
2081 (setq name-list (nreverse (nthcdr (- (length name-list)
2082 bibtex-autokey-names)
2083 (nreverse name-list)))
2084 additional-names bibtex-autokey-additional-names))
2085 (concat (mapconcat 'identity name-list
2086 bibtex-autokey-name-separator)
2087 additional-names)))))
50e4b39e
RS
2088
2089(defun bibtex-autokey-demangle-name (fullname)
a9d77f1f 2090 "Get the last part from a well-formed FULLNAME and perform abbreviations."
f9bd4abe 2091 (let* (case-fold-search
7fbf4804
SM
2092 (name (cond ((string-match "\\([A-Z][^, ]*\\)[^,]*," fullname)
2093 ;; Name is of the form "von Last, First" or
2094 ;; "von Last, Jr, First"
2095 ;; --> Take the first capital part before the comma
dd310c45 2096 (match-string 1 fullname))
7fbf4804
SM
2097 ((string-match "\\([^, ]*\\)," fullname)
2098 ;; Strange name: we have a comma, but nothing capital
2099 ;; So we accept even lowercase names
dd310c45
SM
2100 (match-string 1 fullname))
2101 ((string-match "\\(\\<[a-z][^ ]* +\\)+\\([A-Z][^ ]*\\)"
7fbf4804
SM
2102 fullname)
2103 ;; name is of the form "First von Last", "von Last",
2104 ;; "First von von Last", or "d'Last"
2105 ;; --> take the first capital part after the "von" parts
dd310c45
SM
2106 (match-string 2 fullname))
2107 ((string-match "\\([^ ]+\\) *\\'" fullname)
7fbf4804
SM
2108 ;; name is of the form "First Middle Last" or "Last"
2109 ;; --> take the last token
dd310c45 2110 (match-string 1 fullname))
7fbf4804 2111 (t (error "Name `%s' is incorrectly formed" fullname)))))
02c8032e
SM
2112 (funcall bibtex-autokey-name-case-convert
2113 (bibtex-autokey-abbrev name bibtex-autokey-name-length))))
7fbf4804 2114
e0dc0c55
SM
2115(defun bibtex-autokey-get-year ()
2116 "Return year field contents as a string obeying `bibtex-autokey-year-length'."
2117 (let ((yearfield (bibtex-autokey-get-field "year")))
2118 (substring yearfield (max 0 (- (length yearfield)
2119 bibtex-autokey-year-length)))))
2120
7fbf4804 2121(defun bibtex-autokey-get-title ()
e0dc0c55
SM
2122 "Get title field contents up to a terminator.
2123Return the result as a string"
d528bff7
SM
2124 (let ((case-fold-search t)
2125 (titlestring
7fbf4804
SM
2126 (bibtex-autokey-get-field "title"
2127 bibtex-autokey-titleword-change-strings)))
2128 ;; ignore everything past a terminator
02c8032e
SM
2129 (if (string-match bibtex-autokey-title-terminators titlestring)
2130 (setq titlestring (substring titlestring 0 (match-beginning 0))))
e0dc0c55 2131 ;; gather words from titlestring into a list. Ignore
7fbf4804 2132 ;; specific words and use only a specific amount of words.
8bf38a9b 2133 (let ((counter 0)
e0dc0c55 2134 titlewords titlewords-extra word)
7fbf4804
SM
2135 (while (and (or (not (numberp bibtex-autokey-titlewords))
2136 (< counter (+ bibtex-autokey-titlewords
2137 bibtex-autokey-titlewords-stretch)))
2138 (string-match "\\b\\w+" titlestring))
e0dc0c55
SM
2139 (setq word (match-string 0 titlestring)
2140 titlestring (substring titlestring (match-end 0)))
2141 ;; Ignore words matched by one of the elements of
2142 ;; bibtex-autokey-titleword-ignore
d528bff7
SM
2143 (unless (let ((lst bibtex-autokey-titleword-ignore))
2144 (while (and lst
2145 (not (string-match (concat "\\`\\(?:" (car lst)
e0dc0c55 2146 "\\)\\'") word)))
d528bff7
SM
2147 (setq lst (cdr lst)))
2148 lst)
02c8032e 2149 (setq counter (1+ counter))
7fbf4804 2150 (if (or (not (numberp bibtex-autokey-titlewords))
d10e87a2 2151 (<= counter bibtex-autokey-titlewords))
e0dc0c55
SM
2152 (push word titlewords)
2153 (push word titlewords-extra))))
2154 ;; Obey bibtex-autokey-titlewords-stretch:
2155 ;; If by now we have processed all words in titlestring, we include
2156 ;; titlewords-extra in titlewords. Otherwise, we ignore titlewords-extra.
7fbf4804 2157 (unless (string-match "\\b\\w+" titlestring)
e0dc0c55
SM
2158 (setq titlewords (append titlewords-extra titlewords)))
2159 (mapconcat 'bibtex-autokey-demangle-title (nreverse titlewords)
2160 bibtex-autokey-titleword-separator))))
7fbf4804
SM
2161
2162(defun bibtex-autokey-demangle-title (titleword)
2163 "Do some abbreviations on TITLEWORD.
2164The rules are defined in `bibtex-autokey-titleword-abbrevs'
2165and `bibtex-autokey-titleword-length'."
d528bff7 2166 (let ((case-fold-search t)
8bf38a9b
SM
2167 (alist bibtex-autokey-titleword-abbrevs))
2168 (while (and alist
2169 (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'")
2170 titleword)))
2171 (setq alist (cdr alist)))
2172 (if alist
2173 (cdar alist)
02c8032e
SM
2174 (funcall bibtex-autokey-titleword-case-convert
2175 (bibtex-autokey-abbrev titleword bibtex-autokey-titleword-length)))))
cb4ad359
RS
2176
2177(defun bibtex-generate-autokey ()
02c8032e
SM
2178 "Generate automatically a key for a BibTeX entry.
2179Use the author/editor, the year and the title field.
2180The algorithm works as follows.
2181
2182The name part:
2183 1. Use the author or editor field to generate the name part of the key.
2184 2. Change the content of the name field according to
2185 `bibtex-autokey-name-change-strings' (see there for further detail).
2186 3. Use the first `bibtex-autokey-names' names in the name field. If there
2187 are up to `bibtex-autokey-names' + `bibtex-autokey-names-stretch' names,
2188 use all names.
2189 4. Use only the last names to form the name part. From these last names,
2190 take at least `bibtex-autokey-name-length' characters (truncate only
2191 after a consonant or at a word end).
2192 5. Convert all last names using the function
ab2d0cdb 2193 `bibtex-autokey-name-case-convert'.
02c8032e
SM
2194 6. Build the name part of the key by concatenating all abbreviated last
2195 names with the string `bibtex-autokey-name-separator' between any two.
2196 If there are more names in the name field than names used in the name
2197 part, append the string `bibtex-autokey-additional-names'.
2198
2199The year part:
2200 1. Build the year part of the key by truncating the content of the year
2201 field to the rightmost `bibtex-autokey-year-length' digits (useful
2202 values are 2 and 4).
2203 2. If the year field (or any other field required to generate the key)
2204 is absent, but the entry has a valid crossref field and
7fbf4804
SM
2205 `bibtex-autokey-use-crossref' is non-nil, use the field of the
2206 crossreferenced entry instead.
02c8032e
SM
2207
2208The title part
2209 1. Change the content of the title field according to
2210 `bibtex-autokey-titleword-change-strings' (see there for further detail).
2211 2. Truncate the title before the first match of
2212 `bibtex-autokey-title-terminators' and delete those words which appear
2213 in `bibtex-autokey-titleword-ignore'. Build the title part using the
2214 first `bibtex-autokey-titlewords' words from this truncated title.
2215 If the truncated title ends after up to `bibtex-autokey-titlewords' +
2216 `bibtex-autokey-titlewords-stretch' words, use all words from the
2217 truncated title.
2218 3. For every title word that appears in `bibtex-autokey-titleword-abbrevs'
2219 use the corresponding abbreviation (see documentation of this variable
2220 for further detail).
2221 4. From every title word not generated by an abbreviation, take at least
2222 `bibtex-autokey-titleword-length' characters (truncate only after
2223 a consonant or at a word end).
2224 5. Convert all title words using the function
ab2d0cdb 2225 `bibtex-autokey-titleword-case-convert'.
02c8032e
SM
2226 6. Build the title part by concatenating all abbreviated title words with
2227 the string `bibtex-autokey-titleword-separator' between any two.
2228
2229Concatenate the key:
2230 1. Concatenate `bibtex-autokey-prefix-string', the name part, the year
2231 part and the title part. If the name part and the year part are both
2232 non-empty insert `bibtex-autokey-name-year-separator' between the two.
2233 If the title part and the year (or name) part are non-empty, insert
2234 `bibtex-autokey-year-title-separator' between the two.
2235 2. If `bibtex-autokey-before-presentation-function' is non-nil, it must be
2236 a function taking one argument. Call this function with the generated
2237 key as the argument. Use the return value of this function (a string)
2238 as the key.
2239 3. If `bibtex-autokey-edit-before-use' is non-nil, present the key in the
2240 minibuffer to the user for editing. Insert the key given by the user."
e0dc0c55
SM
2241 (let* ((names (bibtex-autokey-get-names))
2242 (year (bibtex-autokey-get-year))
2243 (title (bibtex-autokey-get-title))
7fbf4804 2244 (autokey (concat bibtex-autokey-prefix-string
e0dc0c55
SM
2245 names
2246 (unless (or (equal names "")
2247 (equal year ""))
7fbf4804 2248 bibtex-autokey-name-year-separator)
e0dc0c55
SM
2249 year
2250 (unless (or (and (equal names "")
2251 (equal year ""))
2252 (equal title ""))
7fbf4804 2253 bibtex-autokey-year-title-separator)
e0dc0c55 2254 title)))
ab2d0cdb 2255 (if bibtex-autokey-before-presentation-function
7fbf4804
SM
2256 (funcall bibtex-autokey-before-presentation-function autokey)
2257 autokey)))
e5167999 2258
7fbf4804 2259\f
02c8032e
SM
2260(defun bibtex-global-key-alist ()
2261 "Return global key alist based on `bibtex-files'."
2262 (if bibtex-files
2263 (apply 'append
2264 (mapcar (lambda (buf)
2265 (with-current-buffer buf bibtex-reference-keys))
2266 (bibtex-files-expand t)))
2267 bibtex-reference-keys))
2268
2269(defun bibtex-read-key (prompt &optional key global)
2270 "Read BibTeX key from minibuffer using PROMPT and default KEY.
2271If optional arg GLOBAL is non-nil, completion is based on the keys in
2272`bibtex-reference-keys' of `bibtex-files',"
2273 (let (completion-ignore-case)
2274 (completing-read prompt (if global (bibtex-global-key-alist)
2275 bibtex-reference-keys)
2276 nil nil key 'bibtex-key-history)))
2277
2278(defun bibtex-read-string-key (&optional key)
2279 "Read BibTeX string key from minibuffer using default KEY."
2280 (let ((completion-ignore-case t))
2281 (completing-read "String key: " bibtex-strings
2282 nil nil key 'bibtex-key-history)))
e0dc0c55
SM
2283
2284(defun bibtex-parse-keys (&optional abortable verbose)
7fbf4804 2285 "Set `bibtex-reference-keys' to the keys used in the whole buffer.
02c8032e
SM
2286Find both entry keys and crossref entries. If ABORTABLE is non-nil abort
2287on user input. If VERBOSE is non-nil give messages about progress.
2288Return alist of keys if parsing was completed, `aborted' otherwise."
e0dc0c55 2289 (let (ref-keys crossref-keys)
7fbf4804
SM
2290 (save-excursion
2291 (save-match-data
7fbf4804
SM
2292 (if verbose
2293 (bibtex-progress-message
2294 (concat (buffer-name) ": parsing reference keys")))
d715b065
KG
2295 (catch 'userkey
2296 (goto-char (point-min))
2297 (if bibtex-parse-keys-fast
2298 (let ((case-fold-search t)
2299 (re (concat bibtex-entry-head "\\|"
2300 ",[ \t\n]*crossref[ \t\n]*=[ \t\n]*"
2301 "\\(\"[^\"]*\"\\|{[^}]*}\\)[ \t\n]*[,})]")))
2302 (while (re-search-forward re nil t)
2303 (if (and abortable (input-pending-p))
2304 ;; user has aborted by typing a key --> return `aborted'
2305 (throw 'userkey 'aborted))
e0dc0c55
SM
2306 (cond ((match-end 3)
2307 ;; This is a crossref.
2308 (let ((key (buffer-substring-no-properties
2309 (1+ (match-beginning 3)) (1- (match-end 3)))))
2310 (unless (assoc key crossref-keys)
2311 (push (list key) crossref-keys))))
2312 ;; only keys of known entries
2313 ((assoc-string (bibtex-type-in-head)
2314 bibtex-entry-field-alist t)
2315 ;; This is an entry.
2316 (let ((key (bibtex-key-in-head)))
2317 (unless (assoc key ref-keys)
2318 (push (cons key t) ref-keys)))))))
d715b065
KG
2319
2320 (let (;; ignore @String entries because they are handled
2321 ;; separately by bibtex-parse-strings
2322 (bibtex-sort-ignore-string-entries t)
e0dc0c55 2323 bounds)
d715b065
KG
2324 (bibtex-map-entries
2325 (lambda (key beg end)
2326 (if (and abortable
2327 (input-pending-p))
2328 ;; user has aborted by typing a key --> return `aborted'
2329 (throw 'userkey 'aborted))
2330 (if verbose (bibtex-progress-message))
e0dc0c55
SM
2331 (unless (assoc key ref-keys)
2332 (push (cons key t) ref-keys))
d715b065 2333 (if (and (setq bounds (bibtex-search-forward-field "crossref" end))
e0dc0c55
SM
2334 (setq key (bibtex-text-in-field-bounds bounds t))
2335 (not (assoc key crossref-keys)))
2336 (push (list key) crossref-keys))))))
d715b065 2337
e0dc0c55
SM
2338 (dolist (key crossref-keys)
2339 (unless (assoc (car key) ref-keys) (push key ref-keys)))
7fbf4804
SM
2340 (if verbose
2341 (bibtex-progress-message 'done))
d715b065 2342 ;; successful operation --> return `bibtex-reference-keys'
e0dc0c55 2343 (setq bibtex-reference-keys ref-keys))))))
7fbf4804 2344
d715b065 2345(defun bibtex-parse-strings (&optional add abortable)
7fbf4804 2346 "Set `bibtex-strings' to the string definitions in the whole buffer.
d715b065 2347If ADD is non-nil add the new strings to `bibtex-strings' instead of
a9d77f1f
SM
2348simply resetting it. If ADD is an alist of strings, also add ADD to
2349`bibtex-strings'. If ABORTABLE is non-nil abort on user input.
d715b065 2350Return alist of strings if parsing was completed, `aborted' otherwise."
7fbf4804
SM
2351 (save-excursion
2352 (save-match-data
2353 (goto-char (point-min))
d715b065
KG
2354 (let ((strings (if (and add
2355 (listp bibtex-strings))
2356 bibtex-strings))
7fbf4804 2357 bounds key)
d715b065
KG
2358 (if (listp add)
2359 (dolist (string add)
d528bff7 2360 (unless (assoc-string (car string) strings t)
d715b065
KG
2361 (push string strings))))
2362 (catch 'userkey
2363 (while (setq bounds (bibtex-search-forward-string))
2364 (if (and abortable
2365 (input-pending-p))
2366 ;; user has aborted by typing a key --> return `aborted'
2367 (throw 'userkey 'aborted))
2368 (setq key (bibtex-reference-key-in-string bounds))
d528bff7
SM
2369 (unless (assoc-string key strings t)
2370 (push (cons key (bibtex-text-in-string bounds t))
2371 strings))
d715b065
KG
2372 (goto-char (bibtex-end-of-text-in-string bounds)))
2373 ;; successful operation --> return `bibtex-strings'
2374 (setq bibtex-strings strings))))))
7fbf4804
SM
2375
2376(defun bibtex-string-files-init ()
2377 "Return initialization for `bibtex-strings'.
e0dc0c55 2378Use `bibtex-predefined-strings' and BibTeX files `bibtex-string-files'."
7fbf4804 2379 (save-match-data
e0dc0c55 2380 (let ((dirlist (split-string (or bibtex-string-file-path default-directory)
7fbf4804
SM
2381 ":+"))
2382 (case-fold-search)
e0dc0c55
SM
2383 string-files fullfilename compl bounds found)
2384 ;; collect absolute file names of valid string files
7fbf4804 2385 (dolist (filename bibtex-string-files)
dd310c45 2386 (unless (string-match "\\.bib\\'" filename)
7fbf4804
SM
2387 (setq filename (concat filename ".bib")))
2388 ;; test filenames
e0dc0c55
SM
2389 (if (file-name-absolute-p filename)
2390 (if (file-readable-p filename)
2391 (push filename string-files)
2392 (error "BibTeX strings file %s not found" filename))
7fbf4804
SM
2393 (dolist (dir dirlist)
2394 (when (file-readable-p
2395 (setq fullfilename (expand-file-name filename dir)))
e0dc0c55 2396 (push fullfilename string-files)
7fbf4804
SM
2397 (setq found t)))
2398 (unless found
d715b065 2399 (error "File %s not in paths defined via bibtex-string-file-path"
7fbf4804 2400 filename))))
e0dc0c55
SM
2401 ;; parse string files
2402 (dolist (filename string-files)
2403 (with-temp-buffer
2404 (insert-file-contents filename)
2405 (goto-char (point-min))
2406 (while (setq bounds (bibtex-search-forward-string))
2407 (push (cons (bibtex-reference-key-in-string bounds)
2408 (bibtex-text-in-string bounds t))
2409 compl)
2410 (goto-char (bibtex-end-of-string bounds)))))
7fbf4804 2411 (append bibtex-predefined-strings (nreverse compl)))))
50e4b39e
RS
2412
2413(defun bibtex-parse-buffers-stealthily ()
a9d77f1f 2414 "Parse buffer in the background during idle time.
e0dc0c55 2415Called by `run-with-idle-timer'. Whenever Emacs has been idle
02c8032e
SM
2416for `bibtex-parse-keys-timeout' seconds, parse all BibTeX buffers
2417which have been modified after last parsing.
2418Parsing initializes `bibtex-reference-keys' and `bibtex-strings'."
7fbf4804
SM
2419 (save-excursion
2420 (let ((buffers (buffer-list))
2421 (strings-init (bibtex-string-files-init)))
50e4b39e
RS
2422 (while (and buffers (not (input-pending-p)))
2423 (set-buffer (car buffers))
7fbf4804
SM
2424 (if (and (eq major-mode 'bibtex-mode)
2425 (not (eq (buffer-modified-tick)
2426 bibtex-buffer-last-parsed-tick)))
2427 (save-restriction
2428 (widen)
2429 ;; Output no progress messages in bibtex-parse-keys
2430 ;; because when in y-or-n-p that can hide the question.
e0dc0c55 2431 (if (and (listp (bibtex-parse-keys t))
7fbf4804 2432 ;; update bibtex-strings
d715b065 2433 (listp (bibtex-parse-strings strings-init t)))
7fbf4804
SM
2434
2435 ;; remember that parsing was successful
2436 (setq bibtex-buffer-last-parsed-tick (buffer-modified-tick)))))
2437 (setq buffers (cdr buffers))))))
2438
02c8032e 2439(defun bibtex-files-expand (&optional current force)
e0dc0c55
SM
2440 "Return an expanded list of BibTeX buffers based on `bibtex-files'.
2441Initialize in these buffers `bibtex-reference-keys' if not yet set.
02c8032e
SM
2442List of BibTeX buffers includes current buffer if CURRENT is non-nil.
2443If FORCE is non-nil, (re)initialize `bibtex-reference-keys' even if
2444already set."
e0dc0c55
SM
2445 (let ((file-path (split-string (or bibtex-file-path default-directory) ":+"))
2446 file-list dir-list buffer-list)
2447 (dolist (file bibtex-files)
2448 (cond ((eq file 'bibtex-file-path)
2449 (setq dir-list (append dir-list file-path)))
2450 ((file-accessible-directory-p file)
2451 (push file dir-list))
2452 ((progn (unless (string-match "\\.bib\\'" file)
2453 (setq file (concat file ".bib")))
2454 (file-name-absolute-p file))
2455 (push file file-list))
2456 (t
2457 (let (fullfilename found)
2458 (dolist (dir file-path)
2459 (when (file-readable-p
2460 (setq fullfilename (expand-file-name file dir)))
2461 (push fullfilename file-list)
2462 (setq found t)))
2463 (unless found
2464 (error "File %s not in paths defined via bibtex-file-path"
2465 file))))))
2466 (dolist (file file-list)
2467 (unless (file-readable-p file)
2468 (error "BibTeX file %s not found" file)))
2469 ;; expand dir-list
2470 (dolist (dir dir-list)
2471 (setq file-list
2472 (append file-list (directory-files dir t "\\.bib\\'" t))))
2473 (delete-dups file-list)
2474 (dolist (file file-list)
2475 (when (file-readable-p file)
2476 (push (find-file-noselect file) buffer-list)
2477 (with-current-buffer (car buffer-list)
02c8032e 2478 (if (or force (not (listp bibtex-reference-keys)))
e0dc0c55
SM
2479 (bibtex-parse-keys)))))
2480 (cond ((and current (not (memq (current-buffer) buffer-list)))
02c8032e
SM
2481 (push (current-buffer) buffer-list)
2482 (if force (bibtex-parse-keys)))
e0dc0c55
SM
2483 ((and (not current) (memq (current-buffer) buffer-list))
2484 (setq buffer-list (delq (current-buffer) buffer-list))))
2485 buffer-list))
2486
7fbf4804 2487(defun bibtex-complete-internal (completions)
a9d77f1f 2488 "Complete word fragment before point to longest prefix of COMPLETIONS.
02c8032e 2489COMPLETIONS is an alist of strings. If point is not after the part
a9d77f1f 2490of a word, all strings are listed. Return completion."
50e4b39e 2491 (let* ((case-fold-search t)
50e4b39e
RS
2492 (beg (save-excursion
2493 (re-search-backward "[ \t{\"]")
2494 (forward-char)
2495 (point)))
7fbf4804 2496 (end (point))
50e4b39e 2497 (part-of-word (buffer-substring-no-properties beg end))
7fbf4804
SM
2498 (completion (try-completion part-of-word completions)))
2499 (cond ((not completion)
2500 (error "Can't find completion for `%s'" part-of-word))
2501 ((eq completion t)
2502 part-of-word)
50e4b39e
RS
2503 ((not (string= part-of-word completion))
2504 (delete-region beg end)
2505 (insert completion)
7fbf4804 2506 completion)
50e4b39e
RS
2507 (t
2508 (message "Making completion list...")
7fbf4804
SM
2509 (with-output-to-temp-buffer "*Completions*"
2510 (display-completion-list (all-completions part-of-word
2511 completions)))
2512 (message "Making completion list...done")
8bf38a9b 2513 ;; return value is handled by choose-completion-string-functions
7fbf4804
SM
2514 nil))))
2515
02c8032e 2516(defun bibtex-complete-string-cleanup (str compl)
d715b065 2517 "Cleanup after inserting string STR.
02c8032e
SM
2518Remove enclosing field delimiters for STR. Display message with
2519expansion of STR using expansion list COMPL."
2520 (save-excursion
2521 (bibtex-inside-field)
2522 (let ((bounds (bibtex-enclosing-field))
2523 (abbr (cdr (if (stringp str)
2524 (assoc-string str compl t)))))
2525 (if abbr (message "Abbreviation for `%s'" abbr))
2526 (goto-char (bibtex-start-of-text-in-field bounds))
2527 (let ((boundaries (bibtex-parse-field-string)))
2528 (if (and boundaries
2529 (equal (cdr boundaries)
2530 (bibtex-end-of-text-in-field bounds)))
2531 (bibtex-remove-delimiters))))))
2532
2533(defun bibtex-complete-crossref-cleanup (key)
e0dc0c55
SM
2534 "Display summary message on entry KEY after completion of a crossref key.
2535Use `bibtex-summary-function' to generate summary."
d528bff7 2536 (save-excursion
02c8032e
SM
2537 (if (and (stringp key)
2538 (bibtex-find-entry key t))
2539 (message "Ref: %s" (funcall bibtex-summary-function key)))))
2540
2541(defun bibtex-copy-summary-as-kill ()
2542 "Push summery of current BibTeX entry to kill ring.
e0dc0c55 2543Use `bibtex-summary-function' to generate summary."
02c8032e
SM
2544 (interactive)
2545 (let ((key (save-excursion
2546 (bibtex-beginning-of-entry)
2547 (if (looking-at bibtex-entry-maybe-empty-head)
2548 (bibtex-key-in-head)
2549 (error "No key found")))))
2550 (kill-new (message "%s" (funcall bibtex-summary-function key)))))
e0dc0c55
SM
2551
2552(defun bibtex-summary (key)
2553 "Return summary of BibTeX entry KEY.
2554Used as default value of `bibtex-summary-function'."
2555 ;; It would be neat to customize this function. How?
2556 (save-excursion
02c8032e 2557 (if (bibtex-find-entry key t)
e0dc0c55
SM
2558 (let* ((bibtex-autokey-name-case-convert 'identity)
2559 (bibtex-autokey-name-length 'infty)
2560 (bibtex-autokey-names 1)
2561 (bibtex-autokey-names-stretch 0)
2562 (bibtex-autokey-name-separator " ")
2563 (bibtex-autokey-additional-names " etal")
2564 (names (bibtex-autokey-get-names))
2565 (bibtex-autokey-year-length 4)
2566 (year (bibtex-autokey-get-year))
2567 (bibtex-autokey-titlewords 5)
2568 (bibtex-autokey-titlewords-stretch 2)
2569 (bibtex-autokey-titleword-case-convert 'identity)
2570 (bibtex-autokey-titleword-length 5)
2571 (bibtex-autokey-titleword-separator " ")
2572 (title (bibtex-autokey-get-title))
2573 (journal (bibtex-autokey-get-field
2574 "journal" bibtex-autokey-transcriptions))
2575 (volume (bibtex-autokey-get-field "volume"))
2576 (pages (bibtex-autokey-get-field "pages" '(("-.*\\'" . "")))))
2577 (mapconcat (lambda (arg)
2578 (if (not (string= "" (cdr arg)))
2579 (concat (car arg) (cdr arg))))
2580 `((" " . ,names) (" " . ,year) (": " . ,title)
2581 (", " . ,journal) (" " . ,volume) (":" . ,pages))
2582 ""))
02c8032e 2583 (error "Key `%s' not found" key))))
cb4ad359 2584
50e4b39e 2585(defun bibtex-pop (arg direction)
02c8032e 2586 "Fill current field from the ARGth same field's text in DIRECTION.
a9d77f1f 2587Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
50e4b39e 2588 (let (bibtex-help-message)
02c8032e 2589 (bibtex-find-text))
50e4b39e
RS
2590 (save-excursion
2591 ;; parse current field
2592 (bibtex-inside-field)
f9bd4abe 2593 (let* ((case-fold-search t)
7fbf4804
SM
2594 (bounds (bibtex-enclosing-field))
2595 (start-old-text (bibtex-start-of-text-in-field bounds))
2596 (stop-old-text (bibtex-end-of-text-in-field bounds))
d528bff7 2597 (field-name (bibtex-name-in-field bounds t)))
7fbf4804
SM
2598 ;; if executed several times in a row, start each search where
2599 ;; the last one was finished
2600 (unless (eq last-command 'bibtex-pop)
2601 (bibtex-enclosing-entry-maybe-empty-head)
2602 (setq bibtex-pop-previous-search-point (match-beginning 0)
2603 bibtex-pop-next-search-point (point)))
2604 (if (eq direction 'previous)
2605 (goto-char bibtex-pop-previous-search-point)
2606 (goto-char bibtex-pop-next-search-point))
2607 ;; Now search for arg'th previous/next similar field
2608 (let (bounds failure new-text)
2609 (while (and (not failure)
2610 (> arg 0))
2611 (cond ((eq direction 'previous)
2612 (if (setq bounds (bibtex-search-backward-field field-name))
2613 (goto-char (bibtex-start-of-field bounds))
2614 (setq failure t)))
2615 ((eq direction 'next)
2616 (if (setq bounds (bibtex-search-forward-field field-name))
2617 (goto-char (bibtex-end-of-field bounds))
2618 (setq failure t))))
2619 (setq arg (- arg 1)))
2620 (if failure
2621 (error "No %s matching BibTeX field"
2622 (if (eq direction 'previous) "previous" "next"))
e0dc0c55 2623 ;; Found a matching field. Remember boundaries.
7fbf4804
SM
2624 (setq bibtex-pop-previous-search-point (bibtex-start-of-field bounds)
2625 bibtex-pop-next-search-point (bibtex-end-of-field bounds)
2626 new-text (bibtex-text-in-field-bounds bounds))
2627 (bibtex-flash-head)
2628 ;; Go back to where we started, delete old text, and pop new.
2629 (goto-char stop-old-text)
2630 (delete-region start-old-text stop-old-text)
2631 (insert new-text)))))
50e4b39e 2632 (let (bibtex-help-message)
02c8032e 2633 (bibtex-find-text))
50e4b39e
RS
2634 (setq this-command 'bibtex-pop))
2635
e0dc0c55
SM
2636(defun bibtex-beginning-of-field ()
2637 "Move point backward to beginning of field.
2638This function uses a simple, fast algorithm assuming that the field
2639begins at the beginning of a line. We use this function for font-locking."
2640 (let ((field-reg (concat "^[ \t]*" bibtex-field-name "[ \t]*=")))
2641 (beginning-of-line)
2642 (unless (looking-at field-reg)
2643 (re-search-backward field-reg nil t))))
2644
2645(defun bibtex-font-lock-url (bound)
02c8032e 2646 "Font-lock for URLs. BOUND limits the search."
e0dc0c55
SM
2647 (let ((case-fold-search t)
2648 (pnt (point))
2649 field bounds start end found)
2650 (bibtex-beginning-of-field)
2651 (while (and (not found)
2652 (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t)
2653 (setq field (match-string-no-properties 1)))
2654 (setq bounds (bibtex-parse-field-text))
2655 (progn
2656 (setq start (car bounds) end (cdr bounds))
2657 ;; Always ignore field delimiters
2658 (if (memq (char-before end) '(?\} ?\"))
2659 (setq end (1- end)))
2660 (if (memq (char-after start) '(?\{ ?\"))
2661 (setq start (1+ start)))
2662 (>= bound start)))
2663 (let ((lst bibtex-generate-url-list) url)
2664 (goto-char start)
2665 (while (and (not found)
2666 (setq url (caar lst)))
2667 (setq found (and (bibtex-string= field (car url))
2668 (re-search-forward (cdr url) end t)
2669 (>= (match-beginning 0) pnt))
2670 lst (cdr lst))))
2671 (goto-char end))
2672 (if found (bibtex-button (match-beginning 0) (match-end 0)
2673 'bibtex-url (match-beginning 0)))
2674 found))
2675
2676(defun bibtex-font-lock-crossref (bound)
02c8032e 2677 "Font-lock for crossref fields. BOUND limits the search."
e0dc0c55
SM
2678 (let ((case-fold-search t)
2679 (pnt (point))
2680 (crossref-reg (concat "^[ \t]*crossref[ \t]*=[ \t\n]*"
2681 "\\(\"[^\"]*\"\\|{[^}]*}\\)[ \t\n]*[,})]"))
2682 start end found)
2683 (bibtex-beginning-of-field)
2684 (while (and (not found)
2685 (re-search-forward crossref-reg bound t))
2686 (setq start (1+ (match-beginning 1))
2687 end (1- (match-end 1))
2688 found (>= start pnt)))
2689 (if found (bibtex-button start end 'bibtex-find-crossref
2690 (buffer-substring-no-properties start end)
2691 start t))
2692 found))
2693
2694(defun bibtex-button-action (button)
2695 "Call BUTTON's BibTeX function."
2696 (apply (button-get button 'bibtex-function)
2697 (button-get button 'bibtex-args)))
2698
2699(define-button-type 'bibtex-url
2700 'action 'bibtex-button-action
2701 'bibtex-function 'bibtex-url
2702 'help-echo (purecopy "mouse-2, RET: follow URL"))
2703
2704(define-button-type 'bibtex-find-crossref
2705 'action 'bibtex-button-action
2706 'bibtex-function 'bibtex-find-crossref
2707 'help-echo (purecopy "mouse-2, RET: follow crossref"))
2708
2709(defun bibtex-button (beg end type &rest args)
02c8032e 2710 "Make a BibTeX button from BEG to END of type TYPE in the current buffer."
e0dc0c55
SM
2711 (make-text-button beg end 'type type 'bibtex-args args))
2712
50e4b39e
RS
2713\f
2714;; Interactive Functions:
2715
2716;;;###autoload
2717(defun bibtex-mode ()
2718 "Major mode for editing BibTeX files.
2719
50e4b39e
RS
2720General information on working with BibTeX mode:
2721
02c8032e
SM
2722Use commands such as \\[bibtex-Book] to get a template for a specific entry.
2723Then fill in all desired fields using \\[bibtex-next-field] to jump from field
2724to field. After having filled in all desired fields in the entry, clean the
2725new entry with the command \\[bibtex-clean-entry].
cb4ad359 2726
d715b065 2727Some features of BibTeX mode are available only by setting the variable
d10e87a2
SM
2728`bibtex-maintain-sorted-entries' to non-nil. However, then BibTeX mode
2729works only with buffers containing valid (syntactical correct) and sorted
2730entries. This is usually the case, if you have created a buffer completely
2731with BibTeX mode and finished every new entry with \\[bibtex-clean-entry].
50e4b39e 2732
d715b065
KG
2733For third party BibTeX files, call the function `bibtex-convert-alien'
2734to fully take advantage of all features of BibTeX mode.
50e4b39e
RS
2735
2736
2737Special information:
2738
d10e87a2 2739A command such as \\[bibtex-Book] outlines the fields for a BibTeX book entry.
cb4ad359 2740
02c8032e
SM
2741The names of optional fields start with the string OPT, and are thus ignored
2742by BibTeX. The names of alternative fields from which only one is required
2743start with the string ALT. The OPT or ALT string may be removed from
2744the name of a field with \\[bibtex-remove-OPT-or-ALT].
50e4b39e
RS
2745\\[bibtex-make-field] inserts a new field after the current one.
2746\\[bibtex-kill-field] kills the current field entirely.
d715b065 2747\\[bibtex-yank] yanks the last recently killed field after the current field.
50e4b39e 2748\\[bibtex-remove-delimiters] removes the double-quotes or braces around the text of the current field.
02c8032e
SM
2749\\[bibtex-empty-field] replaces the text of the current field with the default \"\" or {}.
2750\\[bibtex-find-text] moves point to the end of the current field.
2751\\[bibtex-complete] completes word fragment before point according to context.
50e4b39e
RS
2752
2753The command \\[bibtex-clean-entry] cleans the current entry, i.e. it removes OPT/ALT
02c8032e
SM
2754from the names of all non-empty optional or alternative fields, checks that
2755no required fields are empty, and does some formatting dependent on the value
2756of `bibtex-entry-format'. Furthermore, it can automatically generate a key
2757for the BibTeX entry, see `bibtex-generate-autokey'.
f0cb6034
RS
2758Note: some functions in BibTeX mode depend on entries being in a special
2759format (all fields beginning on separate lines), so it is usually a bad
7fbf4804 2760idea to remove `realign' from `bibtex-entry-format'.
cb4ad359 2761
02c8032e
SM
2762BibTeX mode supports Imenu and hideshow minor mode (`hs-minor-mode').
2763
2764----------------------------------------------------------
2765Entry to BibTeX mode calls the value of `bibtex-mode-hook'
2766if that value is non-nil.
50e4b39e 2767
f0cb6034 2768\\{bibtex-mode-map}"
cb4ad359
RS
2769 (interactive)
2770 (kill-all-local-variables)
2771 (use-local-map bibtex-mode-map)
2772 (setq major-mode 'bibtex-mode)
2773 (setq mode-name "BibTeX")
2774 (set-syntax-table bibtex-mode-syntax-table)
7fbf4804 2775 (make-local-variable 'bibtex-buffer-last-parsed-tick)
50e4b39e 2776 ;; Install stealthy parse function if not already installed
7fbf4804 2777 (unless bibtex-parse-idle-timer
e0dc0c55 2778 (setq bibtex-parse-idle-timer (run-with-idle-timer
7fbf4804
SM
2779 bibtex-parse-keys-timeout t
2780 'bibtex-parse-buffers-stealthily)))
2781 (set (make-local-variable 'paragraph-start) "[ \f\n\t]*$")
2782 (set (make-local-variable 'comment-start) bibtex-comment-start)
2783 (set (make-local-variable 'comment-start-skip)
2784 (concat (regexp-quote bibtex-comment-start) "\\>[ \t]*"))
2785 (set (make-local-variable 'comment-column) 0)
dd310c45 2786 (set (make-local-variable 'defun-prompt-regexp) "^[ \t]*@[a-zA-Z0-9]+[ \t]*")
7fbf4804 2787 (set (make-local-variable 'outline-regexp) "[ \t]*@")
d715b065 2788 (set (make-local-variable 'fill-paragraph-function) 'bibtex-fill-field)
7fbf4804 2789 (set (make-local-variable 'fill-prefix) (make-string (+ bibtex-entry-offset
e0dc0c55
SM
2790 bibtex-contline-indentation)
2791 ? ))
7fbf4804
SM
2792 (set (make-local-variable 'font-lock-defaults)
2793 '(bibtex-font-lock-keywords
2794 nil t ((?$ . "\"")
2795 ;; Mathematical expressions should be fontified as strings
2796 (?\" . ".")
2797 ;; Quotes are field delimiters and quote-delimited
2798 ;; entries should be fontified in the same way as
2799 ;; brace-delimited ones
2800 )
2801 nil
d715b065 2802 (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
e0dc0c55 2803 (font-lock-extra-managed-props . (category))
d715b065
KG
2804 (font-lock-mark-block-function
2805 . (lambda ()
d528bff7 2806 (set-mark (bibtex-end-of-entry))
d715b065 2807 (bibtex-beginning-of-entry)))))
50e4b39e 2808 (setq imenu-generic-expression
02c8032e
SM
2809 (list (list nil bibtex-entry-head bibtex-key-in-head))
2810 imenu-case-fold-search t)
7fbf4804 2811 (make-local-variable 'choose-completion-string-functions)
ab2d0cdb
RS
2812 ;; XEmacs needs easy-menu-add, Emacs does not care
2813 (easy-menu-add bibtex-edit-menu)
2814 (easy-menu-add bibtex-entry-menu)
cb4ad359 2815 (run-hooks 'bibtex-mode-hook))
9ae11a89 2816
8bf38a9b
SM
2817(defun bibtex-field-list (entry-type)
2818 "Return list of allowed fields for entry ENTRY-TYPE.
2819More specifically, the return value is a cons pair (REQUIRED . OPTIONAL),
2820where REQUIRED and OPTIONAL are lists of the required and optional field
02c8032e
SM
2821names for ENTRY-TYPE according to `bibtex-entry-field-alist',
2822`bibtex-include-OPTkey', `bibtex-include-OPTcrossref',
2823and `bibtex-user-optional-fields'."
c2fb6415 2824 (let ((e (assoc-string entry-type bibtex-entry-field-alist t))
8bf38a9b
SM
2825 required optional)
2826 (unless e
2827 (error "Bibtex entry type %s not defined" entry-type))
2828 (if (and (member-ignore-case entry-type bibtex-include-OPTcrossref)
2829 (nth 2 e))
2830 (setq required (nth 0 (nth 2 e))
2831 optional (nth 1 (nth 2 e)))
2832 (setq required (nth 0 (nth 1 e))
2833 optional (nth 1 (nth 1 e))))
2834 (if bibtex-include-OPTkey
2835 (push (list "key"
2836 "Used for reference key creation if author and editor fields are missing"
2837 (if (or (stringp bibtex-include-OPTkey)
2838 (fboundp bibtex-include-OPTkey))
2839 bibtex-include-OPTkey))
2840 optional))
2841 (if (member-ignore-case entry-type bibtex-include-OPTcrossref)
2842 (push '("crossref" "Reference key of the cross-referenced entry")
2843 optional))
2844 (setq optional (append optional bibtex-user-optional-fields))
2845 (cons required optional)))
2846
50e4b39e 2847(defun bibtex-entry (entry-type)
a9d77f1f 2848 "Insert a new BibTeX entry of type ENTRY-TYPE.
02c8032e
SM
2849After insertion call the value of `bibtex-add-entry-hook' if that value
2850is non-nil."
2851 (interactive
2852 (let ((completion-ignore-case t))
2853 (list (completing-read "Entry Type: " bibtex-entry-field-alist
2854 nil t nil 'bibtex-entry-type-history))))
8bf38a9b
SM
2855 (let ((key (if bibtex-maintain-sorted-entries
2856 (bibtex-read-key (format "%s key: " entry-type))))
2857 (field-list (bibtex-field-list entry-type)))
7fbf4804
SM
2858 (unless (bibtex-prepare-new-entry (list key nil entry-type))
2859 (error "Entry with key `%s' already exists" key))
50e4b39e
RS
2860 (indent-to-column bibtex-entry-offset)
2861 (insert "@" entry-type (bibtex-entry-left-delimiter))
8bf38a9b 2862 (if key (insert key))
9ae11a89 2863 (save-excursion
a9d77f1f
SM
2864 (mapc 'bibtex-make-field (car field-list))
2865 (mapc 'bibtex-make-optional-field (cdr field-list))
50e4b39e
RS
2866 (if bibtex-comma-after-last-field
2867 (insert ","))
2868 (insert "\n")
2869 (indent-to-column bibtex-entry-offset)
2870 (insert (bibtex-entry-right-delimiter) "\n\n"))
0640d7bf 2871 (bibtex-next-field t)
d715b065
KG
2872 (if (member-ignore-case entry-type bibtex-autofill-types)
2873 (bibtex-autofill-entry))
9ae11a89 2874 (run-hooks 'bibtex-add-entry-hook)))
e5167999 2875
8bf38a9b
SM
2876(defun bibtex-entry-update ()
2877 "Update an existing BibTeX entry.
2878In the BibTeX entry at point, make new fields for those items that may occur
02c8032e 2879according to `bibtex-field-list', but are not yet present."
8bf38a9b
SM
2880 (interactive)
2881 (save-excursion
2882 (bibtex-beginning-of-entry)
2883 ;; For inserting new fields, we use the fact that
2884 ;; bibtex-parse-entry moves point to the end of the last field.
2885 (let* ((fields-alist (bibtex-parse-entry))
2886 (field-list (bibtex-field-list
e0dc0c55 2887 (cdr (assoc "=type=" fields-alist)))))
8bf38a9b 2888 (dolist (field (car field-list))
d528bff7 2889 (unless (assoc-string (car field) fields-alist t)
8bf38a9b
SM
2890 (bibtex-make-field field)))
2891 (dolist (field (cdr field-list))
d528bff7 2892 (unless (assoc-string (car field) fields-alist t)
8bf38a9b
SM
2893 (bibtex-make-optional-field field))))))
2894
d715b065
KG
2895(defun bibtex-parse-entry ()
2896 "Parse entry at point, return an alist.
2897The alist elements have the form (FIELD . TEXT), where FIELD can also be
d528bff7
SM
2898the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\"
2899TEXT may be nil. Remove \"OPT\" and \"ALT\" from FIELD.
2900Move point to the end of the last field."
d715b065 2901 (let (alist bounds)
cb75af76 2902 (when (looking-at bibtex-entry-maybe-empty-head)
e0dc0c55
SM
2903 (push (cons "=type=" (bibtex-type-in-head)) alist)
2904 (push (cons "=key=" (bibtex-key-in-head)) alist)
cb75af76 2905 (goto-char (match-end 0))
d715b065 2906 (while (setq bounds (bibtex-parse-field bibtex-field-name))
d528bff7 2907 (push (cons (bibtex-name-in-field bounds t)
d715b065
KG
2908 (bibtex-text-in-field-bounds bounds))
2909 alist)
2910 (goto-char (bibtex-end-of-field bounds))))
2911 alist))
2912
2913(defun bibtex-autofill-entry ()
02c8032e
SM
2914 "Try to fill fields of current BibTeX entry based on neighboring entries.
2915The current entry must have a key. Determine the neighboring entry
2916\(previouse or next\) whose key is more similar to the key of the current
2917entry. For all empty fields of the current entry insert the corresponding
2918field contents of the neighboring entry. Finally try to update the text
2919based on the difference between the keys of the neighboring and the current
2920entry (for example, the year parts of the keys)."
d715b065
KG
2921 (interactive)
2922 (undo-boundary) ;So you can easily undo it, if it didn't work right.
2923 (bibtex-beginning-of-entry)
2924 (when (looking-at bibtex-entry-head)
e0dc0c55
SM
2925 (let ((type (bibtex-type-in-head))
2926 (key (bibtex-key-in-head))
d715b065
KG
2927 (key-end (match-end bibtex-key-in-head))
2928 (case-fold-search t)
2929 tmp other-key other bounds)
2930 ;; The fields we want to change start right after the key.
2931 (goto-char key-end)
2932 ;; First see whether to use the previous or the next entry
2933 ;; for "inspiration".
2934 (save-excursion
2935 (goto-char (1- (match-beginning 0)))
2936 (bibtex-beginning-of-entry)
02c8032e
SM
2937 (if (and (looking-at bibtex-entry-head)
2938 (bibtex-string= type (bibtex-type-in-head))
2939 ;; In case we found ourselves :-(
2940 (not (equal key (setq tmp (bibtex-key-in-head)))))
2941 (setq other-key tmp
2942 other (point))))
d715b065
KG
2943 (save-excursion
2944 (bibtex-end-of-entry)
2945 (bibtex-skip-to-valid-entry)
02c8032e
SM
2946 (if (and (looking-at bibtex-entry-head)
2947 (bibtex-string= type (bibtex-type-in-head))
2948 ;; In case we found ourselves :-(
2949 (not (equal key (setq tmp (bibtex-key-in-head))))
2950 (or (not other-key)
2951 ;; Check which is the best match.
2952 (< (length (try-completion "" (list key other-key)))
2953 (length (try-completion "" (list key tmp))))))
2954 (setq other-key tmp
2955 other (point))))
d715b065
KG
2956 ;; Then fill the new entry's fields with the chosen other entry.
2957 (when other
2958 (setq other (save-excursion (goto-char other) (bibtex-parse-entry)))
2959 (setq key-end (point)) ;In case parse-entry changed the buffer.
2960 (while (setq bounds (bibtex-parse-field bibtex-field-name))
d528bff7
SM
2961 (let ((text (assoc-string (bibtex-name-in-field bounds t)
2962 other t)))
d715b065
KG
2963 (goto-char (bibtex-start-of-text-in-field bounds))
2964 (if (not (and (looking-at bibtex-empty-field-re) text))
2965 (goto-char (bibtex-end-of-field bounds))
2966 (delete-region (point) (bibtex-end-of-text-in-field bounds))
2967 (insert (cdr text)))))
2968 ;; Finally try to update the text based on the difference between
2969 ;; the two keys.
2970 (let* ((prefix (try-completion "" (list key other-key)))
2971 ;; If the keys are foo91 and foo92, don't replace 1 for 2
2972 ;; but 91 for 92 instead.
2973 (_ (if (string-match "[0-9]+\\'" prefix)
2974 (setq prefix (substring prefix 0 (match-beginning 0)))))
2975 (suffix (substring key (length prefix)))
2976 (other-suffix (substring other-key (length prefix))))
2977 (while (re-search-backward (regexp-quote other-suffix) key-end 'move)
2978 (replace-match suffix)))))))
2979
cb4ad359 2980(defun bibtex-print-help-message ()
7fbf4804 2981 "Print helpful information about current field in current BibTeX entry."
cb4ad359 2982 (interactive)
7fbf4804
SM
2983 (save-excursion
2984 (let* ((case-fold-search t)
d528bff7 2985 (field-name (bibtex-name-in-field (bibtex-enclosing-field) t))
8bf38a9b
SM
2986 (field-list (bibtex-field-list (progn (re-search-backward
2987 bibtex-entry-maybe-empty-head nil t)
2988 (bibtex-type-in-head))))
c2fb6415
RS
2989 (comment (assoc-string field-name
2990 (append (car field-list)
2991 (cdr field-list))
2992 t)))
31bc4210 2993 (if comment
8bf38a9b 2994 (message (nth 1 comment))
7fbf4804 2995 (message "No comment available")))))
d30bfc76 2996
02c8032e 2997(defun bibtex-make-field (field &optional move interactive)
d715b065
KG
2998 "Make a field named FIELD in current BibTeX entry.
2999FIELD is either a string or a list of the form
3000\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in
a9d77f1f 3001`bibtex-entry-field-alist'.
02c8032e
SM
3002If MOVE is non-nil, move point past the present field before making
3003the new field. If INTERACTIVE is non-nil, move point to the end of
3004the new field. Otherwise move point past the new field.
3005MOVE and INTERACTIVE are t when called interactively."
7fbf4804 3006 (interactive
8bf38a9b
SM
3007 (list (let ((completion-ignore-case t)
3008 (field-list (bibtex-field-list
e0dc0c55
SM
3009 (save-excursion
3010 (bibtex-enclosing-entry-maybe-empty-head)
3011 (bibtex-type-in-head)))))
8bf38a9b
SM
3012 (completing-read "BibTeX field name: "
3013 (append (car field-list) (cdr field-list))
3f3ed959 3014 nil nil nil bibtex-field-history))
02c8032e 3015 t t))
d715b065
KG
3016 (unless (consp field)
3017 (setq field (list field)))
02c8032e 3018 (if move
d715b065 3019 (let (bibtex-help-message)
02c8032e 3020 (bibtex-find-text)
d715b065
KG
3021 (if (looking-at "[}\"]")
3022 (forward-char))))
3023 (insert ",\n")
3024 (indent-to-column (+ bibtex-entry-offset bibtex-field-indentation))
3025 (if (nth 3 field) (insert "ALT"))
3026 (insert (car field) " ")
3027 (if bibtex-align-at-equal-sign
3028 (indent-to-column (+ bibtex-entry-offset
3029 (- bibtex-text-indentation 2))))
3030 (insert "= ")
d528bff7
SM
3031 (unless bibtex-align-at-equal-sign
3032 (indent-to-column (+ bibtex-entry-offset
3033 bibtex-text-indentation)))
d715b065 3034 (let ((init (nth 2 field)))
02c8032e
SM
3035 (insert (cond ((stringp init) init)
3036 ((fboundp init) (funcall init))
3037 (t (concat (bibtex-field-left-delimiter)
3038 (bibtex-field-right-delimiter))))))
2c10c0f0 3039 (when interactive
8bf38a9b
SM
3040 (forward-char -1)
3041 (bibtex-print-help-message)))
9ae11a89 3042
cb4ad359 3043(defun bibtex-beginning-of-entry ()
7fbf4804 3044 "Move to beginning of BibTeX entry (beginning of line).
cb4ad359 3045If inside an entry, move to the beginning of it, otherwise move to the
a9d77f1f
SM
3046beginning of the previous entry. If point is ahead of all BibTeX entries
3047move point to the beginning of buffer. Return the new location of point."
745bc783 3048 (interactive)
50e4b39e
RS
3049 (skip-chars-forward " \t")
3050 (if (looking-at "@")
a9cb9b80 3051 (forward-char))
d715b065
KG
3052 (re-search-backward "^[ \t]*@" nil 'move)
3053 (point))
e5167999 3054
cb4ad359 3055(defun bibtex-end-of-entry ()
7fbf4804 3056 "Move to end of BibTeX entry (past the closing brace).
cb4ad359 3057If inside an entry, move to the end of it, otherwise move to the end
a9d77f1f 3058of the previous entry. Do not move if ahead of first entry.
d715b065 3059Return the new location of point."
745bc783 3060 (interactive)
7fbf4804
SM
3061 (let ((case-fold-search t)
3062 (org (point))
3063 (pnt (bibtex-beginning-of-entry))
3064 err bounds)
d715b065
KG
3065 (cond ((looking-at bibtex-valid-entry-whitespace-re)
3066 (bibtex-search-entry t nil t)
3067 (unless (equal (match-beginning 0) pnt)
3068 (setq err t)))
3069 ((setq bounds (bibtex-parse-string))
7fbf4804
SM
3070 (goto-char (bibtex-end-of-string bounds)))
3071 ((looking-at "[ \t]*@[ \t]*preamble[ \t\n]*")
3072 (goto-char (match-end 0))
02c8032e
SM
3073 (if (looking-at "[({]")
3074 (forward-sexp 1)
3075 (setq err t)))
7fbf4804
SM
3076 (t
3077 (if (interactive-p)
3078 (message "Not on a known BibTeX entry."))
3079 (goto-char org)))
3080 (when err
3081 (goto-char pnt)
3082 (error "Syntactically incorrect BibTeX entry starts here")))
50e4b39e 3083 (point))
f0cb6034 3084
d10e87a2
SM
3085(defun bibtex-goto-line (arg)
3086 "Goto line ARG, counting from beginning of (narrowed) buffer."
3087 ;; code adapted from `goto-line'
3088 (goto-char (point-min))
3089 (if (eq selective-display t)
3090 (re-search-forward "[\n\C-m]" nil 'end (1- arg))
3091 (forward-line (1- arg))))
3092
3093(defun bibtex-reposition-window ()
7fbf4804 3094 "Make the current BibTeX entry visible.
d10e87a2
SM
3095If entry is smaller than `window-body-height', entry is centered in window.
3096Otherwise display the beginning of entry."
3097 (interactive)
3098 (let ((pnt (point))
3099 (beg (line-number-at-pos (bibtex-beginning-of-entry)))
3100 (end (line-number-at-pos (bibtex-end-of-entry))))
3101 (if (> (window-body-height) (- end beg))
3102 ;; entry fits in current window
3103 (progn
3104 (bibtex-goto-line (/ (+ 1 beg end) 2))
3105 (recenter)
3106 (goto-char pnt))
3107 ;; entry too large for current window
3108 (bibtex-goto-line beg)
3109 (recenter 0)
3110 (if (> (1+ (- (line-number-at-pos pnt) beg))
3111 (window-body-height))
3112 (bibtex-goto-line beg)
3113 (goto-char pnt)))))
50e4b39e
RS
3114
3115(defun bibtex-mark-entry ()
3116 "Put mark at beginning, point at end of current BibTeX entry."
3117 (interactive)
3118 (set-mark (bibtex-beginning-of-entry))
3119 (bibtex-end-of-entry))
3120
3121(defun bibtex-count-entries (&optional count-string-entries)
3122 "Count number of entries in current buffer or region.
d10e87a2
SM
3123With prefix argument COUNT-STRING-ENTRIES count all entries,
3124otherwise count all entries except @String entries.
3125If mark is active count entries in region, if not in whole buffer."
50e4b39e 3126 (interactive "P")
7fbf4804 3127 (let ((number 0)
50e4b39e
RS
3128 (bibtex-sort-ignore-string-entries
3129 (not count-string-entries)))
7fbf4804
SM
3130 (save-excursion
3131 (save-restriction
e0dc0c55 3132 (narrow-to-region (if mark-active (region-beginning)
7fbf4804 3133 (bibtex-beginning-of-first-entry))
e0dc0c55 3134 (if mark-active (region-end) (point-max)))
d715b065 3135 (bibtex-map-entries (lambda (key beg end)
7fbf4804
SM
3136 (setq number (1+ number))))))
3137 (message "%s contains %d entries."
e0dc0c55 3138 (if mark-active "Region" "Buffer")
d715b065 3139 number)))
50e4b39e 3140
cb4ad359 3141(defun bibtex-ispell-entry ()
d10e87a2 3142 "Check BibTeX entry for spelling errors."
745bc783 3143 (interactive)
d715b065
KG
3144 (ispell-region (save-excursion (bibtex-beginning-of-entry))
3145 (save-excursion (bibtex-end-of-entry))))
745bc783 3146
cb4ad359 3147(defun bibtex-ispell-abstract ()
d10e87a2 3148 "Check abstract of BibTeX entry for spelling errors."
745bc783 3149 (interactive)
d715b065
KG
3150 (let ((bounds (save-excursion
3151 (bibtex-beginning-of-entry)
3152 (bibtex-search-forward-field "abstract" t))))
7fbf4804
SM
3153 (if bounds
3154 (ispell-region (bibtex-start-of-text-in-field bounds)
3155 (bibtex-end-of-text-in-field bounds))
3156 (error "No abstract in entry"))))
745bc783 3157
cb4ad359
RS
3158(defun bibtex-narrow-to-entry ()
3159 "Narrow buffer to current BibTeX entry."
745bc783 3160 (interactive)
cb4ad359 3161 (save-excursion
7fbf4804
SM
3162 (widen)
3163 (narrow-to-region (bibtex-beginning-of-entry)
3164 (bibtex-end-of-entry))))
3165
3166(defun bibtex-entry-index ()
02c8032e 3167 "Return index of BibTeX entry head at or past position of point.
7fbf4804 3168The index is a list (KEY CROSSREF-KEY ENTRY-NAME) that is used for sorting
02c8032e
SM
3169the entries of the BibTeX buffer. CROSSREF-KEY is nil unless the value
3170of `bibtex-maintain-sorted-entries' is `crossref'. Move point to the end
3171of the head of the entry found. Return nil if no entry found."
7fbf4804
SM
3172 (let ((case-fold-search t))
3173 (if (re-search-forward bibtex-entry-maybe-empty-head nil t)
3174 (let ((key (bibtex-key-in-head))
d715b065
KG
3175 ;; all entry names should be downcase (for ease of comparison)
3176 (entry-name (downcase (bibtex-type-in-head))))
7fbf4804 3177 ;; Don't search CROSSREF-KEY if we don't need it.
02c8032e
SM
3178 (if (eq bibtex-maintain-sorted-entries 'crossref)
3179 (let ((bounds (bibtex-search-forward-field
3180 "\\(OPT\\)?crossref" t)))
3181 (list key
3182 (if bounds (bibtex-text-in-field-bounds bounds t))
3183 entry-name))
8bf38a9b 3184 (list key nil entry-name))))))
7fbf4804
SM
3185
3186(defun bibtex-lessp (index1 index2)
3187 "Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2.
3188Each index is a list (KEY CROSSREF-KEY ENTRY-NAME).
8bf38a9b
SM
3189The predicate depends on the variable `bibtex-maintain-sorted-entries'.
3190If its value is nil use plain sorting."
7fbf4804
SM
3191 (cond ((not index1) (not index2)) ; indices can be nil
3192 ((not index2) nil)
02c8032e 3193 ((eq bibtex-maintain-sorted-entries 'crossref)
7fbf4804
SM
3194 (if (nth 1 index1)
3195 (if (nth 1 index2)
3196 (or (string-lessp (nth 1 index1) (nth 1 index2))
3197 (and (string-equal (nth 1 index1) (nth 1 index2))
3198 (string-lessp (nth 0 index1) (nth 0 index2))))
3199 (not (string-lessp (nth 0 index2) (nth 1 index1))))
3200 (if (nth 1 index2)
3201 (string-lessp (nth 0 index1) (nth 1 index2))
3202 (string-lessp (nth 0 index1) (nth 0 index2)))))
02c8032e 3203 ((eq bibtex-maintain-sorted-entries 'entry-class)
d715b065
KG
3204 (let ((n1 (cdr (or (assoc (nth 2 index1) bibtex-sort-entry-class-alist)
3205 (assoc 'catch-all bibtex-sort-entry-class-alist)
3206 '(nil . 1000)))) ; if there is nothing else
3207 (n2 (cdr (or (assoc (nth 2 index2) bibtex-sort-entry-class-alist)
3208 (assoc 'catch-all bibtex-sort-entry-class-alist)
3209 '(nil . 1000))))) ; if there is nothing else
7fbf4804
SM
3210 (or (< n1 n2)
3211 (and (= n1 n2)
3212 (string-lessp (car index1) (car index2))))))
02c8032e 3213 (t ; (eq bibtex-maintain-sorted-entries 'plain)
7fbf4804 3214 (string-lessp (car index1) (car index2)))))
745bc783 3215
50e4b39e
RS
3216(defun bibtex-sort-buffer ()
3217 "Sort BibTeX buffer alphabetically by key.
7fbf4804 3218The predicate for sorting is defined via `bibtex-maintain-sorted-entries'.
a9d77f1f
SM
3219If its value is nil use plain sorting. Text outside of BibTeX entries is not
3220affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries
d10e87a2 3221are ignored."
745bc783 3222 (interactive)
cb4ad359 3223 (save-restriction
7fbf4804
SM
3224 (narrow-to-region (bibtex-beginning-of-first-entry)
3225 (save-excursion (goto-char (point-max))
3226 (bibtex-end-of-entry)))
55fe21fc 3227 (bibtex-skip-to-valid-entry)
7fbf4804
SM
3228 (sort-subr nil
3229 'bibtex-skip-to-valid-entry ; NEXTREC function
3230 'bibtex-end-of-entry ; ENDREC function
3231 'bibtex-entry-index ; STARTKEY function
3232 nil ; ENDKEY function
3233 'bibtex-lessp))) ; PREDICATE
3234
e0dc0c55 3235(defun bibtex-find-crossref (crossref-key &optional pnt split)
7fbf4804 3236 "Move point to the beginning of BibTeX entry CROSSREF-KEY.
02c8032e
SM
3237If `bibtex-files' is non-nil, search all these files.
3238Otherwise the search is limited to the current buffer.
3239Return position of entry if CROSSREF-KEY is found or nil otherwise.
3240If CROSSREF-KEY is in the same buffer like current entry but before it
3241an error is signaled. Optional arg PNT is the position of the referencing
3242entry. It defaults to position of point. If optional arg SPLIT is non-nil,
3243split window so that both the referencing and the crossrefed entry are
3244displayed.
d715b065 3245If called interactively, CROSSREF-KEY defaults to crossref key of current
e0dc0c55 3246entry and SPLIT is t."
d715b065
KG
3247 (interactive
3248 (let ((crossref-key
3249 (save-excursion
3250 (bibtex-beginning-of-entry)
3251 (let ((bounds (bibtex-search-forward-field "crossref" t)))
3252 (if bounds
3253 (bibtex-text-in-field-bounds bounds t))))))
02c8032e
SM
3254 (list (bibtex-read-key "Find crossref key: " crossref-key t)
3255 (point) t)))
3256 (let (buffer pos eqb)
3257 (save-excursion
3258 (setq pos (bibtex-find-entry crossref-key t)
3259 buffer (current-buffer)))
3260 (setq eqb (eq buffer (current-buffer)))
e0dc0c55 3261 (cond ((not pos)
02c8032e
SM
3262 (if split (message "Crossref key `%s' not found" crossref-key)))
3263 (split ; called (quasi) interactively
3264 (unless pnt (setq pnt (point)))
e0dc0c55 3265 (goto-char pnt)
02c8032e
SM
3266 (if eqb (select-window (split-window))
3267 (pop-to-buffer buffer))
e0dc0c55 3268 (goto-char pos)
d10e87a2 3269 (bibtex-reposition-window)
e0dc0c55 3270 (beginning-of-line)
02c8032e 3271 (if (and eqb (> pnt pos))
e0dc0c55 3272 (error "The referencing entry must preceed the crossrefed entry!")))
02c8032e
SM
3273 ;; `bibtex-find-crossref' is called noninteractively during
3274 ;; clean-up of an entry. Then it is not possible to check
3275 ;; whether the current entry and the crossrefed entry have
3276 ;; the correct sorting order.
3277 (eqb (goto-char pos))
3278 (t (set-buffer buffer) (goto-char pos)))
e0dc0c55 3279 pos))
7fbf4804 3280
02c8032e 3281(defun bibtex-find-entry (key &optional global start display)
7fbf4804 3282 "Move point to the beginning of BibTeX entry named KEY.
d528bff7 3283Return position of entry if KEY is found or nil if not found.
02c8032e
SM
3284With prefix arg GLOBAL non-nil, search KEY in `bibtex-files'.
3285Otherwise the search is limited to the current buffer.
d528bff7
SM
3286Optional arg START is buffer position where the search starts.
3287If it is nil, start search at beginning of buffer.
02c8032e
SM
3288If DISPLAY is non-nil, display the buffer containing KEY.
3289Otherwise, use `set-buffer'. DISPLAY is t when called interactively."
3290 (interactive (list (bibtex-read-key "Find key: " nil current-prefix-arg)
3291 current-prefix-arg nil t))
3292 (if (and global bibtex-files)
3293 (let ((buffer-list (bibtex-files-expand t))
3294 buffer found)
3295 (while (and (not found)
3296 (setq buffer (pop buffer-list)))
3297 (with-current-buffer buffer
3298 (if (cdr (assoc-string key bibtex-reference-keys))
3299 ;; `bibtex-find-entry' moves point if key found
3300 (setq found (bibtex-find-entry key)))))
3301 (cond ((and found display)
3302 (let ((same-window-buffer-names
3303 (cons (buffer-name buffer) same-window-buffer-names)))
d10e87a2
SM
3304 (pop-to-buffer buffer)
3305 (bibtex-reposition-window)))
02c8032e 3306 (found (set-buffer buffer))
d10e87a2 3307 (display (message "Key `%s' not found" key)))
02c8032e
SM
3308 found)
3309
3310 (let* (case-fold-search
3311 (pnt (save-excursion
3312 (goto-char (or start (point-min)))
3313 (if (re-search-forward (concat "^[ \t]*\\("
3314 bibtex-entry-type
3315 "\\)[ \t]*[({][ \t\n]*\\("
3316 (regexp-quote key)
3317 "\\)[ \t\n]*[,=]")
3318 nil t)
3319 (match-beginning 0)))))
3320 (cond (pnt
d10e87a2
SM
3321 (goto-char pnt)
3322 (if display (bibtex-reposition-window)))
3323 (display (message "Key `%s' not found" key)))
3324 pnt)))
7fbf4804
SM
3325
3326(defun bibtex-prepare-new-entry (index)
3327 "Prepare a new BibTeX entry with index INDEX.
3328INDEX is a list (KEY CROSSREF-KEY ENTRY-NAME).
3329Move point where the entry KEY should be placed.
3330If `bibtex-maintain-sorted-entries' is non-nil, perform a binary
d10e87a2
SM
3331search to look for place for KEY. This requires that buffer is sorted,
3332see \\[bibtex-validate].)
7fbf4804
SM
3333Return t if preparation was successful or nil if entry KEY already exists."
3334 (let ((key (nth 0 index))
3335 key-exist)
3336 (cond ((or (null key)
3337 (and (stringp key)
3338 (string-equal key ""))
3339 (and (not (setq key-exist (bibtex-find-entry key)))
3340 (not bibtex-maintain-sorted-entries)))
3341 (bibtex-move-outside-of-entry))
3342 ;; if key-exist is non-nil due to the previous cond clause
3343 ;; then point will be at beginning of entry named key.
3344 (key-exist)
3345 (t ; bibtex-maintain-sorted-entries is non-nil
3346 (let* ((case-fold-search t)
3347 (left (save-excursion (bibtex-beginning-of-first-entry)
3348 (bibtex-skip-to-valid-entry)
3349 (point)))
3350 (right (save-excursion (bibtex-beginning-of-last-entry)
3351 (bibtex-end-of-entry)))
3352 (found (if (>= left right) left))
3353 actual-index new)
3354 (save-excursion
3355 ;; Binary search
3356 (while (not found)
3357 (goto-char (/ (+ left right) 2))
3358 (bibtex-skip-to-valid-entry t)
3359 (setq actual-index (bibtex-entry-index))
3360 (cond ((bibtex-lessp index actual-index)
3361 (setq new (bibtex-beginning-of-entry))
3362 (if (equal right new)
3363 (setq found right)
3364 (setq right new)))
3365 (t
3366 (bibtex-end-of-entry)
3367 (bibtex-skip-to-valid-entry)
3368 (setq new (point))
3369 (if (equal left new)
3370 (setq found right)
3371 (setq left new))))))
3372 (goto-char found)
3373 (bibtex-beginning-of-entry)
3374 (setq actual-index (save-excursion (bibtex-entry-index)))
3375 (when (or (not actual-index)
3376 (bibtex-lessp actual-index index))
3377 ;; buffer contains no valid entries or
3378 ;; greater than last entry --> append
3379 (bibtex-end-of-entry)
d528bff7 3380 (unless (bobp) (newline (forward-line 2)))
7fbf4804
SM
3381 (beginning-of-line)))))
3382 (unless key-exist t)))
cb4ad359 3383
50e4b39e
RS
3384(defun bibtex-validate (&optional test-thoroughly)
3385 "Validate if buffer or region is syntactically correct.
e0dc0c55
SM
3386Check also for duplicate keys and correct sort order provided
3387`bibtex-maintain-sorted-entries' is non-nil.
3388With optional argument TEST-THOROUGHLY non-nil check also for
3389the absence of required fields and for questionable month fields.
7fbf4804 3390If mark is active, validate current region, if not the whole buffer.
e0dc0c55
SM
3391Only check known entry types, so you can put comments outside of entries.
3392Return t if test was successful, nil otherwise."
31bc4210 3393 (interactive "P")
7fbf4804
SM
3394 (let* ((case-fold-search t)
3395 error-list syntax-error)
3396 (save-excursion
3397 (save-restriction
e0dc0c55 3398 (narrow-to-region (if mark-active (region-beginning)
7fbf4804 3399 (bibtex-beginning-of-first-entry))
e0dc0c55 3400 (if mark-active (region-end) (point-max)))
7fbf4804
SM
3401
3402 ;; looking if entries fit syntactical structure
3403 (goto-char (point-min))
3404 (bibtex-progress-message "Checking syntactical structure")
3405 (let (bibtex-sort-ignore-string-entries)
3406 (while (re-search-forward "^[ \t]*@" nil t)
3407 (bibtex-progress-message)
3408 (forward-char -1)
3409 (let ((pnt (point)))
3410 (if (not (looking-at bibtex-any-valid-entry-re))
3411 (forward-char)
3412 (bibtex-skip-to-valid-entry)
3413 (if (equal (point) pnt)
3414 (forward-char)
3415 (goto-char pnt)
e0dc0c55 3416 (push (cons (bibtex-current-line)
7fbf4804
SM
3417 "Syntax error (check esp. commas, braces, and quotes)")
3418 error-list)
3419 (forward-char))))))
3420 (bibtex-progress-message 'done)
3421
3422 (if error-list
e0dc0c55 3423 ;; proceed only if there were no syntax errors.
7fbf4804 3424 (setq syntax-error t)
e0dc0c55
SM
3425
3426 ;; looking for duplicate keys and correct sort order
3427 (let (previous current key-list)
3428 (bibtex-progress-message "Checking for duplicate keys")
3429 (bibtex-map-entries
3430 (lambda (key beg end)
3431 (bibtex-progress-message)
3432 (goto-char beg)
3433 (setq current (bibtex-entry-index))
3434 (cond ((not previous))
3435 ((member key key-list)
3436 (push (cons (bibtex-current-line)
3437 (format "Duplicate key `%s'" key))
3438 error-list))
3439 ((and bibtex-maintain-sorted-entries
3440 (not (bibtex-lessp previous current)))
3441 (push (cons (bibtex-current-line)
3442 "Entries out of order")
3443 error-list)))
3444 (push key key-list)
3445 (setq previous current)))
3446 (bibtex-progress-message 'done))
3447
3448 ;; Check for duplicate keys in `bibtex-files'.
3449 (bibtex-parse-keys)
02c8032e
SM
3450 ;; We don't want to be fooled by outdated `bibtex-reference-keys'.
3451 (dolist (buffer (bibtex-files-expand nil t))
3452 (dolist (key (with-current-buffer buffer bibtex-reference-keys))
e0dc0c55
SM
3453 (when (and (cdr key)
3454 (cdr (assoc-string (car key) bibtex-reference-keys)))
3455 (bibtex-find-entry (car key))
3456 (push (cons (bibtex-current-line)
3457 (format "Duplicate key `%s' in %s" (car key)
3458 (abbreviate-file-name (buffer-file-name buffer))))
3459 error-list))))
7fbf4804
SM
3460
3461 (when test-thoroughly
7fbf4804
SM
3462 (bibtex-progress-message
3463 "Checking required fields and month fields")
d528bff7 3464 (let ((bibtex-sort-ignore-string-entries t))
55fe21fc 3465 (bibtex-map-entries
d715b065 3466 (lambda (key beg end)
50e4b39e 3467 (bibtex-progress-message)
d715b065 3468 (let* ((entry-list (progn
7fbf4804
SM
3469 (goto-char beg)
3470 (bibtex-search-entry nil end)
c2fb6415
RS
3471 (assoc-string (bibtex-type-in-head)
3472 bibtex-entry-field-alist t)))
7fbf4804
SM
3473 (req (copy-sequence (elt (elt entry-list 1) 0)))
3474 (creq (copy-sequence (elt (elt entry-list 2) 0)))
e0dc0c55 3475 crossref-there bounds alt-there field)
7fbf4804
SM
3476 (goto-char beg)
3477 (while (setq bounds (bibtex-search-forward-field
3478 bibtex-field-name end))
3479 (goto-char (bibtex-start-of-text-in-field bounds))
d528bff7
SM
3480 (let ((field-name (bibtex-name-in-field bounds)))
3481 (if (and (bibtex-string= field-name "month")
e0dc0c55
SM
3482 ;; Check only abbreviated month fields.
3483 (let ((month (bibtex-text-in-field-bounds bounds)))
3484 (not (or (string-match "\\`[\"{].+[\"}]\\'" month)
3485 (assoc-string
3486 month
3487 bibtex-predefined-month-strings t)))))
3488 (push (cons (bibtex-current-line)
7fbf4804
SM
3489 "Questionable month field")
3490 error-list))
e0dc0c55
SM
3491 (setq field (assoc-string field-name req t))
3492 (if (nth 3 field)
3493 (if alt-there (push (cons (bibtex-current-line)
3494 "More than one non-empty alternative")
3495 error-list)
3496 (setq alt-there t)))
3497 (setq req (delete field req)
c2fb6415 3498 creq (delete (assoc-string field-name creq t) creq))
d528bff7 3499 (if (bibtex-string= field-name "crossref")
7fbf4804
SM
3500 (setq crossref-there t))))
3501 (if crossref-there
3502 (setq req creq))
e0dc0c55
SM
3503 (let (alt)
3504 (dolist (field req)
3505 (if (nth 3 field)
3506 (push (car field) alt)
3507 (push (cons (save-excursion (goto-char beg)
3508 (bibtex-current-line))
3509 (format "Required field `%s' missing"
3510 (car field)))
3511 error-list)))
3512 ;; The following fails if there are more than two
3513 ;; alternatives in a BibTeX entry, which isn't
3514 ;; the case momentarily.
3515 (if (cdr alt)
3516 (push (cons (save-excursion (goto-char beg)
3517 (bibtex-current-line))
3518 (format "Alternative fields `%s'/`%s' missing"
3519 (car alt) (cadr alt)))
3520 error-list)))))))
7fbf4804 3521 (bibtex-progress-message 'done)))))
e0dc0c55 3522
50e4b39e 3523 (if error-list
e0dc0c55
SM
3524 (let ((file (file-name-nondirectory (buffer-file-name)))
3525 (dir default-directory)
3526 (err-buf "*BibTeX validation errors*"))
3527 (setq error-list (sort error-list 'car-less-than-car))
3528 (with-current-buffer (get-buffer-create err-buf)
3529 (setq default-directory dir)
3530 (unless (eq major-mode 'compilation-mode) (compilation-mode))
3531 (toggle-read-only -1)
3532 (delete-region (point-min) (point-max))
3533 (insert "BibTeX mode command `bibtex-validate'\n"
3534 (if syntax-error
3535 "Maybe undetected errors due to syntax errors. Correct and validate again.\n"
3536 "\n"))
3537 (dolist (err error-list)
3538 (insert (format "%s:%d: %s\n" file (car err) (cdr err))))
3539 (set-buffer-modified-p nil)
3540 (toggle-read-only 1)
3541 (goto-line 3)) ; first error message
3542 (display-buffer err-buf)
3543 ;; return nil
3544 nil)
3545 (message "%s is syntactically correct"
3546 (if mark-active "Region" "Buffer"))
3547 t)))
3548
3549(defun bibtex-validate-globally (&optional strings)
3550 "Check for duplicate keys in `bibtex-files'.
02c8032e 3551With optional prefix arg STRINGS, check for duplicate strings, too.
e0dc0c55
SM
3552Return t if test was successful, nil otherwise."
3553 (interactive "P")
3554 (let ((buffer-list (bibtex-files-expand t))
3555 buffer-key-list current-buf current-keys error-list)
3556 ;; Check for duplicate keys within BibTeX buffer
3557 (dolist (buffer buffer-list)
3558 (save-excursion
3559 (set-buffer buffer)
3560 (let (entry-type key key-list)
50e4b39e 3561 (goto-char (point-min))
e0dc0c55
SM
3562 (while (re-search-forward bibtex-entry-head nil t)
3563 (setq entry-type (bibtex-type-in-head)
3564 key (bibtex-key-in-head))
3565 (if (or (and strings (bibtex-string= entry-type "string"))
3566 (assoc-string entry-type bibtex-entry-field-alist t))
3567 (if (member key key-list)
3568 (push (format "%s:%d: Duplicate key `%s'\n"
3569 (buffer-file-name)
3570 (bibtex-current-line) key)
3571 error-list)
3572 (push key key-list))))
3573 (push (cons buffer key-list) buffer-key-list))))
3574
3575 ;; Check for duplicate keys among BibTeX buffers
3576 (while (setq current-buf (pop buffer-list))
3577 (setq current-keys (cdr (assq current-buf buffer-key-list)))
3578 (with-current-buffer current-buf
3579 (dolist (buffer buffer-list)
3580 (dolist (key (cdr (assq buffer buffer-key-list)))
3581 (when (assoc-string key current-keys)
3582 (bibtex-find-entry key)
3583 (push (format "%s:%d: Duplicat key `%s' in %s\n"
3584 (buffer-file-name) (bibtex-current-line) key
3585 (abbreviate-file-name (buffer-file-name buffer)))
3586 error-list))))))
3587
3588 ;; Process error list
3589 (if error-list
3590 (let ((err-buf "*BibTeX validation errors*"))
3591 (with-current-buffer (get-buffer-create err-buf)
3592 (unless (eq major-mode 'compilation-mode) (compilation-mode))
3593 (toggle-read-only -1)
3594 (delete-region (point-min) (point-max))
3595 (insert "BibTeX mode command `bibtex-validate-globally'\n\n")
3596 (dolist (err (sort error-list 'string-lessp)) (insert err))
3597 (set-buffer-modified-p nil)
3598 (toggle-read-only 1)
3599 (goto-line 3)) ; first error message
3600 (display-buffer err-buf)
50e4b39e
RS
3601 ;; return nil
3602 nil)
e0dc0c55 3603 (message "No duplicate keys.")
50e4b39e 3604 t)))
745bc783 3605
02c8032e
SM
3606(defun bibtex-next-field (begin)
3607 "Move point to end of text of next BibTeX field.
3608With prefix BEGIN non-nil, move point to its beginning."
745bc783
JB
3609 (interactive "P")
3610 (bibtex-inside-field)
3611 (let ((start (point)))
3612 (condition-case ()
7fbf4804
SM
3613 (let ((bounds (bibtex-enclosing-field)))
3614 (goto-char (bibtex-end-of-field bounds))
3615 (forward-char 2))
745bc783
JB
3616 (error
3617 (goto-char start)
3618 (end-of-line)
50e4b39e 3619 (forward-char))))
02c8032e 3620 (bibtex-find-text begin))
745bc783 3621
02c8032e
SM
3622(defun bibtex-find-text (&optional begin noerror)
3623 "Move point to end of text of current BibTeX field.
3624With optional prefix BEGIN non-nil, move point to its beginning.
3625Unless NOERROR is non-nil, an error is signaled if point is not
3626on a BibTeX field."
3627 (interactive "P")
3628 (let* ((pnt (point))
3629 (_ (bibtex-inside-field))
3630 (bounds (bibtex-enclosing-field t)))
3631 (beginning-of-line)
3632 (cond (bounds
3633 (if begin
3634 (progn (goto-char (bibtex-start-of-text-in-field bounds))
3635 (if (looking-at "[{\"]")
3636 (forward-char)))
3637 (goto-char (bibtex-end-of-text-in-field bounds))
3638 (if (or (= (preceding-char) ?})
3639 (= (preceding-char) ?\"))
3640 (forward-char -1)))
3641 (if bibtex-help-message
3642 (bibtex-print-help-message)))
3643 ((setq bounds (bibtex-parse-string))
3644 (goto-char (if begin
3645 (1+ (bibtex-start-of-text-in-string bounds))
3646 (1- (bibtex-end-of-text-in-string bounds)))))
3647 ((looking-at bibtex-entry-maybe-empty-head)
3648 (goto-char (if begin
3649 (match-beginning bibtex-key-in-head)
3650 (match-end 0))))
3651 (t
3652 (goto-char pnt)
3653 (unless noerror (error "Not on BibTeX field"))))))
50e4b39e
RS
3654
3655(defun bibtex-remove-OPT-or-ALT ()
7fbf4804
SM
3656 "Remove the string starting optional/alternative fields.
3657Align text and go thereafter to end of text."
745bc783 3658 (interactive)
f9bd4abe 3659 (bibtex-inside-field)
7fbf4804
SM
3660 (let ((case-fold-search t)
3661 (bounds (bibtex-enclosing-field)))
50e4b39e 3662 (save-excursion
f9bd4abe 3663 (goto-char (bibtex-start-of-name-in-field bounds))
7fbf4804 3664 (when (looking-at "OPT\\|ALT")
d715b065 3665 (delete-region (match-beginning 0) (match-end 0))
7fbf4804
SM
3666 ;; make field non-OPT
3667 (search-forward "=")
3668 (forward-char -1)
3669 (delete-horizontal-space)
3670 (if bibtex-align-at-equal-sign
3671 (indent-to-column (- bibtex-text-indentation 2))
3672 (insert " "))
3673 (search-forward "=")
3674 (delete-horizontal-space)
3675 (if bibtex-align-at-equal-sign
3676 (insert " ")
3677 (indent-to-column bibtex-text-indentation))))
50e4b39e
RS
3678 (bibtex-inside-field)))
3679
3680(defun bibtex-remove-delimiters ()
7fbf4804 3681 "Remove \"\" or {} around string."
745bc783 3682 (interactive)
f9bd4abe
GM
3683 (save-excursion
3684 (bibtex-inside-field)
d528bff7
SM
3685 (let* ((bounds (bibtex-enclosing-field))
3686 (end (bibtex-end-of-text-in-field bounds))
3687 (start (bibtex-start-of-text-in-field bounds)))
3688 (if (memq (char-before end) '(?\} ?\"))
3689 (delete-region (1- end) end))
3690 (if (memq (char-after start) '(?\{ ?\"))
3691 (delete-region start (1+ start))))))
50e4b39e
RS
3692
3693(defun bibtex-kill-field (&optional copy-only)
7fbf4804
SM
3694 "Kill the entire enclosing BibTeX field.
3695With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring',
d0388eac 3696but do not actually kill it."
50e4b39e 3697 (interactive "P")
7fbf4804 3698 (save-excursion
745bc783 3699 (bibtex-inside-field)
7fbf4804
SM
3700 (let* ((case-fold-search t)
3701 (bounds (bibtex-enclosing-field))
3702 (end (bibtex-end-of-field bounds))
3703 (beg (bibtex-start-of-field bounds)))
3704 (goto-char end)
50e4b39e 3705 (skip-chars-forward " \t\n,")
02c8032e 3706 (push (list (bibtex-name-in-field bounds) nil
7fbf4804
SM
3707 (bibtex-text-in-field-bounds bounds))
3708 bibtex-field-kill-ring)
50e4b39e 3709 (if (> (length bibtex-field-kill-ring) bibtex-field-kill-ring-max)
7fbf4804
SM
3710 (setcdr (nthcdr (1- bibtex-field-kill-ring-max)
3711 bibtex-field-kill-ring)
3712 nil))
50e4b39e 3713 (setq bibtex-field-kill-ring-yank-pointer bibtex-field-kill-ring)
7fbf4804
SM
3714 (unless copy-only
3715 (delete-region beg end))))
50e4b39e
RS
3716 (setq bibtex-last-kill-command 'field))
3717
3718(defun bibtex-copy-field-as-kill ()
02c8032e 3719 "Copy the BibTeX field at point to the kill ring."
50e4b39e
RS
3720 (interactive)
3721 (bibtex-kill-field t))
745bc783 3722
50e4b39e 3723(defun bibtex-kill-entry (&optional copy-only)
f9bd4abe 3724 "Kill the entire enclosing BibTeX entry.
02c8032e
SM
3725With prefix arg COPY-ONLY, copy the current entry to `bibtex-entry-kill-ring',
3726but do not actually kill it."
50e4b39e 3727 (interactive "P")
7fbf4804
SM
3728 (save-excursion
3729 (let* ((case-fold-search t)
3730 (beg (bibtex-beginning-of-entry))
3731 (end (progn (bibtex-end-of-entry)
3732 (if (re-search-forward
3733 bibtex-entry-maybe-empty-head nil 'move)
3734 (goto-char (match-beginning 0)))
3735 (point))))
02c8032e 3736 (push (buffer-substring-no-properties beg end)
7fbf4804
SM
3737 bibtex-entry-kill-ring)
3738 (if (> (length bibtex-entry-kill-ring) bibtex-entry-kill-ring-max)
3739 (setcdr (nthcdr (1- bibtex-entry-kill-ring-max)
3740 bibtex-entry-kill-ring)
3741 nil))
e0dc0c55
SM
3742 (setq bibtex-entry-kill-ring-yank-pointer bibtex-entry-kill-ring)
3743 (unless copy-only
3744 (delete-region beg end))))
50e4b39e
RS
3745 (setq bibtex-last-kill-command 'entry))
3746
3747(defun bibtex-copy-entry-as-kill ()
d528bff7 3748 "Copy the entire enclosing BibTeX entry to `bibtex-entry-kill-ring'."
745bc783 3749 (interactive)
50e4b39e
RS
3750 (bibtex-kill-entry t))
3751
3752(defun bibtex-yank (&optional n)
3753 "Reinsert the last BibTeX item.
3754More precisely, reinsert the field or entry killed or yanked most recently.
3755With argument N, reinsert the Nth most recently killed BibTeX item.
3756See also the command \\[bibtex-yank-pop]]."
3757 (interactive "*p")
02c8032e 3758 (bibtex-insert-kill (1- n))
f0cb6034 3759 (setq this-command 'bibtex-yank))
50e4b39e
RS
3760
3761(defun bibtex-yank-pop (n)
02c8032e 3762 "Replace just-yanked killed BibTeX item with a different item.
50e4b39e 3763This command is allowed only immediately after a `bibtex-yank' or a
02c8032e
SM
3764`bibtex-yank-pop'. At such a time, the region contains a reinserted
3765previously killed BibTeX item. `bibtex-yank-pop' deletes that item
3766and inserts in its place a different killed BibTeX item.
50e4b39e
RS
3767
3768With no argument, the previous kill is inserted.
3769With argument N, insert the Nth previous kill.
3770If N is negative, this is a more recent kill.
3771
3772The sequence of kills wraps around, so that after the oldest one
3773comes the newest one."
3774 (interactive "*p")
d528bff7
SM
3775 (unless (eq last-command 'bibtex-yank)
3776 (error "Previous command was not a BibTeX yank"))
50e4b39e
RS
3777 (setq this-command 'bibtex-yank)
3778 (let ((inhibit-read-only t))
3779 (delete-region (point) (mark t))
02c8032e 3780 (bibtex-insert-kill n)))
745bc783
JB
3781
3782(defun bibtex-empty-field ()
cb4ad359 3783 "Delete the text part of the current field, replace with empty text."
745bc783
JB
3784 (interactive)
3785 (bibtex-inside-field)
f9bd4abe
GM
3786 (let ((bounds (bibtex-enclosing-field)))
3787 (goto-char (bibtex-start-of-text-in-field bounds))
3788 (delete-region (point) (bibtex-end-of-text-in-field bounds))
3789 (insert (concat (bibtex-field-left-delimiter)
7fbf4804 3790 (bibtex-field-right-delimiter)) )
f9bd4abe 3791 (bibtex-find-text t)))
745bc783 3792
31bc4210 3793(defun bibtex-pop-previous (arg)
d0388eac 3794 "Replace text of current field with the similar field in previous entry.
f0cb6034 3795With arg, goes up ARG entries. Repeated, goes up so many times. May be
31bc4210
RS
3796intermixed with \\[bibtex-pop-next] (bibtex-pop-next)."
3797 (interactive "p")
3798 (bibtex-pop arg 'previous))
745bc783
JB
3799
3800(defun bibtex-pop-next (arg)
3801 "Replace text of current field with the text of similar field in next entry.
f0cb6034 3802With arg, goes down ARG entries. Repeated, goes down so many times. May be
745bc783
JB
3803intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)."
3804 (interactive "p")
31bc4210 3805 (bibtex-pop arg 'next))
745bc783 3806
7fbf4804 3807(defun bibtex-clean-entry (&optional new-key called-by-reformat)
cb4ad359 3808 "Finish editing the current BibTeX entry and clean it up.
d715b065 3809Check that no required fields are empty and formats entry dependent
7fbf4804 3810on the value of `bibtex-entry-format'.
f9bd4abe 3811If the reference key of the entry is empty or a prefix argument is given,
d10e87a2 3812calculate a new reference key. (Note: this works only if fields in entry
7fbf4804
SM
3813begin on separate lines prior to calling `bibtex-clean-entry' or if
3814'realign is contained in `bibtex-entry-format'.)
d715b065 3815Don't call `bibtex-clean-entry' on @Preamble entries.
50e4b39e 3816At end of the cleaning process, the functions in
7fbf4804
SM
3817`bibtex-clean-entry-hook' are called with region narrowed to entry."
3818 ;; Opt. arg called-by-reformat is t if bibtex-clean-entry
3819 ;; is called by bibtex-reformat
cb4ad359 3820 (interactive "P")
7fbf4804 3821 (let ((case-fold-search t)
02c8032e
SM
3822 (start (bibtex-beginning-of-entry))
3823 (_ (looking-at bibtex-entry-maybe-empty-head))
3824 (entry-type (bibtex-type-in-head))
3825 (key (bibtex-key-in-head)))
d715b065 3826 ;; formatting
d528bff7 3827 (cond ((bibtex-string= entry-type "preamble")
d715b065
KG
3828 ;; (bibtex-format-preamble)
3829 (error "No clean up of @Preamble entries"))
02c8032e
SM
3830 ((bibtex-string= entry-type "string")
3831 (setq entry-type 'string))
e0dc0c55 3832 ;; (bibtex-format-string)
d715b065
KG
3833 (t (bibtex-format-entry)))
3834 ;; set key
7fbf4804 3835 (when (or new-key (not key))
d715b065 3836 (setq key (bibtex-generate-autokey))
d528bff7
SM
3837 ;; Sometimes bibtex-generate-autokey returns an empty string
3838 (if (or bibtex-autokey-edit-before-use (string= "" key))
02c8032e
SM
3839 (setq key (if (eq entry-type 'string)
3840 (bibtex-read-string-key key)
3841 (bibtex-read-key "Key to use: " key))))
3842 (save-excursion
3843 (re-search-forward (if (eq entry-type 'string)
3844 bibtex-string-maybe-empty-head
3845 bibtex-entry-maybe-empty-head))
3846 (if (match-beginning bibtex-key-in-head)
3847 (delete-region (match-beginning bibtex-key-in-head)
3848 (match-end bibtex-key-in-head)))
3849 (insert key)))
e0dc0c55 3850
4f9ae122 3851 (unless called-by-reformat
02c8032e
SM
3852 (let* ((end (save-excursion
3853 (bibtex-end-of-entry)
3854 (if (re-search-forward
3855 bibtex-entry-maybe-empty-head nil 'move)
3856 (goto-char (match-beginning 0)))
3857 (point)))
4f9ae122 3858 (entry (buffer-substring start end))
e0dc0c55
SM
3859 ;; include the crossref key in index
3860 (index (let ((bibtex-maintain-sorted-entries 'crossref))
02c8032e 3861 (bibtex-entry-index))) ; moves point to end of head
d528bff7 3862 error)
e0dc0c55 3863 ;; sorting
4f9ae122
SM
3864 (if (and bibtex-maintain-sorted-entries
3865 (not (and bibtex-sort-ignore-string-entries
02c8032e 3866 (eq entry-type 'string))))
4f9ae122
SM
3867 (progn
3868 (delete-region start end)
02c8032e
SM
3869 (setq error (not (bibtex-prepare-new-entry index))
3870 start (point)) ; update start
3871 (save-excursion (insert entry)))
d528bff7
SM
3872 (bibtex-find-entry key)
3873 (setq error (or (/= (point) start)
02c8032e 3874 (bibtex-find-entry key nil end))))
d528bff7 3875 (if error
e0dc0c55
SM
3876 (error "New inserted entry yields duplicate key"))
3877 (dolist (buffer (bibtex-files-expand))
3878 (with-current-buffer buffer
3879 (if (cdr (assoc-string key bibtex-reference-keys))
3880 (error "Duplicate key in %s" (buffer-file-name)))))
3881
3882 ;; Only update the list of keys if it has been built already.
02c8032e 3883 (cond ((eq entry-type 'string)
e0dc0c55
SM
3884 (if (and (listp bibtex-strings)
3885 (not (assoc key bibtex-strings)))
02c8032e
SM
3886 (push (cons key (bibtex-text-in-string
3887 (save-excursion (bibtex-parse-string)) t))
3888 bibtex-strings)))
e0dc0c55
SM
3889 ;; We have a normal entry.
3890 ((listp bibtex-reference-keys)
3891 (cond ((not (assoc key bibtex-reference-keys))
3892 (push (cons key t) bibtex-reference-keys))
3893 ((not (cdr (assoc key bibtex-reference-keys)))
3894 ;; Turn a crossref key into a header key
3895 (setq bibtex-reference-keys
3896 (cons (cons key t)
3897 (delete (list key) bibtex-reference-keys)))))
3898 ;; Handle crossref key.
3899 (if (and (nth 1 index)
3900 (not (assoc (nth 1 index) bibtex-reference-keys)))
3901 (push (list (nth 1 index)) bibtex-reference-keys)))))
3902
3903 ;; final clean up
3904 (if bibtex-clean-entry-hook
3905 (save-excursion
3906 (save-restriction
3907 (bibtex-narrow-to-entry)
3908 (run-hooks 'bibtex-clean-entry-hook)))))))
50e4b39e 3909
d715b065
KG
3910(defun bibtex-fill-field-bounds (bounds justify &optional move)
3911 "Fill BibTeX field delimited by BOUNDS.
3912If JUSTIFY is non-nil justify as well.
3913If optional arg MOVE is non-nil move point to end of field."
3914 (let ((end-field (copy-marker (bibtex-end-of-field bounds))))
3915 (goto-char (bibtex-start-of-field bounds))
3916 (if justify
3917 (progn
3918 (forward-char)
3919 (bibtex-delete-whitespace)
3920 (open-line 1)
3921 (forward-char)
3922 (indent-to-column (+ bibtex-entry-offset
3923 bibtex-field-indentation))
3924 (re-search-forward "[ \t\n]*=" end-field)
3925 (replace-match "=")
3926 (forward-char -1)
3927 (if bibtex-align-at-equal-sign
3928 (indent-to-column
3929 (+ bibtex-entry-offset (- bibtex-text-indentation 2)))
3930 (insert " "))
3931 (forward-char)
3932 (bibtex-delete-whitespace)
3933 (if bibtex-align-at-equal-sign
3934 (insert " ")
3935 (indent-to-column bibtex-text-indentation)))
3936 (re-search-forward "[ \t\n]*=[ \t\n]*" end-field))
3937 (while (re-search-forward "[ \t\n]+" end-field 'move)
3938 (replace-match " "))
3939 (do-auto-fill)
3940 (if move (goto-char end-field))))
3941
3942(defun bibtex-fill-field (&optional justify)
3943 "Like \\[fill-paragraph], but fill current BibTeX field.
3944Optional prefix arg JUSTIFY non-nil means justify as well.
3945In BibTeX mode this function is bound to `fill-paragraph-function'."
3946 (interactive "*P")
3947 (let ((pnt (copy-marker (point)))
3948 (bounds (bibtex-enclosing-field)))
3949 (when bounds
3950 (bibtex-fill-field-bounds bounds justify)
3951 (goto-char pnt))))
3952
50e4b39e 3953(defun bibtex-fill-entry ()
7fbf4804
SM
3954 "Fill current BibTeX entry.
3955Realign entry, so that every field starts on a separate line. Field
d0388eac 3956names appear in column `bibtex-field-indentation', field text starts in
f0cb6034 3957column `bibtex-text-indentation' and continuation lines start here, too.
d715b065 3958If `bibtex-align-at-equal-sign' is non-nil, align equal signs, too."
50e4b39e
RS
3959 (interactive "*")
3960 (let ((pnt (copy-marker (point)))
7fbf4804
SM
3961 (end (copy-marker (bibtex-end-of-entry)))
3962 bounds)
50e4b39e 3963 (bibtex-beginning-of-entry)
55fe21fc 3964 (bibtex-delete-whitespace)
50e4b39e 3965 (indent-to-column bibtex-entry-offset)
7fbf4804 3966 (while (setq bounds (bibtex-search-forward-field bibtex-field-name end))
d715b065 3967 (bibtex-fill-field-bounds bounds t t))
50e4b39e
RS
3968 (if (looking-at ",")
3969 (forward-char))
55fe21fc 3970 (bibtex-delete-whitespace)
50e4b39e
RS
3971 (open-line 1)
3972 (forward-char)
3973 (indent-to-column bibtex-entry-offset)
3974 (goto-char pnt)))
3975
4f9ae122
SM
3976(defun bibtex-realign ()
3977 "Realign BibTeX entries such that they are separated by one blank line."
3978 (goto-char (point-min))
3979 (let ((case-fold-search t))
e0dc0c55
SM
3980 ;; No blank lines prior to the first valid entry if there no
3981 ;; non-white characters in front of it.
4f9ae122
SM
3982 (when (looking-at bibtex-valid-entry-whitespace-re)
3983 (replace-match "\\1"))
e0dc0c55 3984 ;; Valid entries are separated by one blank line.
4f9ae122 3985 (while (re-search-forward bibtex-valid-entry-whitespace-re nil t)
e0dc0c55
SM
3986 (replace-match "\n\n\\1"))
3987 ;; One blank line past the last valid entry if it is followed by
3988 ;; non-white characters, no blank line otherwise.
3989 (beginning-of-line)
3990 (when (re-search-forward bibtex-valid-entry-re nil t)
3991 (bibtex-end-of-entry)
3992 (bibtex-delete-whitespace)
3993 (open-line (if (eobp) 1 2)))))
4f9ae122
SM
3994
3995(defun bibtex-reformat (&optional read-options)
d0388eac 3996 "Reformat all BibTeX entries in buffer or region.
e0dc0c55 3997Without prefix argument, reformatting is based on `bibtex-entry-format'.
d0388eac 3998With prefix argument, read options for reformatting from minibuffer.
f0cb6034 3999With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again.
4f9ae122 4000If mark is active reformat entries in region, if not in whole buffer."
50e4b39e
RS
4001 (interactive "*P")
4002 (let* ((pnt (point))
4003 (use-previous-options
4f9ae122 4004 (and (equal (prefix-numeric-value read-options) 16)
50e4b39e 4005 (or bibtex-reformat-previous-options
f9bd4abe 4006 bibtex-reformat-previous-reference-keys)))
50e4b39e 4007 (bibtex-entry-format
e0dc0c55
SM
4008 (cond (read-options
4009 (if use-previous-options
4010 bibtex-reformat-previous-options
4011 (setq bibtex-reformat-previous-options
4012 (mapcar (lambda (option)
4013 (if (y-or-n-p (car option)) (cdr option)))
4014 `(("Realign entries (recommended)? " . 'realign)
4015 ("Remove empty optional and alternative fields? " . 'opts-or-alts)
4016 ("Remove delimiters around pure numerical fields? " . 'numerical-fields)
4017 (,(concat (if bibtex-comma-after-last-field "Insert" "Remove")
4018 " comma at end of entry? ") . 'last-comma)
4019 ("Replace double page dashes by single ones? " . 'page-dashes)
4020 ("Inherit booktitle? " . 'inherit-booktitle)
4021 ("Force delimiters? " . 'delimiters)
4022 ("Unify case of entry types and field names? " . 'unify-case))))))
4023 ;; Do not include required-fields because `bibtex-reformat'
4024 ;; cannot handle the error messages of `bibtex-format-entry'.
4025 ;; Use `bibtex-validate' to check for required fields.
4026 ((eq t bibtex-entry-format)
4027 '(realign opts-or-alts numerical-fields delimiters
4028 last-comma page-dashes unify-case inherit-booktitle))
4029 (t
4030 (remove 'required-fields (push 'realign bibtex-entry-format)))))
4f9ae122
SM
4031 (reformat-reference-keys
4032 (if read-options
4033 (if use-previous-options
4034 bibtex-reformat-previous-reference-keys
4035 (setq bibtex-reformat-previous-reference-keys
4036 (y-or-n-p "Generate new reference keys automatically? ")))))
4f9ae122
SM
4037 (bibtex-sort-ignore-string-entries t)
4038 bibtex-autokey-edit-before-use)
4039
50e4b39e 4040 (save-restriction
e0dc0c55
SM
4041 (narrow-to-region (if mark-active (region-beginning) (point-min))
4042 (if mark-active (region-end) (point-max)))
4f9ae122 4043 (if (memq 'realign bibtex-entry-format)
e0dc0c55 4044 (bibtex-realign))
50e4b39e 4045 (bibtex-progress-message "Formatting" 1)
d715b065 4046 (bibtex-map-entries (lambda (key beg end)
7fbf4804 4047 (bibtex-progress-message)
4f9ae122 4048 (bibtex-clean-entry reformat-reference-keys t)))
50e4b39e 4049 (bibtex-progress-message 'done))
e0dc0c55 4050 (when reformat-reference-keys
4f9ae122 4051 (kill-local-variable 'bibtex-reference-keys)
e0dc0c55
SM
4052 (when bibtex-maintain-sorted-entries
4053 (bibtex-progress-message "Sorting" 1)
4054 (bibtex-sort-buffer)
4055 (bibtex-progress-message 'done)))
50e4b39e
RS
4056 (goto-char pnt)))
4057
4f9ae122 4058(defun bibtex-convert-alien (&optional read-options)
d10e87a2 4059 "Make an alien BibTeX buffer fully usable by BibTeX mode.
4f9ae122 4060If a file does not conform with all standards used by BibTeX mode,
d10e87a2 4061some of the high-level features of BibTeX mode are not available.
7fbf4804 4062This function tries to convert current buffer to conform with these standards.
4f9ae122
SM
4063With prefix argument READ-OPTIONS non-nil, read options for reformatting
4064entries from minibuffer."
50e4b39e
RS
4065 (interactive "*P")
4066 (message "Starting to validate buffer...")
4067 (sit-for 1 nil t)
4f9ae122 4068 (bibtex-realign)
50e4b39e
RS
4069 (message
4070 "If errors occur, correct them and call `bibtex-convert-alien' again")
4071 (sit-for 5 nil t)
7fbf4804
SM
4072 (deactivate-mark) ; So bibtex-validate works on the whole buffer.
4073 (when (let (bibtex-maintain-sorted-entries)
4074 (bibtex-validate))
4075 (message "Starting to reformat entries...")
4076 (sit-for 2 nil t)
4f9ae122 4077 (bibtex-reformat read-options)
7fbf4804
SM
4078 (goto-char (point-max))
4079 (message "Buffer is now parsable. Please save it.")))
4080
4081(defun bibtex-complete ()
4082 "Complete word fragment before point according to context.
d715b065 4083If point is inside key or crossref field perform key completion based on
d528bff7
SM
4084`bibtex-reference-keys'. Inside a month field perform key completion
4085based on `bibtex-predefined-month-strings'. Inside any other field
4086perform string completion based on `bibtex-strings'. An error is
4087signaled if point is outside key or BibTeX field."
7fbf4804 4088 (interactive)
d528bff7
SM
4089 (let ((pnt (point))
4090 (case-fold-search t)
4091 bounds name compl)
7fbf4804
SM
4092 (save-excursion
4093 (if (and (setq bounds (bibtex-enclosing-field t))
4094 (>= pnt (bibtex-start-of-text-in-field bounds))
4095 (<= pnt (bibtex-end-of-text-in-field bounds)))
d528bff7
SM
4096 (setq name (bibtex-name-in-field bounds t)
4097 compl (cond ((bibtex-string= name "crossref")
02c8032e
SM
4098 ;; point is in crossref field
4099 'crossref-key)
d528bff7 4100 ((bibtex-string= name "month")
02c8032e 4101 ;; point is in month field
d528bff7 4102 bibtex-predefined-month-strings)
02c8032e 4103 ;; point is in other field
d528bff7
SM
4104 (t (if (listp bibtex-strings)
4105 bibtex-strings
4106 ;; so that bibtex-complete-string-cleanup
4107 ;; can do its job
4108 (bibtex-parse-strings
4109 (bibtex-string-files-init))))))
7fbf4804 4110 (bibtex-beginning-of-entry)
02c8032e
SM
4111 (cond ((and (looking-at bibtex-string-maybe-empty-head)
4112 ;; point is inside a string key
4113 (or (and (match-beginning bibtex-key-in-head)
4114 (>= pnt (match-beginning bibtex-key-in-head))
4115 (<= pnt (match-end bibtex-key-in-head)))
4116 ;; or point is on empty string key
4117 (and (not (match-beginning bibtex-key-in-head))
4118 (= pnt (match-end 0)))))
4119 (setq compl 'string))
4120 ((and (looking-at bibtex-entry-maybe-empty-head)
4121 ;; point is inside a key
4122 (or (and (match-beginning bibtex-key-in-head)
4123 (>= pnt (match-beginning bibtex-key-in-head))
4124 (<= pnt (match-end bibtex-key-in-head)))
4125 ;; or point is on empty key
4126 (and (not (match-beginning bibtex-key-in-head))
4127 (= pnt (match-end 0)))))
4128 (setq compl 'key)))))
4129
4130 (cond ((eq compl 'key)
4131 ;; key completion: no cleanup needed
4132 (let (completion-ignore-case)
4133 (bibtex-complete-internal (bibtex-global-key-alist))))
4134
4135 ((eq compl 'crossref-key)
4136 ;; crossref key completion
4137 (let (completion-ignore-case)
4138 (setq choose-completion-string-functions
4139 (lambda (choice buffer mini-p base-size)
4140 (let ((choose-completion-string-functions nil))
4141 (choose-completion-string choice buffer base-size))
4142 (bibtex-complete-crossref-cleanup choice)
4143 ;; return t (needed by choose-completion-string-functions)
4144 t))
4145 (bibtex-complete-crossref-cleanup (bibtex-complete-internal
4146 (bibtex-global-key-alist)))))
4147
4148 ((eq compl 'string)
4149 ;; string key completion: no cleanup needed
4150 (let ((completion-ignore-case t))
4151 (bibtex-complete-internal bibtex-strings)))
7fbf4804 4152
d528bff7 4153 (compl
7fbf4804 4154 ;; string completion
02c8032e
SM
4155 (let ((completion-ignore-case t))
4156 (setq choose-completion-string-functions
4157 `(lambda (choice buffer mini-p base-size)
4158 (let ((choose-completion-string-functions nil))
4159 (choose-completion-string choice buffer base-size))
4160 (bibtex-complete-string-cleanup choice ',compl)
4161 ;; return t (needed by choose-completion-string-functions)
4162 t))
4163 (bibtex-complete-string-cleanup (bibtex-complete-internal compl)
4164 compl)))
7fbf4804
SM
4165
4166 (t (error "Point outside key or BibTeX field")))))
745bc783 4167
cb4ad359 4168(defun bibtex-Article ()
f0cb6034 4169 "Insert a new BibTeX @Article entry; see also `bibtex-entry'."
7fbf4804 4170 (interactive "*")
cb4ad359 4171 (bibtex-entry "Article"))
2798dfd6 4172
cb4ad359 4173(defun bibtex-Book ()
f0cb6034 4174 "Insert a new BibTeX @Book entry; see also `bibtex-entry'."
7fbf4804 4175 (interactive "*")
cb4ad359 4176 (bibtex-entry "Book"))
2798dfd6 4177
cb4ad359 4178(defun bibtex-Booklet ()
f0cb6034 4179 "Insert a new BibTeX @Booklet entry; see also `bibtex-entry'."
7fbf4804 4180 (interactive "*")
cb4ad359
RS
4181 (bibtex-entry "Booklet"))
4182
4183(defun bibtex-InBook ()
f0cb6034 4184 "Insert a new BibTeX @InBook entry; see also `bibtex-entry'."
7fbf4804 4185 (interactive "*")
cb4ad359
RS
4186 (bibtex-entry "InBook"))
4187
4188(defun bibtex-InCollection ()
f0cb6034 4189 "Insert a new BibTeX @InCollection entry; see also `bibtex-entry'."
7fbf4804 4190 (interactive "*")
cb4ad359
RS
4191 (bibtex-entry "InCollection"))
4192
4193(defun bibtex-InProceedings ()
f0cb6034 4194 "Insert a new BibTeX @InProceedings entry; see also `bibtex-entry'."
7fbf4804 4195 (interactive "*")
cb4ad359
RS
4196 (bibtex-entry "InProceedings"))
4197
4198(defun bibtex-Manual ()
f0cb6034 4199 "Insert a new BibTeX @Manual entry; see also `bibtex-entry'."
7fbf4804 4200 (interactive "*")
cb4ad359
RS
4201 (bibtex-entry "Manual"))
4202
4203(defun bibtex-MastersThesis ()
f0cb6034 4204 "Insert a new BibTeX @MastersThesis entry; see also `bibtex-entry'."
7fbf4804 4205 (interactive "*")
cb4ad359
RS
4206 (bibtex-entry "MastersThesis"))
4207
4208(defun bibtex-Misc ()
f0cb6034 4209 "Insert a new BibTeX @Misc entry; see also `bibtex-entry'."
7fbf4804 4210 (interactive "*")
cb4ad359
RS
4211 (bibtex-entry "Misc"))
4212
4213(defun bibtex-PhdThesis ()
f0cb6034 4214 "Insert a new BibTeX @PhdThesis entry; see also `bibtex-entry'."
7fbf4804 4215 (interactive "*")
cb4ad359
RS
4216 (bibtex-entry "PhdThesis"))
4217
4218(defun bibtex-Proceedings ()
f0cb6034 4219 "Insert a new BibTeX @Proceedings entry; see also `bibtex-entry'."
7fbf4804 4220 (interactive "*")
cb4ad359
RS
4221 (bibtex-entry "Proceedings"))
4222
4223(defun bibtex-TechReport ()
f0cb6034 4224 "Insert a new BibTeX @TechReport entry; see also `bibtex-entry'."
7fbf4804 4225 (interactive "*")
cb4ad359
RS
4226 (bibtex-entry "TechReport"))
4227
4228(defun bibtex-Unpublished ()
f0cb6034 4229 "Insert a new BibTeX @Unpublished entry; see also `bibtex-entry'."
7fbf4804 4230 (interactive "*")
cb4ad359
RS
4231 (bibtex-entry "Unpublished"))
4232
7fbf4804
SM
4233(defun bibtex-String (&optional key)
4234 "Insert a new BibTeX @String entry with key KEY."
02c8032e 4235 (interactive (list (bibtex-read-string-key)))
7fbf4804 4236 (let ((bibtex-maintain-sorted-entries
d528bff7
SM
4237 (unless bibtex-sort-ignore-string-entries
4238 bibtex-maintain-sorted-entries))
7fbf4804
SM
4239 endpos)
4240 (unless (bibtex-prepare-new-entry (list key nil "String"))
4241 (error "Entry with key `%s' already exists" key))
4242 (if (zerop (length key)) (setq key nil))
50e4b39e 4243 (indent-to-column bibtex-entry-offset)
7fbf4804
SM
4244 (insert "@String"
4245 (bibtex-entry-left-delimiter))
4246 (if key
4247 (insert key)
4248 (setq endpos (point)))
4249 (insert " = "
4250 (bibtex-field-left-delimiter))
4251 (if key
4252 (setq endpos (point)))
4253 (insert (bibtex-field-right-delimiter)
4254 (bibtex-entry-right-delimiter)
4255 "\n")
4256 (goto-char endpos)))
50e4b39e
RS
4257
4258(defun bibtex-Preamble ()
f0cb6034 4259 "Insert a new BibTeX @Preamble entry."
7fbf4804 4260 (interactive "*")
cb4ad359 4261 (bibtex-move-outside-of-entry)
50e4b39e 4262 (indent-to-column bibtex-entry-offset)
7fbf4804 4263 (insert "@Preamble"
d715b065
KG
4264 (bibtex-entry-left-delimiter))
4265 (let ((endpos (point)))
4266 (insert (bibtex-entry-right-delimiter)
4267 "\n")
4268 (goto-char endpos)))
2798dfd6 4269
e0dc0c55
SM
4270(defun bibtex-url (&optional pos)
4271 "Browse a URL for the BibTeX entry at point.
4272Optional POS is the location of the BibTeX entry.
d528bff7 4273The URL is generated using the schemes defined in `bibtex-generate-url-list'
a9d77f1f 4274\(see there\). Then the URL is passed to `browse-url'."
e0dc0c55 4275 (interactive)
d528bff7 4276 (save-excursion
e0dc0c55 4277 (if pos (goto-char pos))
d528bff7
SM
4278 (bibtex-beginning-of-entry)
4279 (let ((fields-alist (bibtex-parse-entry))
e0dc0c55 4280 ;; Always ignore case,
d528bff7
SM
4281 (case-fold-search t)
4282 (lst bibtex-generate-url-list)
4283 field url scheme)
e0dc0c55 4284 (while (setq scheme (pop lst))
a9d77f1f
SM
4285 (when (and (setq field (cdr (assoc-string (caar scheme)
4286 fields-alist t)))
e0dc0c55 4287 ;; Always remove field delimiters
02c8032e 4288 (progn (setq field (bibtex-remove-delimiters-string field))
e0dc0c55
SM
4289 (string-match (cdar scheme) field)))
4290 (setq lst nil)
a9d77f1f
SM
4291 (if (null (cdr scheme))
4292 (setq url (match-string 0 field)))
d528bff7 4293 (dolist (step (cdr scheme))
e0dc0c55
SM
4294 (cond ((stringp step)
4295 (setq url (concat url step)))
4296 ((setq field (cdr (assoc-string (car step) fields-alist t)))
4297 ;; Always remove field delimiters
02c8032e 4298 (setq field (bibtex-remove-delimiters-string field))
e0dc0c55
SM
4299 (if (string-match (nth 1 step) field)
4300 (setq field (cond
4301 ((functionp (nth 2 step))
4302 (funcall (nth 2 step) field))
4303 ((numberp (nth 2 step))
4304 (match-string (nth 2 step) field))
4305 (t
02c8032e 4306 (replace-match (nth 2 step) t nil field))))
e0dc0c55
SM
4307 ;; If the scheme is set up correctly,
4308 ;; we should never reach this point
4309 (error "Match failed: %s" field))
4310 (setq url (concat url field)))
4311 ;; If the scheme is set up correctly,
4312 ;; we should never reach this point
4313 (t (error "Step failed: %s" step))))
4314 (message "%s" url)
4315 (browse-url url)))
4316 (unless url (message "No URL known.")))))
d528bff7 4317
745bc783 4318\f
5c69dbfc 4319;; Make BibTeX a Feature
cb4ad359
RS
4320
4321(provide 'bibtex)
745bc783 4322
8bf38a9b 4323;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04
9ae11a89 4324;;; bibtex.el ends here