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