(flyspell-large-region): Call ispell-check-version.
[bpt/emacs.git] / lisp / textmodes / bibtex.el
CommitLineData
c0274f38
ER
1;;; bibtex.el --- BibTeX mode for GNU Emacs
2
3731a850
TTN
3;; Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2002, 2003,
4;; 2004, 2005 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
1fdecd0c 1123 (concat "[ \t]*\\(" bibtex-valid-entry-re "\\)")
7fbf4804
SM
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
f5fab556
MY
2525 completions)
2526 part-of-word))
7fbf4804 2527 (message "Making completion list...done")
8bf38a9b 2528 ;; return value is handled by choose-completion-string-functions
7fbf4804
SM
2529 nil))))
2530
02c8032e 2531(defun bibtex-complete-string-cleanup (str compl)
d715b065 2532 "Cleanup after inserting string STR.
02c8032e
SM
2533Remove enclosing field delimiters for STR. Display message with
2534expansion of STR using expansion list COMPL."
2535 (save-excursion
2536 (bibtex-inside-field)
2537 (let ((bounds (bibtex-enclosing-field))
2538 (abbr (cdr (if (stringp str)
2539 (assoc-string str compl t)))))
2540 (if abbr (message "Abbreviation for `%s'" abbr))
2541 (goto-char (bibtex-start-of-text-in-field bounds))
2542 (let ((boundaries (bibtex-parse-field-string)))
2543 (if (and boundaries
2544 (equal (cdr boundaries)
2545 (bibtex-end-of-text-in-field bounds)))
2546 (bibtex-remove-delimiters))))))
2547
2548(defun bibtex-complete-crossref-cleanup (key)
e0dc0c55
SM
2549 "Display summary message on entry KEY after completion of a crossref key.
2550Use `bibtex-summary-function' to generate summary."
d528bff7 2551 (save-excursion
02c8032e
SM
2552 (if (and (stringp key)
2553 (bibtex-find-entry key t))
921a9483 2554 (message "Ref: %s" (funcall bibtex-summary-function)))))
02c8032e
SM
2555
2556(defun bibtex-copy-summary-as-kill ()
2557 "Push summery of current BibTeX entry to kill ring.
e0dc0c55 2558Use `bibtex-summary-function' to generate summary."
02c8032e 2559 (interactive)
921a9483
SM
2560 (save-excursion
2561 (bibtex-beginning-of-entry)
2562 (if (looking-at bibtex-entry-maybe-empty-head)
2563 (kill-new (message "%s" (funcall bibtex-summary-function)))
2564 (error "No entry found"))))
2565
2566(defun bibtex-summary ()
2567 "Return summary of current BibTeX entry.
e0dc0c55
SM
2568Used as default value of `bibtex-summary-function'."
2569 ;; It would be neat to customize this function. How?
1fdecd0c
RF
2570 (if (looking-at bibtex-entry-maybe-empty-head)
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 ""))
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)
9cee7d84 2665 (<= (point) bound)
e0dc0c55
SM
2666 (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t)
2667 (setq field (match-string-no-properties 1)))
2668 (setq bounds (bibtex-parse-field-text))
2669 (progn
2670 (setq start (car bounds) end (cdr bounds))
2671 ;; Always ignore field delimiters
2672 (if (memq (char-before end) '(?\} ?\"))
2673 (setq end (1- end)))
2674 (if (memq (char-after start) '(?\{ ?\"))
2675 (setq start (1+ start)))
2676 (>= bound start)))
2677 (let ((lst bibtex-generate-url-list) url)
2678 (goto-char start)
2679 (while (and (not found)
63d516ce 2680 (setq url (car (pop lst))))
e0dc0c55
SM
2681 (setq found (and (bibtex-string= field (car url))
2682 (re-search-forward (cdr url) end t)
63d516ce 2683 (>= (match-beginning 0) pnt)))))
e0dc0c55
SM
2684 (goto-char end))
2685 (if found (bibtex-button (match-beginning 0) (match-end 0)
2686 'bibtex-url (match-beginning 0)))
2687 found))
2688
2689(defun bibtex-font-lock-crossref (bound)
02c8032e 2690 "Font-lock for crossref fields. BOUND limits the search."
e0dc0c55
SM
2691 (let ((case-fold-search t)
2692 (pnt (point))
2693 (crossref-reg (concat "^[ \t]*crossref[ \t]*=[ \t\n]*"
2694 "\\(\"[^\"]*\"\\|{[^}]*}\\)[ \t\n]*[,})]"))
2695 start end found)
2696 (bibtex-beginning-of-field)
2697 (while (and (not found)
2698 (re-search-forward crossref-reg bound t))
2699 (setq start (1+ (match-beginning 1))
2700 end (1- (match-end 1))
2701 found (>= start pnt)))
2702 (if found (bibtex-button start end 'bibtex-find-crossref
2703 (buffer-substring-no-properties start end)
2704 start t))
2705 found))
2706
2707(defun bibtex-button-action (button)
2708 "Call BUTTON's BibTeX function."
2709 (apply (button-get button 'bibtex-function)
2710 (button-get button 'bibtex-args)))
2711
2712(define-button-type 'bibtex-url
2713 'action 'bibtex-button-action
2714 'bibtex-function 'bibtex-url
2715 'help-echo (purecopy "mouse-2, RET: follow URL"))
2716
2717(define-button-type 'bibtex-find-crossref
2718 'action 'bibtex-button-action
2719 'bibtex-function 'bibtex-find-crossref
2720 'help-echo (purecopy "mouse-2, RET: follow crossref"))
2721
2722(defun bibtex-button (beg end type &rest args)
02c8032e 2723 "Make a BibTeX button from BEG to END of type TYPE in the current buffer."
e0dc0c55
SM
2724 (make-text-button beg end 'type type 'bibtex-args args))
2725
50e4b39e
RS
2726\f
2727;; Interactive Functions:
2728
2729;;;###autoload
2730(defun bibtex-mode ()
2731 "Major mode for editing BibTeX files.
2732
50e4b39e
RS
2733General information on working with BibTeX mode:
2734
02c8032e
SM
2735Use commands such as \\[bibtex-Book] to get a template for a specific entry.
2736Then fill in all desired fields using \\[bibtex-next-field] to jump from field
2737to field. After having filled in all desired fields in the entry, clean the
2738new entry with the command \\[bibtex-clean-entry].
cb4ad359 2739
d715b065 2740Some features of BibTeX mode are available only by setting the variable
d10e87a2
SM
2741`bibtex-maintain-sorted-entries' to non-nil. However, then BibTeX mode
2742works only with buffers containing valid (syntactical correct) and sorted
2743entries. This is usually the case, if you have created a buffer completely
2744with BibTeX mode and finished every new entry with \\[bibtex-clean-entry].
50e4b39e 2745
921a9483 2746For third party BibTeX files, call the command \\[bibtex-convert-alien]
d715b065 2747to fully take advantage of all features of BibTeX mode.
50e4b39e
RS
2748
2749
2750Special information:
2751
d10e87a2 2752A command such as \\[bibtex-Book] outlines the fields for a BibTeX book entry.
cb4ad359 2753
02c8032e
SM
2754The names of optional fields start with the string OPT, and are thus ignored
2755by BibTeX. The names of alternative fields from which only one is required
2756start with the string ALT. The OPT or ALT string may be removed from
2757the name of a field with \\[bibtex-remove-OPT-or-ALT].
50e4b39e
RS
2758\\[bibtex-make-field] inserts a new field after the current one.
2759\\[bibtex-kill-field] kills the current field entirely.
d715b065 2760\\[bibtex-yank] yanks the last recently killed field after the current field.
50e4b39e 2761\\[bibtex-remove-delimiters] removes the double-quotes or braces around the text of the current field.
02c8032e
SM
2762\\[bibtex-empty-field] replaces the text of the current field with the default \"\" or {}.
2763\\[bibtex-find-text] moves point to the end of the current field.
2764\\[bibtex-complete] completes word fragment before point according to context.
50e4b39e
RS
2765
2766The command \\[bibtex-clean-entry] cleans the current entry, i.e. it removes OPT/ALT
02c8032e
SM
2767from the names of all non-empty optional or alternative fields, checks that
2768no required fields are empty, and does some formatting dependent on the value
2769of `bibtex-entry-format'. Furthermore, it can automatically generate a key
2770for the BibTeX entry, see `bibtex-generate-autokey'.
f0cb6034
RS
2771Note: some functions in BibTeX mode depend on entries being in a special
2772format (all fields beginning on separate lines), so it is usually a bad
7fbf4804 2773idea to remove `realign' from `bibtex-entry-format'.
cb4ad359 2774
02c8032e
SM
2775BibTeX mode supports Imenu and hideshow minor mode (`hs-minor-mode').
2776
2777----------------------------------------------------------
2778Entry to BibTeX mode calls the value of `bibtex-mode-hook'
2779if that value is non-nil.
50e4b39e 2780
f0cb6034 2781\\{bibtex-mode-map}"
cb4ad359
RS
2782 (interactive)
2783 (kill-all-local-variables)
2784 (use-local-map bibtex-mode-map)
2785 (setq major-mode 'bibtex-mode)
2786 (setq mode-name "BibTeX")
2787 (set-syntax-table bibtex-mode-syntax-table)
7fbf4804 2788 (make-local-variable 'bibtex-buffer-last-parsed-tick)
50e4b39e 2789 ;; Install stealthy parse function if not already installed
7fbf4804 2790 (unless bibtex-parse-idle-timer
e0dc0c55 2791 (setq bibtex-parse-idle-timer (run-with-idle-timer
7fbf4804
SM
2792 bibtex-parse-keys-timeout t
2793 'bibtex-parse-buffers-stealthily)))
2794 (set (make-local-variable 'paragraph-start) "[ \f\n\t]*$")
2795 (set (make-local-variable 'comment-start) bibtex-comment-start)
2796 (set (make-local-variable 'comment-start-skip)
2797 (concat (regexp-quote bibtex-comment-start) "\\>[ \t]*"))
2798 (set (make-local-variable 'comment-column) 0)
a172852f 2799 (set (make-local-variable 'defun-prompt-regexp) "^[ \t]*@[[:alnum:]]+[ \t]*")
7fbf4804 2800 (set (make-local-variable 'outline-regexp) "[ \t]*@")
d715b065 2801 (set (make-local-variable 'fill-paragraph-function) 'bibtex-fill-field)
7fbf4804 2802 (set (make-local-variable 'fill-prefix) (make-string (+ bibtex-entry-offset
e0dc0c55 2803 bibtex-contline-indentation)
ffe68348 2804 ?\s))
7fbf4804
SM
2805 (set (make-local-variable 'font-lock-defaults)
2806 '(bibtex-font-lock-keywords
2807 nil t ((?$ . "\"")
2808 ;; Mathematical expressions should be fontified as strings
2809 (?\" . ".")
2810 ;; Quotes are field delimiters and quote-delimited
2811 ;; entries should be fontified in the same way as
2812 ;; brace-delimited ones
2813 )
2814 nil
d715b065 2815 (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
e0dc0c55 2816 (font-lock-extra-managed-props . (category))
d715b065
KG
2817 (font-lock-mark-block-function
2818 . (lambda ()
d528bff7 2819 (set-mark (bibtex-end-of-entry))
d715b065 2820 (bibtex-beginning-of-entry)))))
50e4b39e 2821 (setq imenu-generic-expression
02c8032e
SM
2822 (list (list nil bibtex-entry-head bibtex-key-in-head))
2823 imenu-case-fold-search t)
7fbf4804 2824 (make-local-variable 'choose-completion-string-functions)
ab2d0cdb
RS
2825 ;; XEmacs needs easy-menu-add, Emacs does not care
2826 (easy-menu-add bibtex-edit-menu)
2827 (easy-menu-add bibtex-entry-menu)
a172852f 2828 (run-mode-hooks 'bibtex-mode-hook))
9ae11a89 2829
8bf38a9b
SM
2830(defun bibtex-field-list (entry-type)
2831 "Return list of allowed fields for entry ENTRY-TYPE.
2832More specifically, the return value is a cons pair (REQUIRED . OPTIONAL),
2833where REQUIRED and OPTIONAL are lists of the required and optional field
02c8032e
SM
2834names for ENTRY-TYPE according to `bibtex-entry-field-alist',
2835`bibtex-include-OPTkey', `bibtex-include-OPTcrossref',
2836and `bibtex-user-optional-fields'."
c2fb6415 2837 (let ((e (assoc-string entry-type bibtex-entry-field-alist t))
8bf38a9b
SM
2838 required optional)
2839 (unless e
31df23f5 2840 (error "BibTeX entry type %s not defined" entry-type))
8bf38a9b
SM
2841 (if (and (member-ignore-case entry-type bibtex-include-OPTcrossref)
2842 (nth 2 e))
2843 (setq required (nth 0 (nth 2 e))
2844 optional (nth 1 (nth 2 e)))
2845 (setq required (nth 0 (nth 1 e))
2846 optional (nth 1 (nth 1 e))))
2847 (if bibtex-include-OPTkey
2848 (push (list "key"
2849 "Used for reference key creation if author and editor fields are missing"
2850 (if (or (stringp bibtex-include-OPTkey)
2851 (fboundp bibtex-include-OPTkey))
2852 bibtex-include-OPTkey))
2853 optional))
2854 (if (member-ignore-case entry-type bibtex-include-OPTcrossref)
2855 (push '("crossref" "Reference key of the cross-referenced entry")
2856 optional))
2857 (setq optional (append optional bibtex-user-optional-fields))
2858 (cons required optional)))
2859
50e4b39e 2860(defun bibtex-entry (entry-type)
a9d77f1f 2861 "Insert a new BibTeX entry of type ENTRY-TYPE.
02c8032e
SM
2862After insertion call the value of `bibtex-add-entry-hook' if that value
2863is non-nil."
2864 (interactive
2865 (let ((completion-ignore-case t))
2866 (list (completing-read "Entry Type: " bibtex-entry-field-alist
2867 nil t nil 'bibtex-entry-type-history))))
8bf38a9b
SM
2868 (let ((key (if bibtex-maintain-sorted-entries
2869 (bibtex-read-key (format "%s key: " entry-type))))
2870 (field-list (bibtex-field-list entry-type)))
7fbf4804
SM
2871 (unless (bibtex-prepare-new-entry (list key nil entry-type))
2872 (error "Entry with key `%s' already exists" key))
50e4b39e
RS
2873 (indent-to-column bibtex-entry-offset)
2874 (insert "@" entry-type (bibtex-entry-left-delimiter))
8bf38a9b 2875 (if key (insert key))
9ae11a89 2876 (save-excursion
a9d77f1f
SM
2877 (mapc 'bibtex-make-field (car field-list))
2878 (mapc 'bibtex-make-optional-field (cdr field-list))
50e4b39e
RS
2879 (if bibtex-comma-after-last-field
2880 (insert ","))
2881 (insert "\n")
2882 (indent-to-column bibtex-entry-offset)
2883 (insert (bibtex-entry-right-delimiter) "\n\n"))
0640d7bf 2884 (bibtex-next-field t)
d715b065
KG
2885 (if (member-ignore-case entry-type bibtex-autofill-types)
2886 (bibtex-autofill-entry))
9ae11a89 2887 (run-hooks 'bibtex-add-entry-hook)))
e5167999 2888
8bf38a9b
SM
2889(defun bibtex-entry-update ()
2890 "Update an existing BibTeX entry.
2891In the BibTeX entry at point, make new fields for those items that may occur
02c8032e 2892according to `bibtex-field-list', but are not yet present."
8bf38a9b
SM
2893 (interactive)
2894 (save-excursion
2895 (bibtex-beginning-of-entry)
2896 ;; For inserting new fields, we use the fact that
2897 ;; bibtex-parse-entry moves point to the end of the last field.
2898 (let* ((fields-alist (bibtex-parse-entry))
2899 (field-list (bibtex-field-list
e0dc0c55 2900 (cdr (assoc "=type=" fields-alist)))))
8bf38a9b 2901 (dolist (field (car field-list))
d528bff7 2902 (unless (assoc-string (car field) fields-alist t)
8bf38a9b
SM
2903 (bibtex-make-field field)))
2904 (dolist (field (cdr field-list))
d528bff7 2905 (unless (assoc-string (car field) fields-alist t)
8bf38a9b
SM
2906 (bibtex-make-optional-field field))))))
2907
d715b065
KG
2908(defun bibtex-parse-entry ()
2909 "Parse entry at point, return an alist.
2910The alist elements have the form (FIELD . TEXT), where FIELD can also be
d528bff7
SM
2911the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\"
2912TEXT may be nil. Remove \"OPT\" and \"ALT\" from FIELD.
2913Move point to the end of the last field."
d715b065 2914 (let (alist bounds)
cb75af76 2915 (when (looking-at bibtex-entry-maybe-empty-head)
e0dc0c55
SM
2916 (push (cons "=type=" (bibtex-type-in-head)) alist)
2917 (push (cons "=key=" (bibtex-key-in-head)) alist)
cb75af76 2918 (goto-char (match-end 0))
d715b065 2919 (while (setq bounds (bibtex-parse-field bibtex-field-name))
d528bff7 2920 (push (cons (bibtex-name-in-field bounds t)
d715b065
KG
2921 (bibtex-text-in-field-bounds bounds))
2922 alist)
2923 (goto-char (bibtex-end-of-field bounds))))
2924 alist))
2925
2926(defun bibtex-autofill-entry ()
02c8032e
SM
2927 "Try to fill fields of current BibTeX entry based on neighboring entries.
2928The current entry must have a key. Determine the neighboring entry
2929\(previouse or next\) whose key is more similar to the key of the current
2930entry. For all empty fields of the current entry insert the corresponding
2931field contents of the neighboring entry. Finally try to update the text
2932based on the difference between the keys of the neighboring and the current
2933entry (for example, the year parts of the keys)."
d715b065
KG
2934 (interactive)
2935 (undo-boundary) ;So you can easily undo it, if it didn't work right.
2936 (bibtex-beginning-of-entry)
2937 (when (looking-at bibtex-entry-head)
e0dc0c55
SM
2938 (let ((type (bibtex-type-in-head))
2939 (key (bibtex-key-in-head))
d715b065
KG
2940 (key-end (match-end bibtex-key-in-head))
2941 (case-fold-search t)
2942 tmp other-key other bounds)
2943 ;; The fields we want to change start right after the key.
2944 (goto-char key-end)
2945 ;; First see whether to use the previous or the next entry
2946 ;; for "inspiration".
2947 (save-excursion
2948 (goto-char (1- (match-beginning 0)))
2949 (bibtex-beginning-of-entry)
02c8032e
SM
2950 (if (and (looking-at bibtex-entry-head)
2951 (bibtex-string= type (bibtex-type-in-head))
2952 ;; In case we found ourselves :-(
2953 (not (equal key (setq tmp (bibtex-key-in-head)))))
2954 (setq other-key tmp
2955 other (point))))
d715b065
KG
2956 (save-excursion
2957 (bibtex-end-of-entry)
2958 (bibtex-skip-to-valid-entry)
02c8032e
SM
2959 (if (and (looking-at bibtex-entry-head)
2960 (bibtex-string= type (bibtex-type-in-head))
2961 ;; In case we found ourselves :-(
2962 (not (equal key (setq tmp (bibtex-key-in-head))))
2963 (or (not other-key)
2964 ;; Check which is the best match.
2965 (< (length (try-completion "" (list key other-key)))
2966 (length (try-completion "" (list key tmp))))))
2967 (setq other-key tmp
2968 other (point))))
d715b065
KG
2969 ;; Then fill the new entry's fields with the chosen other entry.
2970 (when other
2971 (setq other (save-excursion (goto-char other) (bibtex-parse-entry)))
2972 (setq key-end (point)) ;In case parse-entry changed the buffer.
2973 (while (setq bounds (bibtex-parse-field bibtex-field-name))
d528bff7
SM
2974 (let ((text (assoc-string (bibtex-name-in-field bounds t)
2975 other t)))
31df23f5
LK
2976 (if (not (and text
2977 (string-match bibtex-empty-field-re
2978 (buffer-substring-no-properties
2979 (bibtex-start-of-text-in-field bounds)
2980 (bibtex-end-of-text-in-field bounds)))))
d715b065 2981 (goto-char (bibtex-end-of-field bounds))
31df23f5 2982 (goto-char (bibtex-start-of-text-in-field bounds))
d715b065
KG
2983 (delete-region (point) (bibtex-end-of-text-in-field bounds))
2984 (insert (cdr text)))))
2985 ;; Finally try to update the text based on the difference between
2986 ;; the two keys.
2987 (let* ((prefix (try-completion "" (list key other-key)))
2988 ;; If the keys are foo91 and foo92, don't replace 1 for 2
2989 ;; but 91 for 92 instead.
2990 (_ (if (string-match "[0-9]+\\'" prefix)
2991 (setq prefix (substring prefix 0 (match-beginning 0)))))
2992 (suffix (substring key (length prefix)))
2993 (other-suffix (substring other-key (length prefix))))
2994 (while (re-search-backward (regexp-quote other-suffix) key-end 'move)
2995 (replace-match suffix)))))))
2996
cb4ad359 2997(defun bibtex-print-help-message ()
7fbf4804 2998 "Print helpful information about current field in current BibTeX entry."
cb4ad359 2999 (interactive)
7fbf4804
SM
3000 (save-excursion
3001 (let* ((case-fold-search t)
d528bff7 3002 (field-name (bibtex-name-in-field (bibtex-enclosing-field) t))
8bf38a9b
SM
3003 (field-list (bibtex-field-list (progn (re-search-backward
3004 bibtex-entry-maybe-empty-head nil t)
3005 (bibtex-type-in-head))))
c2fb6415
RS
3006 (comment (assoc-string field-name
3007 (append (car field-list)
3008 (cdr field-list))
3009 t)))
31bc4210 3010 (if comment
5673af85 3011 (message "%s" (nth 1 comment))
7fbf4804 3012 (message "No comment available")))))
d30bfc76 3013
02c8032e 3014(defun bibtex-make-field (field &optional move interactive)
d715b065
KG
3015 "Make a field named FIELD in current BibTeX entry.
3016FIELD is either a string or a list of the form
3017\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in
a9d77f1f 3018`bibtex-entry-field-alist'.
02c8032e
SM
3019If MOVE is non-nil, move point past the present field before making
3020the new field. If INTERACTIVE is non-nil, move point to the end of
3021the new field. Otherwise move point past the new field.
3022MOVE and INTERACTIVE are t when called interactively."
7fbf4804 3023 (interactive
8bf38a9b
SM
3024 (list (let ((completion-ignore-case t)
3025 (field-list (bibtex-field-list
e0dc0c55
SM
3026 (save-excursion
3027 (bibtex-enclosing-entry-maybe-empty-head)
3028 (bibtex-type-in-head)))))
8bf38a9b
SM
3029 (completing-read "BibTeX field name: "
3030 (append (car field-list) (cdr field-list))
3f3ed959 3031 nil nil nil bibtex-field-history))
02c8032e 3032 t t))
d715b065
KG
3033 (unless (consp field)
3034 (setq field (list field)))
02c8032e 3035 (if move
d715b065 3036 (let (bibtex-help-message)
02c8032e 3037 (bibtex-find-text)
d715b065
KG
3038 (if (looking-at "[}\"]")
3039 (forward-char))))
3040 (insert ",\n")
3041 (indent-to-column (+ bibtex-entry-offset bibtex-field-indentation))
3042 (if (nth 3 field) (insert "ALT"))
3043 (insert (car field) " ")
3044 (if bibtex-align-at-equal-sign
3045 (indent-to-column (+ bibtex-entry-offset
3046 (- bibtex-text-indentation 2))))
3047 (insert "= ")
d528bff7
SM
3048 (unless bibtex-align-at-equal-sign
3049 (indent-to-column (+ bibtex-entry-offset
3050 bibtex-text-indentation)))
d715b065 3051 (let ((init (nth 2 field)))
02c8032e
SM
3052 (insert (cond ((stringp init) init)
3053 ((fboundp init) (funcall init))
3054 (t (concat (bibtex-field-left-delimiter)
3055 (bibtex-field-right-delimiter))))))
2c10c0f0 3056 (when interactive
8bf38a9b
SM
3057 (forward-char -1)
3058 (bibtex-print-help-message)))
9ae11a89 3059
cb4ad359 3060(defun bibtex-beginning-of-entry ()
7fbf4804 3061 "Move to beginning of BibTeX entry (beginning of line).
cb4ad359 3062If inside an entry, move to the beginning of it, otherwise move to the
a9d77f1f
SM
3063beginning of the previous entry. If point is ahead of all BibTeX entries
3064move point to the beginning of buffer. Return the new location of point."
745bc783 3065 (interactive)
50e4b39e
RS
3066 (skip-chars-forward " \t")
3067 (if (looking-at "@")
a9cb9b80 3068 (forward-char))
d715b065
KG
3069 (re-search-backward "^[ \t]*@" nil 'move)
3070 (point))
e5167999 3071
cb4ad359 3072(defun bibtex-end-of-entry ()
7fbf4804 3073 "Move to end of BibTeX entry (past the closing brace).
cb4ad359 3074If inside an entry, move to the end of it, otherwise move to the end
a9d77f1f 3075of the previous entry. Do not move if ahead of first entry.
d715b065 3076Return the new location of point."
745bc783 3077 (interactive)
7fbf4804
SM
3078 (let ((case-fold-search t)
3079 (org (point))
3080 (pnt (bibtex-beginning-of-entry))
3081 err bounds)
d715b065
KG
3082 (cond ((looking-at bibtex-valid-entry-whitespace-re)
3083 (bibtex-search-entry t nil t)
3084 (unless (equal (match-beginning 0) pnt)
3085 (setq err t)))
3086 ((setq bounds (bibtex-parse-string))
7fbf4804
SM
3087 (goto-char (bibtex-end-of-string bounds)))
3088 ((looking-at "[ \t]*@[ \t]*preamble[ \t\n]*")
3089 (goto-char (match-end 0))
02c8032e
SM
3090 (if (looking-at "[({]")
3091 (forward-sexp 1)
3092 (setq err t)))
7fbf4804
SM
3093 (t
3094 (if (interactive-p)
3095 (message "Not on a known BibTeX entry."))
3096 (goto-char org)))
3097 (when err
3098 (goto-char pnt)
3099 (error "Syntactically incorrect BibTeX entry starts here")))
50e4b39e 3100 (point))
f0cb6034 3101
d10e87a2
SM
3102(defun bibtex-goto-line (arg)
3103 "Goto line ARG, counting from beginning of (narrowed) buffer."
3104 ;; code adapted from `goto-line'
3105 (goto-char (point-min))
3106 (if (eq selective-display t)
3107 (re-search-forward "[\n\C-m]" nil 'end (1- arg))
3108 (forward-line (1- arg))))
3109
3110(defun bibtex-reposition-window ()
7fbf4804 3111 "Make the current BibTeX entry visible.
d10e87a2
SM
3112If entry is smaller than `window-body-height', entry is centered in window.
3113Otherwise display the beginning of entry."
3114 (interactive)
3115 (let ((pnt (point))
3116 (beg (line-number-at-pos (bibtex-beginning-of-entry)))
3117 (end (line-number-at-pos (bibtex-end-of-entry))))
3118 (if (> (window-body-height) (- end beg))
3119 ;; entry fits in current window
3120 (progn
3121 (bibtex-goto-line (/ (+ 1 beg end) 2))
3122 (recenter)
3123 (goto-char pnt))
3124 ;; entry too large for current window
3125 (bibtex-goto-line beg)
3126 (recenter 0)
3127 (if (> (1+ (- (line-number-at-pos pnt) beg))
3128 (window-body-height))
3129 (bibtex-goto-line beg)
3130 (goto-char pnt)))))
50e4b39e
RS
3131
3132(defun bibtex-mark-entry ()
3133 "Put mark at beginning, point at end of current BibTeX entry."
3134 (interactive)
3135 (set-mark (bibtex-beginning-of-entry))
3136 (bibtex-end-of-entry))
3137
3138(defun bibtex-count-entries (&optional count-string-entries)
3139 "Count number of entries in current buffer or region.
d10e87a2
SM
3140With prefix argument COUNT-STRING-ENTRIES count all entries,
3141otherwise count all entries except @String entries.
3142If mark is active count entries in region, if not in whole buffer."
50e4b39e 3143 (interactive "P")
7fbf4804 3144 (let ((number 0)
50e4b39e
RS
3145 (bibtex-sort-ignore-string-entries
3146 (not count-string-entries)))
7fbf4804
SM
3147 (save-excursion
3148 (save-restriction
e0dc0c55 3149 (narrow-to-region (if mark-active (region-beginning)
7fbf4804 3150 (bibtex-beginning-of-first-entry))
e0dc0c55 3151 (if mark-active (region-end) (point-max)))
d715b065 3152 (bibtex-map-entries (lambda (key beg end)
7fbf4804
SM
3153 (setq number (1+ number))))))
3154 (message "%s contains %d entries."
e0dc0c55 3155 (if mark-active "Region" "Buffer")
d715b065 3156 number)))
50e4b39e 3157
cb4ad359 3158(defun bibtex-ispell-entry ()
d10e87a2 3159 "Check BibTeX entry for spelling errors."
745bc783 3160 (interactive)
d715b065
KG
3161 (ispell-region (save-excursion (bibtex-beginning-of-entry))
3162 (save-excursion (bibtex-end-of-entry))))
745bc783 3163
cb4ad359 3164(defun bibtex-ispell-abstract ()
d10e87a2 3165 "Check abstract of BibTeX entry for spelling errors."
745bc783 3166 (interactive)
d715b065
KG
3167 (let ((bounds (save-excursion
3168 (bibtex-beginning-of-entry)
3169 (bibtex-search-forward-field "abstract" t))))
7fbf4804
SM
3170 (if bounds
3171 (ispell-region (bibtex-start-of-text-in-field bounds)
3172 (bibtex-end-of-text-in-field bounds))
3173 (error "No abstract in entry"))))
745bc783 3174
cb4ad359
RS
3175(defun bibtex-narrow-to-entry ()
3176 "Narrow buffer to current BibTeX entry."
745bc783 3177 (interactive)
cb4ad359 3178 (save-excursion
7fbf4804
SM
3179 (widen)
3180 (narrow-to-region (bibtex-beginning-of-entry)
3181 (bibtex-end-of-entry))))
3182
3183(defun bibtex-entry-index ()
02c8032e 3184 "Return index of BibTeX entry head at or past position of point.
7fbf4804 3185The index is a list (KEY CROSSREF-KEY ENTRY-NAME) that is used for sorting
02c8032e
SM
3186the entries of the BibTeX buffer. CROSSREF-KEY is nil unless the value
3187of `bibtex-maintain-sorted-entries' is `crossref'. Move point to the end
3188of the head of the entry found. Return nil if no entry found."
7fbf4804
SM
3189 (let ((case-fold-search t))
3190 (if (re-search-forward bibtex-entry-maybe-empty-head nil t)
3191 (let ((key (bibtex-key-in-head))
d715b065
KG
3192 ;; all entry names should be downcase (for ease of comparison)
3193 (entry-name (downcase (bibtex-type-in-head))))
7fbf4804 3194 ;; Don't search CROSSREF-KEY if we don't need it.
02c8032e
SM
3195 (if (eq bibtex-maintain-sorted-entries 'crossref)
3196 (let ((bounds (bibtex-search-forward-field
3197 "\\(OPT\\)?crossref" t)))
3198 (list key
3199 (if bounds (bibtex-text-in-field-bounds bounds t))
3200 entry-name))
8bf38a9b 3201 (list key nil entry-name))))))
7fbf4804
SM
3202
3203(defun bibtex-lessp (index1 index2)
3204 "Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2.
3205Each index is a list (KEY CROSSREF-KEY ENTRY-NAME).
8bf38a9b
SM
3206The predicate depends on the variable `bibtex-maintain-sorted-entries'.
3207If its value is nil use plain sorting."
7fbf4804
SM
3208 (cond ((not index1) (not index2)) ; indices can be nil
3209 ((not index2) nil)
02c8032e 3210 ((eq bibtex-maintain-sorted-entries 'crossref)
7fbf4804
SM
3211 (if (nth 1 index1)
3212 (if (nth 1 index2)
3213 (or (string-lessp (nth 1 index1) (nth 1 index2))
3214 (and (string-equal (nth 1 index1) (nth 1 index2))
3215 (string-lessp (nth 0 index1) (nth 0 index2))))
3216 (not (string-lessp (nth 0 index2) (nth 1 index1))))
3217 (if (nth 1 index2)
3218 (string-lessp (nth 0 index1) (nth 1 index2))
3219 (string-lessp (nth 0 index1) (nth 0 index2)))))
02c8032e 3220 ((eq bibtex-maintain-sorted-entries 'entry-class)
d715b065
KG
3221 (let ((n1 (cdr (or (assoc (nth 2 index1) bibtex-sort-entry-class-alist)
3222 (assoc 'catch-all bibtex-sort-entry-class-alist)
3223 '(nil . 1000)))) ; if there is nothing else
3224 (n2 (cdr (or (assoc (nth 2 index2) bibtex-sort-entry-class-alist)
3225 (assoc 'catch-all bibtex-sort-entry-class-alist)
3226 '(nil . 1000))))) ; if there is nothing else
7fbf4804
SM
3227 (or (< n1 n2)
3228 (and (= n1 n2)
3229 (string-lessp (car index1) (car index2))))))
02c8032e 3230 (t ; (eq bibtex-maintain-sorted-entries 'plain)
7fbf4804 3231 (string-lessp (car index1) (car index2)))))
745bc783 3232
50e4b39e
RS
3233(defun bibtex-sort-buffer ()
3234 "Sort BibTeX buffer alphabetically by key.
7fbf4804 3235The predicate for sorting is defined via `bibtex-maintain-sorted-entries'.
a9d77f1f
SM
3236If its value is nil use plain sorting. Text outside of BibTeX entries is not
3237affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries
d10e87a2 3238are ignored."
745bc783 3239 (interactive)
cb4ad359 3240 (save-restriction
7fbf4804
SM
3241 (narrow-to-region (bibtex-beginning-of-first-entry)
3242 (save-excursion (goto-char (point-max))
3243 (bibtex-end-of-entry)))
55fe21fc 3244 (bibtex-skip-to-valid-entry)
7fbf4804
SM
3245 (sort-subr nil
3246 'bibtex-skip-to-valid-entry ; NEXTREC function
3247 'bibtex-end-of-entry ; ENDREC function
3248 'bibtex-entry-index ; STARTKEY function
3249 nil ; ENDKEY function
3250 'bibtex-lessp))) ; PREDICATE
3251
e0dc0c55 3252(defun bibtex-find-crossref (crossref-key &optional pnt split)
7fbf4804 3253 "Move point to the beginning of BibTeX entry CROSSREF-KEY.
02c8032e
SM
3254If `bibtex-files' is non-nil, search all these files.
3255Otherwise the search is limited to the current buffer.
3256Return position of entry if CROSSREF-KEY is found or nil otherwise.
3257If CROSSREF-KEY is in the same buffer like current entry but before it
3258an error is signaled. Optional arg PNT is the position of the referencing
3259entry. It defaults to position of point. If optional arg SPLIT is non-nil,
3260split window so that both the referencing and the crossrefed entry are
3261displayed.
d715b065 3262If called interactively, CROSSREF-KEY defaults to crossref key of current
e0dc0c55 3263entry and SPLIT is t."
d715b065
KG
3264 (interactive
3265 (let ((crossref-key
3266 (save-excursion
3267 (bibtex-beginning-of-entry)
3268 (let ((bounds (bibtex-search-forward-field "crossref" t)))
3269 (if bounds
3270 (bibtex-text-in-field-bounds bounds t))))))
02c8032e
SM
3271 (list (bibtex-read-key "Find crossref key: " crossref-key t)
3272 (point) t)))
3273 (let (buffer pos eqb)
3274 (save-excursion
3275 (setq pos (bibtex-find-entry crossref-key t)
3276 buffer (current-buffer)))
3277 (setq eqb (eq buffer (current-buffer)))
e0dc0c55 3278 (cond ((not pos)
02c8032e
SM
3279 (if split (message "Crossref key `%s' not found" crossref-key)))
3280 (split ; called (quasi) interactively
3281 (unless pnt (setq pnt (point)))
e0dc0c55 3282 (goto-char pnt)
02c8032e
SM
3283 (if eqb (select-window (split-window))
3284 (pop-to-buffer buffer))
e0dc0c55 3285 (goto-char pos)
d10e87a2 3286 (bibtex-reposition-window)
e0dc0c55 3287 (beginning-of-line)
02c8032e 3288 (if (and eqb (> pnt pos))
31df23f5 3289 (error "The referencing entry must precede the crossrefed entry!")))
02c8032e
SM
3290 ;; `bibtex-find-crossref' is called noninteractively during
3291 ;; clean-up of an entry. Then it is not possible to check
3292 ;; whether the current entry and the crossrefed entry have
3293 ;; the correct sorting order.
3294 (eqb (goto-char pos))
3295 (t (set-buffer buffer) (goto-char pos)))
e0dc0c55 3296 pos))
7fbf4804 3297
02c8032e 3298(defun bibtex-find-entry (key &optional global start display)
7fbf4804 3299 "Move point to the beginning of BibTeX entry named KEY.
d528bff7 3300Return position of entry if KEY is found or nil if not found.
02c8032e
SM
3301With prefix arg GLOBAL non-nil, search KEY in `bibtex-files'.
3302Otherwise the search is limited to the current buffer.
d528bff7
SM
3303Optional arg START is buffer position where the search starts.
3304If it is nil, start search at beginning of buffer.
02c8032e
SM
3305If DISPLAY is non-nil, display the buffer containing KEY.
3306Otherwise, use `set-buffer'. DISPLAY is t when called interactively."
3307 (interactive (list (bibtex-read-key "Find key: " nil current-prefix-arg)
3308 current-prefix-arg nil t))
3309 (if (and global bibtex-files)
3310 (let ((buffer-list (bibtex-files-expand t))
3311 buffer found)
3312 (while (and (not found)
3313 (setq buffer (pop buffer-list)))
3314 (with-current-buffer buffer
3315 (if (cdr (assoc-string key bibtex-reference-keys))
3316 ;; `bibtex-find-entry' moves point if key found
3317 (setq found (bibtex-find-entry key)))))
3318 (cond ((and found display)
3319 (let ((same-window-buffer-names
3320 (cons (buffer-name buffer) same-window-buffer-names)))
d10e87a2
SM
3321 (pop-to-buffer buffer)
3322 (bibtex-reposition-window)))
02c8032e 3323 (found (set-buffer buffer))
d10e87a2 3324 (display (message "Key `%s' not found" key)))
02c8032e
SM
3325 found)
3326
3327 (let* (case-fold-search
3328 (pnt (save-excursion
3329 (goto-char (or start (point-min)))
3330 (if (re-search-forward (concat "^[ \t]*\\("
3331 bibtex-entry-type
3332 "\\)[ \t]*[({][ \t\n]*\\("
3333 (regexp-quote key)
3334 "\\)[ \t\n]*[,=]")
3335 nil t)
3336 (match-beginning 0)))))
3337 (cond (pnt
d10e87a2
SM
3338 (goto-char pnt)
3339 (if display (bibtex-reposition-window)))
3340 (display (message "Key `%s' not found" key)))
3341 pnt)))
7fbf4804
SM
3342
3343(defun bibtex-prepare-new-entry (index)
3344 "Prepare a new BibTeX entry with index INDEX.
3345INDEX is a list (KEY CROSSREF-KEY ENTRY-NAME).
3346Move point where the entry KEY should be placed.
3347If `bibtex-maintain-sorted-entries' is non-nil, perform a binary
d10e87a2 3348search to look for place for KEY. This requires that buffer is sorted,
921a9483 3349see `bibtex-validate'.
7fbf4804
SM
3350Return t if preparation was successful or nil if entry KEY already exists."
3351 (let ((key (nth 0 index))
3352 key-exist)
3353 (cond ((or (null key)
3354 (and (stringp key)
3355 (string-equal key ""))
3356 (and (not (setq key-exist (bibtex-find-entry key)))
3357 (not bibtex-maintain-sorted-entries)))
3358 (bibtex-move-outside-of-entry))
3359 ;; if key-exist is non-nil due to the previous cond clause
3360 ;; then point will be at beginning of entry named key.
3361 (key-exist)
3362 (t ; bibtex-maintain-sorted-entries is non-nil
3363 (let* ((case-fold-search t)
3364 (left (save-excursion (bibtex-beginning-of-first-entry)
3365 (bibtex-skip-to-valid-entry)
3366 (point)))
3367 (right (save-excursion (bibtex-beginning-of-last-entry)
3368 (bibtex-end-of-entry)))
3369 (found (if (>= left right) left))
3370 actual-index new)
3371 (save-excursion
3372 ;; Binary search
3373 (while (not found)
3374 (goto-char (/ (+ left right) 2))
3375 (bibtex-skip-to-valid-entry t)
3376 (setq actual-index (bibtex-entry-index))
3377 (cond ((bibtex-lessp index actual-index)
3378 (setq new (bibtex-beginning-of-entry))
3379 (if (equal right new)
3380 (setq found right)
3381 (setq right new)))
3382 (t
3383 (bibtex-end-of-entry)
3384 (bibtex-skip-to-valid-entry)
3385 (setq new (point))
3386 (if (equal left new)
3387 (setq found right)
3388 (setq left new))))))
3389 (goto-char found)
3390 (bibtex-beginning-of-entry)
3391 (setq actual-index (save-excursion (bibtex-entry-index)))
3392 (when (or (not actual-index)
3393 (bibtex-lessp actual-index index))
3394 ;; buffer contains no valid entries or
3395 ;; greater than last entry --> append
3396 (bibtex-end-of-entry)
d528bff7 3397 (unless (bobp) (newline (forward-line 2)))
7fbf4804
SM
3398 (beginning-of-line)))))
3399 (unless key-exist t)))
cb4ad359 3400
50e4b39e
RS
3401(defun bibtex-validate (&optional test-thoroughly)
3402 "Validate if buffer or region is syntactically correct.
e0dc0c55
SM
3403Check also for duplicate keys and correct sort order provided
3404`bibtex-maintain-sorted-entries' is non-nil.
3405With optional argument TEST-THOROUGHLY non-nil check also for
3406the absence of required fields and for questionable month fields.
7fbf4804 3407If mark is active, validate current region, if not the whole buffer.
e0dc0c55
SM
3408Only check known entry types, so you can put comments outside of entries.
3409Return t if test was successful, nil otherwise."
31bc4210 3410 (interactive "P")
7fbf4804
SM
3411 (let* ((case-fold-search t)
3412 error-list syntax-error)
3413 (save-excursion
3414 (save-restriction
e0dc0c55 3415 (narrow-to-region (if mark-active (region-beginning)
7fbf4804 3416 (bibtex-beginning-of-first-entry))
e0dc0c55 3417 (if mark-active (region-end) (point-max)))
7fbf4804
SM
3418
3419 ;; looking if entries fit syntactical structure
3420 (goto-char (point-min))
3421 (bibtex-progress-message "Checking syntactical structure")
3422 (let (bibtex-sort-ignore-string-entries)
3423 (while (re-search-forward "^[ \t]*@" nil t)
3424 (bibtex-progress-message)
3425 (forward-char -1)
3426 (let ((pnt (point)))
3427 (if (not (looking-at bibtex-any-valid-entry-re))
3428 (forward-char)
3429 (bibtex-skip-to-valid-entry)
3430 (if (equal (point) pnt)
3431 (forward-char)
3432 (goto-char pnt)
e0dc0c55 3433 (push (cons (bibtex-current-line)
7fbf4804
SM
3434 "Syntax error (check esp. commas, braces, and quotes)")
3435 error-list)
3436 (forward-char))))))
3437 (bibtex-progress-message 'done)
3438
3439 (if error-list
e0dc0c55 3440 ;; proceed only if there were no syntax errors.
7fbf4804 3441 (setq syntax-error t)
e0dc0c55
SM
3442
3443 ;; looking for duplicate keys and correct sort order
3444 (let (previous current key-list)
3445 (bibtex-progress-message "Checking for duplicate keys")
3446 (bibtex-map-entries
3447 (lambda (key beg end)
3448 (bibtex-progress-message)
3449 (goto-char beg)
3450 (setq current (bibtex-entry-index))
3451 (cond ((not previous))
3452 ((member key key-list)
3453 (push (cons (bibtex-current-line)
3454 (format "Duplicate key `%s'" key))
3455 error-list))
3456 ((and bibtex-maintain-sorted-entries
3457 (not (bibtex-lessp previous current)))
3458 (push (cons (bibtex-current-line)
3459 "Entries out of order")
3460 error-list)))
3461 (push key key-list)
3462 (setq previous current)))
3463 (bibtex-progress-message 'done))
3464
3465 ;; Check for duplicate keys in `bibtex-files'.
3466 (bibtex-parse-keys)
02c8032e
SM
3467 ;; We don't want to be fooled by outdated `bibtex-reference-keys'.
3468 (dolist (buffer (bibtex-files-expand nil t))
3469 (dolist (key (with-current-buffer buffer bibtex-reference-keys))
e0dc0c55
SM
3470 (when (and (cdr key)
3471 (cdr (assoc-string (car key) bibtex-reference-keys)))
3472 (bibtex-find-entry (car key))
3473 (push (cons (bibtex-current-line)
3474 (format "Duplicate key `%s' in %s" (car key)
3475 (abbreviate-file-name (buffer-file-name buffer))))
3476 error-list))))
7fbf4804
SM
3477
3478 (when test-thoroughly
7fbf4804
SM
3479 (bibtex-progress-message
3480 "Checking required fields and month fields")
d528bff7 3481 (let ((bibtex-sort-ignore-string-entries t))
55fe21fc 3482 (bibtex-map-entries
d715b065 3483 (lambda (key beg end)
50e4b39e 3484 (bibtex-progress-message)
d715b065 3485 (let* ((entry-list (progn
7fbf4804
SM
3486 (goto-char beg)
3487 (bibtex-search-entry nil end)
c2fb6415
RS
3488 (assoc-string (bibtex-type-in-head)
3489 bibtex-entry-field-alist t)))
7fbf4804
SM
3490 (req (copy-sequence (elt (elt entry-list 1) 0)))
3491 (creq (copy-sequence (elt (elt entry-list 2) 0)))
e0dc0c55 3492 crossref-there bounds alt-there field)
7fbf4804
SM
3493 (goto-char beg)
3494 (while (setq bounds (bibtex-search-forward-field
3495 bibtex-field-name end))
3496 (goto-char (bibtex-start-of-text-in-field bounds))
d528bff7
SM
3497 (let ((field-name (bibtex-name-in-field bounds)))
3498 (if (and (bibtex-string= field-name "month")
e0dc0c55
SM
3499 ;; Check only abbreviated month fields.
3500 (let ((month (bibtex-text-in-field-bounds bounds)))
3501 (not (or (string-match "\\`[\"{].+[\"}]\\'" month)
3502 (assoc-string
3503 month
3504 bibtex-predefined-month-strings t)))))
3505 (push (cons (bibtex-current-line)
7fbf4804
SM
3506 "Questionable month field")
3507 error-list))
e0dc0c55
SM
3508 (setq field (assoc-string field-name req t))
3509 (if (nth 3 field)
3510 (if alt-there (push (cons (bibtex-current-line)
3511 "More than one non-empty alternative")
3512 error-list)
3513 (setq alt-there t)))
3514 (setq req (delete field req)
c2fb6415 3515 creq (delete (assoc-string field-name creq t) creq))
d528bff7 3516 (if (bibtex-string= field-name "crossref")
7fbf4804
SM
3517 (setq crossref-there t))))
3518 (if crossref-there
3519 (setq req creq))
e0dc0c55
SM
3520 (let (alt)
3521 (dolist (field req)
3522 (if (nth 3 field)
3523 (push (car field) alt)
3524 (push (cons (save-excursion (goto-char beg)
3525 (bibtex-current-line))
3526 (format "Required field `%s' missing"
3527 (car field)))
3528 error-list)))
3529 ;; The following fails if there are more than two
3530 ;; alternatives in a BibTeX entry, which isn't
3531 ;; the case momentarily.
3532 (if (cdr alt)
3533 (push (cons (save-excursion (goto-char beg)
3534 (bibtex-current-line))
3535 (format "Alternative fields `%s'/`%s' missing"
3536 (car alt) (cadr alt)))
3537 error-list)))))))
7fbf4804 3538 (bibtex-progress-message 'done)))))
e0dc0c55 3539
50e4b39e 3540 (if error-list
e0dc0c55
SM
3541 (let ((file (file-name-nondirectory (buffer-file-name)))
3542 (dir default-directory)
3543 (err-buf "*BibTeX validation errors*"))
3544 (setq error-list (sort error-list 'car-less-than-car))
3545 (with-current-buffer (get-buffer-create err-buf)
3546 (setq default-directory dir)
3547 (unless (eq major-mode 'compilation-mode) (compilation-mode))
3548 (toggle-read-only -1)
3549 (delete-region (point-min) (point-max))
3550 (insert "BibTeX mode command `bibtex-validate'\n"
3551 (if syntax-error
3552 "Maybe undetected errors due to syntax errors. Correct and validate again.\n"
3553 "\n"))
3554 (dolist (err error-list)
3555 (insert (format "%s:%d: %s\n" file (car err) (cdr err))))
3556 (set-buffer-modified-p nil)
3557 (toggle-read-only 1)
3558 (goto-line 3)) ; first error message
3559 (display-buffer err-buf)
3560 ;; return nil
3561 nil)
3562 (message "%s is syntactically correct"
3563 (if mark-active "Region" "Buffer"))
3564 t)))
3565
3566(defun bibtex-validate-globally (&optional strings)
3567 "Check for duplicate keys in `bibtex-files'.
02c8032e 3568With optional prefix arg STRINGS, check for duplicate strings, too.
e0dc0c55
SM
3569Return t if test was successful, nil otherwise."
3570 (interactive "P")
3571 (let ((buffer-list (bibtex-files-expand t))
3572 buffer-key-list current-buf current-keys error-list)
3573 ;; Check for duplicate keys within BibTeX buffer
3574 (dolist (buffer buffer-list)
3575 (save-excursion
3576 (set-buffer buffer)
3577 (let (entry-type key key-list)
50e4b39e 3578 (goto-char (point-min))
e0dc0c55
SM
3579 (while (re-search-forward bibtex-entry-head nil t)
3580 (setq entry-type (bibtex-type-in-head)
3581 key (bibtex-key-in-head))
3582 (if (or (and strings (bibtex-string= entry-type "string"))
3583 (assoc-string entry-type bibtex-entry-field-alist t))
3584 (if (member key key-list)
3585 (push (format "%s:%d: Duplicate key `%s'\n"
3586 (buffer-file-name)
3587 (bibtex-current-line) key)
3588 error-list)
3589 (push key key-list))))
3590 (push (cons buffer key-list) buffer-key-list))))
3591
3592 ;; Check for duplicate keys among BibTeX buffers
3593 (while (setq current-buf (pop buffer-list))
3594 (setq current-keys (cdr (assq current-buf buffer-key-list)))
3595 (with-current-buffer current-buf
3596 (dolist (buffer buffer-list)
3597 (dolist (key (cdr (assq buffer buffer-key-list)))
3598 (when (assoc-string key current-keys)
3599 (bibtex-find-entry key)
3600 (push (format "%s:%d: Duplicat key `%s' in %s\n"
3601 (buffer-file-name) (bibtex-current-line) key
3602 (abbreviate-file-name (buffer-file-name buffer)))
3603 error-list))))))
3604
3605 ;; Process error list
3606 (if error-list
3607 (let ((err-buf "*BibTeX validation errors*"))
3608 (with-current-buffer (get-buffer-create err-buf)
3609 (unless (eq major-mode 'compilation-mode) (compilation-mode))
3610 (toggle-read-only -1)
3611 (delete-region (point-min) (point-max))
3612 (insert "BibTeX mode command `bibtex-validate-globally'\n\n")
3613 (dolist (err (sort error-list 'string-lessp)) (insert err))
3614 (set-buffer-modified-p nil)
3615 (toggle-read-only 1)
3616 (goto-line 3)) ; first error message
3617 (display-buffer err-buf)
50e4b39e
RS
3618 ;; return nil
3619 nil)
e0dc0c55 3620 (message "No duplicate keys.")
50e4b39e 3621 t)))
745bc783 3622
02c8032e
SM
3623(defun bibtex-next-field (begin)
3624 "Move point to end of text of next BibTeX field.
3625With prefix BEGIN non-nil, move point to its beginning."
745bc783
JB
3626 (interactive "P")
3627 (bibtex-inside-field)
3628 (let ((start (point)))
3629 (condition-case ()
7fbf4804
SM
3630 (let ((bounds (bibtex-enclosing-field)))
3631 (goto-char (bibtex-end-of-field bounds))
3632 (forward-char 2))
745bc783
JB
3633 (error
3634 (goto-char start)
3635 (end-of-line)
50e4b39e 3636 (forward-char))))
02c8032e 3637 (bibtex-find-text begin))
745bc783 3638
02c8032e
SM
3639(defun bibtex-find-text (&optional begin noerror)
3640 "Move point to end of text of current BibTeX field.
3641With optional prefix BEGIN non-nil, move point to its beginning.
3642Unless NOERROR is non-nil, an error is signaled if point is not
3643on a BibTeX field."
3644 (interactive "P")
3645 (let* ((pnt (point))
3646 (_ (bibtex-inside-field))
3647 (bounds (bibtex-enclosing-field t)))
3648 (beginning-of-line)
3649 (cond (bounds
3650 (if begin
3651 (progn (goto-char (bibtex-start-of-text-in-field bounds))
3652 (if (looking-at "[{\"]")
3653 (forward-char)))
3654 (goto-char (bibtex-end-of-text-in-field bounds))
3655 (if (or (= (preceding-char) ?})
3656 (= (preceding-char) ?\"))
3657 (forward-char -1)))
3658 (if bibtex-help-message
3659 (bibtex-print-help-message)))
3660 ((setq bounds (bibtex-parse-string))
3661 (goto-char (if begin
3662 (1+ (bibtex-start-of-text-in-string bounds))
3663 (1- (bibtex-end-of-text-in-string bounds)))))
3664 ((looking-at bibtex-entry-maybe-empty-head)
3665 (goto-char (if begin
3666 (match-beginning bibtex-key-in-head)
3667 (match-end 0))))
3668 (t
3669 (goto-char pnt)
3670 (unless noerror (error "Not on BibTeX field"))))))
50e4b39e
RS
3671
3672(defun bibtex-remove-OPT-or-ALT ()
7fbf4804
SM
3673 "Remove the string starting optional/alternative fields.
3674Align text and go thereafter to end of text."
745bc783 3675 (interactive)
f9bd4abe 3676 (bibtex-inside-field)
7fbf4804
SM
3677 (let ((case-fold-search t)
3678 (bounds (bibtex-enclosing-field)))
50e4b39e 3679 (save-excursion
f9bd4abe 3680 (goto-char (bibtex-start-of-name-in-field bounds))
7fbf4804 3681 (when (looking-at "OPT\\|ALT")
d715b065 3682 (delete-region (match-beginning 0) (match-end 0))
7fbf4804
SM
3683 ;; make field non-OPT
3684 (search-forward "=")
3685 (forward-char -1)
3686 (delete-horizontal-space)
3687 (if bibtex-align-at-equal-sign
3688 (indent-to-column (- bibtex-text-indentation 2))
3689 (insert " "))
3690 (search-forward "=")
3691 (delete-horizontal-space)
3692 (if bibtex-align-at-equal-sign
3693 (insert " ")
3694 (indent-to-column bibtex-text-indentation))))
50e4b39e
RS
3695 (bibtex-inside-field)))
3696
3697(defun bibtex-remove-delimiters ()
7fbf4804 3698 "Remove \"\" or {} around string."
745bc783 3699 (interactive)
f9bd4abe
GM
3700 (save-excursion
3701 (bibtex-inside-field)
d528bff7
SM
3702 (let* ((bounds (bibtex-enclosing-field))
3703 (end (bibtex-end-of-text-in-field bounds))
3704 (start (bibtex-start-of-text-in-field bounds)))
3705 (if (memq (char-before end) '(?\} ?\"))
3706 (delete-region (1- end) end))
3707 (if (memq (char-after start) '(?\{ ?\"))
3708 (delete-region start (1+ start))))))
50e4b39e
RS
3709
3710(defun bibtex-kill-field (&optional copy-only)
7fbf4804
SM
3711 "Kill the entire enclosing BibTeX field.
3712With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring',
d0388eac 3713but do not actually kill it."
50e4b39e 3714 (interactive "P")
7fbf4804 3715 (save-excursion
745bc783 3716 (bibtex-inside-field)
7fbf4804
SM
3717 (let* ((case-fold-search t)
3718 (bounds (bibtex-enclosing-field))
3719 (end (bibtex-end-of-field bounds))
3720 (beg (bibtex-start-of-field bounds)))
3721 (goto-char end)
50e4b39e 3722 (skip-chars-forward " \t\n,")
02c8032e 3723 (push (list (bibtex-name-in-field bounds) nil
7fbf4804
SM
3724 (bibtex-text-in-field-bounds bounds))
3725 bibtex-field-kill-ring)
50e4b39e 3726 (if (> (length bibtex-field-kill-ring) bibtex-field-kill-ring-max)
7fbf4804
SM
3727 (setcdr (nthcdr (1- bibtex-field-kill-ring-max)
3728 bibtex-field-kill-ring)
3729 nil))
50e4b39e 3730 (setq bibtex-field-kill-ring-yank-pointer bibtex-field-kill-ring)
7fbf4804
SM
3731 (unless copy-only
3732 (delete-region beg end))))
50e4b39e
RS
3733 (setq bibtex-last-kill-command 'field))
3734
3735(defun bibtex-copy-field-as-kill ()
02c8032e 3736 "Copy the BibTeX field at point to the kill ring."
50e4b39e
RS
3737 (interactive)
3738 (bibtex-kill-field t))
745bc783 3739
50e4b39e 3740(defun bibtex-kill-entry (&optional copy-only)
f9bd4abe 3741 "Kill the entire enclosing BibTeX entry.
02c8032e
SM
3742With prefix arg COPY-ONLY, copy the current entry to `bibtex-entry-kill-ring',
3743but do not actually kill it."
50e4b39e 3744 (interactive "P")
7fbf4804
SM
3745 (save-excursion
3746 (let* ((case-fold-search t)
3747 (beg (bibtex-beginning-of-entry))
3748 (end (progn (bibtex-end-of-entry)
3749 (if (re-search-forward
3750 bibtex-entry-maybe-empty-head nil 'move)
3751 (goto-char (match-beginning 0)))
3752 (point))))
02c8032e 3753 (push (buffer-substring-no-properties beg end)
7fbf4804
SM
3754 bibtex-entry-kill-ring)
3755 (if (> (length bibtex-entry-kill-ring) bibtex-entry-kill-ring-max)
3756 (setcdr (nthcdr (1- bibtex-entry-kill-ring-max)
3757 bibtex-entry-kill-ring)
3758 nil))
e0dc0c55
SM
3759 (setq bibtex-entry-kill-ring-yank-pointer bibtex-entry-kill-ring)
3760 (unless copy-only
3761 (delete-region beg end))))
50e4b39e
RS
3762 (setq bibtex-last-kill-command 'entry))
3763
3764(defun bibtex-copy-entry-as-kill ()
d528bff7 3765 "Copy the entire enclosing BibTeX entry to `bibtex-entry-kill-ring'."
745bc783 3766 (interactive)
50e4b39e
RS
3767 (bibtex-kill-entry t))
3768
3769(defun bibtex-yank (&optional n)
3770 "Reinsert the last BibTeX item.
3771More precisely, reinsert the field or entry killed or yanked most recently.
3772With argument N, reinsert the Nth most recently killed BibTeX item.
921a9483 3773See also the command \\[bibtex-yank-pop]."
50e4b39e 3774 (interactive "*p")
02c8032e 3775 (bibtex-insert-kill (1- n))
f0cb6034 3776 (setq this-command 'bibtex-yank))
50e4b39e
RS
3777
3778(defun bibtex-yank-pop (n)
02c8032e 3779 "Replace just-yanked killed BibTeX item with a different item.
50e4b39e 3780This command is allowed only immediately after a `bibtex-yank' or a
02c8032e
SM
3781`bibtex-yank-pop'. At such a time, the region contains a reinserted
3782previously killed BibTeX item. `bibtex-yank-pop' deletes that item
3783and inserts in its place a different killed BibTeX item.
50e4b39e
RS
3784
3785With no argument, the previous kill is inserted.
3786With argument N, insert the Nth previous kill.
3787If N is negative, this is a more recent kill.
3788
3789The sequence of kills wraps around, so that after the oldest one
3790comes the newest one."
3791 (interactive "*p")
d528bff7
SM
3792 (unless (eq last-command 'bibtex-yank)
3793 (error "Previous command was not a BibTeX yank"))
50e4b39e
RS
3794 (setq this-command 'bibtex-yank)
3795 (let ((inhibit-read-only t))
3796 (delete-region (point) (mark t))
02c8032e 3797 (bibtex-insert-kill n)))
745bc783
JB
3798
3799(defun bibtex-empty-field ()
cb4ad359 3800 "Delete the text part of the current field, replace with empty text."
745bc783
JB
3801 (interactive)
3802 (bibtex-inside-field)
f9bd4abe
GM
3803 (let ((bounds (bibtex-enclosing-field)))
3804 (goto-char (bibtex-start-of-text-in-field bounds))
3805 (delete-region (point) (bibtex-end-of-text-in-field bounds))
3806 (insert (concat (bibtex-field-left-delimiter)
7fbf4804 3807 (bibtex-field-right-delimiter)) )
f9bd4abe 3808 (bibtex-find-text t)))
745bc783 3809
31bc4210 3810(defun bibtex-pop-previous (arg)
d0388eac 3811 "Replace text of current field with the similar field in previous entry.
f0cb6034 3812With arg, goes up ARG entries. Repeated, goes up so many times. May be
31bc4210
RS
3813intermixed with \\[bibtex-pop-next] (bibtex-pop-next)."
3814 (interactive "p")
3815 (bibtex-pop arg 'previous))
745bc783
JB
3816
3817(defun bibtex-pop-next (arg)
3818 "Replace text of current field with the text of similar field in next entry.
f0cb6034 3819With arg, goes down ARG entries. Repeated, goes down so many times. May be
745bc783
JB
3820intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)."
3821 (interactive "p")
31bc4210 3822 (bibtex-pop arg 'next))
745bc783 3823
7fbf4804 3824(defun bibtex-clean-entry (&optional new-key called-by-reformat)
cb4ad359 3825 "Finish editing the current BibTeX entry and clean it up.
d715b065 3826Check that no required fields are empty and formats entry dependent
7fbf4804 3827on the value of `bibtex-entry-format'.
f9bd4abe 3828If the reference key of the entry is empty or a prefix argument is given,
d10e87a2 3829calculate a new reference key. (Note: this works only if fields in entry
7fbf4804
SM
3830begin on separate lines prior to calling `bibtex-clean-entry' or if
3831'realign is contained in `bibtex-entry-format'.)
d715b065 3832Don't call `bibtex-clean-entry' on @Preamble entries.
50e4b39e 3833At end of the cleaning process, the functions in
7fbf4804
SM
3834`bibtex-clean-entry-hook' are called with region narrowed to entry."
3835 ;; Opt. arg called-by-reformat is t if bibtex-clean-entry
3836 ;; is called by bibtex-reformat
cb4ad359 3837 (interactive "P")
7fbf4804 3838 (let ((case-fold-search t)
02c8032e
SM
3839 (start (bibtex-beginning-of-entry))
3840 (_ (looking-at bibtex-entry-maybe-empty-head))
3841 (entry-type (bibtex-type-in-head))
3842 (key (bibtex-key-in-head)))
d715b065 3843 ;; formatting
d528bff7 3844 (cond ((bibtex-string= entry-type "preamble")
d715b065
KG
3845 ;; (bibtex-format-preamble)
3846 (error "No clean up of @Preamble entries"))
02c8032e
SM
3847 ((bibtex-string= entry-type "string")
3848 (setq entry-type 'string))
e0dc0c55 3849 ;; (bibtex-format-string)
d715b065
KG
3850 (t (bibtex-format-entry)))
3851 ;; set key
7fbf4804 3852 (when (or new-key (not key))
d715b065 3853 (setq key (bibtex-generate-autokey))
d528bff7
SM
3854 ;; Sometimes bibtex-generate-autokey returns an empty string
3855 (if (or bibtex-autokey-edit-before-use (string= "" key))
02c8032e
SM
3856 (setq key (if (eq entry-type 'string)
3857 (bibtex-read-string-key key)
3858 (bibtex-read-key "Key to use: " key))))
3859 (save-excursion
3860 (re-search-forward (if (eq entry-type 'string)
3861 bibtex-string-maybe-empty-head
3862 bibtex-entry-maybe-empty-head))
3863 (if (match-beginning bibtex-key-in-head)
3864 (delete-region (match-beginning bibtex-key-in-head)
3865 (match-end bibtex-key-in-head)))
3866 (insert key)))
e0dc0c55 3867
4f9ae122 3868 (unless called-by-reformat
02c8032e
SM
3869 (let* ((end (save-excursion
3870 (bibtex-end-of-entry)
3871 (if (re-search-forward
3872 bibtex-entry-maybe-empty-head nil 'move)
3873 (goto-char (match-beginning 0)))
3874 (point)))
4f9ae122 3875 (entry (buffer-substring start end))
e0dc0c55
SM
3876 ;; include the crossref key in index
3877 (index (let ((bibtex-maintain-sorted-entries 'crossref))
02c8032e 3878 (bibtex-entry-index))) ; moves point to end of head
d528bff7 3879 error)
e0dc0c55 3880 ;; sorting
4f9ae122
SM
3881 (if (and bibtex-maintain-sorted-entries
3882 (not (and bibtex-sort-ignore-string-entries
02c8032e 3883 (eq entry-type 'string))))
4f9ae122
SM
3884 (progn
3885 (delete-region start end)
02c8032e
SM
3886 (setq error (not (bibtex-prepare-new-entry index))
3887 start (point)) ; update start
3888 (save-excursion (insert entry)))
d528bff7
SM
3889 (bibtex-find-entry key)
3890 (setq error (or (/= (point) start)
02c8032e 3891 (bibtex-find-entry key nil end))))
d528bff7 3892 (if error
e0dc0c55
SM
3893 (error "New inserted entry yields duplicate key"))
3894 (dolist (buffer (bibtex-files-expand))
3895 (with-current-buffer buffer
3896 (if (cdr (assoc-string key bibtex-reference-keys))
3897 (error "Duplicate key in %s" (buffer-file-name)))))
3898
3899 ;; Only update the list of keys if it has been built already.
02c8032e 3900 (cond ((eq entry-type 'string)
e0dc0c55
SM
3901 (if (and (listp bibtex-strings)
3902 (not (assoc key bibtex-strings)))
02c8032e
SM
3903 (push (cons key (bibtex-text-in-string
3904 (save-excursion (bibtex-parse-string)) t))
3905 bibtex-strings)))
e0dc0c55
SM
3906 ;; We have a normal entry.
3907 ((listp bibtex-reference-keys)
3908 (cond ((not (assoc key bibtex-reference-keys))
3909 (push (cons key t) bibtex-reference-keys))
3910 ((not (cdr (assoc key bibtex-reference-keys)))
3911 ;; Turn a crossref key into a header key
3912 (setq bibtex-reference-keys
3913 (cons (cons key t)
3914 (delete (list key) bibtex-reference-keys)))))
3915 ;; Handle crossref key.
3916 (if (and (nth 1 index)
3917 (not (assoc (nth 1 index) bibtex-reference-keys)))
3918 (push (list (nth 1 index)) bibtex-reference-keys)))))
3919
3920 ;; final clean up
3921 (if bibtex-clean-entry-hook
3922 (save-excursion
3923 (save-restriction
3924 (bibtex-narrow-to-entry)
3925 (run-hooks 'bibtex-clean-entry-hook)))))))
50e4b39e 3926
d715b065
KG
3927(defun bibtex-fill-field-bounds (bounds justify &optional move)
3928 "Fill BibTeX field delimited by BOUNDS.
3929If JUSTIFY is non-nil justify as well.
3930If optional arg MOVE is non-nil move point to end of field."
3931 (let ((end-field (copy-marker (bibtex-end-of-field bounds))))
3932 (goto-char (bibtex-start-of-field bounds))
3933 (if justify
3934 (progn
3935 (forward-char)
3936 (bibtex-delete-whitespace)
3937 (open-line 1)
3938 (forward-char)
3939 (indent-to-column (+ bibtex-entry-offset
3940 bibtex-field-indentation))
3941 (re-search-forward "[ \t\n]*=" end-field)
3942 (replace-match "=")
3943 (forward-char -1)
3944 (if bibtex-align-at-equal-sign
3945 (indent-to-column
3946 (+ bibtex-entry-offset (- bibtex-text-indentation 2)))
3947 (insert " "))
3948 (forward-char)
3949 (bibtex-delete-whitespace)
3950 (if bibtex-align-at-equal-sign
3951 (insert " ")
3952 (indent-to-column bibtex-text-indentation)))
3953 (re-search-forward "[ \t\n]*=[ \t\n]*" end-field))
1fdecd0c
RF
3954 ;; Paragraphs within fields are not preserved. Bother?
3955 (fill-region-as-paragraph (line-beginning-position) end-field
3956 default-justification nil (point))
d715b065
KG
3957 (if move (goto-char end-field))))
3958
3959(defun bibtex-fill-field (&optional justify)
3960 "Like \\[fill-paragraph], but fill current BibTeX field.
3961Optional prefix arg JUSTIFY non-nil means justify as well.
3962In BibTeX mode this function is bound to `fill-paragraph-function'."
3963 (interactive "*P")
3964 (let ((pnt (copy-marker (point)))
3965 (bounds (bibtex-enclosing-field)))
3966 (when bounds
3967 (bibtex-fill-field-bounds bounds justify)
3968 (goto-char pnt))))
3969
50e4b39e 3970(defun bibtex-fill-entry ()
7fbf4804
SM
3971 "Fill current BibTeX entry.
3972Realign entry, so that every field starts on a separate line. Field
d0388eac 3973names appear in column `bibtex-field-indentation', field text starts in
f0cb6034 3974column `bibtex-text-indentation' and continuation lines start here, too.
d715b065 3975If `bibtex-align-at-equal-sign' is non-nil, align equal signs, too."
50e4b39e
RS
3976 (interactive "*")
3977 (let ((pnt (copy-marker (point)))
7fbf4804
SM
3978 (end (copy-marker (bibtex-end-of-entry)))
3979 bounds)
50e4b39e 3980 (bibtex-beginning-of-entry)
55fe21fc 3981 (bibtex-delete-whitespace)
50e4b39e 3982 (indent-to-column bibtex-entry-offset)
7fbf4804 3983 (while (setq bounds (bibtex-search-forward-field bibtex-field-name end))
d715b065 3984 (bibtex-fill-field-bounds bounds t t))
50e4b39e
RS
3985 (if (looking-at ",")
3986 (forward-char))
55fe21fc 3987 (bibtex-delete-whitespace)
50e4b39e
RS
3988 (open-line 1)
3989 (forward-char)
3990 (indent-to-column bibtex-entry-offset)
3991 (goto-char pnt)))
3992
4f9ae122
SM
3993(defun bibtex-realign ()
3994 "Realign BibTeX entries such that they are separated by one blank line."
3995 (goto-char (point-min))
1fdecd0c
RF
3996 (let ((case-fold-search t)
3997 (valid-entry (concat "[ \t\n]*\\(" bibtex-valid-entry-re "\\)")))
e0dc0c55
SM
3998 ;; No blank lines prior to the first valid entry if there no
3999 ;; non-white characters in front of it.
1fdecd0c 4000 (when (looking-at valid-entry)
4f9ae122 4001 (replace-match "\\1"))
e0dc0c55 4002 ;; Valid entries are separated by one blank line.
1fdecd0c 4003 (while (re-search-forward valid-entry nil t)
e0dc0c55
SM
4004 (replace-match "\n\n\\1"))
4005 ;; One blank line past the last valid entry if it is followed by
4006 ;; non-white characters, no blank line otherwise.
4007 (beginning-of-line)
4008 (when (re-search-forward bibtex-valid-entry-re nil t)
4009 (bibtex-end-of-entry)
4010 (bibtex-delete-whitespace)
4011 (open-line (if (eobp) 1 2)))))
4f9ae122
SM
4012
4013(defun bibtex-reformat (&optional read-options)
d0388eac 4014 "Reformat all BibTeX entries in buffer or region.
e0dc0c55 4015Without prefix argument, reformatting is based on `bibtex-entry-format'.
d0388eac 4016With prefix argument, read options for reformatting from minibuffer.
f0cb6034 4017With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again.
4f9ae122 4018If mark is active reformat entries in region, if not in whole buffer."
50e4b39e
RS
4019 (interactive "*P")
4020 (let* ((pnt (point))
4021 (use-previous-options
4f9ae122 4022 (and (equal (prefix-numeric-value read-options) 16)
50e4b39e 4023 (or bibtex-reformat-previous-options
f9bd4abe 4024 bibtex-reformat-previous-reference-keys)))
50e4b39e 4025 (bibtex-entry-format
e0dc0c55
SM
4026 (cond (read-options
4027 (if use-previous-options
4028 bibtex-reformat-previous-options
4029 (setq bibtex-reformat-previous-options
4030 (mapcar (lambda (option)
4031 (if (y-or-n-p (car option)) (cdr option)))
4032 `(("Realign entries (recommended)? " . 'realign)
4033 ("Remove empty optional and alternative fields? " . 'opts-or-alts)
4034 ("Remove delimiters around pure numerical fields? " . 'numerical-fields)
4035 (,(concat (if bibtex-comma-after-last-field "Insert" "Remove")
4036 " comma at end of entry? ") . 'last-comma)
4037 ("Replace double page dashes by single ones? " . 'page-dashes)
4038 ("Inherit booktitle? " . 'inherit-booktitle)
4039 ("Force delimiters? " . 'delimiters)
4040 ("Unify case of entry types and field names? " . 'unify-case))))))
4041 ;; Do not include required-fields because `bibtex-reformat'
4042 ;; cannot handle the error messages of `bibtex-format-entry'.
4043 ;; Use `bibtex-validate' to check for required fields.
4044 ((eq t bibtex-entry-format)
4045 '(realign opts-or-alts numerical-fields delimiters
4046 last-comma page-dashes unify-case inherit-booktitle))
4047 (t
4048 (remove 'required-fields (push 'realign bibtex-entry-format)))))
4f9ae122
SM
4049 (reformat-reference-keys
4050 (if read-options
4051 (if use-previous-options
4052 bibtex-reformat-previous-reference-keys
4053 (setq bibtex-reformat-previous-reference-keys
4054 (y-or-n-p "Generate new reference keys automatically? ")))))
4f9ae122
SM
4055 (bibtex-sort-ignore-string-entries t)
4056 bibtex-autokey-edit-before-use)
4057
50e4b39e 4058 (save-restriction
e0dc0c55
SM
4059 (narrow-to-region (if mark-active (region-beginning) (point-min))
4060 (if mark-active (region-end) (point-max)))
4f9ae122 4061 (if (memq 'realign bibtex-entry-format)
e0dc0c55 4062 (bibtex-realign))
50e4b39e 4063 (bibtex-progress-message "Formatting" 1)
d715b065 4064 (bibtex-map-entries (lambda (key beg end)
7fbf4804 4065 (bibtex-progress-message)
4f9ae122 4066 (bibtex-clean-entry reformat-reference-keys t)))
50e4b39e 4067 (bibtex-progress-message 'done))
e0dc0c55 4068 (when reformat-reference-keys
4f9ae122 4069 (kill-local-variable 'bibtex-reference-keys)
e0dc0c55
SM
4070 (when bibtex-maintain-sorted-entries
4071 (bibtex-progress-message "Sorting" 1)
4072 (bibtex-sort-buffer)
4073 (bibtex-progress-message 'done)))
50e4b39e
RS
4074 (goto-char pnt)))
4075
4f9ae122 4076(defun bibtex-convert-alien (&optional read-options)
d10e87a2 4077 "Make an alien BibTeX buffer fully usable by BibTeX mode.
4f9ae122 4078If a file does not conform with all standards used by BibTeX mode,
d10e87a2 4079some of the high-level features of BibTeX mode are not available.
7fbf4804 4080This function tries to convert current buffer to conform with these standards.
4f9ae122
SM
4081With prefix argument READ-OPTIONS non-nil, read options for reformatting
4082entries from minibuffer."
50e4b39e
RS
4083 (interactive "*P")
4084 (message "Starting to validate buffer...")
4085 (sit-for 1 nil t)
4f9ae122 4086 (bibtex-realign)
50e4b39e
RS
4087 (message
4088 "If errors occur, correct them and call `bibtex-convert-alien' again")
4089 (sit-for 5 nil t)
7fbf4804
SM
4090 (deactivate-mark) ; So bibtex-validate works on the whole buffer.
4091 (when (let (bibtex-maintain-sorted-entries)
4092 (bibtex-validate))
4093 (message "Starting to reformat entries...")
4094 (sit-for 2 nil t)
4f9ae122 4095 (bibtex-reformat read-options)
7fbf4804
SM
4096 (goto-char (point-max))
4097 (message "Buffer is now parsable. Please save it.")))
4098
4099(defun bibtex-complete ()
4100 "Complete word fragment before point according to context.
d715b065 4101If point is inside key or crossref field perform key completion based on
d528bff7
SM
4102`bibtex-reference-keys'. Inside a month field perform key completion
4103based on `bibtex-predefined-month-strings'. Inside any other field
4104perform string completion based on `bibtex-strings'. An error is
4105signaled if point is outside key or BibTeX field."
7fbf4804 4106 (interactive)
d528bff7
SM
4107 (let ((pnt (point))
4108 (case-fold-search t)
4109 bounds name compl)
7fbf4804
SM
4110 (save-excursion
4111 (if (and (setq bounds (bibtex-enclosing-field t))
4112 (>= pnt (bibtex-start-of-text-in-field bounds))
4113 (<= pnt (bibtex-end-of-text-in-field bounds)))
d528bff7
SM
4114 (setq name (bibtex-name-in-field bounds t)
4115 compl (cond ((bibtex-string= name "crossref")
02c8032e
SM
4116 ;; point is in crossref field
4117 'crossref-key)
d528bff7 4118 ((bibtex-string= name "month")
02c8032e 4119 ;; point is in month field
d528bff7 4120 bibtex-predefined-month-strings)
02c8032e 4121 ;; point is in other field
d528bff7
SM
4122 (t (if (listp bibtex-strings)
4123 bibtex-strings
4124 ;; so that bibtex-complete-string-cleanup
4125 ;; can do its job
4126 (bibtex-parse-strings
4127 (bibtex-string-files-init))))))
7fbf4804 4128 (bibtex-beginning-of-entry)
02c8032e
SM
4129 (cond ((and (looking-at bibtex-string-maybe-empty-head)
4130 ;; point is inside a string key
4131 (or (and (match-beginning bibtex-key-in-head)
4132 (>= pnt (match-beginning bibtex-key-in-head))
4133 (<= pnt (match-end bibtex-key-in-head)))
4134 ;; or point is on empty string key
4135 (and (not (match-beginning bibtex-key-in-head))
4136 (= pnt (match-end 0)))))
4137 (setq compl 'string))
4138 ((and (looking-at bibtex-entry-maybe-empty-head)
4139 ;; point is inside a key
4140 (or (and (match-beginning bibtex-key-in-head)
4141 (>= pnt (match-beginning bibtex-key-in-head))
4142 (<= pnt (match-end bibtex-key-in-head)))
4143 ;; or point is on empty key
4144 (and (not (match-beginning bibtex-key-in-head))
4145 (= pnt (match-end 0)))))
4146 (setq compl 'key)))))
4147
4148 (cond ((eq compl 'key)
4149 ;; key completion: no cleanup needed
4150 (let (completion-ignore-case)
4151 (bibtex-complete-internal (bibtex-global-key-alist))))
4152
4153 ((eq compl 'crossref-key)
4154 ;; crossref key completion
4155 (let (completion-ignore-case)
4156 (setq choose-completion-string-functions
4157 (lambda (choice buffer mini-p base-size)
4158 (let ((choose-completion-string-functions nil))
4159 (choose-completion-string choice buffer base-size))
4160 (bibtex-complete-crossref-cleanup choice)
4161 ;; return t (needed by choose-completion-string-functions)
4162 t))
4163 (bibtex-complete-crossref-cleanup (bibtex-complete-internal
4164 (bibtex-global-key-alist)))))
4165
4166 ((eq compl 'string)
4167 ;; string key completion: no cleanup needed
4168 (let ((completion-ignore-case t))
4169 (bibtex-complete-internal bibtex-strings)))
7fbf4804 4170
d528bff7 4171 (compl
7fbf4804 4172 ;; string completion
02c8032e
SM
4173 (let ((completion-ignore-case t))
4174 (setq choose-completion-string-functions
4175 `(lambda (choice buffer mini-p base-size)
4176 (let ((choose-completion-string-functions nil))
4177 (choose-completion-string choice buffer base-size))
4178 (bibtex-complete-string-cleanup choice ',compl)
4179 ;; return t (needed by choose-completion-string-functions)
4180 t))
4181 (bibtex-complete-string-cleanup (bibtex-complete-internal compl)
4182 compl)))
7fbf4804
SM
4183
4184 (t (error "Point outside key or BibTeX field")))))
745bc783 4185
cb4ad359 4186(defun bibtex-Article ()
f0cb6034 4187 "Insert a new BibTeX @Article entry; see also `bibtex-entry'."
7fbf4804 4188 (interactive "*")
cb4ad359 4189 (bibtex-entry "Article"))
2798dfd6 4190
cb4ad359 4191(defun bibtex-Book ()
f0cb6034 4192 "Insert a new BibTeX @Book entry; see also `bibtex-entry'."
7fbf4804 4193 (interactive "*")
cb4ad359 4194 (bibtex-entry "Book"))
2798dfd6 4195
cb4ad359 4196(defun bibtex-Booklet ()
f0cb6034 4197 "Insert a new BibTeX @Booklet entry; see also `bibtex-entry'."
7fbf4804 4198 (interactive "*")
cb4ad359
RS
4199 (bibtex-entry "Booklet"))
4200
4201(defun bibtex-InBook ()
f0cb6034 4202 "Insert a new BibTeX @InBook entry; see also `bibtex-entry'."
7fbf4804 4203 (interactive "*")
cb4ad359
RS
4204 (bibtex-entry "InBook"))
4205
4206(defun bibtex-InCollection ()
f0cb6034 4207 "Insert a new BibTeX @InCollection entry; see also `bibtex-entry'."
7fbf4804 4208 (interactive "*")
cb4ad359
RS
4209 (bibtex-entry "InCollection"))
4210
4211(defun bibtex-InProceedings ()
f0cb6034 4212 "Insert a new BibTeX @InProceedings entry; see also `bibtex-entry'."
7fbf4804 4213 (interactive "*")
cb4ad359
RS
4214 (bibtex-entry "InProceedings"))
4215
4216(defun bibtex-Manual ()
f0cb6034 4217 "Insert a new BibTeX @Manual entry; see also `bibtex-entry'."
7fbf4804 4218 (interactive "*")
cb4ad359
RS
4219 (bibtex-entry "Manual"))
4220
4221(defun bibtex-MastersThesis ()
f0cb6034 4222 "Insert a new BibTeX @MastersThesis entry; see also `bibtex-entry'."
7fbf4804 4223 (interactive "*")
cb4ad359
RS
4224 (bibtex-entry "MastersThesis"))
4225
4226(defun bibtex-Misc ()
f0cb6034 4227 "Insert a new BibTeX @Misc entry; see also `bibtex-entry'."
7fbf4804 4228 (interactive "*")
cb4ad359
RS
4229 (bibtex-entry "Misc"))
4230
4231(defun bibtex-PhdThesis ()
f0cb6034 4232 "Insert a new BibTeX @PhdThesis entry; see also `bibtex-entry'."
7fbf4804 4233 (interactive "*")
cb4ad359
RS
4234 (bibtex-entry "PhdThesis"))
4235
4236(defun bibtex-Proceedings ()
f0cb6034 4237 "Insert a new BibTeX @Proceedings entry; see also `bibtex-entry'."
7fbf4804 4238 (interactive "*")
cb4ad359
RS
4239 (bibtex-entry "Proceedings"))
4240
4241(defun bibtex-TechReport ()
f0cb6034 4242 "Insert a new BibTeX @TechReport entry; see also `bibtex-entry'."
7fbf4804 4243 (interactive "*")
cb4ad359
RS
4244 (bibtex-entry "TechReport"))
4245
4246(defun bibtex-Unpublished ()
f0cb6034 4247 "Insert a new BibTeX @Unpublished entry; see also `bibtex-entry'."
7fbf4804 4248 (interactive "*")
cb4ad359
RS
4249 (bibtex-entry "Unpublished"))
4250
7fbf4804
SM
4251(defun bibtex-String (&optional key)
4252 "Insert a new BibTeX @String entry with key KEY."
02c8032e 4253 (interactive (list (bibtex-read-string-key)))
7fbf4804 4254 (let ((bibtex-maintain-sorted-entries
d528bff7
SM
4255 (unless bibtex-sort-ignore-string-entries
4256 bibtex-maintain-sorted-entries))
7fbf4804
SM
4257 endpos)
4258 (unless (bibtex-prepare-new-entry (list key nil "String"))
4259 (error "Entry with key `%s' already exists" key))
4260 (if (zerop (length key)) (setq key nil))
50e4b39e 4261 (indent-to-column bibtex-entry-offset)
7fbf4804
SM
4262 (insert "@String"
4263 (bibtex-entry-left-delimiter))
4264 (if key
4265 (insert key)
4266 (setq endpos (point)))
4267 (insert " = "
4268 (bibtex-field-left-delimiter))
4269 (if key
4270 (setq endpos (point)))
4271 (insert (bibtex-field-right-delimiter)
4272 (bibtex-entry-right-delimiter)
4273 "\n")
4274 (goto-char endpos)))
50e4b39e
RS
4275
4276(defun bibtex-Preamble ()
f0cb6034 4277 "Insert a new BibTeX @Preamble entry."
7fbf4804 4278 (interactive "*")
cb4ad359 4279 (bibtex-move-outside-of-entry)
50e4b39e 4280 (indent-to-column bibtex-entry-offset)
7fbf4804 4281 (insert "@Preamble"
c2fa1079
SM
4282 (bibtex-entry-left-delimiter)
4283 (bibtex-field-left-delimiter))
d715b065
KG
4284 (let ((endpos (point)))
4285 (insert (bibtex-entry-right-delimiter)
c2fa1079 4286 (bibtex-field-right-delimiter)
d715b065
KG
4287 "\n")
4288 (goto-char endpos)))
2798dfd6 4289
e0dc0c55
SM
4290(defun bibtex-url (&optional pos)
4291 "Browse a URL for the BibTeX entry at point.
4292Optional POS is the location of the BibTeX entry.
d528bff7 4293The URL is generated using the schemes defined in `bibtex-generate-url-list'
a9d77f1f 4294\(see there\). Then the URL is passed to `browse-url'."
e0dc0c55 4295 (interactive)
d528bff7 4296 (save-excursion
e0dc0c55 4297 (if pos (goto-char pos))
d528bff7
SM
4298 (bibtex-beginning-of-entry)
4299 (let ((fields-alist (bibtex-parse-entry))
e0dc0c55 4300 ;; Always ignore case,
d528bff7
SM
4301 (case-fold-search t)
4302 (lst bibtex-generate-url-list)
63d516ce 4303 field url scheme obj fmt)
e0dc0c55 4304 (while (setq scheme (pop lst))
a9d77f1f
SM
4305 (when (and (setq field (cdr (assoc-string (caar scheme)
4306 fields-alist t)))
e0dc0c55 4307 ;; Always remove field delimiters
02c8032e 4308 (progn (setq field (bibtex-remove-delimiters-string field))
e0dc0c55 4309 (string-match (cdar scheme) field)))
63d516ce
SM
4310 (setq lst nil
4311 scheme (cdr scheme)
4312 url (if (null scheme) (match-string 0 field)
4313 (if (stringp (car scheme))
4314 (setq fmt (pop scheme)))
4315 (dolist (step scheme)
4316 ;; Always remove field delimiters
4317 (setq field (bibtex-remove-delimiters-string
4318 (cdr (assoc-string (car step) fields-alist t))))
4319 (if (string-match (nth 1 step) field)
4320 (setq field (cond ((functionp (nth 2 step))
4321 (funcall (nth 2 step) field))
4322 ((numberp (nth 2 step))
4323 (match-string (nth 2 step) field))
4324 (t
4325 (replace-match (nth 2 step) t nil field))))
4326 ;; If the scheme is set up correctly,
4327 ;; we should never reach this point
4328 (error "Match failed: %s" field))
4329 (push field obj))
4330 (if fmt (apply 'format fmt (nreverse obj))
4331 (apply 'concat (nreverse obj)))))
4332 (browse-url (message "%s" url))))
e0dc0c55 4333 (unless url (message "No URL known.")))))
d528bff7 4334
745bc783 4335\f
5c69dbfc 4336;; Make BibTeX a Feature
cb4ad359
RS
4337
4338(provide 'bibtex)
745bc783 4339
8bf38a9b 4340;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04
9ae11a89 4341;;; bibtex.el ends here